revset: add support for file(kind:pattern) syntax

There are no more callers of parse_function_argument_to_string(), so it's
removed. This function was a thin wrapper of literal parser, and can be
easily reintroduced if needed.
This commit is contained in:
Yuya Nishihara 2024-04-05 22:04:32 +09:00
parent 850887cf09
commit 8b32a8a916
4 changed files with 42 additions and 23 deletions

View file

@ -70,6 +70,6 @@ tags()+++::
merges()
~merges()
# These are unbearably slow, so only filter within small set
file(Makefile) & v1.0.0..v1.2.0
file(root:"Makefile") & v1.0.0..v1.2.0
empty() & v1.0.0..v1.2.0
conflict() & v1.0.0..v1.2.0

View file

@ -152,15 +152,28 @@ fn test_bad_function_call() {
= Function "file": Expected at least 1 argument
"###);
let stderr = test_env.jj_cmd_failure(&repo_path, &["log", "-r", "file(a, not:a-string)"]);
let stderr = test_env.jj_cmd_failure(&repo_path, &["log", "-r", "file(a, not@a-string)"]);
insta::assert_snapshot!(stderr, @r###"
Error: Failed to parse revset: Function "file": Expected function argument of type string
Error: Failed to parse revset: Function "file": Expected function argument of file pattern
Caused by: --> 1:9
|
1 | file(a, not:a-string)
1 | file(a, not@a-string)
| ^----------^
|
= Function "file": Expected function argument of type string
= Function "file": Expected function argument of file pattern
"###);
let stderr = test_env.jj_cmd_failure(&repo_path, &["log", "-r", r#"file(foo:"bar")"#]);
insta::assert_snapshot!(stderr, @r###"
Error: Failed to parse revset: Function "file": Invalid file pattern
Caused by:
1: --> 1:6
|
1 | file(foo:"bar")
| ^-------^
|
= Function "file": Invalid file pattern
2: Invalid file pattern kind "foo:"
"###);
let stderr = test_env.jj_cmd_failure(&repo_path, &["log", "-r", r#"file(a, "../out")"#]);

View file

@ -156,9 +156,8 @@ given [string pattern](#string-patterns).
* `empty()`: Commits modifying no files. This also includes `merges()` without
user modifications and `root()`.
* `file(relativepath)` or `file("relativepath"[, "relativepath"]...)`: Commits
modifying one of the paths specified. Currently, string patterns are *not*
supported in the path arguments.
* `file(pattern[, pattern]...)`: Commits modifying paths matching one of the
given [file patterns](filesets.md#file-patterns).
Paths are relative to the directory `jj` was invoked from. A directory name
will match all files in that directory and its subdirectories.

View file

@ -33,13 +33,12 @@ use thiserror::Error;
use crate::backend::{BackendError, BackendResult, ChangeId, CommitId};
use crate::commit::Commit;
use crate::fileset::FilesetExpression;
use crate::fileset::{FilePattern, FilesetExpression, FilesetParseContext};
use crate::git;
use crate::hex_util::to_forward_hex;
use crate::object_id::{HexPrefix, PrefixResolution};
use crate::op_store::WorkspaceId;
use crate::repo::Repo;
use crate::repo_path::RepoPathBuf;
use crate::revset_graph::RevsetGraphEdge;
use crate::store::Store;
use crate::str_util::StringPattern;
@ -1339,18 +1338,14 @@ static BUILTIN_FUNCTION_MAP: Lazy<HashMap<&'static str, RevsetFunction>> = Lazy:
map.insert("file", |name, arguments_pair, state| {
let arguments_span = arguments_pair.as_span();
if let Some(ctx) = state.workspace_ctx {
let ctx = FilesetParseContext {
cwd: ctx.cwd,
workspace_root: ctx.workspace_root,
};
let file_expressions: Vec<_> = arguments_pair
.into_inner()
.map(|arg| -> Result<_, RevsetParseError> {
let span = arg.as_span();
let needle = parse_function_argument_to_string(name, arg, state)?;
let path = RepoPathBuf::parse_fs_path(ctx.cwd, ctx.workspace_root, needle)
.map_err(|e| {
RevsetParseError::invalid_arguments(name, "Invalid file pattern", span)
.with_source(e)
})?;
Ok(FilesetExpression::prefix_path(path))
})
.map(|arg| parse_function_argument_to_file_pattern(name, arg, state, &ctx))
.map_ok(FilesetExpression::pattern)
.try_collect()?;
if file_expressions.is_empty() {
Err(RevsetParseError::invalid_arguments(
@ -1497,12 +1492,17 @@ fn expect_named_arguments_vec<'i>(
Ok((required, optional))
}
fn parse_function_argument_to_string(
fn parse_function_argument_to_file_pattern(
name: &str,
pair: Pair<Rule>,
state: ParseState,
) -> Result<String, RevsetParseError> {
parse_function_argument_as_literal("string", name, pair, state)
ctx: &FilesetParseContext,
) -> Result<FilePattern, RevsetParseError> {
let parse_pattern = |value: &str, kind: Option<&str>| match kind {
Some(kind) => FilePattern::from_str_kind(ctx, value, kind),
None => FilePattern::cwd_prefix_path(ctx, value),
};
parse_function_argument_as_pattern("file pattern", name, pair, state, parse_pattern)
}
fn parse_function_argument_to_string_pattern(
@ -2587,6 +2587,7 @@ mod tests {
use assert_matches::assert_matches;
use super::*;
use crate::repo_path::RepoPathBuf;
fn parse(revset_str: &str) -> Result<Rc<RevsetExpression>, RevsetParseErrorKind> {
parse_with_aliases(revset_str, [] as [(&str, &str); 0])
@ -3343,6 +3344,12 @@ mod tests {
FilesetExpression::prefix_path(RepoPathBuf::from_internal_string("foo"))
)))
);
assert_eq!(
parse_with_workspace(r#"file(file:"foo")"#, &WorkspaceId::default()),
Ok(RevsetExpression::filter(RevsetFilterPredicate::File(
FilesetExpression::file_path(RepoPathBuf::from_internal_string("foo"))
)))
);
assert_eq!(
parse_with_workspace("file(foo, bar, baz)", &WorkspaceId::default()),
Ok(RevsetExpression::filter(RevsetFilterPredicate::File(