From: Brian Warner Date: Mon, 30 Nov 2009 21:10:09 +0000 (-0800) Subject: Implement more coherent behavior when copying with dircaps/filecaps (closes #761... X-Git-Url: https://git.rkrishnan.org/specifications/components/com_hotproperty/reliability?a=commitdiff_plain;h=74974b27fe0444388cd31aa4e1058e631d92417b;p=tahoe-lafs%2Ftahoe-lafs.git Implement more coherent behavior when copying with dircaps/filecaps (closes #761). Patch by Kevan Carstensen. --- diff --git a/src/allmydata/scripts/tahoe_cp.py b/src/allmydata/scripts/tahoe_cp.py index 797f8782..8cf543da 100644 --- a/src/allmydata/scripts/tahoe_cp.py +++ b/src/allmydata/scripts/tahoe_cp.py @@ -441,13 +441,13 @@ class Copier: self.caps_only = options["caps-only"] self.cache = {} try: - self.try_copy() + status = self.try_copy() + return status except TahoeError, te: Failure().printTraceback(self.stderr) print >>self.stderr te.display(self.stderr) return 1 - return 0 def try_copy(self): source_specs = self.options.sources @@ -498,6 +498,13 @@ class Copier: return self.copy_file(source, target) if isinstance(target, (LocalDirectoryTarget, TahoeDirectoryTarget)): + # We're copying to an existing directory -- make sure that we + # have target names for everything + for (name, source) in sources: + if name is None and isinstance(source, TahoeFileSource): + self.to_stderr( + "error: you must specify a destination filename") + return 1 return self.copy_to_directory(sources, target) self.to_stderr("unknown target") @@ -587,6 +594,8 @@ class Copier: writecap = ascii_or_none(d.get("rw_uri")) readcap = ascii_or_none(d.get("ro_uri")) mutable = d.get("mutable", False) # older nodes don't provide it + if source_spec.rfind('/') != -1: + name = source_spec[source_spec.rfind('/')+1:] t = TahoeFileSource(self.nodeurl, mutable, writecap, readcap) return name, t diff --git a/src/allmydata/test/test_cli.py b/src/allmydata/test/test_cli.py index b88ed4c0..fd12128c 100644 --- a/src/allmydata/test/test_cli.py +++ b/src/allmydata/test/test_cli.py @@ -934,6 +934,66 @@ class Cp(GridTestMixin, CLITestMixin, unittest.TestCase): dn, "tahoe:")) return d + def test_copy_using_filecap(self): + self.basedir = "cli/Cp/test_copy_using_filecap" + self.set_up_grid() + outdir = os.path.join(self.basedir, "outdir") + os.mkdir(outdir) + self.do_cli("create-alias", "tahoe") + fn1 = os.path.join(self.basedir, "Metallica") + fn2 = os.path.join(outdir, "Not Metallica") + fn3 = os.path.join(outdir, "test2") + DATA1 = "puppies" * 10000 + open(fn1, "wb").write(DATA1) + d = self.do_cli("put", fn1) + def _put_file((rc, out, err)): + self.failUnlessEqual(rc, 0) + # keep track of the filecap + self.filecap = out.strip() + d.addCallback(_put_file) + # Let's try copying this to the disk using the filecap + # cp FILECAP filename + d.addCallback(lambda res: self.do_cli("cp", self.filecap, fn2)) + def _copy_file((rc, out, err)): + self.failUnlessEqual(rc, 0) + results = open(fn2, "r").read() + self.failUnlessEqual(results, DATA1) + # Test with ./ (see #761) + # cp FILECAP localdir + d.addCallback(lambda res: self.do_cli("cp", self.filecap, outdir)) + def _resp((rc, out, err)): + self.failUnlessEqual(rc, 1) + self.failUnlessIn("error: you must specify a destination filename", + err) + d.addCallback(_resp) + # Create a directory, linked at tahoe:test + d.addCallback(lambda res: self.do_cli("mkdir", "tahoe:test")) + def _get_dir((rc, out, err)): + self.failUnlessEqual(rc, 0) + self.dircap = out.strip() + d.addCallback(_get_dir) + # Upload a file to the directory + d.addCallback(lambda res: + self.do_cli("put", fn1, "tahoe:test/test_file")) + d.addCallback(lambda (rc, out, err): self.failUnlessEqual(rc, 0)) + # cp DIRCAP/filename localdir + d.addCallback(lambda res: + self.do_cli("cp", self.dircap + "/test_file", outdir)) + def _get_resp((rc, out, err)): + self.failUnlessEqual(rc, 0) + results = open(os.path.join(outdir, "test_file"), "r").read() + self.failUnlessEqual(results, DATA1) + d.addCallback(_get_resp) + # cp -r DIRCAP/filename filename2 + d.addCallback(lambda res: + self.do_cli("cp", self.dircap + "/test_file", fn3)) + def _get_resp2((rc, out, err)): + self.failUnlessEqual(rc, 0) + results = open(fn3, "r").read() + self.failUnlessEqual(results, DATA1) + d.addCallback(_get_resp2) + return d + class Backup(GridTestMixin, CLITestMixin, StallMixin, unittest.TestCase): def writeto(self, path, data):