From 55bbf175c6493d50d2c017d33b0f07fd72939910 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sat, 29 Apr 2023 09:17:14 +0530 Subject: [PATCH] Port send file mapping tests --- kittens/transfer/send.go | 6 +- kittens/transfer/send_test.go | 102 +++++++++++++++++++++++++++++++ kittens/transfer/utils.go | 3 + kitty_tests/file_transmission.py | 48 --------------- tools/utils/paths.go | 2 +- 5 files changed, 109 insertions(+), 52 deletions(-) create mode 100644 kittens/transfer/send_test.go diff --git a/kittens/transfer/send.go b/kittens/transfer/send.go index 6bac44f05..812b695c4 100644 --- a/kittens/transfer/send.go +++ b/kittens/transfer/send.go @@ -189,8 +189,8 @@ func process_normal_files(opts *Options, args []string) (ans []*File, err error) return ans, fmt.Errorf("Must specify at least one local path and one remote path") } args = slices.Clone(args) - remote_base := filepath.ToSlash(args[0]) - args = args[1:] + remote_base := filepath.ToSlash(args[len(args)-1]) + args = args[:len(args)-1] if len(args) > 1 && !strings.HasSuffix(remote_base, "/") { remote_base += "/" } @@ -223,7 +223,7 @@ func files_for_send(opts *Options, args []string) (files []*File, err error) { } } - remove := make([]int, len(files)) + remove := make([]int, 0, len(files)) // detect symlinks to other transferred files for i, f := range files { if f.file_type == SYMLINK_FILE { diff --git a/kittens/transfer/send_test.go b/kittens/transfer/send_test.go new file mode 100644 index 000000000..275603847 --- /dev/null +++ b/kittens/transfer/send_test.go @@ -0,0 +1,102 @@ +// License: GPLv3 Copyright: 2023, Kovid Goyal, + +package transfer + +import ( + "fmt" + "os" + "path/filepath" + "strings" + "testing" + + "github.com/google/go-cmp/cmp" +) + +var _ = fmt.Print + +func TestPathMappingSend(t *testing.T) { + opts := &Options{} + tdir := t.TempDir() + b := filepath.Join(tdir, "b") + os.Mkdir(b, 0o700) + os.WriteFile(filepath.Join(b, "r"), nil, 0600) + os.Mkdir(filepath.Join(b, "d"), 0o700) + os.WriteFile(filepath.Join(b, "d", "r"), nil, 0600) + + gm := func(args ...string) ([]*File, error) { + return files_for_send(opts, args) + } + + mp := func(path string, is_remote bool) string { + path = strings.TrimSpace(path) + if strings.HasPrefix(path, "~") || filepath.IsAbs(path) { + return path + } + return filepath.Join(tdir, path) + } + + tf := func(expected string, args ...string) { + files, err := gm(args...) + if err != nil { + t.Fatalf("Failed with mode: %s cwd: %s home: %s and args: %#v\n%s", opts.Mode, cwd_path(), home_path(), args, err) + } + actual := make(map[string]string) + for _, f := range files { + actual[f.expanded_local_path] = f.remote_path + } + e := make(map[string]string, len(actual)) + for _, rec := range strings.Split(expected, " ") { + k, v, _ := strings.Cut(rec, ":") + e[mp(k, false)] = mp(v, true) + } + if diff := cmp.Diff(e, actual); diff != "" { + t.Fatalf("Failed with mode: %s cwd: %s home: %s and args: %#v\n%s", opts.Mode, cwd_path(), home_path(), args, diff) + } + } + + opts.Mode = "mirror" + run_with_paths(b, "/foo/bar", func() { + tf("b/r:b/r b/d:b/d b/d/r:b/d/r", "r", "d") + tf("b/r:b/r b/d/r:b/d/r", "r", "d/r") + }) + run_with_paths(b, tdir, func() { + tf("b/r:~/b/r b/d:~/b/d b/d/r:~/b/d/r", "r", "d") + }) + opts.Mode = "normal" + run_with_paths("/some/else", "/foo/bar", func() { + tf("b/r:/dest/r b/d:/dest/d b/d/r:/dest/d/r", filepath.Join(b, "r"), filepath.Join(b, "d"), "/dest") + tf("b/r:~/dest/r b/d:~/dest/d b/d/r:~/dest/d/r", filepath.Join(b, "r"), filepath.Join(b, "d"), "~/dest") + }) + run_with_paths(b, "/foo/bar", func() { + tf("b/r:/dest/r b/d:/dest/d b/d/r:/dest/d/r", "r", "d", "/dest") + }) + os.Symlink("/foo/b", filepath.Join(b, "e")) + os.Symlink("r", filepath.Join(b, "s")) + os.Link(filepath.Join(b, "r"), filepath.Join(b, "h")) + + file_idx := 0 + first_file := func(args ...string) *File { + files, err := gm(args...) + if err != nil { + t.Fatal(err) + } + return files[file_idx] + } + ae := func(a any, b any) { + if diff := cmp.Diff(a, b); diff != "" { + t.Fatalf("%s", diff) + } + } + run_with_paths("/some/else", "/foo/bar", func() { + f := first_file(filepath.Join(b, "e"), "dest") + ae(f.symbolic_link_target, "path:/foo/b") + f = first_file(filepath.Join(b, "s"), filepath.Join(b, "r"), "dest") + ae(f.symbolic_link_target, "fid:2") + f = first_file(filepath.Join(b, "h"), "dest") + ae(f.file_type, REGULAR_FILE) + file_idx = 1 + f = first_file(filepath.Join(b, "h"), filepath.Join(b, "r"), "dest") + ae(f.hard_link_target, "1") + ae(f.file_type, LINK_FILE) + }) +} diff --git a/kittens/transfer/utils.go b/kittens/transfer/utils.go index f13baa15e..5b058b92e 100644 --- a/kittens/transfer/utils.go +++ b/kittens/transfer/utils.go @@ -33,6 +33,9 @@ func home_path() string { } func abspath(path string, use_home ...bool) string { + if filepath.IsAbs(path) { + return path + } var base string if len(use_home) > 0 && use_home[0] { base = home_path() diff --git a/kitty_tests/file_transmission.py b/kitty_tests/file_transmission.py index 25c46ddc7..56b3a9db6 100644 --- a/kitty_tests/file_transmission.py +++ b/kitty_tests/file_transmission.py @@ -427,51 +427,3 @@ class TestFileTransmission(BaseTest): self.assertEqual(files[1].remote_target, files[2].remote_id) self.assertEqual(files[3].ftype, FileType.link) self.assertEqual(files[3].remote_target, files[2].remote_id) - - def test_path_mapping_send(self): - opts = parse_transfer_args([])[0] - b = Path(os.path.join(self.tdir, 'b')) - os.makedirs(b) - open(b / 'r', 'w').close() - os.mkdir(b / 'd') - open(b / 'd' / 'r', 'w').close() - - def gm(*args): - return files_for_send(opts, list(map(str, args))) - - def am(files, kw): - m = {f.expanded_local_path: f.remote_path for f in files} - kw = {str(k): str(v) for k, v in kw.items()} - self.ae(m, kw) - - def tf(args, expected): - files = gm(*args) - self.ae(len(files), len(expected)) - am(files, expected) - - opts.mode = 'mirror' - with set_paths(cwd=b, home='/foo/bar'): - tf(['r', 'd'], {b/'r': b/'r', b/'d': b/'d', b/'d'/'r': b/'d'/'r'}) - tf(['r', 'd/r'], {b/'r': b/'r', b/'d'/'r': b/'d'/'r'}) - with set_paths(cwd=b, home=self.tdir): - tf(['r', 'd'], {b/'r': '~/b/r', b/'d': '~/b/d', b/'d'/'r': '~/b/d/r'}) - opts.mode = 'normal' - with set_paths(cwd='/some/else', home='/foo/bar'): - tf([b/'r', b/'d', '/dest'], {b/'r': '/dest/r', b/'d': '/dest/d', b/'d'/'r': '/dest/d/r'}) - tf([b/'r', b/'d', '~/dest'], {b/'r': '~/dest/r', b/'d': '~/dest/d', b/'d'/'r': '~/dest/d/r'}) - with set_paths(cwd=b, home='/foo/bar'): - tf(['r', 'd', '/dest'], {b/'r': '/dest/r', b/'d': '/dest/d', b/'d'/'r': '/dest/d/r'}) - - os.symlink('/foo/b', b / 'e') - os.symlink('r', b / 's') - os.link(b / 'r', b / 'h') - with set_paths(cwd='/some/else', home='/foo/bar'): - files = gm(b / 'e', 'dest') - self.ae(files[0].symbolic_link_target, 'path:/foo/b') - files = gm(b / 's', b / 'r', 'dest') - self.ae(files[0].symbolic_link_target, 'fid:2') - files = gm(b / 'h', 'dest') - self.ae(files[0].file_type, FileType.regular) - files = gm(b / 'h', b / 'r', 'dest') - self.ae(files[1].file_type, FileType.link) - self.ae(files[1].hard_link_target, '1') diff --git a/tools/utils/paths.go b/tools/utils/paths.go index 8c5495ab5..3446e2f8b 100644 --- a/tools/utils/paths.go +++ b/tools/utils/paths.go @@ -315,7 +315,7 @@ func Commonpath(paths ...string) (longest_prefix string) { a = a[na:] b = b[nb:] } - longest_prefix = a[:sz] + longest_prefix = paths[0][:sz] } return }