diff --git a/kittens/transfer/receive.py b/kittens/transfer/receive.py index 50256aac4..ea2f719a0 100644 --- a/kittens/transfer/receive.py +++ b/kittens/transfer/receive.py @@ -112,7 +112,7 @@ def files_for_receive(cli_opts: TransferCLIOptions, dest: str, files: List[File] dest_path = os.path.join(dest, posixpath.basename(files_for_spec[0].remote_path)) else: dest_path = dest - tree = make_tree(files_for_spec, expand_home(dest_path)) + tree = make_tree(files_for_spec, os.path.dirname(expand_home(dest_path))) for x in tree: yield x.entry diff --git a/kitty/file_transmission.py b/kitty/file_transmission.py index 6c78be9dc..4f106f30a 100644 --- a/kitty/file_transmission.py +++ b/kitty/file_transmission.py @@ -91,7 +91,7 @@ def iter_file_metadata(file_specs: Iterable[Tuple[str, str]]) -> Iterator[Union[ path = abspath(path, use_home=True) try: sr = os.stat(path, follow_symlinks=False) - read_ok = os.access(path, os.R_OK) + read_ok = os.access(path, os.R_OK, follow_symlinks=False) except OSError as err: errname = errno.errorcode.get(err.errno, 'EFAIL') yield TransmissionError(file_id=spec_id, code=errname, msg='Failed to read spec') @@ -123,7 +123,7 @@ def iter_file_metadata(file_specs: Iterable[Tuple[str, str]]) -> Iterator[Union[ base = cmds[0] if base.ftype is FileType.symlink: try: - dest = os.readlink(base.name) + dest = os.path.realpath(base.name) except OSError: pass else: diff --git a/kitty_tests/file_transmission.py b/kitty_tests/file_transmission.py index dcabf7c1f..cc421a050 100644 --- a/kitty_tests/file_transmission.py +++ b/kitty_tests/file_transmission.py @@ -360,6 +360,15 @@ class TestFileTransmission(BaseTest): kw = {str(k): expand_home(str(v)) for k, v in kw.items()} self.ae(kw, m) + def gm(all_specs): + specs = list((str(i), str(s)) for i, s in enumerate(all_specs)) + files = [] + for x in iter_file_metadata(specs): + if isinstance(x, Exception): + raise x + files.append(File(x)) + return files, specs + def tf(args, expected, different_home=''): if opts.mode == 'mirror': all_specs = args @@ -367,8 +376,7 @@ class TestFileTransmission(BaseTest): else: all_specs = args[:-1] dest = args[-1] - specs = list((str(i), str(s)) for i, s in enumerate(all_specs)) - files = list(map(File, iter_file_metadata(specs))) + files, specs = gm(all_specs) orig_home = home_path() with set_paths(cwd_path(), different_home or orig_home): files = list(files_for_receive(opts, dest, files, orig_home, specs)) @@ -382,6 +390,21 @@ class TestFileTransmission(BaseTest): with set_paths(cwd=b, home=self.tdir): tf([b/'r', b/'d'], {b/'r': '~/b/r', b/'d': '~/b/d', b/'d'/'r': '~/b/d/r'}, different_home='/foo/bar') 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([b/'r', b/'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', b/'s', b/'r', b / 'h'))[0] + self.assertEqual(files[0].ftype, FileType.symlink) + self.assertEqual(files[1].ftype, FileType.symlink) + 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]