mirror of
https://github.com/martinvonz/jj.git
synced 2025-01-08 05:39:20 +00:00
cli: filter out branches to list without cloning the map
This commit is contained in:
parent
d0bc34e0f2
commit
28e5ee35aa
1 changed files with 23 additions and 23 deletions
|
@ -4,9 +4,9 @@ use clap::builder::NonEmptyStringValueParser;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use jj_lib::backend::{CommitId, ObjectId};
|
use jj_lib::backend::{CommitId, ObjectId};
|
||||||
use jj_lib::git;
|
use jj_lib::git;
|
||||||
use jj_lib::op_store::{BranchTarget, RefTarget};
|
use jj_lib::op_store::RefTarget;
|
||||||
use jj_lib::repo::Repo;
|
use jj_lib::repo::Repo;
|
||||||
use jj_lib::revset::{self, RevsetExpression};
|
use jj_lib::revset::{self, RevsetExpression, StringPattern};
|
||||||
use jj_lib::view::View;
|
use jj_lib::view::View;
|
||||||
|
|
||||||
use crate::cli_util::{user_error, user_error_with_hint, CommandError, CommandHelper, RevisionArg};
|
use crate::cli_util::{user_error, user_error_with_hint, CommandError, CommandHelper, RevisionArg};
|
||||||
|
@ -320,39 +320,34 @@ fn cmd_branch_list(
|
||||||
) -> Result<(), CommandError> {
|
) -> Result<(), CommandError> {
|
||||||
let workspace_command = command.workspace_helper(ui)?;
|
let workspace_command = command.workspace_helper(ui)?;
|
||||||
let repo = workspace_command.repo();
|
let repo = workspace_command.repo();
|
||||||
let mut all_branches = repo.view().branches().clone(); // TODO: useless clone
|
let view = repo.view();
|
||||||
if !args.revisions.is_empty() {
|
let branch_names_to_list: Option<HashSet<&str>> = if !args.revisions.is_empty() {
|
||||||
// Match against local targets only, which is consistent with "jj git push".
|
// Match against local targets only, which is consistent with "jj git push".
|
||||||
fn local_targets(branch_target: &BranchTarget) -> impl Iterator<Item = &CommitId> {
|
|
||||||
branch_target.local_target.added_ids()
|
|
||||||
}
|
|
||||||
|
|
||||||
let filter_expressions: Vec<_> = args
|
let filter_expressions: Vec<_> = args
|
||||||
.revisions
|
.revisions
|
||||||
.iter()
|
.iter()
|
||||||
.map(|revision_str| workspace_command.parse_revset(revision_str, Some(ui)))
|
.map(|revision_str| workspace_command.parse_revset(revision_str, Some(ui)))
|
||||||
.try_collect()?;
|
.try_collect()?;
|
||||||
let filter_expression = RevsetExpression::union_all(&filter_expressions);
|
let filter_expression = RevsetExpression::union_all(&filter_expressions);
|
||||||
// Intersects with the set of all branch targets to minimize the lookup space.
|
// Intersects with the set of local branch targets to minimize the lookup space.
|
||||||
let all_targets = all_branches
|
let revset_expression = RevsetExpression::branches(StringPattern::everything())
|
||||||
.values()
|
.intersection(&filter_expression);
|
||||||
.flat_map(local_targets)
|
|
||||||
.cloned()
|
|
||||||
.collect();
|
|
||||||
let revset_expression =
|
|
||||||
RevsetExpression::commits(all_targets).intersection(&filter_expression);
|
|
||||||
let revset_expression = revset::optimize(revset_expression);
|
let revset_expression = revset::optimize(revset_expression);
|
||||||
let revset = workspace_command.evaluate_revset(revset_expression)?;
|
let revset = workspace_command.evaluate_revset(revset_expression)?;
|
||||||
let filtered_targets: HashSet<CommitId> = revset.iter().collect();
|
let filtered_targets: HashSet<CommitId> = revset.iter().collect();
|
||||||
// TODO: If we add name-based filter like --glob, this might have to be
|
// TODO: Suppose we have name-based filter like --glob, should these filters
|
||||||
// rewritten as a positive list or predicate function. Should they
|
|
||||||
// be AND-ed or OR-ed? Maybe OR as "jj git push" would do. Perhaps, we
|
// be AND-ed or OR-ed? Maybe OR as "jj git push" would do. Perhaps, we
|
||||||
// can consider these options as producers of branch names, not filters
|
// can consider these options as producers of branch names, not filters
|
||||||
// of different kind (which are typically intersected.)
|
// of different kind (which are typically intersected.)
|
||||||
all_branches.retain(|_, branch_target| {
|
let branch_names = view
|
||||||
local_targets(branch_target).any(|id| filtered_targets.contains(id))
|
.local_branches()
|
||||||
});
|
.filter(|(_, target)| target.added_ids().any(|id| filtered_targets.contains(id)))
|
||||||
}
|
.map(|(name, _)| name)
|
||||||
|
.collect();
|
||||||
|
Some(branch_names)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
let no_branches_template = workspace_command.parse_commit_template(
|
let no_branches_template = workspace_command.parse_commit_template(
|
||||||
&command
|
&command
|
||||||
|
@ -391,7 +386,12 @@ fn cmd_branch_list(
|
||||||
let mut formatter = ui.stdout_formatter();
|
let mut formatter = ui.stdout_formatter();
|
||||||
let formatter = formatter.as_mut();
|
let formatter = formatter.as_mut();
|
||||||
|
|
||||||
for (name, branch_target) in all_branches {
|
let branches_to_list = view.branches().iter().filter(|&(name, _)| {
|
||||||
|
branch_names_to_list
|
||||||
|
.as_ref()
|
||||||
|
.map_or(true, |branch_names| branch_names.contains(name.as_str()))
|
||||||
|
});
|
||||||
|
for (name, branch_target) in branches_to_list {
|
||||||
let found_non_git_remote = {
|
let found_non_git_remote = {
|
||||||
let pseudo_remote_count = branch_target
|
let pseudo_remote_count = branch_target
|
||||||
.remote_targets
|
.remote_targets
|
||||||
|
|
Loading…
Reference in a new issue