Skip to content

Commit

Permalink
cli branch list: list tracked branches by remote
Browse files Browse the repository at this point in the history
Add a way for users to list tracked branches by specifying remote names.

This change keeps the current `--all` printing logic, but:

- Skip over the branch altogether if it doesn't contain a specified
tracked remote
- Skip over the remote if it's not a specified tracked remote
- Don't print the untracked_remote_refs at the end

Usage:

`jj branch list --tracked origin --tracked git`
`jj branch list -t origin`
  • Loading branch information
prscoelho committed Feb 22, 2024
1 parent f97e929 commit a1156b0
Show file tree
Hide file tree
Showing 5 changed files with 175 additions and 4 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,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 <remote name>` option which can be used
multiple times to specify multiple remotes.

### Fixed bugs

* On Windows, symlinks in the repo are now materialized as regular files in the
Expand Down
28 changes: 26 additions & 2 deletions cli/src/commands/branch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,13 @@ 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 for specified remotes
#[arg(long, short, conflicts_with_all = ["names", "revisions", "all"], value_name = "REMOTE")]
tracked: Vec<String>,

/// Show branches whose local name matches
///
/// By default, the specified name matches exactly. Use `glob:` prefix to
Expand Down Expand Up @@ -685,6 +689,22 @@ fn cmd_branch_list(
.into_iter()
.partition::<Vec<_>, _>(|&(_, remote_ref)| remote_ref.is_tracking());

let tracked_found: HashSet<&str> = args
.tracked
.iter()
.filter(|queried_remote| {
tracking_remote_refs
.iter()
.any(|(tracking_remote, _)| tracking_remote == queried_remote)
})
.map(String::as_str)
.collect();

let args_tracked = !args.tracked.is_empty();
if args_tracked && tracked_found.is_empty() {
continue;
}

if branch_target.local_target.is_present() || !tracking_remote_refs.is_empty() {
write!(formatter.labeled("branch"), "{name}")?;
if branch_target.local_target.is_present() {
Expand All @@ -696,7 +716,11 @@ 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 {

let skip_synced = synced && !args_tracked;
let skip_tracked = args_tracked && !tracked_found.contains(remote);

if !args.all && (skip_synced || skip_tracked) {
continue;
}
write!(formatter, " ")?;
Expand Down
3 changes: 1 addition & 2 deletions cli/tests/[email protected]
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
source: cli/tests/test_generate_md_cli_help.rs
description: "AUTO-GENERATED FILE, DO NOT EDIT. This cli reference is generated as an `insta` snapshot. MkDocs follows they symlink from docs/cli-reference.md to the snap. Unfortunately, `insta` unavoidably creates this header. Luckily, MkDocs ignores the header since it has the same format as Markdown headers. TODO: MkDocs may fail on Windows if symlinks are not enabled in the OS settings"
---

<!-- BEGIN MARKDOWN-->

# Command-Line Help for `jj`
Expand Down Expand Up @@ -302,6 +301,7 @@ For information about branches, see https://github.com/martinvonz/jj/blob/main/d
Possible values: `true`, `false`
* `-t`, `--tracked <REMOTE>` — Show remote tracked branches for specified remotes
* `-r`, `--revisions <REVISIONS>` — Show branches whose local targets are in the given revisions
Expand Down Expand Up @@ -1972,4 +1972,3 @@ For information about stale working copies, see https://github.com/martinvonz/jj
This document was generated automatically by
<a href="https://crates.io/crates/clap-markdown"><code>clap-markdown</code></a>.
</i></small>
130 changes: 130 additions & 0 deletions cli/tests/test_branch_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1206,6 +1206,136 @@ 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"]);

// Setup upstream
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,
&["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
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", "origin"]), @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
"###
);

// Querying for a non-existant remote results in no branches shown

Check failure on line 1314 in cli/tests/test_branch_command.rs

View workflow job for this annotation

GitHub Actions / Codespell

non-existant ==> non-existent
insta::assert_snapshot!(
test_env.jj_cmd_success(&local_path, &["branch", "list", "--tracked", "non-existant"]), @""

Check failure on line 1316 in cli/tests/test_branch_command.rs

View workflow job for this annotation

GitHub Actions / Codespell

non-existant ==> non-existent
);

insta::assert_snapshot!(
test_env.jj_cmd_success(&local_path, &["branch", "list", "-t", "git", "-t", "origin", "-t", "upstream"]), @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-sync: lolpmnqw 32fa6da0 (empty) upstream-sync
@git: lolpmnqw 32fa6da0 (empty) upstream-sync
@upstream: lolpmnqw 32fa6da0 (empty) upstream-sync
"###
);
}

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])
Expand Down
15 changes: 15 additions & 0 deletions docs/branches.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,21 @@ $ # 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 <remote name>` or `jj branch list -t <remote name>`.

You can also list multiple remotes `jj branch list -t <remote name> -t <remote name>`.

Example:

```sh
# List all tracked @origin branches.
$ jj branch list --tracked origin
# List all tracked @origin or @git branches.
$ jj branch list -t origin -t git
```

### Automatic tracking of branches & `git.auto-local-branch` option

There are two situations where `jj` tracks branches automatically. `jj git
Expand Down

0 comments on commit a1156b0

Please sign in to comment.