ok/jj
1
0
Fork 0
forked from mirrors/jj

cli branch list: list tracked branches

Add an option to list tracked branches only

This option keeps most of the current `--all` printing logic, but:

- Omits local Git-tracking branches by default (can be extended to
  support filtering by remote).
- Skip over the branch altogether if it doesn't contain tracked remotes
- Don't print the untracked_remote_refs at the end

Usage:

`jj branch list -t`
`jj branch list --tracked`
`jj branch list --tracked <branch name>`
This commit is contained in:
Paulo Coelho 2024-02-21 18:27:50 +00:00
parent 1cbf2b4acf
commit e9243a7638
5 changed files with 177 additions and 8 deletions

View file

@ -74,6 +74,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* Added completions for [Nushell](https://nushell.sh) to `jj util completion`
* `jj branch list` now supports a `--tracked/-t` option which can be used to
show tracked branches only. Omits local Git-tracking branches by default.
### Fixed bugs
* On Windows, symlinks in the repo are now materialized as regular files in the

View file

@ -100,9 +100,14 @@ pub struct BranchDeleteArgs {
pub struct BranchListArgs {
/// Show all tracking and non-tracking remote branches including the ones
/// whose targets are synchronized with the local branches.
#[arg(long, short, conflicts_with_all = ["names", "revisions"])]
#[arg(long, short, conflicts_with_all = ["names", "revisions", "tracked"])]
all: bool,
/// Show remote tracked branches only. Omits local Git-tracking branches by
/// default.
#[arg(long, short, conflicts_with_all = ["all"])]
tracked: bool,
/// Show branches whose local name matches
///
/// By default, the specified name matches exactly. Use `glob:` prefix to
@ -679,13 +684,19 @@ fn cmd_branch_list(
.map_or(true, |branch_names| branch_names.contains(name))
});
for (name, branch_target) in branches_to_list {
let (tracking_remote_refs, untracked_remote_refs) =
branch_target
.remote_refs
.into_iter()
.partition::<Vec<_>, _>(|&(_, remote_ref)| remote_ref.is_tracking());
let (mut tracking_remote_refs, untracked_remote_refs) = branch_target
.remote_refs
.into_iter()
.partition::<Vec<_>, _>(|&(_, remote_ref)| remote_ref.is_tracking());
if branch_target.local_target.is_present() || !tracking_remote_refs.is_empty() {
if args.tracked {
tracking_remote_refs
.retain(|&(remote, _)| remote != git::REMOTE_NAME_FOR_LOCAL_GIT_REPO);
}
if !args.tracked && branch_target.local_target.is_present()
|| !tracking_remote_refs.is_empty()
{
write!(formatter.labeled("branch"), "{name}")?;
if branch_target.local_target.is_present() {
print_branch_target(formatter, branch_target.local_target)?;
@ -696,7 +707,8 @@ fn cmd_branch_list(
for &(remote, remote_ref) in &tracking_remote_refs {
let synced = remote_ref.target == *branch_target.local_target;
if !args.all && synced {
if !args.all && !args.tracked && synced {
continue;
}
write!(formatter, " ")?;

View file

@ -301,6 +301,10 @@ For information about branches, see https://github.com/martinvonz/jj/blob/main/d
Possible values: `true`, `false`
* `-t`, `--tracked` — Show remote tracked branches only. Omits local Git-tracking branches by default
Possible values: `true`, `false`
* `-r`, `--revisions <REVISIONS>` — Show branches whose local targets are in the given revisions

View file

@ -1206,6 +1206,148 @@ fn test_branch_list_much_remote_divergence() {
"###);
}
#[test]
fn test_branch_list_tracked() {
let test_env = TestEnvironment::default();
test_env.add_config("git.auto-local-branch = true");
// Initialize remote refs
test_env.jj_cmd_ok(test_env.env_root(), &["init", "remote", "--git"]);
let remote_path = test_env.env_root().join("remote");
for branch in [
"remote-sync",
"remote-unsync",
"remote-untrack",
"remote-delete",
] {
test_env.jj_cmd_ok(&remote_path, &["new", "root()", "-m", branch]);
test_env.jj_cmd_ok(&remote_path, &["branch", "create", branch]);
}
test_env.jj_cmd_ok(&remote_path, &["new"]);
test_env.jj_cmd_ok(&remote_path, &["git", "export"]);
// Initialize local refs
let mut remote_git_path = test_env.env_root().join("remote");
remote_git_path.extend([".jj", "repo", "store", "git"]);
test_env.jj_cmd_ok(
test_env.env_root(),
&[
"git",
"clone",
"--colocate",
remote_git_path.to_str().unwrap(),
"local",
],
);
test_env.jj_cmd_ok(test_env.env_root(), &["init", "upstream", "--git"]);
// Initialize a second remote
let mut upstream_git_path = test_env.env_root().join("upstream");
test_env.jj_cmd_ok(
&upstream_git_path,
&["new", "root()", "-m", "upstream-sync"],
);
test_env.jj_cmd_ok(&upstream_git_path, &["branch", "create", "upstream-sync"]);
test_env.jj_cmd_ok(&upstream_git_path, &["new"]);
test_env.jj_cmd_ok(&upstream_git_path, &["git", "export"]);
upstream_git_path.extend([".jj", "repo", "store", "git"]);
let local_path = test_env.env_root().join("local");
test_env.jj_cmd_ok(
&local_path,
&[
"git",
"remote",
"add",
"upstream",
upstream_git_path.to_str().unwrap(),
],
);
test_env.jj_cmd_ok(&local_path, &["git", "fetch", "--all-remotes"]);
test_env.jj_cmd_ok(&local_path, &["new", "root()", "-m", "local-only"]);
test_env.jj_cmd_ok(&local_path, &["branch", "create", "local-only"]);
// Mutate refs in local repository
test_env.jj_cmd_ok(&local_path, &["branch", "delete", "remote-delete"]);
test_env.jj_cmd_ok(&local_path, &["branch", "delete", "remote-untrack"]);
test_env.jj_cmd_ok(&local_path, &["branch", "untrack", "remote-untrack@origin"]);
test_env.jj_cmd_ok(
&local_path,
&[
"git",
"push",
"--remote",
"upstream",
"--branch",
"remote-unsync",
],
);
test_env.jj_cmd_ok(
&local_path,
&["branch", "set", "--allow-backwards", "remote-unsync"],
);
insta::assert_snapshot!(
test_env.jj_cmd_success(&local_path, &["branch", "list", "--all"]), @r###"
local-only: nmzmmopx e1da745b (empty) local-only
@git: nmzmmopx e1da745b (empty) local-only
remote-delete (deleted)
@origin: mnmymoky 203e60eb (empty) remote-delete
(this branch will be *deleted permanently* on the remote on the next `jj git push`. Use `jj branch forget` to prevent this)
remote-sync: zwtyzrop c761c7ea (empty) remote-sync
@git: zwtyzrop c761c7ea (empty) remote-sync
@origin: zwtyzrop c761c7ea (empty) remote-sync
remote-unsync: nmzmmopx e1da745b (empty) local-only
@git: nmzmmopx e1da745b (empty) local-only
@origin (ahead by 1 commits, behind by 1 commits): qpsqxpyq 38ef8af7 (empty) remote-unsync
@upstream (ahead by 1 commits, behind by 1 commits): qpsqxpyq 38ef8af7 (empty) remote-unsync
remote-untrack@origin: vmortlor 71a16b05 (empty) remote-untrack
upstream-sync: lolpmnqw 32fa6da0 (empty) upstream-sync
@git: lolpmnqw 32fa6da0 (empty) upstream-sync
@upstream: lolpmnqw 32fa6da0 (empty) upstream-sync
"###);
insta::assert_snapshot!(
test_env.jj_cmd_success(&local_path, &["branch", "list", "--tracked"]), @r###"
remote-delete (deleted)
@origin: mnmymoky 203e60eb (empty) remote-delete
(this branch will be *deleted permanently* on the remote on the next `jj git push`. Use `jj branch forget` to prevent this)
remote-sync: zwtyzrop c761c7ea (empty) remote-sync
@origin: zwtyzrop c761c7ea (empty) remote-sync
remote-unsync: nmzmmopx e1da745b (empty) local-only
@origin (ahead by 1 commits, behind by 1 commits): qpsqxpyq 38ef8af7 (empty) remote-unsync
@upstream (ahead by 1 commits, behind by 1 commits): qpsqxpyq 38ef8af7 (empty) remote-unsync
upstream-sync: lolpmnqw 32fa6da0 (empty) upstream-sync
@upstream: lolpmnqw 32fa6da0 (empty) upstream-sync
"###
);
insta::assert_snapshot!(
test_env.jj_cmd_success(&local_path, &["branch", "list", "--tracked", "remote-unsync"]), @r###"
remote-unsync: nmzmmopx e1da745b (empty) local-only
@origin (ahead by 1 commits, behind by 1 commits): qpsqxpyq 38ef8af7 (empty) remote-unsync
@upstream (ahead by 1 commits, behind by 1 commits): qpsqxpyq 38ef8af7 (empty) remote-unsync
"###);
insta::assert_snapshot!(
test_env.jj_cmd_success(&local_path, &["branch", "list", "--tracked", "remote-untrack"]), @"");
test_env.jj_cmd_ok(
&local_path,
&["branch", "untrack", "remote-unsync@upstream"],
);
insta::assert_snapshot!(
test_env.jj_cmd_success(&local_path, &["branch", "list", "--tracked", "remote-unsync"]), @r###"
remote-unsync: nmzmmopx e1da745b (empty) local-only
@origin (ahead by 1 commits, behind by 1 commits): qpsqxpyq 38ef8af7 (empty) remote-unsync
"###);
}
fn get_log_output(test_env: &TestEnvironment, cwd: &Path) -> String {
let template = r#"branches ++ " " ++ commit_id.short()"#;
test_env.jj_cmd_success(cwd, &["log", "-T", template])

View file

@ -113,6 +113,14 @@ $ # The local branch (e.g. stuff) is unaffected. It may or may not still
$ # be tracking branches on other remotes (e.g. stuff@upstream).
```
### Listing tracked branches
To list tracked branches, you can `jj branch list --tracked` or `jj branch list -t`.
This command omits local Git-tracking branches by default.
You can see if a specific branch is tracked with `jj branch list --tracked <branch name>`.
### Automatic tracking of branches & `git.auto-local-branch` option
There are two situations where `jj` tracks branches automatically. `jj git