diff --git a/kittens/ssh/copy.py b/kittens/ssh/copy.py index 9d908d972..f2ae3b63e 100644 --- a/kittens/ssh/copy.py +++ b/kittens/ssh/copy.py @@ -40,7 +40,7 @@ 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/**`. 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. +and patterns starting with a single :code:`*` (as opposed to two asterisks) match any filename prefix. See the :link:`detailed syntax `. diff --git a/kitty_tests/ssh.py b/kitty_tests/ssh.py index db1f4d283..4bccb6b14 100644 --- a/kitty_tests/ssh.py +++ b/kitty_tests/ssh.py @@ -85,7 +85,7 @@ copy s1 copy --symlink-strategy=keep-path s2 copy --dest=a/sfa simple-file copy --glob g.* -copy --exclude */w.* d1 +copy --exclude **/w.* d1 ''' self.check_bootstrap( sh, remote_home, test_script='env; exit 0', SHELL_INTEGRATION_VALUE='', conf=conf, home=local_home, @@ -220,7 +220,7 @@ env COLORTERM test_script = f'print("UNTAR_DONE", flush=True); {test_script}' else: test_script = f'echo "UNTAR_DONE"; {test_script}' - conf += '\nshell_integration ' + SHELL_INTEGRATION_VALUE or 'disabled' + conf += '\nshell_integration ' + (SHELL_INTEGRATION_VALUE or 'disabled') conf += '\ninterpreter ' + sh env = os.environ.copy() if home: diff --git a/tools/cmd/ssh/config.go b/tools/cmd/ssh/config.go index fcefb1e16..a84e0977d 100644 --- a/tools/cmd/ssh/config.go +++ b/tools/cmd/ssh/config.go @@ -247,12 +247,12 @@ func get_file_data(callback func(h *tar.Header, data []byte) error, seen map[fil u, ok := s.Sys().(unix.Stat_t) cb := func(h *tar.Header, data []byte) error { h.Name = arcname + if h.Typeflag == tar.TypeDir { + h.Name = strings.TrimRight(h.Name, "/") + "/" + } h.Size = int64(len(data)) - h.Mode = int64(s.Mode()) - + h.Mode = int64(s.Mode().Perm()) h.ModTime = s.ModTime() - h.Uid, h.Gid = 0, 0 - h.Uname, h.Gname = "", "" h.Format = tar.FormatPAX if ok { h.AccessTime = time.Unix(0, u.Atim.Nano()) @@ -293,9 +293,9 @@ func get_file_data(callback func(h *tar.Header, data []byte) error, seen map[fil } if werr == nil { rel, err := filepath.Rel(local_path, path) - if err != nil { + if err == nil { aname := filepath.Join(arcname, rel) - return get_file_data(callback, seen, path, aname, nil, false) + return get_file_data(callback, seen, clean_path, aname, nil, false) } } return nil @@ -325,7 +325,7 @@ func get_file_data(callback func(h *tar.Header, data []byte) error, seen map[fil func (ci *CopyInstruction) get_file_data(callback func(h *tar.Header, data []byte) error, seen map[file_unique_id]string) (err error) { ep := ci.exclude_patterns for _, folder_name := range []string{"__pycache__", ".DS_Store"} { - ep = append(ep, "*/"+folder_name, "*/"+folder_name+"/*") + ep = append(ep, "**/"+folder_name, "**/"+folder_name+"/**") } return get_file_data(callback, seen, ci.local_path, ci.arcname, ep, true) } diff --git a/tools/cmd/ssh/config_test.go b/tools/cmd/ssh/config_test.go index dff66dbe3..ef2dd16da 100644 --- a/tools/cmd/ssh/config_test.go +++ b/tools/cmd/ssh/config_test.go @@ -23,10 +23,13 @@ func TestSSHConfigParsing(t *testing.T) { cf := filepath.Join(tdir, "ssh.conf") rt := func(expected_env ...string) { os.WriteFile(cf, []byte(conf), 0o600) - c, err := load_config(hostname, username, nil, cf) + c, bad_lines, err := load_config(hostname, username, nil, cf) if err != nil { t.Fatal(err) } + if len(bad_lines) != 0 { + t.Fatalf("Bad config line: %s with error: %s", bad_lines[0].Line, bad_lines[0].Err) + } actual := final_env_instructions(for_python, func(key string) (string, bool) { if key == "LOCAL_ENV" { return "LOCAL_VAL", true diff --git a/tools/cmd/ssh/main.go b/tools/cmd/ssh/main.go index fc652f1ae..c3380cfaa 100644 --- a/tools/cmd/ssh/main.go +++ b/tools/cmd/ssh/main.go @@ -275,7 +275,10 @@ func make_tarfile(cd *connection_data, get_local_env func(string) (string, bool) return } for _, ci := range cd.host_opts.Copy { - get_file_data(add, seen, ci.local_path, ci.arcname, ci.exclude_patterns, true) + err = get_file_data(add, seen, ci.local_path, ci.arcname, ci.exclude_patterns, true) + if err != nil { + return nil, err + } } type fe struct { arcname string diff --git a/tools/cmd/ssh/main_test.go b/tools/cmd/ssh/main_test.go index ab859145c..e3fb09054 100644 --- a/tools/cmd/ssh/main_test.go +++ b/tools/cmd/ssh/main_test.go @@ -50,10 +50,13 @@ func basic_connection_data(overrides ...string) *connection_data { script_type: "sh", request_id: "123-123", remote_args: []string{}, username: "testuser", hostname_for_match: "host.test", } - opts, err := load_config(ans.hostname_for_match, ans.username, overrides, "") + opts, bad_lines, err := load_config(ans.hostname_for_match, ans.username, overrides, "") if err != nil { panic(err) } + if len(bad_lines) != 0 { + panic(fmt.Sprintf("Bad config lines: %s with error: %s", bad_lines[0].Line, bad_lines[0].Err)) + } ans.host_opts = opts return ans } diff --git a/tools/cmd/ssh/utils.go b/tools/cmd/ssh/utils.go index f0708994f..ef2514260 100644 --- a/tools/cmd/ssh/utils.go +++ b/tools/cmd/ssh/utils.go @@ -227,7 +227,7 @@ type KittyOpts struct { Term, Shell_integration string } -var RelevantKittyOpts = (&utils.Once[KittyOpts]{Run: func() KittyOpts { +func read_relevant_kitty_opts(path string) KittyOpts { ans := KittyOpts{Term: kitty.KittyConfigDefaults.Term, Shell_integration: kitty.KittyConfigDefaults.Shell_integration} handle_line := func(key, val string) error { switch key { @@ -239,6 +239,10 @@ var RelevantKittyOpts = (&utils.Once[KittyOpts]{Run: func() KittyOpts { return nil } cp := config.ConfigParser{LineHandler: handle_line} - cp.ParseFiles(filepath.Join(utils.ConfigDir(), "kitty.conf")) + cp.ParseFiles(path) return ans +} + +var RelevantKittyOpts = (&utils.Once[KittyOpts]{Run: func() KittyOpts { + return read_relevant_kitty_opts(filepath.Join(utils.ConfigDir(), "kitty.conf")) }}).Get diff --git a/tools/cmd/ssh/utils_test.go b/tools/cmd/ssh/utils_test.go index 36a010878..2d9990ca3 100644 --- a/tools/cmd/ssh/utils_test.go +++ b/tools/cmd/ssh/utils_test.go @@ -8,7 +8,6 @@ import ( "path/filepath" "testing" - "kitty/tools/utils" "kitty/tools/utils/shlex" "github.com/google/go-cmp/cmp" @@ -57,14 +56,13 @@ func TestParseSSHArgs(t *testing.T) { func TestRelevantKittyOpts(t *testing.T) { tdir := t.TempDir() - orig := utils.ConfigDir - utils.ConfigDir = func() string { return tdir } - defer func() { utils.ConfigDir = orig }() - os.WriteFile(filepath.Join(tdir, "kitty.conf"), []byte("term XXX\nshell_integration changed\nterm abcd"), 0o600) - if RelevantKittyOpts().Term != "abcd" { + path := filepath.Join(tdir, "kitty.conf") + os.WriteFile(path, []byte("term XXX\nshell_integration changed\nterm abcd"), 0o600) + rko := read_relevant_kitty_opts(path) + if rko.Term != "abcd" { t.Fatalf("Unexpected TERM: %s", RelevantKittyOpts().Term) } - if RelevantKittyOpts().Shell_integration != "changed" { + if rko.Shell_integration != "changed" { t.Fatalf("Unexpected shell_integration: %s", RelevantKittyOpts().Shell_integration) } }