Implement more coherent behavior when copying with dircaps/filecaps (closes #761). Patch by Kevan Carstensen.

This commit is contained in:
Brian Warner 2009-11-30 13:10:09 -08:00
parent 91e7cb484b
commit 74974b27fe
2 changed files with 71 additions and 2 deletions

View File

@ -441,13 +441,13 @@ class Copier:
self.caps_only = options["caps-only"] self.caps_only = options["caps-only"]
self.cache = {} self.cache = {}
try: try:
self.try_copy() status = self.try_copy()
return status
except TahoeError, te: except TahoeError, te:
Failure().printTraceback(self.stderr) Failure().printTraceback(self.stderr)
print >>self.stderr print >>self.stderr
te.display(self.stderr) te.display(self.stderr)
return 1 return 1
return 0
def try_copy(self): def try_copy(self):
source_specs = self.options.sources source_specs = self.options.sources
@ -498,6 +498,13 @@ class Copier:
return self.copy_file(source, target) return self.copy_file(source, target)
if isinstance(target, (LocalDirectoryTarget, TahoeDirectoryTarget)): 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) return self.copy_to_directory(sources, target)
self.to_stderr("unknown target") self.to_stderr("unknown target")
@ -587,6 +594,8 @@ class Copier:
writecap = ascii_or_none(d.get("rw_uri")) writecap = ascii_or_none(d.get("rw_uri"))
readcap = ascii_or_none(d.get("ro_uri")) readcap = ascii_or_none(d.get("ro_uri"))
mutable = d.get("mutable", False) # older nodes don't provide it 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) t = TahoeFileSource(self.nodeurl, mutable, writecap, readcap)
return name, t return name, t

View File

@ -934,6 +934,66 @@ class Cp(GridTestMixin, CLITestMixin, unittest.TestCase):
dn, "tahoe:")) dn, "tahoe:"))
return d 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): class Backup(GridTestMixin, CLITestMixin, StallMixin, unittest.TestCase):
def writeto(self, path, data): def writeto(self, path, data):