From ed258e155db1eee971d23f078796fb8545f235cb Mon Sep 17 00:00:00 2001 From: Owen Avery Date: Fri, 6 Dec 2024 15:04:10 -0500 Subject: [PATCH 1/2] gerris: Allow partial upstream failures --- src/git.rs | 2 +- src/git/cherry_pick.rs | 13 +++++++++++++ src/upstream.rs | 26 ++++++++++++++++++++++---- 3 files changed, 36 insertions(+), 5 deletions(-) diff --git a/src/git.rs b/src/git.rs index 047a2ed..a745c47 100644 --- a/src/git.rs +++ b/src/git.rs @@ -14,7 +14,7 @@ mod rev_list; mod switch; pub use branch::{branch, StartingPoint}; -pub use cherry_pick::cherry_pick; +pub use cherry_pick::{cherry_pick, cherry_pick_abort}; pub use commit::commit; pub use fetch::fetch; pub use log::log; diff --git a/src/git/cherry_pick.rs b/src/git/cherry_pick.rs index ce92f72..1477f95 100644 --- a/src/git/cherry_pick.rs +++ b/src/git/cherry_pick.rs @@ -18,3 +18,16 @@ impl GitCmd for CherryPick { cmd.arg("cherry-pick").arg(self.commit); } } + +#[derive(Default)] +pub struct CherryPickAbort; + +pub fn cherry_pick_abort() -> CherryPickAbort { + CherryPickAbort +} + +impl GitCmd for CherryPickAbort { + fn setup(self, cmd: &mut Command) { + cmd.arg("cherry-pick").arg("--abort"); + } +} diff --git a/src/upstream.rs b/src/upstream.rs index 62f950c..95241b0 100644 --- a/src/upstream.rs +++ b/src/upstream.rs @@ -224,12 +224,30 @@ pub async fn prepare_commits( info!("created branch `{new_branch}`"); - rev_list.lines().try_for_each(|commit| { + // cherry-pick until we hit a commit we can't apply + // if we hit such a commit, only error if we haven't applied any commits + let mut had_successful_cherry_pick = false; + for commit in rev_list.lines() { info!("cherry-picking {commit}..."); - git::cherry_pick(git::Commit(commit)).spawn()?; - maybe_prefix_cherry_picked_commit() - })?; + match git::cherry_pick(git::Commit(commit)).spawn() { + Err(e_cherry) => { + if !had_successful_cherry_pick { + info!("failed on first commit"); + return Err(Error::Git(e_cherry)) + } else if let Err(e_abort) = git::cherry_pick_abort().spawn() { + info!("failed to abort cherry-pick"); + return Err(Error::Git(e_abort)) + } else { + info!("failed, stopping early"); + break + } + } + _ => had_successful_cherry_pick = true + } + + maybe_prefix_cherry_picked_commit()?; + } info!("pushing branch..."); git::push() From 7ab586429514e980394b7947ed7a16abb31c078a Mon Sep 17 00:00:00 2001 From: Owen Avery Date: Fri, 6 Dec 2024 20:59:21 -0500 Subject: [PATCH 2/2] gerris: Attempt to work around upstream-only commits --- src/upstream.rs | 78 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 53 insertions(+), 25 deletions(-) diff --git a/src/upstream.rs b/src/upstream.rs index 95241b0..fff63f8 100644 --- a/src/upstream.rs +++ b/src/upstream.rs @@ -141,6 +141,57 @@ pub fn maybe_prefix_cherry_picked_commit() -> Result<(), Error> { Ok(()) } +// returns (them_msg, us) +fn find_last_upstreamed_commit_us() -> Result<(String, String), Error> { + let mut branch = git::Branch("gcc/trunk".to_owned()); + + loop { + let last_upstreamed_commit = git::log() + .amount(1) + .grep("gccrs: ") + .branch(branch) + .format(git::Format::Hash) + .spawn()? + .stdout + .trim_end() + .to_owned(); + + info!("found last upstreamed commit: {}", last_upstreamed_commit); + + let last_msg = git::log() + .amount(1) + .branch(git::Branch(last_upstreamed_commit.as_str())) + .format(git::Format::Title) + .spawn()? + .stdout + .strip_prefix("gccrs: ") + .unwrap() + .trim_end() + .to_owned(); + + info!("commit title: {}", last_msg); + + let last_commit_us = git::log() + .amount(1) + .grep(last_msg.as_str()) + .branch(git::Branch("upstream/master")) + .grep(last_msg.as_str()) + .format(git::Format::Hash) + .spawn()? + .stdout + .trim_end() + .to_owned(); + + if last_commit_us.is_empty() { + info!("could not find matching commit, skipping"); + branch = git::Branch(last_upstreamed_commit + "~"); + } else { + info!("found equivalent commit: {}", last_commit_us); + return Ok((last_msg, last_commit_us)); + } + } +} + fn prepare_body(last_commit: String, rev_list: String) -> String { format!( " @@ -176,31 +227,8 @@ pub async fn prepare_commits( info!("fetching `gcc`..."); git::fetch().remote("gcc").spawn()?; - let last_upstreamed_commit = git::log() - .amount(1) - .grep("gccrs: ") - .branch(git::Branch("gcc/trunk")) - .format(git::Format::Title) - .spawn()? - .stdout; - - info!("found last upstreamed commit: {}", last_upstreamed_commit); - - let last_msg = last_upstreamed_commit - .strip_prefix("gccrs: ") - .unwrap() - .trim_end(); - - let last_commit_us = git::log() - .amount(1) - .grep(last_msg) - .branch(git::Branch("upstream/master")) - .grep(last_msg) - .format(git::Format::Hash) - .spawn()? - .stdout; - - info!("found equivalent commit: {}", last_commit_us); + let (last_upstreamed_commit, last_commit_us) + = find_last_upstreamed_commit_us()?; let rev_list = git::rev_list(last_commit_us, "upstream/master") .no_merges()