From e4002b56914526ad0e96e57f58c8d8c800523be5 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 24 Feb 2023 13:43:38 +0530 Subject: [PATCH] Switch to a more capable glob implementation that supports ** --- go.mod | 1 + go.sum | 2 ++ kittens/ssh/copy.py | 9 +++++++-- tools/cmd/ssh/config.go | 22 +++++++++++++++++----- 4 files changed, 27 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index e1106df31..8708cc02b 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.20 require ( github.com/ALTree/bigfloat v0.0.0-20220102081255-38c8b72a9924 + github.com/bmatcuk/doublestar v1.3.4 github.com/disintegration/imaging v1.6.2 github.com/google/go-cmp v0.5.8 github.com/google/uuid v1.3.0 diff --git a/go.sum b/go.sum index 43c0e463f..b7d800a22 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,7 @@ github.com/ALTree/bigfloat v0.0.0-20220102081255-38c8b72a9924 h1:DG4UyTVIujioxwJc8Zj8Nabz1L1wTgQ/xNBSQDfdP3I= github.com/ALTree/bigfloat v0.0.0-20220102081255-38c8b72a9924/go.mod h1:+NaH2gLeY6RPBPPQf4aRotPPStg+eXc8f9ZaE4vRfD4= +github.com/bmatcuk/doublestar v1.3.4 h1:gPypJ5xD31uhX6Tf54sDPUOBXTqKH4c9aPY66CyQrS0= +github.com/bmatcuk/doublestar v1.3.4/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE= github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c= github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4= github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= diff --git a/kittens/ssh/copy.py b/kittens/ssh/copy.py index 79c96e51d..9d908d972 100644 --- a/kittens/ssh/copy.py +++ b/kittens/ssh/copy.py @@ -20,7 +20,9 @@ def option_text() -> str: return ''' --glob type=bool-set -Interpret file arguments as glob patterns. +Interpret file arguments as glob patterns. Globbing is based on +Based on standard wildcards with the addition that ``/**/`` matches any number of directories. +See the :link:`detailed syntax `. --dest @@ -36,7 +38,10 @@ type=list A glob pattern. Files with names matching this pattern are excluded from being transferred. Useful when adding directories. Can be specified multiple times, if any of the patterns match the file will be -excluded. To exclude a directory use a pattern like :code:`*/directory_name/*`. +excluded. To exclude a directory use a pattern like :code:`**/directory_name/**`. +Based on standard wildcards with the addition that ``/**/`` matches any number of directories +and patterns starting with a single :code:`*` (as opposed to two asterisks) match any prefix. +See the :link:`detailed syntax `. --symlink-strategy diff --git a/tools/cmd/ssh/config.go b/tools/cmd/ssh/config.go index 5cd7900bb..d6d48831f 100644 --- a/tools/cmd/ssh/config.go +++ b/tools/cmd/ssh/config.go @@ -18,6 +18,7 @@ import ( "kitty/tools/utils/paths" "kitty/tools/utils/shlex" + "github.com/bmatcuk/doublestar" "golang.org/x/sys/unix" ) @@ -143,12 +144,12 @@ func resolve_file_spec(spec string, is_glob bool) ([]string, error) { ans = paths_ctx.AbspathFromHome(ans) } if is_glob { - files, err := filepath.Glob(ans) + files, err := doublestar.Glob(ans) if err != nil { - return nil, err + return nil, fmt.Errorf("%s is not a valid glob pattern with error: %w", spec, err) } if len(files) == 0 { - return nil, fmt.Errorf("%s does not exist", spec) + return nil, fmt.Errorf("%s matches no files", spec) } return files, nil } @@ -228,6 +229,16 @@ type file_unique_id struct { dev, inode uint64 } +func excluded(pattern, path string) bool { + if strings.HasPrefix(pattern, "*") && !strings.HasPrefix(pattern, "**") { + path = filepath.Base(path) + } + if matched, err := doublestar.PathMatch(pattern, path); matched && err == nil { + return true + } + return false +} + func get_file_data(callback func(h *tar.Header, data []byte) error, seen map[file_unique_id]string, local_path, arcname string, exclude_patterns []string, recurse bool) error { s, err := os.Lstat(local_path) if err != nil { @@ -271,11 +282,12 @@ func get_file_data(callback func(h *tar.Header, data []byte) error, seen map[fil if recurse { local_path = filepath.Clean(local_path) return filepath.WalkDir(local_path, func(path string, d fs.DirEntry, werr error) error { - if filepath.Clean(path) == local_path { + clean_path := filepath.Clean(path) + if clean_path == local_path { return nil } for _, pat := range exclude_patterns { - if matched, err := filepath.Match(pat, path); matched && err == nil { + if excluded(pat, clean_path) { return nil } }