From 2d8ffdc0ee314488a1c55cc4f4dd3c6ad03cf09e Mon Sep 17 00:00:00 2001 From: Mark Berger Date: Mon, 5 Aug 2013 09:05:05 -0400 Subject: [PATCH 1/5] Adds test_cli.Cp.test_cp_copies_dir --- src/allmydata/test/test_cli.py | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/allmydata/test/test_cli.py b/src/allmydata/test/test_cli.py index 7039ebb87..473b6aee6 100644 --- a/src/allmydata/test/test_cli.py +++ b/src/allmydata/test/test_cli.py @@ -2473,6 +2473,40 @@ starting copy, 2 files, 1 directories d.addCallback(_check) return d + def test_cp_copies_dir(self): + # This test ensures that a directory is copied using + # tahoe cp -r. Refer to ticket #712: + # https://tahoe-lafs.org/trac/tahoe-lafs/ticket/712 + + self.basedir = "cli/Cp/cp_copies_dir" + self.set_up_grid() + subdir = os.path.join(self.basedir, "foo") + os.mkdir(subdir) + test1_path = os.path.join(subdir, "test1") + fileutil.write(test1_path, "test1") + + d = self.do_cli("create-alias", "tahoe") + d.addCallback(lambda ign: + self.do_cli("cp", "-r", subdir, "tahoe:")) + d.addCallback(lambda ign: + self.do_cli("ls", "tahoe:")) + def _check(res, item): + (rc, out, err) = res + self.failUnlessEqual(rc, 0) + self.failUnlessEqual(err, "") + self.failUnlessIn(item, out, str(res)) + d.addCallback(_check, "foo") + d.addCallback(lambda ign: + self.do_cli("ls", "tahoe:foo/")) + d.addCallback(_check, "test1") + + d.addCallback(lambda ign: fileutil.rm_dir(subdir)) + d.addCallback(lambda ign: self.do_cli("cp", "-r", "tahoe:foo", self.basedir)) + def _check_local_fs(ign): + self.failUnless(os.path.isdir(self.basedir)) + self.failUnless(os.path.isfile(test1_path)) + d.addCallback(_check_local_fs) + return d class Backup(GridTestMixin, CLITestMixin, StallMixin, unittest.TestCase): From 1c96039270f9489a52c5d514ee4702d31bd24c22 Mon Sep 17 00:00:00 2001 From: Mark Berger Date: Mon, 5 Aug 2013 11:53:07 -0400 Subject: [PATCH 2/5] tahoe cp -r now copies the top level directory with its children --- src/allmydata/scripts/tahoe_cp.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/allmydata/scripts/tahoe_cp.py b/src/allmydata/scripts/tahoe_cp.py index cf421ae0d..965aa26f3 100644 --- a/src/allmydata/scripts/tahoe_cp.py +++ b/src/allmydata/scripts/tahoe_cp.py @@ -654,8 +654,9 @@ class Copier: for (name,s) in source_files: self.attach_to_target(s, name, target) - for source in source_dirs: - self.assign_targets(source, target) + for (name, source) in source_dirs: + new_target = target.get_child_target(name) + self.assign_targets(source, new_target) self.progress("targets assigned, %s dirs, %s files" % (len(self.targetmap), self.files_to_copy)) @@ -763,7 +764,9 @@ class Copier: for name,source in source_infos: if isinstance(source, (LocalDirectorySource, TahoeDirectorySource)): source.populate(True) - graphs.append(source) + # Remove trailing slash (if applicable) and get dir name + name = os.path.basename(os.path.normpath(name)) + graphs.append((name, source)) return graphs From 47c8616dd5b7ffe76bdd0bf7df287ac670226ba6 Mon Sep 17 00:00:00 2001 From: Mark Berger Date: Mon, 5 Aug 2013 11:53:44 -0400 Subject: [PATCH 3/5] Fix tests which relied on the old behavior of tahoe cp -r --- src/allmydata/test/test_cli.py | 24 ++++++++++++------------ src/allmydata/test/test_system.py | 12 ++++++------ 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/allmydata/test/test_cli.py b/src/allmydata/test/test_cli.py index 473b6aee6..e6f1cc6f3 100644 --- a/src/allmydata/test/test_cli.py +++ b/src/allmydata/test/test_cli.py @@ -2078,7 +2078,7 @@ class Cp(GridTestMixin, CLITestMixin, unittest.TestCase): d = self.do_cli("create-alias", "tahoe") d.addCallback(lambda res: self.do_cli("mkdir", "tahoe:test/" + artonwall_arg)) d.addCallback(lambda res: self.do_cli("cp", "-r", "tahoe:test", "tahoe:test2")) - d.addCallback(lambda res: self.do_cli("ls", "tahoe:test2")) + d.addCallback(lambda res: self.do_cli("ls", "tahoe:test2/test")) def _check((rc, out, err)): try: unicode_to_output(u"\u00C4rtonwall") @@ -2242,20 +2242,20 @@ class Cp(GridTestMixin, CLITestMixin, unittest.TestCase): self.childuris[k] = to_str(childdata[uri_key]) d.addCallback(_process_directory_json) # Now build a local directory to copy into place, like the following: - # source1/ - # source1/mutable1 - # source1/mutable2 - # source1/imm1 - # source1/imm3 + # test2/ + # test2/mutable1 + # test2/mutable2 + # test2/imm1 + # test2/imm3 def _build_local_directory(ignored): - source1_path = os.path.join(self.basedir, "source1") - fileutil.make_dirs(source1_path) + test2_path = os.path.join(self.basedir, "test2") + fileutil.make_dirs(test2_path) for fn in ("mutable1", "mutable2", "imm1", "imm3"): - fileutil.write(os.path.join(source1_path, fn), fn * 1000) - self.source1_path = source1_path + fileutil.write(os.path.join(test2_path, fn), fn * 1000) + self.test2_path = test2_path d.addCallback(_build_local_directory) d.addCallback(lambda ignored: - self.do_cli("cp", "-r", self.source1_path, "tahoe:test2")) + self.do_cli("cp", "-r", self.test2_path, "tahoe:")) # We expect that mutable1 and mutable2 are overwritten in-place, # so they'll retain their URIs but have different content. @@ -2422,7 +2422,7 @@ class Cp(GridTestMixin, CLITestMixin, unittest.TestCase): fileutil.write(os.path.join(test_dir_path, f), f * 10000) d.addCallback(lambda ignored: - self.do_cli("cp", "-r", test_dir_path, "tahoe:test")) + self.do_cli("cp", "-r", test_dir_path, "tahoe:")) d.addCallback(_check_error_message) d.addCallback(lambda ignored: self.do_cli("ls", "--json", "tahoe:test")) diff --git a/src/allmydata/test/test_system.py b/src/allmydata/test/test_system.py index 42dbc475e..957c14c3f 100644 --- a/src/allmydata/test/test_system.py +++ b/src/allmydata/test/test_system.py @@ -1685,7 +1685,7 @@ class SystemTest(SystemTestMixin, RunBinTahoeMixin, unittest.TestCase): open(os.path.join(sdn2, "rfile5"), "wb").write("rfile5") # from disk into tahoe - d.addCallback(run, "cp", "-r", dn, "tahoe:dir1") + d.addCallback(run, "cp", "-r", dn, "tahoe:") d.addCallback(run, "ls") d.addCallback(_check_ls, ["dir1"]) d.addCallback(run, "ls", "dir1") @@ -1703,7 +1703,7 @@ class SystemTest(SystemTestMixin, RunBinTahoeMixin, unittest.TestCase): def _check_cp_r_out((out,err)): def _cmp(name): old = open(os.path.join(dn, name), "rb").read() - newfn = os.path.join(dn_copy, name) + newfn = os.path.join(dn_copy, "dir1", name) self.failUnless(os.path.exists(newfn)) new = open(newfn, "rb").read() self.failUnlessEqual(old, new) @@ -1722,7 +1722,7 @@ class SystemTest(SystemTestMixin, RunBinTahoeMixin, unittest.TestCase): d.addCallback(run, "cp", "-r", "--caps-only", "tahoe:dir1", dn_copy2) def _check_capsonly((out,err)): # these should all be LITs - x = open(os.path.join(dn_copy2, "subdir2", "rfile4")).read() + x = open(os.path.join(dn_copy2, "dir1", "subdir2", "rfile4")).read() y = uri.from_string_filenode(x) self.failUnlessEqual(y.data, "rfile4") d.addCallback(_check_capsonly) @@ -1731,13 +1731,13 @@ class SystemTest(SystemTestMixin, RunBinTahoeMixin, unittest.TestCase): d.addCallback(run, "cp", "-r", "tahoe:dir1", "tahoe:dir1-copy") d.addCallback(run, "ls") d.addCallback(_check_ls, ["dir1", "dir1-copy"]) - d.addCallback(run, "ls", "dir1-copy") + d.addCallback(run, "ls", "dir1-copy/dir1") d.addCallback(_check_ls, ["rfile1", "rfile2", "rfile3", "subdir2"], ["rfile4", "rfile5"]) - d.addCallback(run, "ls", "tahoe:dir1-copy/subdir2") + d.addCallback(run, "ls", "tahoe:dir1-copy/dir1/subdir2") d.addCallback(_check_ls, ["rfile4", "rfile5"], ["rfile1", "rfile2", "rfile3"]) - d.addCallback(run, "get", "dir1-copy/subdir2/rfile4") + d.addCallback(run, "get", "dir1-copy/dir1/subdir2/rfile4") d.addCallback(_check_stdout_against, data="rfile4") # and copy it a second time, which ought to overwrite the same files From 58106e1c0f5fcc8cbd4979f29d7041d103d18d5e Mon Sep 17 00:00:00 2001 From: "Mark J. Berger" Date: Tue, 27 Aug 2013 11:54:33 -0400 Subject: [PATCH 4/5] Documentation updates --- docs/frontends/CLI.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/frontends/CLI.rst b/docs/frontends/CLI.rst index ec612558f..4becace1b 100644 --- a/docs/frontends/CLI.rst +++ b/docs/frontends/CLI.rst @@ -448,6 +448,11 @@ Command Examples This copies a file from your ``tahoe:`` root to a different directory, set up earlier with "``tahoe add-alias fun DIRCAP``" or "``tahoe create-alias fun``". + ``tahoe cp -r ~/my_dir/ tahoe:`` + + This copies the folder ``~/my_dir/`` and all its children to the grid, creating + the new folder ``tahoe:my_dir``. + ``tahoe unlink uploaded.txt`` ``tahoe unlink tahoe:uploaded.txt`` From 2018ff435ac47f080321bfc691c726d28fa7759c Mon Sep 17 00:00:00 2001 From: Brian Warner Date: Tue, 2 Sep 2014 12:40:21 -0700 Subject: [PATCH 5/5] CLI.rst: expand the 'cp -r' subdirectory example --- docs/frontends/CLI.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/frontends/CLI.rst b/docs/frontends/CLI.rst index 4becace1b..e91632f57 100644 --- a/docs/frontends/CLI.rst +++ b/docs/frontends/CLI.rst @@ -451,7 +451,9 @@ Command Examples ``tahoe cp -r ~/my_dir/ tahoe:`` This copies the folder ``~/my_dir/`` and all its children to the grid, creating - the new folder ``tahoe:my_dir``. + the new folder ``tahoe:my_dir``. Note that the trailing slash is not required: + all source arguments which are directories will be copied into new + subdirectories of the target. ``tahoe unlink uploaded.txt``