don't leave repo in an intermediate state if autorebase is interrupted

This commit is contained in:
Timothy Andrew 2020-06-17 18:32:43 +05:30
parent 66db59d11f
commit 359f96fd2d
No known key found for this signature in database
GPG Key ID: ABD64509E977B249
2 changed files with 12 additions and 6 deletions

View File

@ -23,10 +23,6 @@ With this graph built up, the tool can:
- Log a simple list of all PRs in the stack (+ dependencies) to stdout. - Log a simple list of all PRs in the stack (+ dependencies) to stdout.
- Automatically update the stack + push after making local changes. - Automatically update the stack + push after making local changes.
Some caveats:
- The `autorebase` command is not entirely idempotent in cases where it doesn't complete fully. In particular, if all local branches are updated but the final push doesn't go through, you can't run the command again without performing a (manual) reset. This happens because the command relies on remote tracking branches as signposts (this is true at the moment, but it's something of an artifical limitation - there's no reason we can't use a custom signpost of some kind to get around this) to make sure we don't cherry-pick too far.
## Usage ## Usage
```bash ```bash

View File

@ -175,7 +175,9 @@ pub async fn perform_rebase(
let base = rev_to_commit(&repo, &remote_ref(remote, pr.base())); let base = rev_to_commit(&repo, &remote_ref(remote, pr.base()));
let head = rev_to_commit(&repo, pr.head()); let head = rev_to_commit(&repo, pr.head());
let mut stop_cherry_pick_at = repo.merge_base(base.id(), head.id()).unwrap(); let mut stop_cherry_pick_at = repo.merge_base(base.id(), head.id()).unwrap();
let mut update_local_branches_to = vec![];
println!("Checking out {:?}", base); println!("Checking out {:?}", base);
checkout_commit(&repo, &base, None); checkout_commit(&repo, &base, None);
@ -197,8 +199,10 @@ pub async fn perform_rebase(
// TODO: Skip if remote/<branch> is the same SHA as <branch> (only until the first cherry-pick) // TODO: Skip if remote/<branch> is the same SHA as <branch> (only until the first cherry-pick)
cherry_pick_range(&repo, &mut walk); cherry_pick_range(&repo, &mut walk);
// Update local branch so it points to the stack we're building now // Record the commit (in the new stack) that the local branch should now point to.
repo.branch(pr.head(), &head_commit(&repo), true).unwrap(); // Actually perform the switch later on in a batch so we don't leave the repo in
// a troubled state if this process is interrupted.
update_local_branches_to.push((pr.head(), head_commit(&repo)));
// Use remote branch as boundary for the next cherry-pick // Use remote branch as boundary for the next cherry-pick
let from = rev_to_commit(&repo, &remote_ref(remote, pr.head())); let from = rev_to_commit(&repo, &remote_ref(remote, pr.head()));
@ -221,5 +225,11 @@ pub async fn perform_rebase(
command.spawn()?.await?; command.spawn()?.await?;
println!("\nUpdating local branches so they point to the new stack.\n");
for (branch, target) in update_local_branches_to {
println!(" + Branch {} now points to {}", branch, target.id());
repo.branch(branch, &target, true).unwrap();
}
Ok(()) Ok(())
} }