From: Brian Warner Date: Sun, 27 Dec 2009 22:54:43 +0000 (-0500) Subject: Fix 'tahoe ls' on files (#771). Patch adapted from Kevan Carstensen. X-Git-Tag: trac-4200~59 X-Git-Url: https://git.rkrishnan.org/components/com_hotproperty/simplejson/encoder.py.html?a=commitdiff_plain;h=a8a768ef9dbd2ffa433ac204c0343368a20dbe2b;p=tahoe-lafs%2Ftahoe-lafs.git Fix 'tahoe ls' on files (#771). Patch adapted from Kevan Carstensen. web/filenode.py: also serve edge metadata when using t=json on a DIRCAP/childname object. tahoe_ls.py: list file objects as if we were listing one-entry directories. Show edge metadata if we have it, which will be true when doing 'tahoe ls DIRCAP/filename' and false when doing 'tahoe ls FILECAP' --- diff --git a/src/allmydata/scripts/tahoe_ls.py b/src/allmydata/scripts/tahoe_ls.py index 1552da42..88bbde96 100644 --- a/src/allmydata/scripts/tahoe_ls.py +++ b/src/allmydata/scripts/tahoe_ls.py @@ -52,7 +52,7 @@ def list(options): children = d['children'] elif nodetype == "filenode": childname = path.split("/")[-1] - children = {childname: d} + children = {childname: (nodetype, d)} childnames = sorted(children.keys()) now = time.time() diff --git a/src/allmydata/test/test_cli.py b/src/allmydata/test/test_cli.py index fd12128c..3c5829f9 100644 --- a/src/allmydata/test/test_cli.py +++ b/src/allmydata/test/test_cli.py @@ -785,6 +785,11 @@ class List(GridTestMixin, CLITestMixin, unittest.TestCase): d.addCallback(_check3) d.addCallback(lambda ign: self.do_cli("ls", "0share")) d.addCallback(_check3) + def _check4((rc, out, err)): + self.failUnlessEqual(rc, 0) + self.failUnlessIn("good", out) + d.addCallback(lambda ign: self.do_cli("ls", "good")) + d.addCallback(_check4) return d class Mv(GridTestMixin, CLITestMixin, unittest.TestCase): diff --git a/src/allmydata/test/test_web.py b/src/allmydata/test/test_web.py index fd5e9942..529afe76 100644 --- a/src/allmydata/test/test_web.py +++ b/src/allmydata/test/test_web.py @@ -860,13 +860,26 @@ class Web(WebMixin, WebErrorMixin, testutil.StallMixin, unittest.TestCase): d.addBoth(self.should404, "test_DELETE_FILEURL_missing2") return d + def failUnlessHasBarDotTxtMetadata(self, res): + data = simplejson.loads(res) + self.failUnless(isinstance(data, list)) + self.failUnless(data[1].has_key("metadata")) + self.failUnless(data[1]["metadata"].has_key("ctime")) + self.failUnless(data[1]["metadata"].has_key("mtime")) + self.failUnlessEqual(data[1]["metadata"]["ctime"], + self._bar_txt_metadata["ctime"]) + def test_GET_FILEURL_json(self): # twisted.web.http.parse_qs ignores any query args without an '=', so # I can't do "GET /path?json", I have to do "GET /path/t=json" # instead. This may make it tricky to emulate the S3 interface # completely. d = self.GET(self.public_url + "/foo/bar.txt?t=json") - d.addCallback(self.failUnlessIsBarJSON) + def _check1(data): + self.failUnlessIsBarJSON(data) + self.failUnlessHasBarDotTxtMetadata(data) + return + d.addCallback(_check1) return d def test_GET_FILEURL_json_missing(self): diff --git a/src/allmydata/web/filenode.py b/src/allmydata/web/filenode.py index daf3d43f..b6a9a790 100644 --- a/src/allmydata/web/filenode.py +++ b/src/allmydata/web/filenode.py @@ -186,7 +186,12 @@ class FileNodeHandler(RenderMixin, rend.Page, ReplaceMeMixin): d.addCallback(lambda dn: FileDownloader(dn, filename)) return d if t == "json": - return FileJSONMetadata(ctx, self.node) + if self.parentnode and self.name: + d = self.parentnode.get_metadata_for(self.name) + else: + d = defer.succeed(None) + d.addCallback(lambda md: FileJSONMetadata(ctx, self.node, md)) + return d if t == "info": return MoreInfo(self.node) if t == "uri": @@ -421,7 +426,7 @@ class FileDownloader(rend.Page): return req.deferred -def FileJSONMetadata(ctx, filenode): +def FileJSONMetadata(ctx, filenode, edge_metadata=None): if filenode.is_readonly(): rw_uri = None ro_uri = filenode.get_uri() @@ -438,6 +443,8 @@ def FileJSONMetadata(ctx, filenode): if verifycap: data[1]['verify_uri'] = verifycap.to_string() data[1]['mutable'] = filenode.is_mutable() + if edge_metadata: + data[1]["metadata"] = edge_metadata return text_plain(simplejson.dumps(data, indent=1) + "\n", ctx) def FileURI(ctx, filenode):