diff --git a/tools/cmd/diff/collect.go b/tools/cmd/diff/collect.go index 9e656f0e5..5e5dd84aa 100644 --- a/tools/cmd/diff/collect.go +++ b/tools/cmd/diff/collect.go @@ -227,9 +227,9 @@ func (self *Collection) Apply(f func(path, typ, changed_path string) error) erro return nil } -func allowed(path string) bool { +func allowed(path string, patterns ...string) bool { name := filepath.Base(path) - for _, pat := range conf.Ignore_name { + for _, pat := range patterns { if matched, err := filepath.Match(pat, name); err == nil && matched { return false } @@ -257,9 +257,9 @@ func resolve_remote_name(path, defval string) string { return defval } -func walk(base string, names *utils.Set[string], pmap map[string]string) error { +func walk(base string, patterns []string, names *utils.Set[string], pmap, path_name_map map[string]string) error { return filepath.WalkDir(base, func(path string, d fs.DirEntry, err error) error { - is_allowed := allowed(path) + is_allowed := allowed(path, patterns...) if !is_allowed { if d.IsDir() { return fs.SkipDir @@ -289,11 +289,11 @@ func walk(base string, names *utils.Set[string], pmap map[string]string) error { func (self *Collection) collect_files(left, right string) error { left_names, right_names := utils.NewSet[string](16), utils.NewSet[string](16) left_path_map, right_path_map := make(map[string]string, 16), make(map[string]string, 16) - err := walk(left, left_names, left_path_map) + err := walk(left, conf.Ignore_name, left_names, left_path_map, path_name_map) if err != nil { return err } - err = walk(right, right_names, right_path_map) + err = walk(right, conf.Ignore_name, right_names, right_path_map, path_name_map) common_names := left_names.Intersect(right_names) changed_names := utils.NewSet[string](common_names.Len()) for n := range common_names.Iterable() { diff --git a/tools/cmd/diff/collect_test.go b/tools/cmd/diff/collect_test.go new file mode 100644 index 000000000..e9bbb448d --- /dev/null +++ b/tools/cmd/diff/collect_test.go @@ -0,0 +1,53 @@ +// License: GPLv3 Copyright: 2023, Kovid Goyal, + +package diff + +import ( + "fmt" + "os" + "path/filepath" + "testing" + + "kitty/tools/utils" + + "github.com/google/go-cmp/cmp" +) + +var _ = fmt.Print + +func TestDiffCollectWalk(t *testing.T) { + tdir := t.TempDir() + j := func(x ...string) string { return filepath.Join(append([]string{tdir}, x...)...) } + os.MkdirAll(j("a", "b"), 0o700) + os.WriteFile(j("a/b/c"), nil, 0o600) + os.WriteFile(j("b"), nil, 0o600) + os.WriteFile(j("d"), nil, 0o600) + os.WriteFile(j("e"), nil, 0o600) + os.WriteFile(j("#d#"), nil, 0o600) + os.WriteFile(j("e~"), nil, 0o600) + os.MkdirAll(j("f"), 0o700) + os.WriteFile(j("f/g"), nil, 0o600) + os.WriteFile(j("h space"), nil, 0o600) + + expected_names := utils.NewSetWithItems("d", "e", "f/g", "h space") + expected_pmap := map[string]string{ + "d": j("d"), + "e": j("e"), + "f/g": j("f/g"), + "h space": j("h space"), + } + names := utils.NewSet[string](16) + pmap := make(map[string]string, 16) + if err := walk(tdir, []string{"*~", "#*#", "b"}, names, pmap, map[string]string{}); err != nil { + t.Fatal(err) + } + if diff := cmp.Diff( + utils.Sort(expected_names.AsSlice(), func(a, b string) bool { return a < b }), + utils.Sort(names.AsSlice(), func(a, b string) bool { return a < b }), + ); diff != "" { + t.Fatal(diff) + } + if diff := cmp.Diff(expected_pmap, pmap); diff != "" { + t.Fatal(diff) + } +} diff --git a/tools/utils/misc.go b/tools/utils/misc.go index 6e523cb0b..0ebb01697 100644 --- a/tools/utils/misc.go +++ b/tools/utils/misc.go @@ -4,7 +4,6 @@ package utils import ( "fmt" - "sort" "golang.org/x/exp/constraints" "golang.org/x/exp/slices" @@ -74,26 +73,29 @@ func Repeat[T any](x T, n int) []T { } func Sort[T any](s []T, less func(a, b T) bool) []T { - sort.Slice(s, func(i, j int) bool { return less(s[i], s[j]) }) + slices.SortFunc(s, less) return s } func StableSort[T any](s []T, less func(a, b T) bool) []T { - sort.SliceStable(s, func(i, j int) bool { return less(s[i], s[j]) }) + slices.SortStableFunc(s, less) return s } -func sort_with_key[T any, C constraints.Ordered](impl func(any, func(int, int) bool), s []T, key func(a T) C) []T { - temp := make([]struct { +func sort_with_key[T any, C constraints.Ordered](stable bool, s []T, key func(a T) C) []T { + type t struct { key C val T - }, len(s)) + } + temp := make([]t, len(s)) for i, x := range s { temp[i].val, temp[i].key = x, key(x) } - impl(temp, func(i, j int) bool { - return temp[i].key < temp[j].key - }) + if stable { + slices.SortStableFunc(temp, func(a, b t) bool { return a.key < b.key }) + } else { + slices.SortFunc(temp, func(a, b t) bool { return a.key < b.key }) + } for i, x := range temp { s[i] = x.val } @@ -101,11 +103,11 @@ func sort_with_key[T any, C constraints.Ordered](impl func(any, func(int, int) b } func SortWithKey[T any, C constraints.Ordered](s []T, key func(a T) C) []T { - return sort_with_key(sort.Slice, s, key) + return sort_with_key(false, s, key) } func StableSortWithKey[T any, C constraints.Ordered](s []T, key func(a T) C) []T { - return sort_with_key(sort.SliceStable, s, key) + return sort_with_key(true, s, key) } func Max[T constraints.Ordered](a T, items ...T) (ans T) {