cli: backout: add templates.backout_description configuration

Closes #5676.
This commit is contained in:
Benjamin Tan 2024-04-26 21:56:55 +08:00
parent 23691a636c
commit e021036740
5 changed files with 85 additions and 15 deletions

View File

@ -51,6 +51,9 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
useful for making machine-readable templates by escaping problematic
characters like `\n`.
* The description of commits backed out by `jj backout` can now be configured
using `templates.backout_description`.
### Fixed bugs
* `jj status` now shows untracked files under untracked directories.

View File

@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use bstr::ByteVec as _;
use clap_complete::ArgValueCandidates;
use itertools::Itertools as _;
use jj_lib::object_id::ObjectId;
@ -22,9 +23,13 @@ use crate::cli_util::CommandHelper;
use crate::cli_util::RevisionArg;
use crate::command_error::CommandError;
use crate::complete;
use crate::formatter::PlainTextFormatter;
use crate::ui::Ui;
/// Apply the reverse of a revision on top of another revision
/// Apply the reverse of given revisions on top of another revision
///
/// The description of the new revisions can be customized with the
/// `templates.backout_description` config variable.
#[derive(clap::Args, Clone, Debug)]
pub(crate) struct BackoutArgs {
/// The revision(s) to apply the reverse of
@ -67,7 +72,6 @@ pub(crate) fn cmd_backout(
let destination = workspace_command.resolve_single_rev(ui, revision_str)?;
parents.push(destination);
}
let mut tx = workspace_command.start_transaction();
let transaction_description = if to_back_out.len() == 1 {
format!("back out commit {}", to_back_out[0].id().hex())
} else {
@ -77,18 +81,31 @@ pub(crate) fn cmd_backout(
to_back_out.len() - 1
)
};
let commits_to_back_out_with_new_commit_descriptions = {
let template_text = command
.settings()
.get_string("templates.backout_description")?;
let template = workspace_command.parse_commit_template(ui, &template_text)?;
to_back_out
.into_iter()
.map(|commit| {
let mut output = Vec::new();
template
.format(&commit, &mut PlainTextFormatter::new(&mut output))
.expect("write() to vec backed formatter should never fail");
// Template output is usually UTF-8, but it can contain file content.
let commit_description = output.into_string_lossy();
(commit, commit_description)
})
.collect_vec()
};
let mut tx = workspace_command.start_transaction();
let mut new_base_tree = merge_commit_trees(tx.repo(), &parents)?;
for commit_to_back_out in to_back_out {
let commit_to_back_out_subject = commit_to_back_out
.description()
.lines()
.next()
.unwrap_or_default();
let new_commit_description = format!(
"Back out \"{}\"\n\nThis backs out commit {}.\n",
commit_to_back_out_subject,
&commit_to_back_out.id().hex()
);
for (commit_to_back_out, new_commit_description) in
commits_to_back_out_with_new_commit_descriptions
{
let old_base_tree = commit_to_back_out.parent_tree(tx.repo())?;
let old_tree = commit_to_back_out.tree()?;
let new_tree = new_base_tree.merge(&old_tree, &old_base_tree)?;

View File

@ -1,4 +1,12 @@
[templates]
backout_description = '''
concat(
'Back out "' ++ description.first_line() ++ '"' ++ "\n",
"\n",
"This backs out commit " ++ commit_id ++ ".\n",
)
'''
bookmark_list = '''
if(remote,
if(tracked,

View File

@ -122,7 +122,7 @@ To get started, see the tutorial at https://jj-vcs.github.io/jj/latest/tutorial/
* `abandon` — Abandon a revision
* `absorb` — Move changes from a revision into the stack of mutable revisions
* `backout` — Apply the reverse of a revision on top of another revision
* `backout` — Apply the reverse of given revisions on top of another revision
* `bookmark` — Manage bookmarks [default alias: b]
* `commit` — Update the description and create a new change on top
* `config` — Manage config options
@ -259,7 +259,9 @@ The modification made by `jj absorb` can be reviewed by `jj op show -p`.
## `jj backout`
Apply the reverse of a revision on top of another revision
Apply the reverse of given revisions on top of another revision
The description of the new revisions can be customized with the `templates.backout_description` config variable.
**Usage:** `jj backout [OPTIONS]`

View File

@ -188,6 +188,46 @@ fn test_backout_multiple() {
"#);
}
#[test]
fn test_backout_description_template() {
let test_env = TestEnvironment::default();
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
test_env.add_config(
r#"
[templates]
backout_description = '''
separate(" ",
"Revert commit",
commit_id.short(),
'"' ++ description.first_line() ++ '"',
)
'''
"#,
);
let repo_path = test_env.env_root().join("repo");
create_commit(&test_env, &repo_path, "a", &[], &[("a", "a\n")]);
// Test the setup
insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r#"
@ 2443ea76b0b1 a
000000000000
"#);
let stdout = test_env.jj_cmd_success(&repo_path, &["diff", "-s"]);
insta::assert_snapshot!(stdout, @r###"
A a
"###);
// Verify that message of backed out commit follows the template
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["backout", "-r", "a"]);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(stderr, @"");
insta::assert_snapshot!(get_log_output(&test_env, &repo_path), @r#"
1db880a5204e Revert commit 2443ea76b0b1 "a"
@ 2443ea76b0b1 a
000000000000
"#);
}
fn get_log_output(test_env: &TestEnvironment, cwd: &Path) -> String {
let template = r#"commit_id.short() ++ " " ++ description"#;
test_env.jj_cmd_success(cwd, &["log", "-T", template])