mirror of
https://github.com/martinvonz/jj.git
synced 2025-02-01 00:50:57 +00:00
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:
parent
a9694cba27
commit
30984dae4a
5 changed files with 33 additions and 25 deletions
|
@ -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
|
* `jj status` now supports filtering by paths. For example, `jj status .` will
|
||||||
only list changed files that are descendants of the current directory.
|
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
|
* A new config option `ui.allow-filesets` has been added to enable ["fileset"
|
||||||
syntax](docs/filesets.md#file-patterns).
|
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.
|
* `jj prev` and `jj next` now work when the working copy revision is a merge.
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ use indexmap::{IndexMap, IndexSet};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use jj_lib::backend::{ChangeId, CommitId, MergedTreeId, TreeValue};
|
use jj_lib::backend::{ChangeId, CommitId, MergedTreeId, TreeValue};
|
||||||
use jj_lib::commit::Commit;
|
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::git_backend::GitBackend;
|
||||||
use jj_lib::gitignore::{GitIgnoreError, GitIgnoreFile};
|
use jj_lib::gitignore::{GitIgnoreError, GitIgnoreFile};
|
||||||
use jj_lib::hex_util::to_reverse_hex;
|
use jj_lib::hex_util::to_reverse_hex;
|
||||||
|
@ -657,14 +657,7 @@ impl WorkspaceCommandHelper {
|
||||||
if values.is_empty() {
|
if values.is_empty() {
|
||||||
Ok(FilesetExpression::all())
|
Ok(FilesetExpression::all())
|
||||||
} else if self.settings.config().get_bool("ui.allow-filesets")? {
|
} else if self.settings.config().get_bool("ui.allow-filesets")? {
|
||||||
let ctx = self.fileset_parse_context();
|
self.parse_union_filesets(values)
|
||||||
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))
|
|
||||||
} else {
|
} else {
|
||||||
let expressions = values
|
let expressions = values
|
||||||
.iter()
|
.iter()
|
||||||
|
|
|
@ -825,15 +825,26 @@ fn test_log_filtered_by_path() {
|
||||||
// Fileset/pattern syntax is disabled by default.
|
// Fileset/pattern syntax is disabled by default.
|
||||||
let stderr = test_env.jj_cmd_failure(
|
let stderr = test_env.jj_cmd_failure(
|
||||||
test_env.env_root(),
|
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###"
|
insta::assert_snapshot!(stderr.replace('\\', "/"), @r###"
|
||||||
Error: Path "root:file1" is not in the repo "repo"
|
Error: Path "all()" is not in the repo "repo"
|
||||||
Caused by: Invalid component ".." in repo-relative path "../root:file1"
|
Caused by: Invalid component ".." in repo-relative path "../all()"
|
||||||
"###);
|
"###);
|
||||||
|
|
||||||
test_env.add_config("ui.allow-filesets = true");
|
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.
|
// "root:<path>" is resolved relative to the workspace root.
|
||||||
let stdout = test_env.jj_cmd_success(
|
let stdout = test_env.jj_cmd_success(
|
||||||
test_env.env_root(),
|
test_env.env_root(),
|
||||||
|
|
|
@ -42,3 +42,17 @@ You can also specify patterns by using functions.
|
||||||
|
|
||||||
* `all()`: Matches everything.
|
* `all()`: Matches everything.
|
||||||
* `none()`: Matches nothing.
|
* `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'
|
||||||
|
```
|
||||||
|
|
|
@ -60,17 +60,6 @@ pub enum FilePattern {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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`.
|
/// Parses the given `input` string as pattern of the specified `kind`.
|
||||||
pub fn from_str_kind(
|
pub fn from_str_kind(
|
||||||
ctx: &FilesetParseContext,
|
ctx: &FilesetParseContext,
|
||||||
|
|
Loading…
Reference in a new issue