Skip to content

Commit 0fb99c1

Browse files
committed
templater: include remote tags in "tags" output
Since we can now update tags internally, local and remote tags may be out of sync in non-colocated Git repositories. "tags" template should indicate that.
1 parent 75041a2 commit 0fb99c1

File tree

4 files changed

+61
-20
lines changed

4 files changed

+61
-20
lines changed

cli/src/commit_templater.rs

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,11 @@ use jj_lib::merge::Diff;
5151
use jj_lib::merge::MergedTreeValue;
5252
use jj_lib::merged_tree::MergedTree;
5353
use jj_lib::object_id::ObjectId as _;
54+
use jj_lib::op_store::LocalRemoteRefTarget;
5455
use jj_lib::op_store::OperationId;
5556
use jj_lib::op_store::RefTarget;
5657
use jj_lib::op_store::RemoteRef;
58+
use jj_lib::ref_name::RefName;
5759
use jj_lib::ref_name::WorkspaceName;
5860
use jj_lib::ref_name::WorkspaceNameBuf;
5961
use jj_lib::repo::Repo;
@@ -920,12 +922,12 @@ pub struct CommitKeywordCache<'repo> {
920922
impl<'repo> CommitKeywordCache<'repo> {
921923
pub fn bookmarks_index(&self, repo: &dyn Repo) -> &Rc<CommitRefsIndex> {
922924
self.bookmarks_index
923-
.get_or_init(|| Rc::new(build_bookmarks_index(repo)))
925+
.get_or_init(|| Rc::new(build_local_remote_refs_index(repo.view().bookmarks())))
924926
}
925927

926928
pub fn tags_index(&self, repo: &dyn Repo) -> &Rc<CommitRefsIndex> {
927929
self.tags_index
928-
.get_or_init(|| Rc::new(build_commit_refs_index(repo.view().local_tags())))
930+
.get_or_init(|| Rc::new(build_local_remote_refs_index(repo.view().tags())))
929931
}
930932

931933
pub fn git_refs_index(&self, repo: &dyn Repo) -> &Rc<CommitRefsIndex> {
@@ -1058,14 +1060,8 @@ fn builtin_commit_methods<'repo>() -> CommitTemplateBuildMethodFnMap<'repo, Comm
10581060
.keyword_cache
10591061
.bookmarks_index(language.repo)
10601062
.clone();
1061-
let out_property = self_property.map(move |commit| {
1062-
index
1063-
.get(commit.id())
1064-
.iter()
1065-
.filter(|commit_ref| commit_ref.is_local() || !commit_ref.synced)
1066-
.cloned()
1067-
.collect_vec()
1068-
});
1063+
let out_property =
1064+
self_property.map(move |commit| collect_distinct_refs(index.get(commit.id())));
10691065
Ok(out_property.into_dyn_wrapped())
10701066
},
10711067
);
@@ -1112,7 +1108,8 @@ fn builtin_commit_methods<'repo>() -> CommitTemplateBuildMethodFnMap<'repo, Comm
11121108
|language, _diagnostics, _build_ctx, self_property, function| {
11131109
function.expect_no_arguments()?;
11141110
let index = language.keyword_cache.tags_index(language.repo).clone();
1115-
let out_property = self_property.map(move |commit| index.get(commit.id()).to_vec());
1111+
let out_property =
1112+
self_property.map(move |commit| collect_distinct_refs(index.get(commit.id())));
11161113
Ok(out_property.into_dyn_wrapped())
11171114
},
11181115
);
@@ -1784,22 +1781,23 @@ impl CommitRefsIndex {
17841781
}
17851782
}
17861783

