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

revset: add support for glob:pattern

This commit is contained in:
Yuya Nishihara 2023-10-20 02:46:26 +09:00
parent f7c8622981
commit cfcc76571c
6 changed files with 27 additions and 1 deletions

View file

@ -53,6 +53,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* `jj workspace forget` can now forget multiple workspaces at once.
* `branches()`/`remote_branches()`/`author()`/`committer()`/`description()`
revsets now support glob matching.
### Fixed bugs
* Updating the working copy to a commit where a file that's currently ignored

1
Cargo.lock generated
View file

@ -1051,6 +1051,7 @@ dependencies = [
"esl01-renderdag",
"futures 0.3.28",
"git2",
"glob",
"hex",
"insta",
"itertools 0.11.0",

View file

@ -145,6 +145,7 @@ Functions that perform string matching support the following pattern syntax.
* `"string"`, `substring:"string"`: Matches strings that contain `string`.
* `exact:"string"`: Matches strings exactly equal to `string`.
* `glob:"pattern"`: Matches strings with Unix-style shell wildcard `pattern`.
## Aliases

View file

@ -30,6 +30,7 @@ digest = { workspace = true }
futures = { workspace = true }
either = { workspace = true }
git2 = { workspace = true }
glob = { workspace = true }
hex = { workspace = true }
itertools = { workspace = true }
maplit = { workspace = true }

View file

@ -26,6 +26,9 @@ pub enum StringPatternParseError {
/// Unknown pattern kind is specified.
#[error(r#"Invalid string pattern kind "{0}""#)]
InvalidKind(String),
/// Failed to parse glob pattern.
#[error(transparent)]
GlobPattern(glob::PatternError),
}
/// Pattern to be tested against string property like commit description or
@ -34,6 +37,8 @@ pub enum StringPatternParseError {
pub enum StringPattern {
/// Matches strings exactly equal to `string`.
Exact(String),
/// Unix-style shell wildcard pattern.
Glob(glob::Pattern),
/// Matches strings that contain `substring`.
Substring(String),
}
@ -44,10 +49,20 @@ impl StringPattern {
StringPattern::Substring(String::new())
}
/// Parses the given string as glob pattern.
pub fn glob(src: &str) -> Result<Self, StringPatternParseError> {
// TODO: might be better to do parsing and compilation separately since
// not all backends would use the compiled pattern object.
// TODO: if no meta character found, it can be mapped to Exact.
let pattern = glob::Pattern::new(src).map_err(StringPatternParseError::GlobPattern)?;
Ok(StringPattern::Glob(pattern))
}
/// Parses the given string as pattern of the specified `kind`.
pub fn from_str_kind(src: &str, kind: &str) -> Result<Self, StringPatternParseError> {
match kind {
"exact" => Ok(StringPattern::Exact(src.to_owned())),
"glob" => StringPattern::glob(src),
"substring" => Ok(StringPattern::Substring(src.to_owned())),
_ => Err(StringPatternParseError::InvalidKind(kind.to_owned())),
}
@ -59,7 +74,7 @@ impl StringPattern {
pub fn as_exact(&self) -> Option<&str> {
match self {
StringPattern::Exact(literal) => Some(literal),
StringPattern::Substring(_) => None,
StringPattern::Glob(_) | StringPattern::Substring(_) => None,
}
}
@ -67,6 +82,7 @@ impl StringPattern {
pub fn matches(&self, haystack: &str) -> bool {
match self {
StringPattern::Exact(literal) => haystack == literal,
StringPattern::Glob(pattern) => pattern.matches(haystack),
StringPattern::Substring(needle) => haystack.contains(needle),
}
}

View file

@ -1775,6 +1775,10 @@ fn test_evaluate_expression_branches() {
resolve_commit_ids(mut_repo, "branches(exact:branch1)"),
vec![commit1.id().clone()]
);
assert_eq!(
resolve_commit_ids(mut_repo, r#"branches(glob:"branch?")"#),
vec![commit2.id().clone(), commit1.id().clone()]
);
// Can silently resolve to an empty set if there's no matches
assert_eq!(resolve_commit_ids(mut_repo, "branches(branch3)"), vec![]);
assert_eq!(