git-push: extract function that looks up branches by revisions

cmd_git_push() is large. Let's split it up.
This commit is contained in:
Yuya Nishihara 2024-03-17 14:04:20 +09:00
parent 4e9d35d049
commit 02c0927734

View file

@ -799,7 +799,6 @@ fn cmd_git_push(
}; };
let repo = workspace_command.repo().clone(); let repo = workspace_command.repo().clone();
let wc_commit_id = workspace_command.get_wc_commit_id().cloned();
let change_commits: Vec<_> = args let change_commits: Vec<_> = args
.change .change
.iter() .iter()
@ -910,36 +909,13 @@ fn cmd_git_push(
let use_default_revset = let use_default_revset =
args.branch.is_empty() && args.change.is_empty() && args.revisions.is_empty(); args.branch.is_empty() && args.change.is_empty() && args.revisions.is_empty();
let revision_commit_ids: HashSet<_> = if use_default_revset { let branches_targeted = find_branches_targeted_by_revisions(
let Some(wc_commit_id) = wc_commit_id else { ui,
return Err(user_error("Nothing checked out in this workspace")); tx.base_workspace_helper(),
}; &remote,
let current_branches_expression = RevsetExpression::remote_branches( &args.revisions,
StringPattern::everything(), use_default_revset,
StringPattern::Exact(remote.to_owned()), )?;
)
.range(&RevsetExpression::commit(wc_commit_id))
.intersection(&RevsetExpression::branches(StringPattern::everything()));
let current_branches_revset = tx
.base_workspace_helper()
.evaluate_revset(current_branches_expression)?;
current_branches_revset.iter().collect()
} else {
// TODO: Narrow search space to local target commits.
// TODO: Remove redundant CommitId -> Commit -> CommitId round trip.
resolve_multiple_nonempty_revsets(&args.revisions, tx.base_workspace_helper())?
.iter()
.map(|commit| commit.id().clone())
.collect()
};
let branches_targeted = repo
.view()
.local_remote_branches(&remote)
.filter(|(_, targets)| {
let mut local_ids = targets.local_target.added_ids();
local_ids.any(|id| revision_commit_ids.contains(id))
})
.collect_vec();
for &(branch_name, targets) in &branches_targeted { for &(branch_name, targets) in &branches_targeted {
if !seen_branches.insert(branch_name.to_owned()) { if !seen_branches.insert(branch_name.to_owned()) {
continue; continue;
@ -950,21 +926,6 @@ fn cmd_git_push(
Err(reason) => reason.print(ui)?, Err(reason) => reason.print(ui)?,
} }
} }
if branches_targeted.is_empty() {
if use_default_revset {
writeln!(
ui.warning(),
"No branches found in the default push revset, \
`remote_branches(remote={remote})..@`."
)?;
} else if !args.revisions.is_empty() {
writeln!(
ui.warning(),
"No branches point to the specified revisions."
)?;
} else { /* A plain "Nothing changed" message will suffice */
}
}
tx_description = format!( tx_description = format!(
"push {} to git remote {}", "push {} to git remote {}",
@ -1207,6 +1168,61 @@ fn find_branches_to_push<'a>(
} }
} }
fn find_branches_targeted_by_revisions<'a>(
ui: &Ui,
workspace_command: &'a WorkspaceCommandHelper,
remote_name: &str,
revisions: &[RevisionArg],
use_default_revset: bool,
) -> Result<Vec<(&'a str, LocalAndRemoteRef<'a>)>, CommandError> {
let revision_commit_ids: HashSet<_> = if use_default_revset {
let Some(wc_commit_id) = workspace_command.get_wc_commit_id().cloned() else {
return Err(user_error("Nothing checked out in this workspace"));
};
let current_branches_expression = RevsetExpression::remote_branches(
StringPattern::everything(),
StringPattern::Exact(remote_name.to_owned()),
)
.range(&RevsetExpression::commit(wc_commit_id))
.intersection(&RevsetExpression::branches(StringPattern::everything()));
let current_branches_revset =
workspace_command.evaluate_revset(current_branches_expression)?;
current_branches_revset.iter().collect()
} else {
// TODO: Narrow search space to local target commits.
// TODO: Remove redundant CommitId -> Commit -> CommitId round trip.
resolve_multiple_nonempty_revsets(revisions, workspace_command)?
.iter()
.map(|commit| commit.id().clone())
.collect()
};
let branches_targeted = workspace_command
.repo()
.view()
.local_remote_branches(remote_name)
.filter(|(_, targets)| {
let mut local_ids = targets.local_target.added_ids();
local_ids.any(|id| revision_commit_ids.contains(id))
})
.collect_vec();
if branches_targeted.is_empty() {
if use_default_revset {
writeln!(
ui.warning(),
"No branches found in the default push revset, \
`remote_branches(remote={remote_name})..@`."
)?;
} else if !revisions.is_empty() {
writeln!(
ui.warning(),
"No branches point to the specified revisions."
)?;
} else { /* A plain "Nothing changed" message will suffice */
}
}
Ok(branches_targeted)
}
fn cmd_git_import( fn cmd_git_import(
ui: &mut Ui, ui: &mut Ui,
command: &CommandHelper, command: &CommandHelper,