1787-
fn build_bookmarks_index(repo: &dyn Repo) -> CommitRefsIndex {
1784+
fn build_local_remote_refs_index<'a>(
1785+
local_remote_refs: impl IntoIterator<Item = (&'a RefName, LocalRemoteRefTarget<'a>)>,
1786+
) -> CommitRefsIndex {
17881787
let mut index = CommitRefsIndex::default();
1789-
for (bookmark_name, bookmark_target) in repo.view().bookmarks() {
1790-
let local_target = bookmark_target.local_target;
1791-
let remote_refs = bookmark_target.remote_refs;
1788+
for (name, target) in local_remote_refs {
1789+
let local_target = target.local_target;
1790+
let remote_refs = target.remote_refs;
17921791
if local_target.is_present() {
17931792
let commit_ref = CommitRef::local(
1794-
bookmark_name,
1793+
name,
17951794
local_target.clone(),
17961795
remote_refs.iter().map(|&(_, remote_ref)| remote_ref),
17971796
);
17981797
index.insert(local_target.added_ids(), commit_ref);
17991798
}
18001799
for &(remote_name, remote_ref) in &remote_refs {
1801-
let commit_ref =
1802-
CommitRef::remote(bookmark_name, remote_name, remote_ref.clone(), local_target);
1800+
let commit_ref = CommitRef::remote(name, remote_name, remote_ref.clone(), local_target);
18031801
index.insert(remote_ref.target.added_ids(), commit_ref);
18041802
}
18051803
}
@@ -1817,6 +1815,14 @@ fn build_commit_refs_index<'a, K: Into<String>>(
18171815
index
18181816
}
18191817

1818+
fn collect_distinct_refs(commit_refs: &[Rc<CommitRef>]) -> Vec<Rc<CommitRef>> {
1819+
commit_refs
1820+
.iter()
1821+
.filter(|commit_ref| commit_ref.is_local() || !commit_ref.synced)
1822+
.cloned()
1823+
.collect()
1824+
}
1825+
18201826
/// Wrapper to render ref/remote name in revset syntax.
18211827
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize)]
18221828
#[serde(transparent)]

cli/tests/test_commit_template.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -741,6 +741,32 @@ fn test_log_bookmarks() {
741741
");
742742
}
743743

744+
#[test]
745+
fn test_log_tags() {
746+
let test_env = TestEnvironment::default();
747+
test_env.run_jj_in(".", ["git", "init", "repo"]).success();
748+
let work_dir = test_env.work_dir("repo");
749+
750+
work_dir.run_jj(["commit", "-mcommit1"]).success();
751+
work_dir.run_jj(["commit", "-mcommit2"]).success();
752+
work_dir.run_jj(["tag", "set", "-r@--", "foo"]).success();
753+
work_dir.run_jj(["tag", "set", "-r@-", "bar"]).success();
754+
work_dir.run_jj(["git", "export"]).success();
755+
work_dir
756+
.run_jj(["tag", "set", "--allow-move", "-r@-", "foo", "baz"])
757+
.success();
758+
759+
let template = r#"commit_id.short() ++ " " ++ if(tags, tags, "(no tags)") ++ "\n""#;
760+
let output = work_dir.run_jj(["log", "-rall()", "-T", template]);
761+
insta::assert_snapshot!(output, @r"
762+
@ 510df2613fc8 (no tags)
763+
◆ 3f672e728535 bar baz foo*
764+
◆ b876c5f49546 foo@git
765+
◆ 000000000000 (no tags)
766+
[EOF]
767+
");
768+
}
769+
744770
#[test]
745771
fn test_log_git_head() {
746772
let test_env = TestEnvironment::default();

docs/templates.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,13 +147,15 @@ This type cannot be printed. The following methods are defined.
147147
* `.current_working_copy() -> Boolean`: True for the working-copy commit of the
148148
current workspace.
149149
* `.bookmarks() -> List<CommitRef>`: Local and remote bookmarks pointing to the
150-
commit. A tracking remote bookmark will be included only if its target is
150+
commit. A tracked remote bookmark will be included only if its target is
151151
different from the local one.
152152
* `.local_bookmarks() -> List<CommitRef>`: All local bookmarks pointing to the
153153
commit.
154154
* `.remote_bookmarks() -> List<CommitRef>`: All remote bookmarks pointing to the
155155
commit.
156-
* `.tags() -> List<CommitRef>`
156+
* `.tags() -> List<CommitRef>`: Local and remote tags pointing to the commit. A
157+
tracked remote tag will be included only if its target is different from the
158+
local one.
157159
* `.git_refs() -> List<CommitRef>`
158160
* `.git_head() -> Boolean`: True for the Git `HEAD` commit.
159161
* `.divergent() -> Boolean`: True if the commit's change id corresponds to multiple

lib/src/view.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,13 @@ impl View {
8686
)
8787
}
8888

89+
/// Iterates pair of local and remote tags by tag name.
90+
pub fn tags(&self) -> impl Iterator<Item = (&RefName, LocalRemoteRefTarget<'_>)> {
91+
op_store::merge_join_ref_views(&self.data.local_tags, &self.data.remote_views, |view| {
92+
&view.tags
93+
})
94+
}
95+
8996
pub fn git_refs(&self) -> &BTreeMap<GitRefNameBuf, RefTarget> {
9097
&self.data.git_refs
9198
}

0 commit comments

Comments
 (0)