Skip to content

Commit 14ad12b

Browse files
committed
templates: Expose status_char to the template language
1 parent 1aa079b commit 14ad12b

File tree

4 files changed

+69
-3
lines changed

4 files changed

+69
-3
lines changed

CHANGELOG.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,10 @@ should not be broken.
101101
* Added `join()` template function. This is different from `separate()` in that
102102
it adds a separator between all arguments, even if empty.
103103

104-
* `TreeDiffEntry` type now has a `formatted_path()` method that formats
105-
renames/copies appropriately.
104+
* `TreeDiffEntry` type now has `formatted_path()` and `status_char()` methods.
105+
`formatted_path()` shows renames/copies with common prefix extraction (e.g.,
106+
`src/{old => new}/file.rs`). `status_char()` returns single-character status
107+
codes (M/A/D/C/R).
106108

107109
### Fixed bugs
108110

cli/src/commit_templater.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2414,7 +2414,18 @@ fn builtin_tree_diff_entry_methods<'repo>() -> CommitTemplateBuildMethodFnMap<'r
24142414
Ok(out_property.into_dyn_wrapped())
24152415
},
24162416
);
2417-
// TODO: add status_code() or status_char()?
2417+
map.insert(
2418+
"status_char",
2419+
|_language, _diagnostics, _build_ctx, self_property, function| {
2420+
function.expect_no_arguments()?;
2421+
let out_property = self_property.map(|entry| {
2422+
let (_label, sigil) =
2423+
diff_util::diff_status_label_and_char(&entry.path, &entry.values);
2424+
sigil.to_string()
2425+
});
2426+
Ok(out_property.into_dyn_wrapped())
2427+
},
2428+
);
24182429
map.insert(
24192430
"source",
24202431
|_language, _diagnostics, _build_ctx, self_property, function| {

cli/tests/test_commit_template.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1492,6 +1492,57 @@ fn test_log_diff_formatted_path() {
14921492
");
14931493
}
14941494

1495+
#[test]
1496+
fn test_log_diff_status_char() {
1497+
let test_env = TestEnvironment::default();
1498+
test_env.run_jj_in(".", ["git", "init", "repo"]).success();
1499+
let work_dir = test_env.work_dir("repo");
1500+
1501+
// Create a structure with nested directories.
1502+
work_dir.create_dir("src");
1503+
work_dir.create_dir("src/old");
1504+
work_dir.create_dir("src/new");
1505+
work_dir.write_file("src/old/file.rs", "content");
1506+
work_dir.write_file("src/common.rs", "content");
1507+
work_dir.write_file("top.txt", "content");
1508+
work_dir.run_jj(["commit", "-m", "initial"]).success();
1509+
1510+
// Rename within nested directory (common prefix/suffix).
1511+
work_dir
1512+
.run_jj(["file", "track", "src/new/file.rs"])
1513+
.success();
1514+
work_dir.write_file("src/new/file.rs", "content");
1515+
std::fs::remove_file(work_dir.root().join("src/old/file.rs")).unwrap();
1516+
work_dir.run_jj(["commit", "-m", "rename nested"]).success();
1517+
1518+
// Rename at top level.
1519+
work_dir.run_jj(["file", "track", "renamed.txt"]).success();
1520+
work_dir.write_file("renamed.txt", "content");
1521+
std::fs::remove_file(work_dir.root().join("top.txt")).unwrap();
1522+
work_dir.run_jj(["commit", "-m", "rename top"]).success();
1523+
1524+
let template = indoc! {r#"
1525+
concat(
1526+
description.first_line() ++ ":\n",
1527+
diff.files().map(|e|
1528+
e.status_char() ++ " " ++ e.path() ++ "\n"
1529+
).join(""),
1530+
)
1531+
"#};
1532+
let output = work_dir.run_jj(["log", "--no-graph", "-r", "::@- & ~root()", "-T", template]);
1533+
insta::assert_snapshot!(output, @r"
1534+
rename top:
1535+
R renamed.txt
1536+
rename nested:
1537+
R src/new/file.rs
1538+
initial:
1539+
A src/common.rs
1540+
A src/old/file.rs
1541+
A top.txt
1542+
[EOF]
1543+
");
1544+
}
1545+
14951546
#[test]
14961547
fn test_file_list_entries() {
14971548
let test_env = TestEnvironment::default();

docs/templates.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -603,6 +603,8 @@ This type cannot be printed. The following methods are defined.
603603
points to the target (or right) entry.
604604
* `.status() -> String`: One of `"modified"`, `"added"`, `"removed"`,
605605
`"copied"`, or `"renamed"`.
606+
* `.status_char() -> String`: Single-character status indicator: `"M"` for modified,
607+
`"A"` for added, `"D"` for removed, `"C"` for copied, or `"R"` for renamed.
606608
* `.formatted_path() -> String`: Formatted path with common prefix/suffix extraction
607609
for renames and copies. For example, `src/{old => new}/file.rs` instead of showing
608610
full paths. For non-copy/rename operations, equivalent to `.path()`.

0 commit comments

Comments
 (0)