Skip to content

Commit

Permalink
fix: Add enabled config for fix tools
Browse files Browse the repository at this point in the history
Adds an optional `fix.tools.TOOL.enabled` config that disables use of a fix
tool (if omitted, the tool is enabled). This is useful for defining tools in
the user's configuration without enabling them for all repositories:

```toml
# ~/.jjconfig.toml
[fix.tools.rustfmt]
enabled = false
command = ["rustfmt", "--emit", "stdout"]
patterns = ["glob:'**/*.rs'"]
```

Then to enable it in a repository:

```shell
$ jj config set --repo fix.tools.rustfmt.enabled true
```

This also allows Jujutsu to ship some built-in tool configurations that are
disabled by default.
  • Loading branch information
jennings committed Dec 30, 2024
1 parent 8d56074 commit 4f76320
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 2 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
below it, similar to a "scissor line" in git. When editing multiple commits,
only ignore until the next `JJ: describe` line.

* `enabled`: Enables or disables the tool. If omitted, the tool is enabled.
This is useful for defining disabled tools in user configuration that can be
enabled in individual repositories with one config setting.

### Fixed bugs

* The `$NO_COLOR` environment variable must now be non-empty to be respected.
Expand Down
22 changes: 20 additions & 2 deletions cli/src/commands/fix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ use crate::ui::Ui;
/// empty, no files will be affected by the tool. If there are multiple
/// patterns, the tool is applied only once to each file in the union of the
/// patterns.
/// - `enabled`: Enables or disables the tool. If omitted, the tool is enabled.
/// This is useful for defining disabled tools in user configuration that can
/// be enabled in individual repositories with one config setting.
///
/// For example, the following configuration defines how two code formatters
/// (`clang-format` and `black`) will apply to three different file extensions
Expand Down Expand Up @@ -440,6 +443,12 @@ struct ToolsConfig {
struct RawToolConfig {
command: CommandNameAndArgs,
patterns: Vec<String>,
#[serde(default = "default_tool_enabled")]
enabled: bool,
}

fn default_tool_enabled() -> bool {
true
}

/// Parses the `fix.tools` config table.
Expand Down Expand Up @@ -484,9 +493,18 @@ fn get_tools_config(ui: &mut Ui, settings: &UserSettings) -> Result<ToolsConfig,
.table_keys("fix.tools")
// Sort keys early so errors are deterministic.
.sorted()
.map(|name| -> Result<ToolConfig, CommandError> {
.filter_map(
|name| -> Option<Result<(RawToolConfig, &str), CommandError>> {
match settings.get::<RawToolConfig>(["fix", "tools", name]) {
Ok(tool) if tool.enabled => Some(Ok((tool, name))),
Ok(_) => None,
Err(err) => Some(Err(err.into())),
}
},
)
.map(|r| -> Result<ToolConfig, CommandError> {
let (tool, name) = r?;
let mut diagnostics = FilesetDiagnostics::new();
let tool: RawToolConfig = settings.get(["fix", "tools", name])?;
let expression = FilesetExpression::union_all(
tool.patterns
.iter()
Expand Down
5 changes: 5 additions & 0 deletions cli/src/config-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,11 @@
"type": "string"
},
"description": "Filesets that will be affected by this tool"
},
"enabled": {
"type": "boolean",
"description": "Disables this tool if set to false",
"default": true
}
}
},
Expand Down
3 changes: 3 additions & 0 deletions cli/tests/[email protected]
Original file line number Diff line number Diff line change
Expand Up @@ -985,6 +985,9 @@ the values have the following properties:
empty, no files will be affected by the tool. If there are multiple
patterns, the tool is applied only once to each file in the union of the
patterns.
- `enabled`: Enables or disables the tool. If omitted, the tool is enabled.
This is useful for defining disabled tools in user configuration that can
be enabled in individual repositories with one config setting.
For example, the following configuration defines how two code formatters
(`clang-format` and `black`) will apply to three different file extensions
Expand Down
42 changes: 42 additions & 0 deletions cli/tests/test_fix_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,48 @@ fn test_config_multiple_tools_with_same_name() {
insta::assert_snapshot!(content, @"Bar\n");
}

#[test]
fn test_config_disabled_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 escaped_formatter_path = formatter_path.to_str().unwrap().replace('\\', r"\\");
test_env.add_config(format!(
r###"
[fix.tools.tool-1]
# default is enabled
command = ["{formatter}", "--uppercase"]
patterns = ["foo"]
[fix.tools.tool-2]
enabled = true
command = ["{formatter}", "--lowercase"]
patterns = ["bar"]
[fix.tools.tool-3]
enabled = false
command = ["{formatter}", "--lowercase"]
patterns = ["baz"]
"###,
formatter = escaped_formatter_path.as_str()
));

std::fs::write(repo_path.join("foo"), "Foo\n").unwrap();
std::fs::write(repo_path.join("bar"), "Bar\n").unwrap();
std::fs::write(repo_path.join("baz"), "Baz\n").unwrap();

let (_stdout, _stderr) = test_env.jj_cmd_ok(&repo_path, &["fix"]);

let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "foo", "-r", "@"]);
insta::assert_snapshot!(content, @"FOO\n");
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "bar", "-r", "@"]);
insta::assert_snapshot!(content, @"bar\n");
let content = test_env.jj_cmd_success(&repo_path, &["file", "show", "baz", "-r", "@"]);
insta::assert_snapshot!(content, @"Baz\n");
}

#[test]
fn test_config_tables_overlapping_patterns() {
let test_env = TestEnvironment::default();
Expand Down
21 changes: 21 additions & 0 deletions docs/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -960,6 +960,27 @@ command = ["head", "-n", "10"]
patterns = ["numbers.txt"]
```

### Disabling and enabling tools

Tools can be disabled and enabled with the optional `enabled` config. This
allows you to define tools globally but enable them only for specific
repositories.

In the user configuration, define a disabled tool for running rustfmt:

```toml
[fix.tools.rustfmt]
enabled = false
command = ["rustfmt", "--emit", "stdout"]
patterns = ["glob:'**/*.rs'"]
```

Then to use the tool in a specific repository, set the `enabled` config:

```shell
$ jj config set --repo fix.tools.rustfmt.enabled true
```

## Commit Signing

`jj` can be configured to sign and verify the commits it creates using either
Expand Down

0 comments on commit 4f76320

Please sign in to comment.