cli: remove handling of deprecated fix.tool-command config
Some checks are pending
binaries / Build binary artifacts (push) Waiting to run
website / prerelease-docs-build-deploy (ubuntu-24.04) (push) Waiting to run
Scorecards supply-chain security / Scorecards analysis (push) Waiting to run

I originally implemented this as a custom config migration rule, but the next
release is v0.26, so we can just drop support for fix.tool-command.
This commit is contained in:
Yuya Nishihara 2024-12-27 18:27:44 +09:00
parent b97b7384bb
commit e124404af3
5 changed files with 90 additions and 345 deletions

View file

@ -26,6 +26,8 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
* The deprecated `--siblings` options for `jj split` has been removed.
`jj split --parallel` can be used instead.
* The deprecated `fix.tool-command` config option has been removed.
* In colocated repos, the Git index now contains the changes from all parents
of the working copy instead of just the first parent (`HEAD`). 2-sided
conflicts from the merged parents are now added to the Git index as conflicts

View file

@ -28,7 +28,6 @@ use jj_lib::backend::TreeValue;
use jj_lib::fileset;
use jj_lib::fileset::FilesetDiagnostics;
use jj_lib::fileset::FilesetExpression;
use jj_lib::matchers::EverythingMatcher;
use jj_lib::matchers::Matcher;
use jj_lib::merged_tree::MergedTree;
use jj_lib::merged_tree::MergedTreeBuilder;
@ -106,20 +105,6 @@ use crate::ui::Ui;
/// currently unspecified, and may change between releases. If two tools affect
/// the same file, the second tool to run will receive its input from the
/// output of the first tool.
///
/// There is also a deprecated configuration schema that defines a single
/// command that will affect all changed files in the specified revisions. For
/// example, the following configuration would apply the Rust formatter to all
/// changed files (whether they are Rust files or not):
///
/// ```toml
/// [fix]
/// tool-command = ["rustfmt", "--emit", "stdout"]
/// ```
///
/// The tool defined by `tool-command` acts as if it was the first entry in
/// `fix.tools`, and uses `pattern = "all()"``. Support for `tool-command`
/// will be removed in a future version.
#[derive(clap::Args, Clone, Debug)]
#[command(verbatim_doc_comment)]
pub(crate) struct FixArgs {
@ -443,43 +428,10 @@ struct RawToolConfig {
/// Parses the `fix.tools` config table.
///
/// Parses the deprecated `fix.tool-command` config as if it was the first entry
/// in `fix.tools`.
///
/// Fails if any of the commands or patterns are obviously unusable, but does
/// not check for issues that might still occur later like missing executables.
/// This is a place where we could fail earlier in some cases, though.
fn get_tools_config(ui: &mut Ui, settings: &UserSettings) -> Result<ToolsConfig, CommandError> {
let mut tools_config = ToolsConfig { tools: Vec::new() };
// TODO: Remove this block of code and associated documentation after at least
// one release where the feature is marked deprecated.
if let Ok(tool_command) = settings.get::<CommandNameAndArgs>("fix.tool-command") {
// This doesn't change the displayed indices of the `fix.tools` definitions, and
// doesn't have a `name` that could conflict with them. That would matter more
// if we already had better error handling that made use of the `name`.
tools_config.tools.push(ToolConfig {
command: tool_command,
matcher: Box::new(EverythingMatcher),
});
// TODO: Reimplement as a ConfigMigrationRule
writeln!(
ui.warning_default(),
r"The `fix.tool-command` config option is deprecated and will be removed in a future version."
)?;
writeln!(
ui.hint_default(),
r###"Replace it with the following:
[fix.tools.legacy-tool-command]
command = {}
patterns = ["all()"]
"###,
settings
.get_value("fix.tool-command")
.unwrap()
.decorated("", "") // trim whitespace
)?;
}
let tools: Vec<ToolConfig> = settings
.table_keys("fix.tools")
// Sort keys early so errors are deterministic.
@ -509,15 +461,9 @@ fn get_tools_config(ui: &mut Ui, settings: &UserSettings) -> Result<ToolsConfig,
})
})
.try_collect()?;
tools_config.tools.extend(tools);
if tools_config.tools.is_empty() {
// TODO: This is not a useful message when one or both fields are present but
// have the wrong type. After removing `fix.tool-command`, it will be simpler to
// propagate any errors from `settings.get_array("fix.tools")`.
Err(config_error(
"At least one entry of `fix.tools` or `fix.tool-command` is required.".to_string(),
))
if tools.is_empty() {
Err(config_error("No `fix.tools` are configured"))
} else {
Ok(tools_config)
Ok(ToolsConfig { tools })
}
}

