tahoe-lafs/src/allmydata/scripts/tahoe_ls.py

152 lines
4.3 KiB
Python

import urllib, time
import simplejson
from allmydata.scripts.common import get_alias, DEFAULT_ALIAS, escape_path
from allmydata.scripts.common_http import do_http
def list(options):
nodeurl = options['node-url']
aliases = options.aliases
where = options.where
stdout = options.stdout
stderr = options.stderr
if not nodeurl.endswith("/"):
nodeurl += "/"
if where.endswith("/"):
where = where[:-1]
rootcap, path = get_alias(aliases, where, DEFAULT_ALIAS)
url = nodeurl + "uri/%s" % urllib.quote(rootcap)
if path:
# move where.endswith check here?
url += "/" + escape_path(path)
assert not url.endswith("/")
url += "?t=json"
resp = do_http("GET", url)
if resp.status == 404:
print >>stderr, "No such file or directory"
return 2
if resp.status != 200:
print >>stderr, "Error during GET: %s %s %s" % (resp.status,
resp.reason,
resp.read())
if resp.status == 0:
return 3
else:
return resp.status
data = resp.read()
if options['json']:
print >>stdout, data
return
try:
parsed = simplejson.loads(data)
except Exception, le:
le.args = tuple(le.args + (data,))
raise
nodetype, d = parsed
children = {}
if nodetype == "dirnode":
children = d['children']
elif nodetype == "filenode":
childname = path.split("/")[-1]
children = {childname: d}
childnames = sorted(children.keys())
now = time.time()
# we build up a series of rows, then we loop through them to compute a
# maxwidth so we can format them tightly. Size, filename, and URI are the
# variable-width ones.
rows = []
for name in childnames:
name = unicode(name)
child = children[name]
childtype = child[0]
ctime = child[1]["metadata"].get("ctime")
mtime = child[1]["metadata"].get("mtime")
rw_uri = child[1].get("rw_uri")
ro_uri = child[1].get("ro_uri")
if ctime:
# match for formatting that GNU 'ls' does
if (now - ctime) > 6*30*24*60*60:
# old files
fmt = "%b %d %Y"
else:
fmt = "%b %d %H:%M"
ctime_s = time.strftime(fmt, time.localtime(ctime))
else:
ctime_s = "-"
if childtype == "dirnode":
t0 = "d"
size = "-"
classify = "/"
elif childtype == "filenode":
t0 = "-"
size = str(child[1]['size'])
classify = ""
if rw_uri:
classify = "*"
else:
t0 = "?"
size = "?"
classify = "?"
t1 = "-"
if ro_uri:
t1 = "r"
t2 = "-"
if rw_uri:
t2 = "w"
t3 = "-"
if childtype == "dirnode":
t3 = "x"
uri = rw_uri or ro_uri
line = []
if options["long"]:
line.append(t0+t1+t2+t3)
line.append(size)
line.append(ctime_s)
if not options["classify"]:
classify = ""
line.append(name + classify)
if options["uri"]:
line.append(uri)
if options["readonly-uri"]:
line.append(ro_uri or "-")
rows.append(line)
max_widths = []
left_justifys = []
for row in rows:
for i,cell in enumerate(row):
while len(max_widths) <= i:
max_widths.append(0)
while len(left_justifys) <= i:
left_justifys.append(False)
max_widths[i] = max(max_widths[i], len(cell))
if cell.startswith("URI"):
left_justifys[i] = True
if len(left_justifys) == 1:
left_justifys[0] = True
fmt_pieces = []
for i in range(len(max_widths)):
piece = "%"
if left_justifys[i]:
piece += "-"
piece += str(max_widths[i])
piece += "s"
fmt_pieces.append(piece)
fmt = " ".join(fmt_pieces)
for row in rows:
print >>stdout, (fmt % tuple(row)).rstrip()
return 0
# error cases that need improvement:
# list-one-file: tahoe ls my:docs/Makefile