]> git.rkrishnan.org Git - tahoe-lafs/tahoe-lafs.git/blob - src/allmydata/scripts/tahoe_ls.py
Alter CLI utilities to handle nonexistent aliases better
[tahoe-lafs/tahoe-lafs.git] / src / allmydata / scripts / tahoe_ls.py
1
2 import urllib, time
3 import simplejson
4 from allmydata.scripts.common import get_alias, DEFAULT_ALIAS, escape_path, \
5                                      UnknownAliasError
6 from allmydata.scripts.common_http import do_http
7
8 def list(options):
9     nodeurl = options['node-url']
10     aliases = options.aliases
11     where = options.where
12     stdout = options.stdout
13     stderr = options.stderr
14
15     if not nodeurl.endswith("/"):
16         nodeurl += "/"
17     if where.endswith("/"):
18         where = where[:-1]
19     try:
20         rootcap, path = get_alias(aliases, where, DEFAULT_ALIAS)
21     except UnknownAliasError, e:
22         print >>stderr, "error: %s" % e.args[0]
23         return 1
24     url = nodeurl + "uri/%s" % urllib.quote(rootcap)
25     if path:
26         # move where.endswith check here?
27         url += "/" + escape_path(path)
28     assert not url.endswith("/")
29     url += "?t=json"
30     resp = do_http("GET", url)
31     if resp.status == 404:
32         print >>stderr, "No such file or directory"
33         return 2
34     if resp.status != 200:
35         print >>stderr, "Error during GET: %s %s %s" % (resp.status,
36                                                         resp.reason,
37                                                         resp.read())
38         if resp.status == 0:
39             return 3
40         else:
41             return resp.status
42
43     data = resp.read()
44
45     if options['json']:
46         print >>stdout, data
47         return
48
49     try:
50         parsed = simplejson.loads(data)
51     except Exception, le:
52         le.args = tuple(le.args + (data,))
53         raise
54     nodetype, d = parsed
55     children = {}
56     if nodetype == "dirnode":
57         children = d['children']
58     elif nodetype == "filenode":
59         childname = path.split("/")[-1]
60         children = {childname: (nodetype, d)}
61         if "metadata" not in d:
62             d["metadata"] = {}
63     childnames = sorted(children.keys())
64     now = time.time()
65
66     # we build up a series of rows, then we loop through them to compute a
67     # maxwidth so we can format them tightly. Size, filename, and URI are the
68     # variable-width ones.
69     rows = []
70
71     for name in childnames:
72         name = unicode(name)
73         child = children[name]
74         childtype = child[0]
75
76         # See webapi.txt for a discussion of the meanings of unix local
77         # filesystem mtime and ctime, Tahoe mtime and ctime, and Tahoe
78         # linkmotime and linkcrtime.
79         ctime = child[1].get("metadata", {}).get('tahoe', {}).get("linkcrtime")
80         if not ctime:
81             ctime = child[1]["metadata"].get("ctime")
82
83         mtime = child[1].get("metadata", {}).get('tahoe', {}).get("linkmotime")
84         if not mtime:
85             mtime = child[1]["metadata"].get("mtime")
86         rw_uri = child[1].get("rw_uri")
87         ro_uri = child[1].get("ro_uri")
88         if ctime:
89             # match for formatting that GNU 'ls' does
90             if (now - ctime) > 6*30*24*60*60:
91                 # old files
92                 fmt = "%b %d  %Y"
93             else:
94                 fmt = "%b %d %H:%M"
95             ctime_s = time.strftime(fmt, time.localtime(ctime))
96         else:
97             ctime_s = "-"
98         if childtype == "dirnode":
99             t0 = "d"
100             size = "-"
101             classify = "/"
102         elif childtype == "filenode":
103             t0 = "-"
104             size = str(child[1]['size'])
105             classify = ""
106             if rw_uri:
107                 classify = "*"
108         else:
109             t0 = "?"
110             size = "?"
111             classify = "?"
112         t1 = "-"
113         if ro_uri:
114             t1 = "r"
115         t2 = "-"
116         if rw_uri:
117             t2 = "w"
118         t3 = "-"
119         if childtype == "dirnode":
120             t3 = "x"
121
122         uri = rw_uri or ro_uri
123
124         line = []
125         if options["long"]:
126             line.append(t0+t1+t2+t3)
127             line.append(size)
128             line.append(ctime_s)
129         if not options["classify"]:
130             classify = ""
131         line.append(name + classify)
132         if options["uri"]:
133             line.append(uri)
134         if options["readonly-uri"]:
135             line.append(ro_uri or "-")
136
137         rows.append(line)
138
139     max_widths = []
140     left_justifys = []
141     for row in rows:
142         for i,cell in enumerate(row):
143             while len(max_widths) <= i:
144                 max_widths.append(0)
145             while len(left_justifys) <= i:
146                 left_justifys.append(False)
147             max_widths[i] = max(max_widths[i], len(cell))
148             if cell.startswith("URI"):
149                 left_justifys[i] = True
150     if len(left_justifys) == 1:
151         left_justifys[0] = True
152     fmt_pieces = []
153     for i in range(len(max_widths)):
154         piece = "%"
155         if left_justifys[i]:
156             piece += "-"
157         piece += str(max_widths[i])
158         piece += "s"
159         fmt_pieces.append(piece)
160     fmt = " ".join(fmt_pieces)
161     for row in rows:
162         print >>stdout, (fmt % tuple(row)).rstrip()
163
164     return 0
165
166 # error cases that need improvement:
167 #  list-one-file: tahoe ls my:docs/Makefile