Templater: Combine Change and Commit id templates

They will both need the unique prefix functionality.

Change ids previously were just strings.
This commit is contained in:
Ilya Grigoriev 2023-01-02 15:34:54 -08:00
parent 1f6c085c4e
commit 68ad712e12
2 changed files with 71 additions and 48 deletions

View file

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use jujutsu_lib::backend::{CommitId, Signature, Timestamp};
use jujutsu_lib::backend::{Signature, Timestamp};
use jujutsu_lib::commit::Commit;
use jujutsu_lib::op_store::WorkspaceId;
use jujutsu_lib::repo::RepoRef;
@ -22,12 +22,12 @@ use pest_derive::Parser;
use crate::formatter::PlainTextFormatter;
use crate::templater::{
AuthorProperty, BranchProperty, ChangeIdProperty, CommitIdKeyword, CommitterProperty,
ConditionalTemplate, ConflictProperty, ConstantTemplateProperty, DescriptionProperty,
DivergentProperty, DynamicLabelTemplate, EmptyProperty, GitRefsProperty, IsGitHeadProperty,
IsWorkingCopyProperty, LabelTemplate, ListTemplate, LiteralTemplate, SignatureTimestamp,
StringPropertyTemplate, TagProperty, Template, TemplateFunction, TemplateProperty,
WorkingCopiesProperty,
AuthorProperty, BranchProperty, CommitOrChangeId, CommitOrChangeIdKeyword,
CommitOrChangeIdShortest, CommitterProperty, ConditionalTemplate, ConflictProperty,
ConstantTemplateProperty, DescriptionProperty, DivergentProperty, DynamicLabelTemplate,
EmptyProperty, GitRefsProperty, IsGitHeadProperty, IsWorkingCopyProperty, LabelTemplate,
ListTemplate, LiteralTemplate, SignatureTimestamp, StringPropertyTemplate, TagProperty,
Template, TemplateFunction, TemplateProperty, WorkingCopiesProperty,
};
use crate::time_util;
@ -71,14 +71,6 @@ impl TemplateProperty<String, String> for StringFirstLine {
}
}
struct CommitIdShortest;
impl TemplateProperty<CommitId, String> for CommitIdShortest {
fn extract(&self, context: &CommitId) -> String {
CommitIdKeyword::shortest_format(context.clone())
}
}
struct SignatureName;
impl TemplateProperty<Signature, String> for SignatureName {
@ -106,7 +98,7 @@ impl TemplateProperty<Timestamp, String> for RelativeTimestampString {
enum Property<'a, I> {
String(Box<dyn TemplateProperty<I, String> + 'a>),
Boolean(Box<dyn TemplateProperty<I, bool> + 'a>),
CommitId(Box<dyn TemplateProperty<I, CommitId> + 'a>),
CommitOrChangeId(Box<dyn TemplateProperty<I, CommitOrChangeId> + 'a>),
Signature(Box<dyn TemplateProperty<I, Signature> + 'a>),
Timestamp(Box<dyn TemplateProperty<I, Timestamp> + 'a>),
}
@ -122,10 +114,9 @@ impl<'a, I: 'a> Property<'a, I> {
first,
Box::new(move |value| property.extract(&value)),
))),
Property::CommitId(property) => Property::CommitId(Box::new(TemplateFunction::new(
first,
Box::new(move |value| property.extract(&value)),
))),
Property::CommitOrChangeId(property) => Property::CommitOrChangeId(Box::new(
TemplateFunction::new(first, Box::new(move |value| property.extract(&value))),
)),
Property::Signature(property) => Property::Signature(Box::new(TemplateFunction::new(
first,
Box::new(move |value| property.extract(&value)),
@ -163,8 +154,9 @@ fn parse_method_chain<'a, I: 'a>(
let PropertyAndLabels(next_method, labels) = parse_boolean_method(method);
(next_method.after(property), labels)
}
Property::CommitId(property) => {
let PropertyAndLabels(next_method, labels) = parse_commit_id_method(method);
Property::CommitOrChangeId(property) => {
let PropertyAndLabels(next_method, labels) =
parse_commit_or_chain_id_method(method);
(next_method.after(property), labels)
}
Property::Signature(property) => {
@ -207,14 +199,16 @@ fn parse_boolean_method<'a>(method: Pair<Rule>) -> PropertyAndLabels<'a, bool> {
// TODO: pass a context to the returned function (we need the repo to find the
// shortest unambiguous prefix)
fn parse_commit_id_method<'a>(method: Pair<Rule>) -> PropertyAndLabels<'a, CommitId> {
fn parse_commit_or_chain_id_method<'a>(
method: Pair<Rule>,
) -> PropertyAndLabels<'a, CommitOrChangeId> {
assert_eq!(method.as_rule(), Rule::method);
let mut inner = method.into_inner();
let name = inner.next().unwrap();
// TODO: validate arguments
let this_function = match name.as_str() {
"short" => Property::String(Box::new(CommitIdShortest)),
"short" => Property::String(Box::new(CommitOrChangeIdShortest)),
name => panic!("no such commit ID method: {name}"),
};
let chain_method = inner.last().unwrap();
@ -261,8 +255,8 @@ fn parse_commit_keyword<'a>(
assert_eq!(pair.as_rule(), Rule::identifier);
let property = match pair.as_str() {
"description" => Property::String(Box::new(DescriptionProperty)),
"change_id" => Property::String(Box::new(ChangeIdProperty)),
"commit_id" => Property::CommitId(Box::new(CommitIdKeyword)),
"change_id" => Property::CommitOrChangeId(Box::new(CommitOrChangeIdKeyword::change())),
"commit_id" => Property::CommitOrChangeId(Box::new(CommitOrChangeIdKeyword::commit())),
"author" => Property::Signature(Box::new(AuthorProperty)),
"committer" => Property::Signature(Box::new(CommitterProperty)),
"working_copies" => Property::String(Box::new(WorkingCopiesProperty { repo })),
@ -291,9 +285,9 @@ fn coerce_to_string<'a, I: 'a>(
property,
Box::new(|value| String::from(if value { "true" } else { "false" })),
)),
Property::CommitId(property) => Box::new(TemplateFunction::new(
Property::CommitOrChangeId(property) => Box::new(TemplateFunction::new(
property,
Box::new(CommitIdKeyword::default_format),
Box::new(CommitOrChangeIdKeyword::default_format),
)),
Property::Signature(property) => Box::new(TemplateFunction::new(
property,

View file

@ -155,14 +155,6 @@ impl<'a, C> Template<C> for StringPropertyTemplate<'a, C> {
}
}
pub struct ChangeIdProperty;
impl TemplateProperty<Commit, String> for ChangeIdProperty {
fn extract(&self, context: &Commit) -> String {
context.change_id().hex()
}
}
pub struct DescriptionProperty;
impl TemplateProperty<Commit, String> for DescriptionProperty {
@ -415,22 +407,59 @@ impl<'a, C, I, O> TemplateProperty<C, O> for TemplateFunction<'a, C, I, O> {
}
}
pub struct CommitIdKeyword;
#[derive(Debug, Clone)]
pub enum CommitOrChangeId {
CommitId(CommitId),
ChangeId(ChangeId),
}
impl CommitIdKeyword {
pub fn default_format(commit_id: CommitId) -> String {
commit_id.hex()
}
pub fn shortest_format(commit_id: CommitId) -> String {
// TODO: make this actually be the shortest unambiguous prefix
commit_id.hex()[..12].to_string()
impl CommitOrChangeId {
pub fn hex(&self) -> String {
match self {
CommitOrChangeId::CommitId(id) => id.hex(),
CommitOrChangeId::ChangeId(id) => id.hex(),
}
}
}
impl TemplateProperty<Commit, CommitId> for CommitIdKeyword {
fn extract(&self, context: &Commit) -> CommitId {
context.id().clone()
#[derive(Debug, Clone)]
enum CommitOrChange {
Commit,
Change,
}
pub struct CommitOrChangeIdKeyword(CommitOrChange);
impl CommitOrChangeIdKeyword {
pub fn commit() -> Self {
Self(CommitOrChange::Commit)
}
pub fn change() -> Self {
Self(CommitOrChange::Change)
}
pub fn default_format(commit_or_change_id: CommitOrChangeId) -> String {
commit_or_change_id.hex()
}
pub fn shortest_format(commit_or_change_id: CommitOrChangeId) -> String {
commit_or_change_id.hex()[..12].to_string()
}
}
pub struct CommitOrChangeIdShortest;
impl TemplateProperty<CommitOrChangeId, String> for CommitOrChangeIdShortest {
fn extract(&self, context: &CommitOrChangeId) -> String {
CommitOrChangeIdKeyword::shortest_format(context.clone())
}
}
impl TemplateProperty<Commit, CommitOrChangeId> for CommitOrChangeIdKeyword {
fn extract(&self, context: &Commit) -> CommitOrChangeId {
match &self.0 {
CommitOrChange::Commit => CommitOrChangeId::CommitId(context.id().clone()),
CommitOrChange::Change => CommitOrChangeId::ChangeId(context.change_id().clone()),
}
}
}