ok/jj
1
0
Fork 0
forked from mirrors/jj

cli: if enabled, parse path arguments as fileset expressions

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
This commit is contained in:
Yuya Nishihara 2024-04-08 16:43:18 +09:00
parent a9694cba27
commit 30984dae4a
5 changed files with 33 additions and 25 deletions

View file

@ -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.

View file

@ -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;
@ -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()

View file

@ -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(),

View file

@ -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'
```

View file

@ -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,