From e56c29a0af959158d46bf1f9b53393bf10abf0ad Mon Sep 17 00:00:00 2001 From: Essien Ita Essien <34972+essiene@users.noreply.github.com> Date: Sat, 2 Nov 2024 11:04:02 +0000 Subject: [PATCH] git sync: Build update record ## Summary * [X] Get branch pre-fetch heads * [X] Build candidates from prefetch heads * [X] Fetch from remotes * [X] Get branch post-fetch heads * [ ] Rebase * [X] Build old -> new map * [ ] transform descendants ## Details Build a record of old branch heads mapped to the new branch heads. This record will be used to derive the candidates that need rebasing. Issue: #1039 --- cli/src/commands/git/sync.rs | 54 +++++++++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/cli/src/commands/git/sync.rs b/cli/src/commands/git/sync.rs index 784a5607e8..5269dfc1ab 100644 --- a/cli/src/commands/git/sync.rs +++ b/cli/src/commands/git/sync.rs @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +use std::collections::BTreeMap; +use std::collections::BTreeSet; use std::fmt; use clap_complete::ArgValueCandidates; @@ -88,7 +90,14 @@ pub fn cmd_git_sync( drop(guard); let guard = tracing::debug_span!("git.sync.post-fetch").entered(); - let _postfetch_heads = get_branch_heads(tx.repo(), &args.branch)?; + let postfetch_heads = get_branch_heads(tx.repo(), &args.branch)?; + let _update_record = UpdateRecord::new( + &tx, + &BranchHeads { + prefetch: &prefetch_heads, + postfetch: &postfetch_heads, + }, + ); drop(guard); let guard = tracing::debug_span!("git.sync.rebase").entered(); @@ -133,6 +142,49 @@ fn get_branch_heads( Ok(commits) } +fn set_diff(lhs: &[CommitId], rhs: &[CommitId]) -> Vec { + BTreeSet::from_iter(lhs.to_vec()) + .difference(&BTreeSet::from_iter(rhs.to_vec())) + .cloned() + .collect_vec() +} + +struct BranchHeads<'a> { + prefetch: &'a [CommitId], + postfetch: &'a [CommitId], +} + +struct UpdateRecord { + _old_to_new: BTreeMap, +} + +impl UpdateRecord { + fn new(tx: &WorkspaceCommandTransaction, heads: &BranchHeads) -> Self { + let new_heads = set_diff(heads.postfetch, heads.prefetch); + let needs_rebase = set_diff(heads.prefetch, heads.postfetch); + + let mut old_to_new: BTreeMap = BTreeMap::from([]); + + for new in &new_heads { + for old in &needs_rebase { + if old != new && tx.repo().index().is_ancestor(old, new) { + old_to_new.insert(old.clone(), new.clone()); + } + } + } + + for (k, v) in &old_to_new { + let old = short_commit_hash(k); + let new = short_commit_hash(v); + tracing::debug!("rebase children of {old} to {new}"); + } + + UpdateRecord { + _old_to_new: old_to_new, + } + } +} + #[derive(Eq, Ord, PartialEq, PartialOrd)] pub struct CandidateCommit { parent: CommitId,