forked from canonical/snapd
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
i/prompting: implement path pattern matching (canonical#13866)
Path pattern matching is implemented via the doublestar package, which emulates bash's globstar matching. Patterns may include '*' wildcard characters (which match any number of non-separator characters), '**' doublestars (which match zero or more subdirectories), '?' wildcard characters (which match exactly one non-separator character), and nested groups delimited by '{' and '}'. Notably, path patterns are *not* allowed to have character classes delimited by '[' and ']', nor inverted classes of the form "[^abc]". There is a limit on the number of groups allowed in path patterns, but up to that limit, groups may be arbitrarily nested or sequential. Signed-off-by: Oliver Calder <[email protected]> i/prompting: fix typo and add notes to remove test boilerplate Signed-off-by: Oliver Calder <[email protected]> i/prompting: use separate test suite for patterns Signed-off-by: Oliver Calder <[email protected]> i/prompting: improve unit test coverage Signed-off-by: Oliver Calder <[email protected]> * i/prompting: count and validate true number of expanded patterns Rather than counting the number of groups and using it as a heuristic for the number of patterns into which a given path pattern will expand, instead compute the true number of expanded patterns and compare it against a set limit. Signed-off-by: Oliver Calder <[email protected]> * i/prompting: implement path pattern checks in constraints Signed-off-by: Oliver Calder <[email protected]> * i/prompting: throw error if group depth exceeds maximum expanded patterns Signed-off-by: Oliver Calder <[email protected]> * packaging: add doublestar dependency for prompting pattern matching Signed-off-by: Oliver Calder <[email protected]> * i/prompting: remove standalone path pattern validation Signed-off-by: Oliver Calder <[email protected]> --------- Signed-off-by: Oliver Calder <[email protected]>
- Loading branch information
1 parent
8128ed2
commit 6905775
Showing
8 changed files
with
460 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
// -*- Mode: Go; indent-tabs-mode: t -*- | ||
|
||
/* | ||
* Copyright (C) 2024 Canonical Ltd | ||
* | ||
* This program is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License version 3 as | ||
* published by the Free Software Foundation. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
* | ||
*/ | ||
|
||
package prompting | ||
|
||
import ( | ||
"strings" | ||
|
||
doublestar "github.com/bmatcuk/doublestar/v4" | ||
) | ||
|
||
// PathPatternMatch returns true if the given pattern matches the given path. | ||
// | ||
// The pattern should not contain groups, and should likely have been an output | ||
// of ExpandPathPattern. | ||
// | ||
// Paths to directories are received with trailing slashes, but we don't want | ||
// to require the user to include a trailing '/' if they want to match | ||
// directories (and end their pattern with `{,/}` if they want to match both | ||
// directories and non-directories). Thus, we want to ensure that patterns | ||
// without trailing slashes match paths with trailing slashes. However, | ||
// patterns with trailing slashes should not match paths without trailing | ||
// slashes. | ||
// | ||
// The doublestar package has special cases for patterns ending in `/**` and | ||
// `/**/`: `/foo/**`, and `/foo/**/` both match `/foo` and `/foo/`. We want to | ||
// override this behavior to make `/foo/**/` not match `/foo`. We also want to | ||
// override doublestar to make `/foo` match `/foo/`. | ||
func PathPatternMatch(pattern string, path string) (bool, error) { | ||
// Check the usual doublestar match first, in case the pattern is malformed | ||
// and causes an error, and return the error if so. | ||
matched, err := doublestar.Match(pattern, path) | ||
if err != nil { | ||
return false, err | ||
} | ||
// No matter if doublestar matched, return false if pattern ends in '/' but | ||
// path is not a directory. | ||
if strings.HasSuffix(pattern, "/") && !strings.HasSuffix(path, "/") { | ||
return false, nil | ||
} | ||
if matched { | ||
return true, nil | ||
} | ||
if strings.HasSuffix(pattern, "/") { | ||
return false, nil | ||
} | ||
// Try again with a '/' appended to the pattern, so patterns like `/foo` | ||
// match paths like `/foo/`. | ||
return doublestar.Match(pattern+"/", path) | ||
} |
Oops, something went wrong.