From e1d3132ace342716c20f32737a514abaa0132550 Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Sun, 4 Apr 2021 15:05:00 +0300 Subject: feat: commit changes made by Bumper The git tag then points at that commit. --- bumper.md | 4 ++-- src/bin/bumper.rs | 4 +++- src/errors.rs | 15 ++++----------- src/git.rs | 39 ++++++++++++++++++++++++--------------- subplot/bumper.py | 19 ++++++++++++++----- subplot/bumper.yaml | 7 +++++-- 6 files changed, 52 insertions(+), 36 deletions(-) diff --git a/bumper.md b/bumper.md index 130e980..43dd8c7 100644 --- a/bumper.md +++ b/bumper.md @@ -94,9 +94,9 @@ given an installed Bumper given file foo/Cargo.toml from Cargo.toml given file foo/debian/changelog from changelog given all files in foo are committed to git -given the HEAD commit in foo is COMMIT when I run, in foo, bumper 1.2.0 -then in foo, git tag v1.2.0 is a signed tag pointing at +then all changes in foo are committed +then in foo, git tag v1.2.0 is a signed tag then file foo/Cargo.toml matches regex /version\s*=\s*"1\.2\.0"/ then file foo/debian/changelog matches regex / \(0\.1\.0-1\) / then file foo/debian/changelog matches regex / \(1\.2\.0-1\) / diff --git a/src/bin/bumper.rs b/src/bin/bumper.rs index 08242ed..b2e9f68 100644 --- a/src/bin/bumper.rs +++ b/src/bin/bumper.rs @@ -21,7 +21,9 @@ fn bumper() -> Result<(), BumperError> { kind.set_version(&opt.version)?; } - git::tag(&opt.version)?; + let msg = format!("Set version to {}", opt.version); + git::commit(".", &msg)?; + git::tag(".", &opt.version)?; info!("Bumper ends OK"); Ok(()) } diff --git a/src/errors.rs b/src/errors.rs index 3eb8605..6ea498d 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -32,11 +32,11 @@ pub enum BumperError { #[error("Couldn't turn {0} into an absolute path: {1}")] AbsPath(PathBuf, #[source] std::io::Error), - #[error("Failed to run git: {0}")] - GitInvoke(#[source] std::io::Error), + #[error("Failed to run git {1:?} in {0}: {2}")] + GitInvoke(PathBuf, Vec, #[source] std::io::Error), - #[error("Command 'git tag' failed: {0}")] - GitTag(String), + #[error("git {1:?} failed in {0}: {2}")] + Git(PathBuf, Vec, String), #[error("Failed to run dch in {0}: {1}")] DchInvoke(PathBuf, #[source] std::io::Error), @@ -44,10 +44,3 @@ pub enum BumperError { #[error("dch failed in {0}: {1}")] Dch(PathBuf, String), } - -impl BumperError { - pub fn git_tag(stderr: &[u8]) -> Self { - let stderr = String::from_utf8_lossy(stderr).into_owned(); - Self::GitTag(stderr) - } -} diff --git a/src/git.rs b/src/git.rs index 38e99d9..563afa1 100644 --- a/src/git.rs +++ b/src/git.rs @@ -1,26 +1,35 @@ use crate::errors::BumperError; use log::{debug, info}; +use std::path::Path; use std::process::Command; -pub fn tag(version: &str) -> Result<(), BumperError> { - debug!("git tag in {}", std::env::current_dir().unwrap().display()); +pub fn tag>(dirname: P, version: &str) -> Result<(), BumperError> { + let msg = format!("release version {}", version); let tag_name = format!("v{}", version); - info!("Create git tag {}", tag_name); + git(dirname.as_ref(), &["tag", "-am", &msg, &tag_name])?; + Ok(()) +} + +pub fn commit>(dirname: P, msg: &str) -> Result<(), BumperError> { + git(dirname.as_ref(), &["commit", "-am", msg])?; + Ok(()) +} + +fn git(dirname: &Path, args: &[&str]) -> Result<(), BumperError> { + info!("git {:?} in {}", args, dirname.display()); let output = Command::new("git") - .arg("tag") - .arg("-am") - .arg(format!("release version {}", version)) - .arg(format!("v{}", version)) - .output(); - let output = match output { - Ok(output) => output, - Err(err) => { - return Err(BumperError::GitInvoke(err)); - } - }; + .args(args) + .current_dir(dirname) + .output() + .map_err(|err| { + let args = args.iter().map(|s| s.to_string()).collect(); + BumperError::GitInvoke(dirname.to_path_buf(), args, err) + })?; debug!("git exit code was {:?}", output.status.code()); if !output.status.success() { - return Err(BumperError::git_tag(&output.stderr)); + let args = args.iter().map(|s| s.to_string()).collect(); + let stderr = String::from_utf8_lossy(&output.stderr).into_owned(); + return Err(BumperError::Git(dirname.to_path_buf(), args, stderr)); } Ok(()) } diff --git a/subplot/bumper.py b/subplot/bumper.py index 329173c..e340927 100644 --- a/subplot/bumper.py +++ b/subplot/bumper.py @@ -71,17 +71,26 @@ def only_these_files_exist_in(ctx, filenames=None, dirname=None): assert_eq(expect, actual) -def git_tag_points_at(ctx, dirname=None, tag=None, varname=None): +def git_tag_exists(ctx, dirname=None, tag=None): runcmd_run = globals()["runcmd_run"] runcmd_get_stdout = globals()["runcmd_get_stdout"] runcmd_exit_code_is_zero = globals()["runcmd_exit_code_is_zero"] + logging.debug(f"expecting tag {tag} to exist") runcmd_run(ctx, ["git", "show", "--raw", tag], cwd=dirname) runcmd_exit_code_is_zero(ctx) - output = runcmd_get_stdout(ctx) - commit = ctx[varname] - logging.debug(f"expecting tag {tag} to point at {commit}") logging.debug(f"tag: {output!r}") assert output.startswith(f"tag {tag}\n") - assert f"\ncommit {commit}" in output + + +def git_working_tree_is_clean(ctx, dirname=None): + runcmd_run = globals()["runcmd_run"] + runcmd_get_stdout = globals()["runcmd_get_stdout"] + runcmd_exit_code_is_zero = globals()["runcmd_exit_code_is_zero"] + assert_eq = globals()["assert_eq"] + + runcmd_run(ctx, ["git", "status", "--porcelain"], cwd=dirname) + runcmd_exit_code_is_zero(ctx) + output = runcmd_get_stdout(ctx) + assert_eq(output, "") diff --git a/subplot/bumper.yaml b/subplot/bumper.yaml index d1ee4f0..50cf83c 100644 --- a/subplot/bumper.yaml +++ b/subplot/bumper.yaml @@ -16,5 +16,8 @@ - then: "only files {filenames:text} exist in {dirname}" function: only_these_files_exist_in -- then: "in {dirname}, git tag {tag} is a signed tag pointing at <{varname}>" - function: git_tag_points_at +- then: "in {dirname}, git tag {tag} is a signed tag" + function: git_tag_exists + +- then: "all changes in {dirname} are committed" + function: git_working_tree_is_clean -- cgit v1.2.1