Skip to content

Commit

Permalink
revset: add support for glob:pattern
Browse files Browse the repository at this point in the history
  • Loading branch information
yuja committed Oct 21, 2023
1 parent f7c8622 commit cfcc765
Show file tree
Hide file tree
Showing 6 changed files with 27 additions and 1 deletion.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions docs/revsets.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
1 change: 1 addition & 0 deletions lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
Expand Down
18 changes: 17 additions & 1 deletion lib/src/str_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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),
}
Expand All @@ -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())),
}
Expand All @@ -59,14 +74,15 @@ impl StringPattern {
pub fn as_exact(&self) -> Option<&str> {
match self {
StringPattern::Exact(literal) => Some(literal),
StringPattern::Substring(_) => None,
StringPattern::Glob(_) | StringPattern::Substring(_) => None,
}
}

/// Returns true if this pattern matches the `haystack`.
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),
}
}
Expand Down
4 changes: 4 additions & 0 deletions lib/tests/test_revset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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!(
Expand Down

0 comments on commit cfcc765

Please sign in to comment.