diff --git a/README.md b/README.md index abd591e55..68ab1b49e 100644 --- a/README.md +++ b/README.md @@ -225,7 +225,7 @@ $ jj log | head | o fb563a4c6d26 f63e76f175b9 martinvonz@google.com 2021-05-23 22:13:45.000 -07:00 | Jujutsu is ready! -o 080a9b37ff7e 6a91b4ba16c7 martinvonz@google.com 2021-05-23 22:08:37.000 -07:00 refs/remotes/origin/main +o 080a9b37ff7e 6a91b4ba16c7 martinvonz@google.com 2021-05-23 22:08:37.000 -07:00 main | cli: make `jj st` show parent commit before working copy commit o ba8ff31e32fd 302257bdb7e5 martinvonz@google.com 2021-05-23 22:08:12.000 -07:00 | cli: make the working copy changes in `jj status` clearer @@ -250,7 +250,7 @@ union, `&` for intersection and `-` for difference. For example: $ jj log -r '@ | root | git_refs()' @ 192b456b024b f39aeb1a0200 martinvonz@google.com 2021-05-23 23:10:27.000 -07:00 : -o 080a9b37ff7e 6a91b4ba16c7 martinvonz@google.com 2021-05-23 22:08:37.000 -07:00 refs/remotes/origin/main +o 080a9b37ff7e 6a91b4ba16c7 martinvonz@google.com 2021-05-23 22:08:37.000 -07:00 main : cli: make `jj st` show parent commit before working copy commit o 000000000000 000000000000 1970-01-01 00:00:00.000 +00:00 ``` diff --git a/src/commands.rs b/src/commands.rs index 63cde1acf..86b97a1e9 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -1270,7 +1270,8 @@ fn log_template(settings: &UserSettings) -> String { "change: " change_id "\n" "author: " author.name() " <" author.email() "> " author.timestamp() "\n" "committer: " committer.name() " <" committer.email() "> " committer.timestamp() "\n" - "git refs: " git_refs "\n" + "branches: " branches "\n" + "tags: " tags "\n" "open: " open "\n" "pruned: " pruned "\n" "obsolete: " obsolete "\n" @@ -1294,7 +1295,8 @@ fn graph_log_template(settings: &UserSettings) -> String { " " change_id.short() " " author.email() " " label("timestamp", author.timestamp()) - " " git_refs + " " branches + " " tags if(pruned, label("pruned", " pruned")) if(obsolete, label("obsolete", " obsolete")) if(orphan, label("orphan", " orphan")) diff --git a/src/formatter.rs b/src/formatter.rs index ad3156532..6d34bd0d7 100644 --- a/src/formatter.rs +++ b/src/formatter.rs @@ -88,6 +88,8 @@ fn config_colors(user_settings: &UserSettings) -> HashMap { result.insert(String::from("author timestamp"), String::from("cyan")); result.insert(String::from("committer"), String::from("yellow")); result.insert(String::from("committer timestamp"), String::from("cyan")); + result.insert(String::from("branches"), String::from("magenta")); + result.insert(String::from("tags"), String::from("magenta")); result.insert(String::from("git_refs"), String::from("magenta")); result.insert(String::from("pruned"), String::from("red")); result.insert(String::from("obsolete"), String::from("red")); diff --git a/src/template_parser.rs b/src/template_parser.rs index 5c730423d..f24b59d66 100644 --- a/src/template_parser.rs +++ b/src/template_parser.rs @@ -23,11 +23,11 @@ use pest::Parser; use crate::formatter::PlainTextFormatter; use crate::templater::{ - AuthorProperty, ChangeIdProperty, CommitIdKeyword, CommitterProperty, ConditionalTemplate, - ConflictProperty, ConstantTemplateProperty, CurrentCheckoutProperty, DescriptionProperty, - DivergentProperty, DynamicLabelTemplate, GitRefsProperty, LabelTemplate, ListTemplate, - LiteralTemplate, ObsoleteProperty, OpenProperty, OrphanProperty, PrunedProperty, - StringPropertyTemplate, Template, TemplateFunction, TemplateProperty, + AuthorProperty, BranchProperty, ChangeIdProperty, CommitIdKeyword, CommitterProperty, + ConditionalTemplate, ConflictProperty, ConstantTemplateProperty, CurrentCheckoutProperty, + DescriptionProperty, DivergentProperty, DynamicLabelTemplate, GitRefsProperty, LabelTemplate, + ListTemplate, LiteralTemplate, ObsoleteProperty, OpenProperty, OrphanProperty, PrunedProperty, + StringPropertyTemplate, TagProperty, Template, TemplateFunction, TemplateProperty, }; #[derive(Parser)] @@ -240,6 +240,8 @@ fn parse_commit_keyword<'a>(repo: RepoRef<'a>, pair: Pair) -> (Property<'a "open" => Property::Boolean(Box::new(OpenProperty)), "pruned" => Property::Boolean(Box::new(PrunedProperty)), "current_checkout" => Property::Boolean(Box::new(CurrentCheckoutProperty { repo })), + "branches" => Property::String(Box::new(BranchProperty { repo })), + "tags" => Property::String(Box::new(TagProperty { repo })), "git_refs" => Property::String(Box::new(GitRefsProperty { repo })), "obsolete" => Property::Boolean(Box::new(ObsoleteProperty { repo })), "orphan" => Property::Boolean(Box::new(OrphanProperty { repo })), diff --git a/src/templater.rs b/src/templater.rs index b48f0621f..9d19ec738 100644 --- a/src/templater.rs +++ b/src/templater.rs @@ -220,6 +220,58 @@ impl TemplateProperty for CurrentCheckoutProperty<'_> { } } +pub struct BranchProperty<'a> { + pub repo: RepoRef<'a>, +} + +impl TemplateProperty for BranchProperty<'_> { + fn extract(&self, context: &Commit) -> String { + let mut names = vec![]; + for (branch_name, branch_target) in self.repo.view().branches() { + let local_target = branch_target.local_target.as_ref(); + if let Some(local_target) = local_target { + if local_target.has_add(context.id()) { + if local_target.is_conflict() { + names.push(format!("{}?", branch_name)); + } else { + names.push(branch_name.clone()); + } + } + } + for (remote_name, remote_target) in &branch_target.remote_targets { + if Some(remote_target) != local_target && remote_target.has_add(context.id()) { + if remote_target.is_conflict() { + names.push(format!("{}@{}?", branch_name, remote_name)); + } else { + names.push(format!("{}@{}", branch_name, remote_name)); + } + } + } + } + names.join(" ") + } +} + +pub struct TagProperty<'a> { + pub repo: RepoRef<'a>, +} + +impl TemplateProperty for TagProperty<'_> { + fn extract(&self, context: &Commit) -> String { + let mut names = vec![]; + for (tag_name, target) in self.repo.view().tags() { + if target.has_add(context.id()) { + if target.is_conflict() { + names.push(format!("{}?", tag_name)); + } else { + names.push(tag_name.clone()); + } + } + } + names.join(" ") + } +} + pub struct GitRefsProperty<'a> { pub repo: RepoRef<'a>, }