From 9c3f8402fe705b0213b1ecd52adf6ecafcade7b3 Mon Sep 17 00:00:00 2001 From: Benedikt Peetz Date: Wed, 4 Nov 2026 21:06:03 +0100 Subject: pkgs/rollup: Always check the status of git commands Otherwise, we could continue running even though an underlying git command failed. --- pkgs/by-name/ro/rollup/src/main.rs | 107 ++++++++++++++++++++----------------- 1 file changed, 59 insertions(+), 48 deletions(-) (limited to 'pkgs/by-name/ro/rollup/src') diff --git a/pkgs/by-name/ro/rollup/src/main.rs b/pkgs/by-name/ro/rollup/src/main.rs index f49eb81e..4083259f 100644 --- a/pkgs/by-name/ro/rollup/src/main.rs +++ b/pkgs/by-name/ro/rollup/src/main.rs @@ -26,6 +26,54 @@ struct Cli { debug: bool, } +macro_rules! git { + (@base for $finalizer:ident in $to:expr; $($args:literal),*) => { + Command::new("git") + .args([ + "-C", + $to.display().to_string().as_str(), + $($args),* + ]) + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .$finalizer() + .context(concat!("Failed to run `git", $($args),*, "`"))? + }; + (@handle_status $status:expr; $($args:literal),*) => {{ + if !$status.success() { + bail!(concat!("`git", $($args),*, "` failed!")) + } + }}; + (@get_output in $to:expr; $($args:literal),*) => {{ + let output = git!(@base for output in $to; $($args),*); + git!(@handle_status output.status; $($args),*); + + let stdout = String::from_utf8(output.stdout).expect("git should always produce utf8"); + let stderr = String::from_utf8(output.stderr).expect("git should always produce utf8"); + + (stdout, stderr) + }}; + (in $to:expr; $($args:literal),*) => {{ + let status = git!(@base for status in $to; $($args),*); + git!(@handle_status status; $($args),*); + }}; + (@set_stdin_to $stdin:expr; in $to:expr; $($args:literal),*) => {{ + let mut child = git!(@base for spawn in $to; $($args),*); + let mut stdin = child.stdin.take().expect("is piped"); + write!(stdin, "{}", $stdin)?; + drop(stdin); + let output = child.wait_with_output() + .context(concat!("Failed to run `git", $($args),*, "`"))?; + git!(@handle_status output.status; $($args),*); + + let stdout = String::from_utf8(output.stdout).expect("git should always produce utf8"); + let stderr = String::from_utf8(output.stderr).expect("git should always produce utf8"); + + (stdout, stderr) + }}; +} + fn main() -> Result<()> { let args = Cli::parse(); @@ -37,16 +85,8 @@ fn main() -> Result<()> { eprintln!("Successfully parsed all {} patch files.", patches.len()); { - let git_check = Command::new("git") - .args([ - "-C", - args.to.display().to_string().as_str(), - "status", - "--porcelain", - ]) - .output() - .context("Failed to run `git status --procelain`")?; - if !git_check.stdout.is_empty() { + let (stdout, _) = git!(@get_output in args.to; "status", "--porcelain"); + if !stdout.is_empty() { bail!( "`--to` (`{}`) workspace is dirty, refusing to continue.", args.to.display() @@ -56,7 +96,7 @@ fn main() -> Result<()> { for (idx, patch) in patches.iter().enumerate() { eprintln!( - "Applying {}. patch: `{}`...", + "Applying {}. patch: `{}`... ", idx + 1, args.patch_files[idx].display() ); @@ -75,7 +115,7 @@ fn main() -> Result<()> { final_diffs.push(file_diff.to_owned()); } else { eprintln!( - "Dropping remove of `{}`, as the file does not exist in the rollup target.", + " > Dropping remove of `{}`, as the file does not exist in the rollup target.", path.display() ); } @@ -92,7 +132,7 @@ fn main() -> Result<()> { final_diffs.push(file_diff.to_owned()); } else { eprintln!( - "Dropping rename from `{}` to `{}`, as the from file does not exist in the rollup target.", + " > Dropping rename from `{}` to `{}`, as the from file does not exist in the rollup target.", from.display(), to.display() ); @@ -103,7 +143,7 @@ fn main() -> Result<()> { final_diffs.push(file_diff.to_owned()); } else { eprintln!( - "Dropping change to `{}`, as the file does not exist in the rollup target.", + " > Dropping change to `{}`, as the file does not exist in the rollup target.", path.display() ); } @@ -116,40 +156,11 @@ fn main() -> Result<()> { commit_message: patch.commit_message.clone(), }; - let mut apply_child = Command::new("git") - .args(["-C", args.to.display().to_string().as_str(), "apply", "-"]) - .stdin(Stdio::piped()) - .spawn()?; - let mut stdin = apply_child.stdin.take().expect("is piped"); - write!(stdin, "{}", filtered_patch)?; - drop(stdin); - let status = apply_child.wait()?; - if !status.success() { - bail!("git apply failed.") - } - - let add = Command::new("git") - .args(["-C", args.to.display().to_string().as_str(), "add", "."]) - .status()?; - if !add.success() { - bail!("git add ., failed.") - } - - let mut commit_child = Command::new("git") - .args([ - "-C", - args.to.display().to_string().as_str(), - "commit", - "--file=-", - ]) - .stdin(Stdio::piped()) - .spawn()?; - let mut stdin = commit_child.stdin.take().expect("is piped"); - write!(stdin, "{}", filtered_patch.commit_message)?; - drop(stdin); - let status = apply_child.wait()?; - if !status.success() { - bail!("git commit failed.") + git!(@set_stdin_to filtered_patch; in args.to; "apply", "-"); + git!(in args.to; "add", "."); + let (_, stderr) = git!(@set_stdin_to filtered_patch.commit_message; in args.to; "commit", "--file=-", "--quiet"); + if !stderr.is_empty() { + bail!("git commit returned some errors: \n{stderr}"); } } -- cgit v1.3.1