View file

@ -593,13 +593,6 @@
"type": "object",
"description": "Settings for jj fix",
"properties": {
"tool-command": {
"type": "array",
"items": {
"type": "string"
},
"description": "Shell command that takes file content on stdin and returns fixed file content on stdout (deprecated)"
},
"tools": {
"type": "object",
"additionalProperties": {

View file

@ -1007,20 +1007,6 @@ currently unspecified, and may change between releases. If two tools affect
the same file, the second tool to run will receive its input from the
output of the first tool.
There is also a deprecated configuration schema that defines a single
command that will affect all changed files in the specified revisions. For
example, the following configuration would apply the Rust formatter to all
changed files (whether they are Rust files or not):
```toml
[fix]
tool-command = ["rustfmt", "--emit", "stdout"]
```
The tool defined by `tool-command` acts as if it was the first entry in
`fix.tools`, and uses `pattern = "all()"``. Support for `tool-command`
will be removed in a future version.
**Usage:** `jj fix [OPTIONS] [FILESETS]...`
###### **Arguments:**

View file

@ -16,39 +16,34 @@
use std::os::unix::fs::PermissionsExt;
use std::path::PathBuf;
use indoc::formatdoc;
use indoc::indoc;
use jj_lib::file_util::try_symlink;
use crate::common::to_toml_value;
use crate::common::TestEnvironment;
/// Set up a repo where the `jj fix` command uses the fake editor with the given
/// flags. Returns a function that redacts the formatter executable's path from
/// a given string for test determinism.
fn init_with_fake_formatter(args: &[&str]) -> (TestEnvironment, PathBuf, impl Fn(&str) -> String) {
/// flags.
fn init_with_fake_formatter(args: &[&str]) -> (TestEnvironment, PathBuf) {
let test_env = TestEnvironment::default();
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
let repo_path = test_env.env_root().join("repo");
let formatter_path = assert_cmd::cargo::cargo_bin("fake-formatter");
assert!(formatter_path.is_file());
// The deprecated configuration syntax is still used by tests where it doesn't
// make a meaningful difference in coverage. Otherwise, we would have to add
// dedicated test coverage for the deprecated syntax until it is removed. We use
// single quotes here to avoid escaping issues when running the test on Windows.
test_env.add_config(format!(
"fix.tool-command = {}",
toml_edit::Value::from_iter(
test_env.add_config(formatdoc! {"
[fix.tools.fake-formatter]
command = {command}
patterns = ['all()']
",
command = toml_edit::Value::from_iter(
[formatter_path.to_str().unwrap()]
.iter()
.chain(args)
.copied()
)
));
(test_env, repo_path, move |snapshot: &str| {
snapshot.replace(
&to_toml_value(formatter_path.to_str().unwrap()).to_string(),
"<redacted formatter path>",
)
})
});
(test_env, repo_path)
}
#[test]
@ -59,53 +54,15 @@ fn test_config_no_tools() {
std::fs::write(repo_path.join("file"), "content\n").unwrap();
let stderr = test_env.jj_cmd_failure(&repo_path, &["fix"]);
insta::assert_snapshot!(stderr, @r###"
Config error: At least one entry of `fix.tools` or `fix.tool-command` is required.
insta::assert_snapshot!(stderr, @r"
Config error: No `fix.tools` are configured
For help, see https://jj-vcs.github.io/jj/latest/config/.
"###);
");
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "@"]);
insta::assert_snapshot!(content, @"content\n");
}
#[test]
fn test_config_both_legacy_and_table_tools() {
let test_env = TestEnvironment::default();
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
let repo_path = test_env.env_root().join("repo");
let formatter_path = assert_cmd::cargo::cargo_bin("fake-formatter");
assert!(formatter_path.is_file());
let formatter = to_toml_value(formatter_path.to_str().unwrap());
test_env.add_config(format!(
r###"
[fix]
tool-command = [{formatter}, "--append", "legacy change"]
[fix.tools.tool-1]
command = [{formatter}, "--append", "tables change"]
patterns = ["tables-file"]
"###,
));
std::fs::write(repo_path.join("legacy-file"), "legacy content\n").unwrap();
std::fs::write(repo_path.join("tables-file"), "tables content\n").unwrap();
let (_stdout, _stderr) = test_env.jj_cmd_ok(&repo_path, &["fix"]);
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "legacy-file", "-r", "@"]);
insta::assert_snapshot!(content, @r###"
legacy content
legacy change
"###);
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "tables-file", "-r", "@"]);
insta::assert_snapshot!(content, @r###"
tables content
legacy change
tables change
"###);
}
#[test]
fn test_config_multiple_tools() {
let test_env = TestEnvironment::default();
@ -417,42 +374,30 @@ fn test_relative_paths() {
#[test]
fn test_fix_empty_commit() {
let (test_env, repo_path, redact) = init_with_fake_formatter(&["--uppercase"]);
let (test_env, repo_path) = init_with_fake_formatter(&["--uppercase"]);
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["fix", "-s", "@"]);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(redact(&stderr), @r#"
Warning: The `fix.tool-command` config option is deprecated and will be removed in a future version.
Hint: Replace it with the following:
[fix.tools.legacy-tool-command]
command = [<redacted formatter path>, "--uppercase"]
patterns = ["all()"]
insta::assert_snapshot!(stderr, @r"
Fixed 0 commits of 1 checked.
Nothing changed.
"#);
");
}
#[test]
fn test_fix_leaf_commit() {
let (test_env, repo_path, redact) = init_with_fake_formatter(&["--uppercase"]);
let (test_env, repo_path) = init_with_fake_formatter(&["--uppercase"]);
std::fs::write(repo_path.join("file"), "unaffected").unwrap();
test_env.jj_cmd_ok(&repo_path, &["new"]);
std::fs::write(repo_path.join("file"), "affected").unwrap();
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["fix", "-s", "@"]);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(redact(&stderr), @r#"
Warning: The `fix.tool-command` config option is deprecated and will be removed in a future version.
Hint: Replace it with the following:
[fix.tools.legacy-tool-command]
command = [<redacted formatter path>, "--uppercase"]
patterns = ["all()"]
insta::assert_snapshot!(stderr, @r"
Fixed 1 commits of 1 checked.
Working copy now at: rlvkpnrz 85ce8924 (no description set)
Parent commit : qpvuntsm b2ca2bc5 (no description set)
Added 0 files, modified 1 files, removed 0 files
"#);
");
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "@-"]);
insta::assert_snapshot!(content, @"unaffected");
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "@"]);
@ -461,7 +406,7 @@ fn test_fix_leaf_commit() {
#[test]
fn test_fix_parent_commit() {
let (test_env, repo_path, redact) = init_with_fake_formatter(&["--uppercase"]);
let (test_env, repo_path) = init_with_fake_formatter(&["--uppercase"]);
// Using one file name for all commits adds coverage of some possible bugs.
std::fs::write(repo_path.join("file"), "parent").unwrap();
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "parent"]);
@ -474,18 +419,12 @@ fn test_fix_parent_commit() {
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["fix", "-s", "parent"]);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(redact(&stderr), @r#"
Warning: The `fix.tool-command` config option is deprecated and will be removed in a future version.
Hint: Replace it with the following:
[fix.tools.legacy-tool-command]
command = [<redacted formatter path>, "--uppercase"]
patterns = ["all()"]
insta::assert_snapshot!(stderr, @r"
Fixed 3 commits of 3 checked.
Working copy now at: mzvwutvl d30c8ae2 child2 | (no description set)
Parent commit : qpvuntsm 70a4dae2 parent | (no description set)
Added 0 files, modified 1 files, removed 0 files
"#);
");
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "parent"]);
insta::assert_snapshot!(content, @"PARENT");
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "child1"]);
@ -496,7 +435,7 @@ fn test_fix_parent_commit() {
#[test]
fn test_fix_sibling_commit() {
let (test_env, repo_path, redact) = init_with_fake_formatter(&["--uppercase"]);
let (test_env, repo_path) = init_with_fake_formatter(&["--uppercase"]);
std::fs::write(repo_path.join("file"), "parent").unwrap();
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "parent"]);
test_env.jj_cmd_ok(&repo_path, &["new"]);
@ -508,15 +447,7 @@ fn test_fix_sibling_commit() {
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["fix", "-s", "child1"]);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(redact(&stderr), @r#"
Warning: The `fix.tool-command` config option is deprecated and will be removed in a future version.
Hint: Replace it with the following:
[fix.tools.legacy-tool-command]
command = [<redacted formatter path>, "--uppercase"]
patterns = ["all()"]
Fixed 1 commits of 1 checked.
"#);
insta::assert_snapshot!(stderr, @"Fixed 1 commits of 1 checked.");
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "parent"]);
insta::assert_snapshot!(content, @"parent");
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "child1"]);
@ -527,7 +458,7 @@ fn test_fix_sibling_commit() {
#[test]
fn test_default_revset() {
let (test_env, repo_path, redact) = init_with_fake_formatter(&["--uppercase"]);
let (test_env, repo_path) = init_with_fake_formatter(&["--uppercase"]);
std::fs::write(repo_path.join("file"), "trunk1").unwrap();
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "trunk1"]);
test_env.jj_cmd_ok(&repo_path, &["new"]);
@ -553,18 +484,12 @@ fn test_default_revset() {
test_env.add_config(r#"revset-aliases."immutable_heads()" = "trunk2""#);
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["fix"]);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(redact(&stderr), @r#"
Warning: The `fix.tool-command` config option is deprecated and will be removed in a future version.
Hint: Replace it with the following:
[fix.tools.legacy-tool-command]
command = [<redacted formatter path>, "--uppercase"]
patterns = ["all()"]
insta::assert_snapshot!(stderr, @r"
Fixed 3 commits of 3 checked.
Working copy now at: yostqsxw dabc47b2 bar2 | (no description set)
Parent commit : yqosqzyt 984b5924 bar1 | (no description set)
Added 0 files, modified 1 files, removed 0 files
"#);
");
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "trunk1"]);
insta::assert_snapshot!(content, @"trunk1");
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "trunk2"]);
@ -581,7 +506,7 @@ fn test_default_revset() {
#[test]
fn test_custom_default_revset() {
let (test_env, repo_path, redact) = init_with_fake_formatter(&["--uppercase"]);
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, &["bookmark", "create", "foo"]);
@ -596,15 +521,7 @@ fn test_custom_default_revset() {
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["fix"]);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(redact(&stderr), @r#"
Warning: The `fix.tool-command` config option is deprecated and will be removed in a future version.
Hint: Replace it with the following:
[fix.tools.legacy-tool-command]
command = [<redacted formatter path>, "--uppercase"]
patterns = ["all()"]
Fixed 1 commits of 1 checked.
"#);
insta::assert_snapshot!(stderr, @"Fixed 1 commits of 1 checked.");
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "foo"]);
insta::assert_snapshot!(content, @"foo");
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "bar"]);
@ -613,7 +530,7 @@ fn test_custom_default_revset() {
#[test]
fn test_fix_immutable_commit() {
let (test_env, repo_path, redact) = init_with_fake_formatter(&["--uppercase"]);
let (test_env, repo_path) = init_with_fake_formatter(&["--uppercase"]);
std::fs::write(repo_path.join("file"), "immutable").unwrap();
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "immutable"]);
test_env.jj_cmd_ok(&repo_path, &["new"]);
@ -622,17 +539,11 @@ fn test_fix_immutable_commit() {
test_env.add_config(r#"revset-aliases."immutable_heads()" = "immutable""#);
let stderr = test_env.jj_cmd_failure(&repo_path, &["fix", "-s", "immutable"]);
insta::assert_snapshot!(redact(&stderr), @r#"
Warning: The `fix.tool-command` config option is deprecated and will be removed in a future version.
Hint: Replace it with the following:
[fix.tools.legacy-tool-command]
command = [<redacted formatter path>, "--uppercase"]
patterns = ["all()"]
insta::assert_snapshot!(stderr, @r"
Error: Commit e4b41a3ce243 is immutable
Hint: Could not modify commit: qpvuntsm e4b41a3c immutable | (no description set)
Hint: Pass `--ignore-immutable` or configure the set of immutable commits via `revset-aliases.immutable_heads()`.
"#);
");
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "immutable"]);
insta::assert_snapshot!(content, @"immutable");
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "mutable"]);
@ -641,45 +552,33 @@ fn test_fix_immutable_commit() {
#[test]
fn test_fix_empty_file() {
let (test_env, repo_path, redact) = init_with_fake_formatter(&["--uppercase"]);
let (test_env, repo_path) = init_with_fake_formatter(&["--uppercase"]);
std::fs::write(repo_path.join("file"), "").unwrap();
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["fix", "-s", "@"]);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(redact(&stderr), @r#"
Warning: The `fix.tool-command` config option is deprecated and will be removed in a future version.
Hint: Replace it with the following:
[fix.tools.legacy-tool-command]
command = [<redacted formatter path>, "--uppercase"]
patterns = ["all()"]
insta::assert_snapshot!(stderr, @r"
Fixed 0 commits of 1 checked.
Nothing changed.
"#);
");
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "@"]);
insta::assert_snapshot!(content, @"");
}
#[test]
fn test_fix_some_paths() {
let (test_env, repo_path, redact) = init_with_fake_formatter(&["--uppercase"]);
let (test_env, repo_path) = init_with_fake_formatter(&["--uppercase"]);
std::fs::write(repo_path.join("file1"), "foo").unwrap();
std::fs::write(repo_path.join("file2"), "bar").unwrap();
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["fix", "-s", "@", "file1"]);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(redact(&stderr), @r#"
Warning: The `fix.tool-command` config option is deprecated and will be removed in a future version.
Hint: Replace it with the following:
[fix.tools.legacy-tool-command]
command = [<redacted formatter path>, "--uppercase"]
patterns = ["all()"]
insta::assert_snapshot!(stderr, @r"
Fixed 1 commits of 1 checked.
Working copy now at: qpvuntsm 54a90d2b (no description set)
Parent commit : zzzzzzzz 00000000 (empty) (no description set)
Added 0 files, modified 1 files, removed 0 files
"#);
");
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file1"]);
insta::assert_snapshot!(content, @r###"
FOO
@ -690,40 +589,28 @@ fn test_fix_some_paths() {
#[test]
fn test_fix_cyclic() {
let (test_env, repo_path, redact) = init_with_fake_formatter(&["--reverse"]);
let (test_env, repo_path) = init_with_fake_formatter(&["--reverse"]);
std::fs::write(repo_path.join("file"), "content\n").unwrap();
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["fix"]);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(redact(&stderr), @r#"
Warning: The `fix.tool-command` config option is deprecated and will be removed in a future version.
Hint: Replace it with the following:
[fix.tools.legacy-tool-command]
command = [<redacted formatter path>, "--reverse"]
patterns = ["all()"]
insta::assert_snapshot!(stderr, @r"
Fixed 1 commits of 1 checked.
Working copy now at: qpvuntsm bf5e6a5a (no description set)
Parent commit : zzzzzzzz 00000000 (empty) (no description set)
Added 0 files, modified 1 files, removed 0 files
"#);
");
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "@"]);
insta::assert_snapshot!(content, @"tnetnoc\n");
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["fix"]);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(redact(&stderr), @r#"
Warning: The `fix.tool-command` config option is deprecated and will be removed in a future version.
Hint: Replace it with the following:
[fix.tools.legacy-tool-command]
command = [<redacted formatter path>, "--reverse"]
patterns = ["all()"]
insta::assert_snapshot!(stderr, @r"
Fixed 1 commits of 1 checked.
Working copy now at: qpvuntsm 0e2d20d6 (no description set)
Parent commit : zzzzzzzz 00000000 (empty) (no description set)
Added 0 files, modified 1 files, removed 0 files
"#);
");
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "@"]);
insta::assert_snapshot!(content, @"content\n");
}
@ -733,8 +620,7 @@ fn test_deduplication() {
// Append all fixed content to a log file. This assumes we're running the tool
// in the root directory of the repo, which is worth reconsidering if we
// establish a contract regarding cwd.
let (test_env, repo_path, redact) =
init_with_fake_formatter(&["--uppercase", "--tee", "$path-fixlog"]);
let (test_env, repo_path) = init_with_fake_formatter(&["--uppercase", "--tee", "$path-fixlog"]);
// There are at least two interesting cases: the content is repeated immediately
// in the child commit, or later in another descendant.
@ -752,18 +638,12 @@ fn test_deduplication() {
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["fix", "-s", "a"]);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(redact(&stderr), @r#"
Warning: The `fix.tool-command` config option is deprecated and will be removed in a future version.
Hint: Replace it with the following:
[fix.tools.legacy-tool-command]
command = [<redacted formatter path>, "--uppercase", "--tee", "$path-fixlog"]
patterns = ["all()"]
insta::assert_snapshot!(stderr, @r"
Fixed 4 commits of 4 checked.
Working copy now at: yqosqzyt cf770245 d | (no description set)
Parent commit : mzvwutvl 370615a5 c | (empty) (no description set)
Added 0 files, modified 1 files, removed 0 files
"#);
");
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "a"]);
insta::assert_snapshot!(content, @"FOO\n");
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "b"]);
@ -793,21 +673,15 @@ fn sorted_lines(path: PathBuf) -> String {
fn test_executed_but_nothing_changed() {
// Show that the tool ran by causing a side effect with --tee, and test that we
// do the right thing when the tool's output is exactly equal to its input.
let (test_env, repo_path, redact) = init_with_fake_formatter(&["--tee", "$path-copy"]);
let (test_env, repo_path) = init_with_fake_formatter(&["--tee", "$path-copy"]);
std::fs::write(repo_path.join("file"), "content\n").unwrap();
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["fix", "-s", "@"]);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(redact(&stderr), @r#"
Warning: The `fix.tool-command` config option is deprecated and will be removed in a future version.
Hint: Replace it with the following:
[fix.tools.legacy-tool-command]
command = [<redacted formatter path>, "--tee", "$path-copy"]
patterns = ["all()"]
insta::assert_snapshot!(stderr, @r"
Fixed 0 commits of 1 checked.
Nothing changed.
"#);
");
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "@"]);
insta::assert_snapshot!(content, @"content\n");
let copy_content = std::fs::read_to_string(repo_path.join("file-copy").as_os_str()).unwrap();
@ -816,28 +690,22 @@ fn test_executed_but_nothing_changed() {
#[test]
fn test_failure() {
let (test_env, repo_path, redact) = init_with_fake_formatter(&["--fail"]);
let (test_env, repo_path) = init_with_fake_formatter(&["--fail"]);
std::fs::write(repo_path.join("file"), "content").unwrap();
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["fix", "-s", "@"]);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(redact(&stderr), @r#"
Warning: The `fix.tool-command` config option is deprecated and will be removed in a future version.
Hint: Replace it with the following:
[fix.tools.legacy-tool-command]
command = [<redacted formatter path>, "--fail"]
patterns = ["all()"]
insta::assert_snapshot!(stderr, @r"
Fixed 0 commits of 1 checked.
Nothing changed.
"#);
");
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "@"]);
insta::assert_snapshot!(content, @"content");
}
#[test]
fn test_stderr_success() {
let (test_env, repo_path, redact) =
let (test_env, repo_path) =
init_with_fake_formatter(&["--stderr", "error", "--stdout", "new content"]);
std::fs::write(repo_path.join("file"), "old content").unwrap();
@ -845,40 +713,28 @@ fn test_stderr_success() {
// of passing it through directly.
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["fix", "-s", "@"]);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(redact(&stderr), @r#"
Warning: The `fix.tool-command` config option is deprecated and will be removed in a future version.
Hint: Replace it with the following:
[fix.tools.legacy-tool-command]
command = [<redacted formatter path>, "--stderr", "error", "--stdout", "new content"]
patterns = ["all()"]
insta::assert_snapshot!(stderr, @r"
errorFixed 1 commits of 1 checked.
Working copy now at: qpvuntsm 487808ba (no description set)
Parent commit : zzzzzzzz 00000000 (empty) (no description set)
Added 0 files, modified 1 files, removed 0 files
"#);
");
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "@"]);
insta::assert_snapshot!(content, @"new content");
}
#[test]
fn test_stderr_failure() {
let (test_env, repo_path, redact) =
let (test_env, repo_path) =
init_with_fake_formatter(&["--stderr", "error", "--stdout", "new content", "--fail"]);
std::fs::write(repo_path.join("file"), "old content").unwrap();
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["fix", "-s", "@"]);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(redact(&stderr), @r#"
Warning: The `fix.tool-command` config option is deprecated and will be removed in a future version.
Hint: Replace it with the following:
[fix.tools.legacy-tool-command]
command = [<redacted formatter path>, "--stderr", "error", "--stdout", "new content", "--fail"]
patterns = ["all()"]
insta::assert_snapshot!(stderr, @r"
errorFixed 0 commits of 1 checked.
Nothing changed.
"#);
");
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "@"]);
insta::assert_snapshot!(content, @"old content");
}
@ -888,45 +744,37 @@ fn test_missing_command() {
let test_env = TestEnvironment::default();
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init", "repo"]);
let repo_path = test_env.env_root().join("repo");
test_env.add_config(r#"fix.tool-command = ["this_executable_shouldnt_exist"]"#);
test_env.add_config(indoc! {"
[fix.tools.bad-tool]
command = ['this_executable_shouldnt_exist']
patterns = ['all()']
"});
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["fix", "-s", "@"]);
insta::assert_snapshot!(stdout, @"");
// TODO: We should display a warning about invalid tool configurations. When we
// support multiple tools, we should also keep going to see if any of the other
// executions succeed.
insta::assert_snapshot!(stderr, @r###"
Warning: The `fix.tool-command` config option is deprecated and will be removed in a future version.
Hint: Replace it with the following:
[fix.tools.legacy-tool-command]
command = ["this_executable_shouldnt_exist"]
patterns = ["all()"]
insta::assert_snapshot!(stderr, @r"
Fixed 0 commits of 1 checked.
Nothing changed.
"###);
");
}
#[test]
fn test_fix_file_types() {
let (test_env, repo_path, redact) = init_with_fake_formatter(&["--uppercase"]);
let (test_env, repo_path) = init_with_fake_formatter(&["--uppercase"]);
std::fs::write(repo_path.join("file"), "content").unwrap();
std::fs::create_dir(repo_path.join("dir")).unwrap();
try_symlink("file", repo_path.join("link")).unwrap();
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["fix", "-s", "@"]);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(redact(&stderr), @r#"
Warning: The `fix.tool-command` config option is deprecated and will be removed in a future version.
Hint: Replace it with the following:
[fix.tools.legacy-tool-command]
command = [<redacted formatter path>, "--uppercase"]
patterns = ["all()"]
insta::assert_snapshot!(stderr, @r"
Fixed 1 commits of 1 checked.
Working copy now at: qpvuntsm 6836a9e4 (no description set)
Parent commit : zzzzzzzz 00000000 (empty) (no description set)
Added 0 files, modified 1 files, removed 0 files
"#);
");
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "@"]);
insta::assert_snapshot!(content, @"CONTENT");
}
@ -934,7 +782,7 @@ fn test_fix_file_types() {
#[cfg(unix)]
#[test]
fn test_fix_executable() {
let (test_env, repo_path, redact) = init_with_fake_formatter(&["--uppercase"]);
let (test_env, repo_path) = init_with_fake_formatter(&["--uppercase"]);
let path = repo_path.join("file");
std::fs::write(&path, "content").unwrap();
let mut permissions = std::fs::metadata(&path).unwrap().permissions();
@ -943,18 +791,12 @@ fn test_fix_executable() {
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["fix", "-s", "@"]);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(redact(&stderr), @r#"
Warning: The `fix.tool-command` config option is deprecated and will be removed in a future version.
Hint: Replace it with the following:
[fix.tools.legacy-tool-command]
command = [<redacted formatter path>, "--uppercase"]
patterns = ["all()"]
insta::assert_snapshot!(stderr, @r"
Fixed 1 commits of 1 checked.
Working copy now at: qpvuntsm fee78e99 (no description set)
Parent commit : zzzzzzzz 00000000 (empty) (no description set)
Added 0 files, modified 1 files, removed 0 files
"#);
");
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "@"]);
insta::assert_snapshot!(content, @"CONTENT");
let executable = std::fs::metadata(&path).unwrap().permissions().mode() & 0o111;
@ -965,7 +807,7 @@ fn test_fix_executable() {
fn test_fix_trivial_merge_commit() {
// All the changes are attributable to a parent, so none are fixed (in the same
// way that none would be shown in `jj diff -r @`).
let (test_env, repo_path, redact) = init_with_fake_formatter(&["--uppercase"]);
let (test_env, repo_path) = init_with_fake_formatter(&["--uppercase"]);
std::fs::write(repo_path.join("file_a"), "content a").unwrap();
std::fs::write(repo_path.join("file_c"), "content c").unwrap();
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "a"]);
@ -977,16 +819,10 @@ fn test_fix_trivial_merge_commit() {
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["fix", "-s", "@"]);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(redact(&stderr), @r#"
Warning: The `fix.tool-command` config option is deprecated and will be removed in a future version.
Hint: Replace it with the following:
[fix.tools.legacy-tool-command]
command = [<redacted formatter path>, "--uppercase"]
patterns = ["all()"]
insta::assert_snapshot!(stderr, @r"
Fixed 0 commits of 1 checked.
Nothing changed.
"#);
");
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file_a", "-r", "@"]);
insta::assert_snapshot!(content, @"content a");
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file_b", "-r", "@"]);
@ -999,7 +835,7 @@ fn test_fix_trivial_merge_commit() {
fn test_fix_adding_merge_commit() {
// None of the changes are attributable to a parent, so they are all fixed (in
// the same way that they would be shown in `jj diff -r @`).
let (test_env, repo_path, redact) = init_with_fake_formatter(&["--uppercase"]);
let (test_env, repo_path) = init_with_fake_formatter(&["--uppercase"]);
std::fs::write(repo_path.join("file_a"), "content a").unwrap();
std::fs::write(repo_path.join("file_c"), "content c").unwrap();
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "a"]);
@ -1015,19 +851,13 @@ fn test_fix_adding_merge_commit() {
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["fix", "-s", "@"]);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(redact(&stderr), @r#"
Warning: The `fix.tool-command` config option is deprecated and will be removed in a future version.
Hint: Replace it with the following:
[fix.tools.legacy-tool-command]
command = [<redacted formatter path>, "--uppercase"]
patterns = ["all()"]
insta::assert_snapshot!(stderr, @r"
Fixed 1 commits of 1 checked.
Working copy now at: mzvwutvl f93eb5a9 (no description set)
Parent commit : qpvuntsm 6e64e7a7 a | (no description set)
Parent commit : kkmpptxz c536f264 b | (no description set)
Added 0 files, modified 4 files, removed 0 files
"#);
");
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file_a", "-r", "@"]);
insta::assert_snapshot!(content, @"CHANGE A");
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file_b", "-r", "@"]);
@ -1040,7 +870,7 @@ fn test_fix_adding_merge_commit() {
#[test]
fn test_fix_both_sides_of_conflict() {
let (test_env, repo_path, redact) = init_with_fake_formatter(&["--uppercase"]);
let (test_env, repo_path) = init_with_fake_formatter(&["--uppercase"]);
std::fs::write(repo_path.join("file"), "content a\n").unwrap();
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "a"]);
test_env.jj_cmd_ok(&repo_path, &["new", "@-"]);
@ -1052,13 +882,7 @@ fn test_fix_both_sides_of_conflict() {
// fixed if we didn't fix the parents also.
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["fix", "-s", "a", "-s", "b"]);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(redact(&stderr), @r#"
Warning: The `fix.tool-command` config option is deprecated and will be removed in a future version.
Hint: Replace it with the following:
[fix.tools.legacy-tool-command]
command = [<redacted formatter path>, "--uppercase"]
patterns = ["all()"]
insta::assert_snapshot!(stderr, @r"
Fixed 3 commits of 3 checked.
Working copy now at: mzvwutvl a55c6ec2 (conflict) (empty) (no description set)
Parent commit : qpvuntsm 8e8aad69 a | (no description set)
@ -1066,7 +890,7 @@ fn test_fix_both_sides_of_conflict() {
Added 0 files, modified 1 files, removed 0 files
There are unresolved conflicts at these paths:
file 2-sided conflict
"#);
");
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "a"]);
insta::assert_snapshot!(content, @r###"
CONTENT A
@ -1090,7 +914,7 @@ fn test_fix_both_sides_of_conflict() {
fn test_fix_resolve_conflict() {
// If both sides of the conflict look the same after being fixed, the conflict
// will be resolved.
let (test_env, repo_path, redact) = init_with_fake_formatter(&["--uppercase"]);
let (test_env, repo_path) = init_with_fake_formatter(&["--uppercase"]);
std::fs::write(repo_path.join("file"), "Content\n").unwrap();
test_env.jj_cmd_ok(&repo_path, &["bookmark", "create", "a"]);
test_env.jj_cmd_ok(&repo_path, &["new", "@-"]);
@ -1102,19 +926,13 @@ fn test_fix_resolve_conflict() {
// fixed if we didn't fix the parents also.
let (stdout, stderr) = test_env.jj_cmd_ok(&repo_path, &["fix", "-s", "a", "-s", "b"]);
insta::assert_snapshot!(stdout, @"");
insta::assert_snapshot!(redact(&stderr), @r#"
Warning: The `fix.tool-command` config option is deprecated and will be removed in a future version.
Hint: Replace it with the following:
[fix.tools.legacy-tool-command]
command = [<redacted formatter path>, "--uppercase"]
patterns = ["all()"]
insta::assert_snapshot!(stderr, @r"
Fixed 3 commits of 3 checked.
Working copy now at: mzvwutvl 50fd048d (empty) (no description set)
Parent commit : qpvuntsm dd2721f1 a | (no description set)
Parent commit : kkmpptxz 07c27a8e b | (no description set)
Added 0 files, modified 1 files, removed 0 files
"#);
");
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "file", "-r", "@"]);
insta::assert_snapshot!(content, @r###"
CONTENT