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 Sep 6, 2024
1 parent 6f44ed4 commit 9ca3ead
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 2 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

### New features

* Fix tools have a new config `fix.tools.NAME.enabled` which can be
used to disable or re-enable the tool.

### Fixed bugs

## [0.21.0] - 2024-09-04
Expand Down
15 changes: 13 additions & 2 deletions cli/src/commands/fix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,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 @@ -423,6 +426,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 @@ -465,8 +474,10 @@ fn get_tools_config(ui: &mut Ui, config: &config::Config) -> Result<ToolsConfig,
let mut tools: Vec<ToolConfig> = tools_table
.into_iter()
.sorted_by(|a, b| a.0.cmp(&b.0))
.map(|(_name, value)| -> Result<ToolConfig, CommandError> {
let tool: RawToolConfig = value.try_deserialize()?;
.map(|(_name, value): (_, _)| value.try_deserialize::<RawToolConfig>())
.filter_ok(|tool| tool.enabled)
.map(|tool| -> Result<ToolConfig, CommandError> {
let tool = tool?;
Ok(ToolConfig {
command: tool.command,
matcher: FilesetExpression::union_all(
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 @@ -553,6 +553,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 @@ -820,6 +820,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 @@ -192,6 +192,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 @@ -769,6 +769,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 9ca3ead

Please sign in to comment.