From 1d3c3b8ab207e66c978ed026a7393682989111c5 Mon Sep 17 00:00:00 2001 From: Bryce Berger Date: Fri, 20 Dec 2024 08:18:09 -0500 Subject: [PATCH] describe: ignore everything below `ignore-rest` line This implements "scissor" lines. For example: this text is included in the commit message JJ: ignore-rest this text is not, and is encouraged to be rendered as a diff JJ: ignore-rest this text is *still not* included in the commit message When editing multiple commit messages, the `JJ: describe {}` lines are parsed before the description is cleaned up. That means that the following will correctly add descriptions to multiple commits: JJ: describe aaaaaaaaaaaa this text is included in the first commit message JJ: ignore-rest scissored... JJ: describe bbbbbbbbbbbb this text is included in the first commit message JJ: ignore-rest scissored... --- CHANGELOG.md | 4 ++ cli/src/config/templates.toml | 2 - cli/src/description_util.rs | 14 ++++++- cli/tests/test_describe_command.rs | 65 ++++++++++++++++++++++++++++++ docs/config.md | 2 + 5 files changed, 83 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5eb2b46f49..6498ec0c82 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -78,6 +78,10 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). * New `$marker_length` variable to allow merge tools to support longer conflict markers (equivalent to "%L" for Git merge drivers). +* `jj describe` now accepts a `JJ: ignore-rest` line that ignores everything + below it, similar to a "scissor line" in git. When editing multiple commits, + only ignore until the next `JJ: describe` line. + ### Fixed bugs * The `$NO_COLOR` environment variable must now be non-empty to be respected. diff --git a/cli/src/config/templates.toml b/cli/src/config/templates.toml index a89b299f38..ddb12d9bf8 100644 --- a/cli/src/config/templates.toml +++ b/cli/src/config/templates.toml @@ -29,8 +29,6 @@ if(overridden, ) ++ "\n" ''' -# TODO: Provide hook point for diff customization (#1946)? We might want a -# syntax to comment out full text diffs without using the "JJ:" prefix. draft_commit_description = ''' concat( description, diff --git a/cli/src/description_util.rs b/cli/src/description_util.rs index 30fdcb6a42..5f2d56be40 100644 --- a/cli/src/description_util.rs +++ b/cli/src/description_util.rs @@ -5,6 +5,7 @@ use std::path::Path; use bstr::ByteVec as _; use indexmap::IndexMap; use indoc::indoc; +use itertools::FoldWhile; use itertools::Itertools; use jj_lib::backend::CommitId; use jj_lib::commit::Commit; @@ -28,8 +29,17 @@ where { let description = lines .into_iter() - .filter(|line| !line.as_ref().starts_with("JJ:")) - .fold(String::new(), |acc, line| acc + line.as_ref() + "\n"); + .fold_while(String::new(), |acc, line| { + let line = line.as_ref(); + if line.strip_prefix("JJ: ignore-rest").is_some() { + FoldWhile::Done(acc) + } else if line.starts_with("JJ:") { + FoldWhile::Continue(acc) + } else { + FoldWhile::Continue(acc + line + "\n") + } + }) + .into_inner(); text_util::complete_newline(description.trim_matches('\n')) } diff --git a/cli/tests/test_describe_command.rs b/cli/tests/test_describe_command.rs index 8d3f7c920e..a730e86ea8 100644 --- a/cli/tests/test_describe_command.rs +++ b/cli/tests/test_describe_command.rs @@ -140,6 +140,35 @@ fn test_describe() { std::fs::write(&edit_script, "fail").unwrap(); let stderr = test_env.jj_cmd_failure(&repo_path, &["describe"]); assert!(stderr.contains("exited with an error")); + + // ignore everything after the first ignore-rest line + std::fs::write( + &edit_script, + indoc! {" + write + description from editor + + content of message from editor + JJ: ignore-rest + content after ignore line should not be included + JJ: ignore-rest + ignore everything until EOF or next description + "}, + ) + .unwrap(); + let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["describe"]); + insta::assert_snapshot!(stdout, @""); + insta::assert_snapshot!(stderr, @r#" + Working copy now at: qpvuntsm 10fa2dc7 (empty) description from editor + Parent commit : zzzzzzzz 00000000 (empty) (no description set) + "#); + let stdout = + test_env.jj_cmd_success(&repo_path, &["log", "--no-graph", "-r@", "-Tdescription"]); + insta::assert_snapshot!(stdout, @r#" + description from editor + + content of message from editor + "#); } #[test] @@ -384,6 +413,42 @@ fn test_describe_multiple_commits() { std::fs::write(&edit_script, "fail").unwrap(); let stderr = test_env.jj_cmd_failure(&repo_path, &["describe", "@", "@-"]); assert!(stderr.contains("exited with an error")); + + // describe lines should take priority over ignore-rest + std::fs::write( + &edit_script, + indoc! {" + write + JJ: describe 0d76a92ca7cc ------- + description from editor for @- + + JJ: ignore-rest + content after ignore-rest should not be included + + JJ: describe a42f5755e688 ------- + description from editor for @-- + + JJ: ignore-rest + each commit should skip their own ignore-rest + "}, + ) + .unwrap(); + let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["describe", "@-", "@--"]); + insta::assert_snapshot!(stdout, @""); + insta::assert_snapshot!(stderr, @r#" + Updated 2 commits + Rebased 1 descendant commits + Working copy now at: kkmpptxz 1d7701ee (empty) description from editor of @ + Parent commit : rlvkpnrz 5389926e (empty) description from editor for @- + "#); + insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r#" + @ 1d7701eec9bc description from editor of @ + │ + │ further commit message of @ + ○ 5389926ebed6 description from editor for @- + ○ eaa8547ae37a description from editor for @-- + ◆ 000000000000 + "#); } #[test] diff --git a/docs/config.md b/docs/config.md index 7a0de1290a..9d6463f842 100644 --- a/docs/config.md +++ b/docs/config.md @@ -185,6 +185,8 @@ concat( "\nJJ: This commit contains the following changes:\n", "", indent("JJ: ", diff.stat(72)), ), + "\nJJ: ignore-rest\n", + diff.git(), ) ''' ```