Merge pull request #5870 from dolthub/nicktobey/doltignore

Improve dolt_ignore pattern rules
This commit is contained in:
Nick Tobey
2023-05-05 15:14:41 -07:00
committed by GitHub
2 changed files with 50 additions and 2 deletions

View File

@@ -110,6 +110,7 @@ func compilePattern(pattern string) (*regexp.Regexp, error) {
pattern = "^" + regexp.QuoteMeta(pattern) + "$"
pattern = strings.Replace(pattern, "\\?", ".", -1)
pattern = strings.Replace(pattern, "\\*", ".*", -1)
pattern = strings.Replace(pattern, "%", ".*", -1)
return regexp.Compile(pattern)
}
@@ -118,12 +119,29 @@ func compilePattern(pattern string) (*regexp.Regexp, error) {
// match pattern B, but not vice versa.)
func getMoreSpecificPatterns(lessSpecific string) (*regexp.Regexp, error) {
pattern := "^" + regexp.QuoteMeta(lessSpecific) + "$"
// A ? can expand to any character except for a *, since that also has special meaning in patterns.
pattern = strings.Replace(pattern, "\\?", "[^\\*]", -1)
// A ? can expand to any character except for a * or %, since that also has special meaning in patterns.
pattern = strings.Replace(pattern, "\\?", "[^\\*%]", -1)
pattern = strings.Replace(pattern, "\\*", ".*", -1)
pattern = strings.Replace(pattern, "%", ".*", -1)
return regexp.Compile(pattern)
}
// normalizePattern generates an equivalent pattern, such that all equivalent patterns have the same normalized pattern.
// It accomplishes this by replacing all * with %, and removing multiple adjacent %.
// This will get a lot harder to implement once we support escaped characters in patterns.
func normalizePattern(pattern string) string {
pattern = strings.Replace(pattern, "*", "%", -1)
for {
newPattern := strings.Replace(pattern, "%%", "%", -1)
if newPattern == pattern {
break
}
pattern = newPattern
}
return pattern
}
func resolveConflictingPatterns(trueMatches, falseMatches []string, tableName string) (IgnoreResult, error) {
trueMatchesToRemove := map[string]struct{}{}
falseMatchesToRemove := map[string]struct{}{}
@@ -133,6 +151,9 @@ func resolveConflictingPatterns(trueMatches, falseMatches []string, tableName st
return ErrorOccurred, err
}
for _, falseMatch := range falseMatches {
if normalizePattern(trueMatch) == normalizePattern(falseMatch) {
return IgnorePatternConflict, DoltIgnoreConflictError{Table: tableName, TruePatterns: []string{trueMatch}, FalsePatterns: []string{falseMatch}}
}
if trueMatchRegExp.MatchString(falseMatch) {
trueMatchesToRemove[trueMatch] = struct{}{}
}

View File

@@ -12,6 +12,8 @@ INSERT INTO dolt_ignore VALUES
("*_ignore", true),
("do_not_ignore", false),
("%_ignore_too", true),
("commit_*", false),
("commit_me_not", true),
@@ -85,6 +87,7 @@ SQL
dolt sql <<SQL
CREATE TABLE please_ignore (pk int);
CREATE TABLE please_ignore_too (pk int);
CREATE TABLE do_not_ignore (pk int);
CREATE TABLE commit_me (pk int);
CREATE TABLE commit_me_not(pk int);
@@ -96,6 +99,7 @@ SQL
staged=$(get_staged_tables)
[[ ! -z $(echo "$ignored" | grep "please_ignore") ]] || false
[[ ! -z $(echo "$ignored" | grep "please_ignore_too") ]] || false
[[ ! -z $(echo "$staged" | grep "do_not_ignore") ]] || false
[[ ! -z $(echo "$staged" | grep "commit_me") ]] || false
[[ ! -z $(echo "$ignored" | grep "commit_me_not") ]] || false
@@ -375,4 +379,27 @@ SQL
echo "$output"
[[ "$output" =~ "ignoreme" ]] || false
}
@test "ignore: detect when equivalent patterns have different values" {
skip_nbf_ld_1
dolt sql <<SQL
INSERT INTO dolt_ignore VALUES
("**_test", true),
("*_test", false),
("*_foo", true),
("%_foo", false);
CREATE TABLE a_test (pk int);
CREATE TABLE a_foo (pk int);
SQL
conflict=$(get_conflict_tables)
echo "$conflict"
[[ ! -z $(echo "$conflict" | grep "a_test") ]] || false
[[ ! -z $(echo "$conflict" | grep "a_foo") ]] || false
}