mirror of
https://github.com/martinvonz/jj.git
synced 2025-05-05 15:32:49 +00:00
templates: implement Commit.trailers()
This commit is contained in:
parent
6e67d79c10
commit
968806bc64
@ -64,6 +64,9 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
* `jj git fetch` now warns instead of erroring for unknown `git.fetch` remotes
|
||||
if other remotes are available.
|
||||
|
||||
* Commit objects in templates now have `trailers() -> List<Trailer>`, the Trailer
|
||||
objects have `key() -> String` and `value() -> String`.
|
||||
|
||||
### Fixed bugs
|
||||
|
||||
* Fixed crash on change-delete conflict resolution.
|
||||
|
@ -64,6 +64,8 @@ use jj_lib::signing::SignError;
|
||||
use jj_lib::signing::SignResult;
|
||||
use jj_lib::signing::Verification;
|
||||
use jj_lib::store::Store;
|
||||
use jj_lib::trailer;
|
||||
use jj_lib::trailer::Trailer;
|
||||
use once_cell::unsync::OnceCell;
|
||||
use pollster::FutureExt as _;
|
||||
|
||||
@ -332,6 +334,23 @@ impl<'repo> TemplateLanguage<'repo> for CommitTemplateLanguage<'repo> {
|
||||
let build = template_parser::lookup_method(type_name, table, function)?;
|
||||
build(self, diagnostics, build_ctx, property, function)
|
||||
}
|
||||
CommitTemplatePropertyKind::Trailer(property) => {
|
||||
let table = &self.build_fn_table.trailer_methods;
|
||||
let build = template_parser::lookup_method(type_name, table, function)?;
|
||||
build(self, diagnostics, build_ctx, property, function)
|
||||
}
|
||||
CommitTemplatePropertyKind::TrailerList(property) => {
|
||||
// TODO: migrate to table?
|
||||
template_builder::build_formattable_list_method(
|
||||
self,
|
||||
diagnostics,
|
||||
build_ctx,
|
||||
property,
|
||||
function,
|
||||
Self::wrap_trailer,
|
||||
Self::wrap_trailer_list,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -456,6 +475,18 @@ impl<'repo> CommitTemplateLanguage<'repo> {
|
||||
) -> CommitTemplatePropertyKind<'repo> {
|
||||
CommitTemplatePropertyKind::AnnotationLine(Box::new(property))
|
||||
}
|
||||
|
||||
pub fn wrap_trailer(
|
||||
property: impl TemplateProperty<Output = Trailer> + 'repo,
|
||||
) -> CommitTemplatePropertyKind<'repo> {
|
||||
CommitTemplatePropertyKind::Trailer(Box::new(property))
|
||||
}
|
||||
|
||||
pub fn wrap_trailer_list(
|
||||
property: impl TemplateProperty<Output = Vec<Trailer>> + 'repo,
|
||||
) -> CommitTemplatePropertyKind<'repo> {
|
||||
CommitTemplatePropertyKind::TrailerList(Box::new(property))
|
||||
}
|
||||
}
|
||||
|
||||
pub enum CommitTemplatePropertyKind<'repo> {
|
||||
@ -479,6 +510,8 @@ pub enum CommitTemplatePropertyKind<'repo> {
|
||||
Box<dyn TemplateProperty<Output = Option<CryptographicSignature>> + 'repo>,
|
||||
),
|
||||
AnnotationLine(Box<dyn TemplateProperty<Output = AnnotationLine> + 'repo>),
|
||||
Trailer(Box<dyn TemplateProperty<Output = Trailer> + 'repo>),
|
||||
TrailerList(Box<dyn TemplateProperty<Output = Vec<Trailer>> + 'repo>),
|
||||
}
|
||||
|
||||
impl<'repo> IntoTemplateProperty<'repo> for CommitTemplatePropertyKind<'repo> {
|
||||
@ -504,6 +537,8 @@ impl<'repo> IntoTemplateProperty<'repo> for CommitTemplatePropertyKind<'repo> {
|
||||
"Option<CryptographicSignature>"
|
||||
}
|
||||
CommitTemplatePropertyKind::AnnotationLine(_) => "AnnotationLine",
|
||||
CommitTemplatePropertyKind::Trailer(_) => "Trailer",
|
||||
CommitTemplatePropertyKind::TrailerList(_) => "List<Trailer>",
|
||||
}
|
||||
}
|
||||
|
||||
@ -543,6 +578,10 @@ impl<'repo> IntoTemplateProperty<'repo> for CommitTemplatePropertyKind<'repo> {
|
||||
Some(Box::new(property.map(|sig| sig.is_some())))
|
||||
}
|
||||
CommitTemplatePropertyKind::AnnotationLine(_) => None,
|
||||
CommitTemplatePropertyKind::Trailer(_) => None,
|
||||
CommitTemplatePropertyKind::TrailerList(property) => {
|
||||
Some(Box::new(property.map(|l| !l.is_empty())))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -587,6 +626,8 @@ impl<'repo> IntoTemplateProperty<'repo> for CommitTemplatePropertyKind<'repo> {
|
||||
CommitTemplatePropertyKind::DiffStats(property) => Some(property.into_template()),
|
||||
CommitTemplatePropertyKind::CryptographicSignatureOpt(_) => None,
|
||||
CommitTemplatePropertyKind::AnnotationLine(_) => None,
|
||||
CommitTemplatePropertyKind::Trailer(property) => Some(property.into_template()),
|
||||
CommitTemplatePropertyKind::TrailerList(property) => Some(property.into_template()),
|
||||
}
|
||||
}
|
||||
|
||||
@ -613,6 +654,8 @@ impl<'repo> IntoTemplateProperty<'repo> for CommitTemplatePropertyKind<'repo> {
|
||||
(CommitTemplatePropertyKind::DiffStats(_), _) => None,
|
||||
(CommitTemplatePropertyKind::CryptographicSignatureOpt(_), _) => None,
|
||||
(CommitTemplatePropertyKind::AnnotationLine(_), _) => None,
|
||||
(CommitTemplatePropertyKind::Trailer(_), _) => None,
|
||||
(CommitTemplatePropertyKind::TrailerList(_), _) => None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -642,6 +685,8 @@ impl<'repo> IntoTemplateProperty<'repo> for CommitTemplatePropertyKind<'repo> {
|
||||
(CommitTemplatePropertyKind::DiffStats(_), _) => None,
|
||||
(CommitTemplatePropertyKind::CryptographicSignatureOpt(_), _) => None,
|
||||
(CommitTemplatePropertyKind::AnnotationLine(_), _) => None,
|
||||
(CommitTemplatePropertyKind::Trailer(_), _) => None,
|
||||
(CommitTemplatePropertyKind::TrailerList(_), _) => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -665,6 +710,7 @@ pub struct CommitTemplateBuildFnTable<'repo> {
|
||||
pub cryptographic_signature_methods:
|
||||
CommitTemplateBuildMethodFnMap<'repo, CryptographicSignature>,
|
||||
pub annotation_line_methods: CommitTemplateBuildMethodFnMap<'repo, AnnotationLine>,
|
||||
pub trailer_methods: CommitTemplateBuildMethodFnMap<'repo, Trailer>,
|
||||
}
|
||||
|
||||
impl<'repo> CommitTemplateBuildFnTable<'repo> {
|
||||
@ -683,6 +729,7 @@ impl<'repo> CommitTemplateBuildFnTable<'repo> {
|
||||
diff_stats_methods: builtin_diff_stats_methods(),
|
||||
cryptographic_signature_methods: builtin_cryptographic_signature_methods(),
|
||||
annotation_line_methods: builtin_annotation_line_methods(),
|
||||
trailer_methods: builtin_trailer_methods(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -700,6 +747,7 @@ impl<'repo> CommitTemplateBuildFnTable<'repo> {
|
||||
diff_stats_methods: HashMap::new(),
|
||||
cryptographic_signature_methods: HashMap::new(),
|
||||
annotation_line_methods: HashMap::new(),
|
||||
trailer_methods: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -717,6 +765,7 @@ impl<'repo> CommitTemplateBuildFnTable<'repo> {
|
||||
diff_stats_methods,
|
||||
cryptographic_signature_methods,
|
||||
annotation_line_methods,
|
||||
trailer_methods,
|
||||
} = extension;
|
||||
|
||||
self.core.merge(core);
|
||||
@ -740,6 +789,7 @@ impl<'repo> CommitTemplateBuildFnTable<'repo> {
|
||||
cryptographic_signature_methods,
|
||||
);
|
||||
merge_fn_map(&mut self.annotation_line_methods, annotation_line_methods);
|
||||
merge_fn_map(&mut self.trailer_methods, trailer_methods);
|
||||
}
|
||||
}
|
||||
|
||||
@ -798,6 +848,15 @@ fn builtin_commit_methods<'repo>() -> CommitTemplateBuildMethodFnMap<'repo, Comm
|
||||
Ok(L::wrap_string(out_property))
|
||||
},
|
||||
);
|
||||
map.insert(
|
||||
"trailers",
|
||||
|_language, _diagnostics, _build_ctx, self_property, function| {
|
||||
function.expect_no_arguments()?;
|
||||
let out_property = self_property
|
||||
.map(|commit| trailer::parse_description_trailers(commit.description()));
|
||||
Ok(L::wrap_trailer_list(out_property))
|
||||
},
|
||||
);
|
||||
map.insert(
|
||||
"change_id",
|
||||
|_language, _diagnostics, _build_ctx, self_property, function| {
|
||||
@ -2264,3 +2323,37 @@ pub fn builtin_annotation_line_methods<'repo>(
|
||||
);
|
||||
map
|
||||
}
|
||||
|
||||
impl Template for Trailer {
|
||||
fn format(&self, formatter: &mut TemplateFormatter) -> io::Result<()> {
|
||||
write!(formatter, "{}: {}", self.key, self.value)
|
||||
}
|
||||
}
|
||||
|
||||
impl Template for Vec<Trailer> {
|
||||
fn format(&self, formatter: &mut TemplateFormatter) -> io::Result<()> {
|
||||
templater::format_joined(formatter, self, "\n")
|
||||
}
|
||||
}
|
||||
|
||||
fn builtin_trailer_methods<'repo>() -> CommitTemplateBuildMethodFnMap<'repo, Trailer> {
|
||||
type L<'repo> = CommitTemplateLanguage<'repo>;
|
||||
let mut map = CommitTemplateBuildMethodFnMap::<Trailer>::new();
|
||||
map.insert(
|
||||
"key",
|
||||
|_language, _diagnostics, _build_ctx, self_property, function| {
|
||||
function.expect_no_arguments()?;
|
||||
let out_property = self_property.map(|trailer| trailer.key);
|
||||
Ok(L::wrap_string(out_property))
|
||||
},
|
||||
);
|
||||
map.insert(
|
||||
"value",
|
||||
|_language, _diagnostics, _build_ctx, self_property, function| {
|
||||
function.expect_no_arguments()?;
|
||||
let out_property = self_property.map(|trailer| trailer.value);
|
||||
Ok(L::wrap_string(out_property))
|
||||
},
|
||||
);
|
||||
map
|
||||
}
|
||||
|
@ -1674,4 +1674,39 @@ fn test_log_format_trailers() {
|
||||
Signed-off-by: Test User <test.user@example.com>
|
||||
[EOF]
|
||||
");
|
||||
|
||||
work_dir
|
||||
.run_jj([
|
||||
"describe",
|
||||
"-r@",
|
||||
"-m",
|
||||
"a change with trailers",
|
||||
r#"--config=templates.commit_trailers="format_signed_off_by_trailer(self) ++ format_gerrit_change_id_trailer(self)""#,
|
||||
])
|
||||
.success();
|
||||
|
||||
let output = work_dir.run_jj(["log", "--no-graph", "-T", r#"trailers ++ "\n""#, "-r@"]);
|
||||
insta::assert_snapshot!(output, @r"
|
||||
Signed-off-by: Test User <test.user@example.com>
|
||||
Change-Id: I6a6a69649a45c67d3e96a7e5007c110ede34dec5
|
||||
[EOF]
|
||||
");
|
||||
|
||||
let output = work_dir.run_jj([
|
||||
"log",
|
||||
"--no-graph",
|
||||
"-T",
|
||||
"trailers.map(|t| t.key())",
|
||||
"-r@",
|
||||
]);
|
||||
insta::assert_snapshot!(output, @"Signed-off-by Change-Id[EOF]");
|
||||
|
||||
let output = work_dir.run_jj([
|
||||
"log",
|
||||
"--no-graph",
|
||||
"-T",
|
||||
"trailers.map(|t| t.value())",
|
||||
"-r@",
|
||||
]);
|
||||
insta::assert_snapshot!(output, @"Test User <test.user@example.com> I6a6a69649a45c67d3e96a7e5007c110ede34dec5[EOF]");
|
||||
}
|
||||
|
@ -109,6 +109,7 @@ No methods are defined. Can be constructed with `false` or `true` literal.
|
||||
This type cannot be printed. The following methods are defined.
|
||||
|
||||
* `.description() -> String`
|
||||
* `.trailers() -> List<Trailer>`
|
||||
* `.change_id() -> ChangeId`
|
||||
* `.commit_id() -> CommitId`
|
||||
* `.parents() -> List<Commit>`
|
||||
@ -385,6 +386,13 @@ The following methods are defined.
|
||||
* `.end() -> Timestamp`
|
||||
* `.duration() -> String`
|
||||
|
||||
### Trailer type
|
||||
|
||||
The following methods are defined.
|
||||
|
||||
* `.key() -> String`
|
||||
* `.value() -> String`
|
||||
|
||||
### TreeDiff type
|
||||
|
||||
This type cannot be printed. The following methods are defined.
|
||||
|
Loading…
x
Reference in New Issue
Block a user