Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Increase error tolerance #25

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/git.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
13 changes: 13 additions & 0 deletions src/git/cherry_pick.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}
}
104 changes: 75 additions & 29 deletions src/upstream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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!(
"
Expand Down Expand Up @@ -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()
Expand All @@ -224,12 +252,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()
Expand Down