Skip to content

Commit

Permalink
cli: if enabled, parse path arguments as fileset expressions
Browse files Browse the repository at this point in the history
If this doesn't work out, maybe we can try one of these:
 a. fall back to bare file name if expression doesn't contain any operator-like
    characters (e.g. "f(x" is an error, but "f x" can be parsed as bare string)
 b. introduce command-line flag to opt in (e.g. -e FILESET)
 c. introduce pattern prefix to opt in (e.g. set:FILESET)

Closes #3239, #2915, #2286
  • Loading branch information
yuja committed Apr 12, 2024
1 parent a9694cb commit 30984da
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 25 deletions.
5 changes: 3 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* `jj status` now supports filtering by paths. For example, `jj status .` will
only list changed files that are descendants of the current directory.

* A new config option `ui.allow-filesets` has been added to enable [file pattern
syntax](docs/filesets.md#file-patterns).
* A new config option `ui.allow-filesets` has been added to enable ["fileset"
expressions](docs/filesets.md). Note that filesets are currently experimental,
but will be enabled by default in a future release.

* `jj prev` and `jj next` now work when the working copy revision is a merge.

Expand Down
11 changes: 2 additions & 9 deletions cli/src/cli_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ use indexmap::{IndexMap, IndexSet};
use itertools::Itertools;
use jj_lib::backend::{ChangeId, CommitId, MergedTreeId, TreeValue};
use jj_lib::commit::Commit;
use jj_lib::fileset::{FilePattern, FilesetExpression, FilesetParseContext};
use jj_lib::fileset::{FilesetExpression, FilesetParseContext};
use jj_lib::git_backend::GitBackend;
use jj_lib::gitignore::{GitIgnoreError, GitIgnoreFile};
use jj_lib::hex_util::to_reverse_hex;
Expand Down Expand Up @@ -657,14 +657,7 @@ impl WorkspaceCommandHelper {
if values.is_empty() {
Ok(FilesetExpression::all())
} else if self.settings.config().get_bool("ui.allow-filesets")? {
let ctx = self.fileset_parse_context();
let expressions = values
.iter()
.map(|v| FilePattern::parse(&ctx, v))
.map_ok(FilesetExpression::pattern)
.try_collect()
.map_err(user_error)?;
Ok(FilesetExpression::union_all(expressions))
self.parse_union_filesets(values)
} else {
let expressions = values
.iter()
Expand Down
17 changes: 14 additions & 3 deletions cli/tests/test_log_command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -825,15 +825,26 @@ fn test_log_filtered_by_path() {
// Fileset/pattern syntax is disabled by default.
let stderr = test_env.jj_cmd_failure(
test_env.env_root(),
&["log", "-R", repo_path.to_str().unwrap(), "root:file1"],
&["log", "-R", repo_path.to_str().unwrap(), "all()"],
);
insta::assert_snapshot!(stderr.replace('\\', "/"), @r###"
Error: Path "root:file1" is not in the repo "repo"
Caused by: Invalid component ".." in repo-relative path "../root:file1"
Error: Path "all()" is not in the repo "repo"
Caused by: Invalid component ".." in repo-relative path "../all()"
"###);

test_env.add_config("ui.allow-filesets = true");

// empty revisions are filtered out by "all()" fileset.
let stdout = test_env.jj_cmd_success(&repo_path, &["log", "-Tdescription", "-s", "all()"]);
insta::assert_snapshot!(stdout, @r###"
@ second
│ M file1
│ A file2
◉ first
│ A file1
~
"###);

// "root:<path>" is resolved relative to the workspace root.
let stdout = test_env.jj_cmd_success(
test_env.env_root(),
Expand Down
14 changes: 14 additions & 0 deletions docs/filesets.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,17 @@ You can also specify patterns by using functions.

* `all()`: Matches everything.
* `none()`: Matches nothing.

## Examples

Show diff excluding `Cargo.lock`.

```
jj diff '~Cargo.lock'
```

Split a revision in two, putting `foo` into the second commit.

```
jj split '~foo'
```
11 changes: 0 additions & 11 deletions lib/src/fileset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,17 +60,6 @@ pub enum FilePattern {
}

impl FilePattern {
/// Parses the given `input` string as a file pattern.
// TODO: If we decide to parse any file argument as a fileset expression,
// this function can be removed.
pub fn parse(ctx: &FilesetParseContext, input: &str) -> Result<Self, FilePatternParseError> {
if let Some((kind, pat)) = input.split_once(':') {
Self::from_str_kind(ctx, pat, kind)
} else {
Self::cwd_prefix_path(ctx, input)
}
}

/// Parses the given `input` string as pattern of the specified `kind`.
pub fn from_str_kind(
ctx: &FilesetParseContext,
Expand Down

0 comments on commit 30984da

Please sign in to comment.