cli: flatten nested loop that intersects branch targets and commit ids

This commit is contained in:
Yuya Nishihara 2023-07-03 17:27:23 +09:00
parent 78e8790e10
commit 908520dcf5

View file

@ -1,3 +1,4 @@
use std::collections::HashSet;
use std::fs; use std::fs;
use std::io::{Read, Write}; use std::io::{Read, Write};
use std::ops::Deref; use std::ops::Deref;
@ -8,7 +9,7 @@ use std::time::Instant;
use clap::{ArgGroup, Subcommand}; use clap::{ArgGroup, Subcommand};
use itertools::Itertools; use itertools::Itertools;
use jujutsu_lib::backend::{ObjectId, TreeValue}; use jujutsu_lib::backend::{CommitId, ObjectId, TreeValue};
use jujutsu_lib::git::{self, parse_gitmodules, GitFetchError, GitPushError, GitRefUpdate}; use jujutsu_lib::git::{self, parse_gitmodules, GitFetchError, GitPushError, GitRefUpdate};
use jujutsu_lib::git_backend::GitBackend; use jujutsu_lib::git_backend::GitBackend;
use jujutsu_lib::op_store::{BranchTarget, RefTarget}; use jujutsu_lib::op_store::{BranchTarget, RefTarget};
@ -655,14 +656,23 @@ fn cmd_git_push(
.iter() .iter()
.map(|change_str| workspace_command.resolve_single_rev(change_str)) .map(|change_str| workspace_command.resolve_single_rev(change_str))
.try_collect()?; .try_collect()?;
let revision_commits = resolve_multiple_nonempty_revsets(&args.revisions, &workspace_command)?; // TODO: Narrow search space to local target commits.
// TODO: Remove redundant CommitId -> Commit -> CommitId round trip.
let revision_commit_ids: HashSet<_> =
resolve_multiple_nonempty_revsets(&args.revisions, &workspace_command)?
.iter()
.map(|commit| commit.id().clone())
.collect();
fn find_branches_targeting<'a>( fn find_branches_targeting<'a>(
view: &'a View, view: &'a View,
target: &RefTarget, mut is_target: impl FnMut(&'a CommitId) -> bool,
) -> Vec<(&'a String, &'a BranchTarget)> { ) -> Vec<(&'a String, &'a BranchTarget)> {
view.branches() view.branches()
.iter() .iter()
.filter(|(_, branch_target)| branch_target.local_target.as_ref() == Some(target)) .filter(|(_, branch_target)| {
matches!(&branch_target.local_target, Some(RefTarget::Normal(id)) if is_target(id))
})
.collect() .collect()
} }
@ -756,23 +766,17 @@ fn cmd_git_push(
} }
} }
let mut any_revisions_targeted = false; let branches_targeted =
for commit in revision_commits { find_branches_targeting(repo.view(), |id| revision_commit_ids.contains(id));
for (branch_name, branch_target) in for &(branch_name, branch_target) in &branches_targeted {
find_branches_targeting(repo.view(), &RefTarget::Normal(commit.id().clone())) if !seen_branches.insert(branch_name.clone()) {
{ continue;
any_revisions_targeted = true; }
if !seen_branches.insert(branch_name.clone()) { if let Ok(Some(update)) = classify_branch_update(branch_name, branch_target, &remote) {
continue; branch_updates.push((branch_name.clone(), update));
}
if let Ok(Some(update)) =
classify_branch_update(branch_name, branch_target, &remote)
{
branch_updates.push((branch_name.clone(), update));
}
} }
} }
if !args.revisions.is_empty() && !any_revisions_targeted { if !args.revisions.is_empty() && branches_targeted.is_empty() {
return Err(user_error("No branches point to the specified revisions.")); return Err(user_error("No branches point to the specified revisions."));
} }
@ -793,17 +797,14 @@ fn cmd_git_push(
} }
Some(wc_commit) => { Some(wc_commit) => {
// Search for branches targeting @ // Search for branches targeting @
let mut branches = let mut branches = find_branches_targeting(repo.view(), |id| id == &wc_commit);
find_branches_targeting(repo.view(), &RefTarget::Normal(wc_commit.clone()));
if branches.is_empty() { if branches.is_empty() {
// Try @- instead if @ is discardable // Try @- instead if @ is discardable
let commit = repo.store().get_commit(&wc_commit)?; let commit = repo.store().get_commit(&wc_commit)?;
if commit.is_discardable() { if commit.is_discardable() {
if let [parent_commit_id] = commit.parent_ids() { if let [parent_commit_id] = commit.parent_ids() {
branches = find_branches_targeting( branches =
repo.view(), find_branches_targeting(repo.view(), |id| id == parent_commit_id);
&RefTarget::Normal(parent_commit_id.clone()),
);
} }
} }
} }