diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c07e878f02..bdcd132c7a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Show paths to config files when configuration errors occur +* `jj fix` now supports configuring the default revset for `-s` using the + `revsets.fix` config. + ### Fixed bugs ## [0.18.0] - 2024-06-05 diff --git a/cli/src/commands/fix.rs b/cli/src/commands/fix.rs index 6112e0ef87e..7e31a3ebf13 100644 --- a/cli/src/commands/fix.rs +++ b/cli/src/commands/fix.rs @@ -65,7 +65,9 @@ use crate::ui::Ui; #[derive(clap::Args, Clone, Debug)] #[command(verbatim_doc_comment)] pub(crate) struct FixArgs { - /// Fix files in the specified revision(s) and their descendants + /// Fix files in the specified revision(s) and their descendants. If no + /// revisions are specified, this defaults to the `revsets.fix` setting, or + /// `@` if it is not set. #[arg(long, short)] source: Vec, /// Fix only these paths @@ -80,14 +82,14 @@ pub(crate) fn cmd_fix( args: &FixArgs, ) -> Result<(), CommandError> { let mut workspace_command = command.workspace_helper(ui)?; - let root_commits: Vec = workspace_command - .parse_union_revsets(if args.source.is_empty() { - &[RevisionArg::AT] - } else { - &args.source - })? - .evaluate_to_commit_ids()? - .collect(); + let root_commits: Vec = if args.source.is_empty() { + workspace_command + .parse_revset(&RevisionArg::from(command.settings().default_fix_revset()))? + } else { + workspace_command.parse_union_revsets(&args.source)? + } + .evaluate_to_commit_ids()? + .collect(); workspace_command.check_rewritable(root_commits.iter())?; let matcher = workspace_command .parse_file_patterns(&args.paths)? diff --git a/cli/src/config-schema.json b/cli/src/config-schema.json index d9267ac88c3..95df0038988 100644 --- a/cli/src/config-schema.json +++ b/cli/src/config-schema.json @@ -346,6 +346,11 @@ "type": "object", "description": "Revset expressions used by various commands", "properties": { + "fix": { + "type": "string", + "description": "Default set of revisions to fix when no explicit revset is given for jj fix", + "default": "@" + }, "log": { "type": "string", "description": "Default set of revisions to show when no explicit revset is given for jj log and similar commands", diff --git a/cli/src/config/revsets.toml b/cli/src/config/revsets.toml index 60517d3ffb5..776ae15cb02 100644 --- a/cli/src/config/revsets.toml +++ b/cli/src/config/revsets.toml @@ -2,6 +2,7 @@ # adding/updating any of these aliases [revsets] +fix = "@" log = "@ | ancestors(immutable_heads().., 2) | trunk()" [revset-aliases] diff --git a/cli/tests/cli-reference@.md.snap b/cli/tests/cli-reference@.md.snap index 8b074b21e18..7454d797ecf 100644 --- a/cli/tests/cli-reference@.md.snap +++ b/cli/tests/cli-reference@.md.snap @@ -798,7 +798,7 @@ And then run the command `jj fix -s @`. ###### **Options:** -* `-s`, `--source ` — Fix files in the specified revision(s) and their descendants +* `-s`, `--source ` — Fix files in the specified revision(s) and their descendants. If no revisions are specified, this defaults to the `revsets.fix` setting, or `@` if it is not set diff --git a/cli/tests/test_fix_command.rs b/cli/tests/test_fix_command.rs index 2db3e696c37..2e66ed884c6 100644 --- a/cli/tests/test_fix_command.rs +++ b/cli/tests/test_fix_command.rs @@ -139,6 +139,61 @@ fn test_fix_sibling_commit() { insta::assert_snapshot!(content, @"child2"); } +#[test] +fn test_default_revset() { + let (test_env, repo_path) = init_with_fake_formatter(&["--uppercase"]); + std::fs::write(repo_path.join("file"), "foo").unwrap(); + test_env.jj_cmd_ok(&repo_path, &["branch", "create", "foo"]); + test_env.jj_cmd_ok(&repo_path, &["new"]); + std::fs::write(repo_path.join("file"), "bar").unwrap(); + test_env.jj_cmd_ok(&repo_path, &["branch", "create", "bar"]); + test_env.jj_cmd_ok(&repo_path, &["new", "foo"]); + std::fs::write(repo_path.join("file"), "baz").unwrap(); + test_env.jj_cmd_ok(&repo_path, &["branch", "create", "baz"]); + + // With no args and no revset configuration, we fix `@`. + let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["fix"]); + insta::assert_snapshot!(stdout, @""); + insta::assert_snapshot!(stderr, @r###" + Fixed 1 commits of 1 checked. + Working copy now at: mzvwutvl 5205c5f1 baz | (no description set) + Parent commit : qpvuntsm 34af74d0 foo | (no description set) + Added 0 files, modified 1 files, removed 0 files + "###); + let content = test_env.jj_cmd_success(&repo_path, &["print", "file", "-r", "foo"]); + insta::assert_snapshot!(content, @"foo"); + let content = test_env.jj_cmd_success(&repo_path, &["print", "file", "-r", "bar"]); + insta::assert_snapshot!(content, @"bar"); + let content = test_env.jj_cmd_success(&repo_path, &["print", "file", "-r", "baz"]); + insta::assert_snapshot!(content, @"BAZ"); +} + +#[test] +fn test_custom_default_revset() { + let (test_env, repo_path) = init_with_fake_formatter(&["--uppercase"]); + + std::fs::write(repo_path.join("file"), "foo").unwrap(); + test_env.jj_cmd_ok(&repo_path, &["branch", "create", "foo"]); + test_env.jj_cmd_ok(&repo_path, &["new"]); + std::fs::write(repo_path.join("file"), "bar").unwrap(); + test_env.jj_cmd_ok(&repo_path, &["branch", "create", "bar"]); + + // Check out a different commit so that the schema default `@` would behave + // differently from our customized default. + test_env.jj_cmd_ok(&repo_path, &["new", "-r", "foo"]); + test_env.add_config(r#"revsets.fix = "bar""#); + + let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["fix"]); + insta::assert_snapshot!(stdout, @""); + insta::assert_snapshot!(stderr, @r###" + Fixed 1 commits of 1 checked. + "###); + let content = test_env.jj_cmd_success(&repo_path, &["print", "file", "-r", "foo"]); + insta::assert_snapshot!(content, @"foo"); + let content = test_env.jj_cmd_success(&repo_path, &["print", "file", "-r", "bar"]); + insta::assert_snapshot!(content, @"BAR"); +} + #[test] fn test_fix_immutable_commit() { let (test_env, repo_path) = init_with_fake_formatter(&["--uppercase"]); diff --git a/lib/src/settings.rs b/lib/src/settings.rs index 8497ced2a6a..89c5a75c699 100644 --- a/lib/src/settings.rs +++ b/lib/src/settings.rs @@ -208,6 +208,10 @@ impl UserSettings { self.config.get_string("revsets.log").unwrap_or_default() } + pub fn default_fix_revset(&self) -> String { + self.config.get_string("revsets.fix").unwrap_or_default() + } + pub fn signature(&self) -> Signature { let timestamp = self.timestamp.clone().unwrap_or_else(Timestamp::now); Signature {