From 0617dfbfe7e05718791a8ca6e1eaa82306a1c097 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 candidate commits. ## Summary * [X] Get branch pre-fetch heads * [X] Build candidates from prefetch heads * [X] Fetch from remotes * [X] Get branch post-fetch heads * [ ] Rebase ## Details * Candidate commits (parent_id, child_id) are: * branch commits * and their descendants * which are not found in untracked remote branches Issue: #1039 --- cli/src/commands/git/sync.rs | 55 +++++++++++++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/cli/src/commands/git/sync.rs b/cli/src/commands/git/sync.rs index 084edbfb9d..f20fa5f246 100644 --- a/cli/src/commands/git/sync.rs +++ b/cli/src/commands/git/sync.rs @@ -12,16 +12,20 @@ // See the License for the specific language governing permissions and // limitations under the License. +use std::fmt; + use clap_complete::ArgValueCandidates; use itertools::Itertools; use jj_lib::backend::CommitId; use jj_lib::commit::Commit; +use jj_lib::op_store::RemoteRefState; use jj_lib::repo::Repo; use jj_lib::revset::FailingSymbolResolver; use jj_lib::revset::RevsetExpression; use jj_lib::revset::RevsetIteratorExt; use jj_lib::str_util::StringPattern; +use crate::cli_util::short_commit_hash; use crate::cli_util::CommandHelper; use crate::cli_util::WorkspaceCommandTransaction; use crate::command_error::CommandError; @@ -75,7 +79,8 @@ pub fn cmd_git_sync( let mut tx = workspace_command.start_transaction(); let guard = tracing::debug_span!("git.sync.pre-fetch").entered(); - let _prefetch_heads = get_bookmark_heads(tx.base_repo().as_ref(), &args.branch)?; + let prefetch_heads = get_bookmark_heads(tx.base_repo().as_ref(), &args.branch)?; + let _candidates = CandidateCommit::get(tx.repo(), &prefetch_heads)?; drop(guard); let guard = tracing::debug_span!("git.sync.fetch").entered(); @@ -130,6 +135,54 @@ fn get_bookmark_heads( Ok(commits) } +#[derive(Eq, Ord, PartialEq, PartialOrd)] +pub struct CandidateCommit { + parent: CommitId, + child: CommitId, +} + +impl fmt::Display for CandidateCommit { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let parent = short_commit_hash(&self.parent); + let child = short_commit_hash(&self.child); + write!(f, "=> {parent} --> {child}") + } +} + +impl CandidateCommit { + fn get(repo: &dyn Repo, start: &[CommitId]) -> Result, CommandError> { + let commits: Vec = RevsetExpression::commits(start.to_vec()) + .descendants() + .minus(&RevsetExpression::remote_bookmarks( + StringPattern::everything(), + StringPattern::everything(), + Some(RemoteRefState::New), + )) + .resolve_user_expression(repo, &FailingSymbolResolver)? + .evaluate(repo)? + .iter() + .commits(repo.store()) + .try_collect()?; + + Ok(commits + .iter() + .flat_map(|commit| { + commit + .parent_ids() + .iter() + .map(|parent_id| { + let candidate = CandidateCommit { + parent: parent_id.clone(), + child: commit.id().clone(), + }; + tracing::debug!("candidate: {candidate}"); + candidate + }) + .collect::>() + }) + .collect::>()) + } +} fn git_fetch_all( ui: &mut Ui,