diff --git a/CHANGELOG.md b/CHANGELOG.md index 935f07b6ac..b1d9060177 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -66,6 +66,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * The `branches`/`tags`/`git_refs`/`git_head` template keywords now return a list of `RefName`s. They were previously pre-formatted strings. +* The new template keywords `local_branches`/`remote_branches` are added to show + only local/remote branches. + ### Fixed bugs * Updating the working copy to a commit where a file that's currently ignored diff --git a/cli/src/commit_templater.rs b/cli/src/commit_templater.rs index de637d755f..26c948789e 100644 --- a/cli/src/commit_templater.rs +++ b/cli/src/commit_templater.rs @@ -320,6 +320,28 @@ fn build_commit_keyword_opt<'repo>( .collect() })) } + "local_branches" => { + let index = cache.branches_index(repo).clone(); + language.wrap_ref_name_list(wrap_fn(property, move |commit| { + index + .get(commit.id()) + .iter() + .filter(|ref_name| ref_name.is_local()) + .cloned() + .collect() + })) + } + "remote_branches" => { + let index = cache.branches_index(repo).clone(); + language.wrap_ref_name_list(wrap_fn(property, move |commit| { + index + .get(commit.id()) + .iter() + .filter(|ref_name| ref_name.is_remote()) + .cloned() + .collect() + })) + } "tags" => { let index = cache.tags_index(repo).clone(); language.wrap_ref_name_list(wrap_fn(property, move |commit| { @@ -393,6 +415,10 @@ impl RefName { fn is_local(&self) -> bool { self.remote.is_none() } + + fn is_remote(&self) -> bool { + self.remote.is_some() + } } impl Template<()> for RefName { diff --git a/cli/tests/test_commit_template.rs b/cli/tests/test_commit_template.rs index d97683c99f..2480f9fc6a 100644 --- a/cli/tests/test_commit_template.rs +++ b/cli/tests/test_commit_template.rs @@ -379,7 +379,7 @@ fn test_log_branches() { test_env.jj_cmd_ok(&origin_path, &["describe", "-m=description 1"]); test_env.jj_cmd_ok(&origin_path, &["branch", "create", "branch1"]); test_env.jj_cmd_ok(&origin_path, &["new", "root()", "-m=description 2"]); - test_env.jj_cmd_ok(&origin_path, &["branch", "create", "branch2"]); + test_env.jj_cmd_ok(&origin_path, &["branch", "create", "branch2", "unchanged"]); test_env.jj_cmd_ok(&origin_path, &["new", "root()", "-m=description 3"]); test_env.jj_cmd_ok(&origin_path, &["branch", "create", "branch3"]); test_env.jj_cmd_ok(&origin_path, &["git", "export"]); @@ -417,7 +417,7 @@ fn test_log_branches() { │ ◉ 21c33875443e branch1* ├─╯ │ @ a5b4d15489cc branch2* new-branch - │ ◉ 8476341eb395 branch2@origin + │ ◉ 8476341eb395 branch2@origin unchanged ├─╯ ◉ 000000000000 (no branches) "###); @@ -431,10 +431,24 @@ fn test_log_branches() { │ ◉ branch1 ├─╯ │ @ branch2, new-branch - │ ◉ origin/branch2 + │ ◉ origin/branch2, unchanged ├─╯ ◉ "###); + + let template = r#"separate(" ", "L:", local_branches, "R:", remote_branches)"#; + let output = test_env.jj_cmd_success(&workspace_root, &["log", "-T", template]); + insta::assert_snapshot!(output, @r###" + ◉ L: branch3?? R: branch3@origin + │ ◉ L: branch3?? R: + ├─╯ + │ ◉ L: branch1* R: + ├─╯ + │ @ L: branch2* new-branch R: + │ ◉ L: unchanged R: branch2@origin unchanged@origin + ├─╯ + ◉ L: R: + "###); } #[test] diff --git a/docs/templates.md b/docs/templates.md index 36bb88a1b8..f8c4825a2e 100644 --- a/docs/templates.md +++ b/docs/templates.md @@ -25,7 +25,11 @@ The following keywords can be used in `jj log`/`jj obslog` templates. working-copy commit as `@`. * `current_working_copy: Boolean`: True for the working-copy commit of the current workspace. -* `branches: List` +* `branches: List`: Local and remote branches pointing to the commit. + A tracking remote branch will be included only if its target is different + from the local one. +* `local_branches: List`: All local branches pointing to the commit. +* `remote_branches: List`: All remote branches pointing to the commit. * `tags: List` * `git_refs: List` * `git_head: List`