This commit is contained in:
Kovid Goyal 2014-03-28 16:05:23 +05:30
parent 5346868df7
commit a33b6098f7

View File

@ -19,6 +19,7 @@ from calibre.utils.config import device_prefs
MINIMUM_COL_WIDTH = 12 # : Minimum width of columns in ls output MINIMUM_COL_WIDTH = 12 # : Minimum width of columns in ls output
class FileFormatter(object): class FileFormatter(object):
def __init__(self, file): def __init__(self, file):
self.is_dir = file.is_dir self.is_dir = file.is_dir
self.is_readonly = file.is_readonly self.is_readonly = file.is_readonly
@ -33,9 +34,12 @@ class FileFormatter(object):
doc=""" The mode string for this file. There are only two modes read-only and read-write """ doc=""" The mode string for this file. There are only two modes read-only and read-write """
def fget(self): def fget(self):
mode, x = "-", "-" mode, x = "-", "-"
if self.is_dir: mode, x = "d", "x" if self.is_dir:
if self.is_readonly: mode += "r-"+x+"r-"+x+"r-"+x mode, x = "d", "x"
else: mode += "rw"+x+"rw"+x+"rw"+x if self.is_readonly:
mode += "r-"+x+"r-"+x+"r-"+x
else:
mode += "rw"+x+"rw"+x+"rw"+x
return mode return mode
return property(doc=doc, fget=fget) return property(doc=doc, fget=fget)
@ -49,18 +53,20 @@ class FileFormatter(object):
return name return name
return property(doc=doc, fget=fget) return property(doc=doc, fget=fget)
@dynamic_property @dynamic_property
def name_in_color(self): def name_in_color(self):
doc=""" The name in ANSI text. Directories are blue, ebooks are green """ doc=""" The name in ANSI text. Directories are blue, ebooks are green """
def fget(self): def fget(self):
cname = self.name cname = self.name
blue, green, normal = "", "", "" blue, green, normal = "", "", ""
if self.term: blue, green, normal = self.term.BLUE, self.term.GREEN, self.term.NORMAL if self.term:
if self.is_dir: cname = blue + self.name + normal blue, green, normal = self.term.BLUE, self.term.GREEN, self.term.NORMAL
if self.is_dir:
cname = blue + self.name + normal
else: else:
ext = self.name[self.name.rfind("."):] ext = self.name[self.name.rfind("."):]
if ext in (".pdf", ".rtf", ".lrf", ".lrx", ".txt"): cname = green + self.name + normal if ext in (".pdf", ".rtf", ".lrf", ".lrx", ".txt"):
cname = green + self.name + normal
return cname return cname
return property(doc=doc, fget=fget) return property(doc=doc, fget=fget)
@ -113,10 +119,12 @@ def ls(dev, path, recurse=False, human_readable_size=False, ll=False, cols=0):
return rowwidths return rowwidths
output = StringIO.StringIO() output = StringIO.StringIO()
if path.endswith("/") and len(path) > 1: path = path[:-1] if path.endswith("/") and len(path) > 1:
path = path[:-1]
dirs = dev.list(path, recurse) dirs = dev.list(path, recurse)
for dir in dirs: for dir in dirs:
if recurse: print >>output, dir[0] + ":" if recurse:
print >>output, dir[0] + ":"
lsoutput, lscoloutput = [], [] lsoutput, lscoloutput = [], []
files = dir[1] files = dir[1]
maxlen = 0 maxlen = 0
@ -126,7 +134,8 @@ def ls(dev, path, recurse=False, human_readable_size=False, ll=False, cols=0):
if human_readable_size: if human_readable_size:
file = FileFormatter(file) file = FileFormatter(file)
size = len(file.human_readable_size) size = len(file.human_readable_size)
if size > maxlen: maxlen = size if size > maxlen:
maxlen = size
for file in files: for file in files:
file = FileFormatter(file) file = FileFormatter(file)
name = file.name if ll else file.isdir_name name = file.name if ll else file.isdir_name
@ -134,7 +143,8 @@ def ls(dev, path, recurse=False, human_readable_size=False, ll=False, cols=0):
lscoloutput.append(name) lscoloutput.append(name)
if ll: if ll:
size = str(file.size) size = str(file.size)
if human_readable_size: size = file.human_readable_size if human_readable_size:
size = file.human_readable_size
print >>output, file.mode_string, ("%"+str(maxlen)+"s")%size, file.modification_time, name print >>output, file.mode_string, ("%"+str(maxlen)+"s")%size, file.modification_time, name
if not ll and len(lsoutput) > 0: if not ll and len(lsoutput) > 0:
trytable = [] trytable = []
@ -148,8 +158,10 @@ def ls(dev, path, recurse=False, human_readable_size=False, ll=False, cols=0):
if len(item) > colwidth - 1: if len(item) > colwidth - 1:
works, row_break = False, True works, row_break = False, True
break break
if row_break: break if row_break:
if works: break break
if works:
break
rowwidths = row_widths(trytable) rowwidths = row_widths(trytable)
trytablecol = col_split(lscoloutput, len(trytable[0])) trytablecol = col_split(lscoloutput, len(trytable[0]))
for r in range(len(trytable)): for r in range(len(trytable)):
@ -176,7 +188,7 @@ def main():
parser = OptionParser(usage="usage: %prog [options] command args\n\ncommand "+ parser = OptionParser(usage="usage: %prog [options] command args\n\ncommand "+
"is one of: info, books, df, ls, cp, mkdir, touch, cat, rm, eject, test_file\n\n"+ "is one of: info, books, df, ls, cp, mkdir, touch, cat, rm, eject, test_file\n\n"+
"For help on a particular command: %prog command", version=__appname__+" version: " + __version__) "For help on a particular command: %prog command", version=__appname__+" version: " + __version__)
parser.add_option("--log-packets", help="print out packet stream to stdout. "+\ parser.add_option("--log-packets", help="print out packet stream to stdout. "+
"The numbers in the left column are byte offsets that allow the packet size to be read off easily.", "The numbers in the left column are byte offsets that allow the packet size to be read off easily.",
dest="log_packets", action="store_true", default=False) dest="log_packets", action="store_true", default=False)
parser.remove_option("-h") parser.remove_option("-h")
@ -227,7 +239,6 @@ def main():
d.specialize_global_preferences(device_prefs) d.specialize_global_preferences(device_prefs)
break break
try: try:
if command == "df": if command == "df":
total = dev.total_space(end_session=False) total = dev.total_space(end_session=False)
@ -235,7 +246,7 @@ def main():
where = ("Memory", "Card A", "Card B") where = ("Memory", "Card A", "Card B")
print "Filesystem\tSize \tUsed \tAvail \tUse%" print "Filesystem\tSize \tUsed \tAvail \tUse%"
for i in range(3): for i in range(3):
print "%-10s\t%s\t%s\t%s\t%s"%(where[i], human_readable(total[i]), human_readable(total[i]-free[i]), human_readable(free[i]),\ print "%-10s\t%s\t%s\t%s\t%s"%(where[i], human_readable(total[i]), human_readable(total[i]-free[i]), human_readable(free[i]),
str(0 if total[i]==0 else int(100*(total[i]-free[i])/(total[i]*1.)))+"%") str(0 if total[i]==0 else int(100*(total[i]-free[i])/(total[i]*1.)))+"%")
elif command == 'eject': elif command == 'eject':
dev.eject() dev.eject()
@ -244,9 +255,11 @@ def main():
for book in dev.books(): for book in dev.books():
print book print book
print "\nBooks on storage carda:" print "\nBooks on storage carda:"
for book in dev.books(oncard='carda'): print book for book in dev.books(oncard='carda'):
print book
print "\nBooks on storage cardb:" print "\nBooks on storage cardb:"
for book in dev.books(oncard='cardb'): print book for book in dev.books(oncard='cardb'):
print book
elif command == "mkdir": elif command == "mkdir":
parser = OptionParser(usage="usage: %prog mkdir [options] path\nCreate a directory on the device\n\npath must begin with / or card:/") parser = OptionParser(usage="usage: %prog mkdir [options] path\nCreate a directory on the device\n\npath must begin with / or card:/")
if len(args) != 1: if len(args) != 1:
@ -255,8 +268,11 @@ def main():
dev.mkdir(args[0]) dev.mkdir(args[0])
elif command == "ls": elif command == "ls":
parser = OptionParser(usage="usage: %prog ls [options] path\nList files on the device\n\npath must begin with / or card:/") parser = OptionParser(usage="usage: %prog ls [options] path\nList files on the device\n\npath must begin with / or card:/")
parser.add_option("-l", help="In addition to the name of each file, print the file type, permissions, and timestamp (the modification time, in the local timezone). Times are local.", dest="ll", action="store_true", default=False) parser.add_option(
parser.add_option("-R", help="Recursively list subdirectories encountered. /dev and /proc are omitted", dest="recurse", action="store_true", default=False) "-l", help="In addition to the name of each file, print the file type, permissions, and timestamp (the modification time, in the local timezone). Times are local.", # noqa
dest="ll", action="store_true", default=False)
parser.add_option("-R", help="Recursively list subdirectories encountered. /dev and /proc are omitted",
dest="recurse", action="store_true", default=False)
parser.remove_option("-h") parser.remove_option("-h")
parser.add_option("-h", "--human-readable", help="show sizes in human readable format", dest="hrs", action="store_true", default=False) parser.add_option("-h", "--human-readable", help="show sizes in human readable format", dest="hrs", action="store_true", default=False)
options, args = parser.parse_args(args) options, args = parser.parse_args(args)
@ -283,7 +299,8 @@ def main():
if args[0].startswith("dev:"): if args[0].startswith("dev:"):
outfile = args[1] outfile = args[1]
path = args[0][7:] path = args[0][7:]
if path.endswith("/"): path = path[:-1] if path.endswith("/"):
path = path[:-1]
if os.path.isdir(outfile): if os.path.isdir(outfile):
outfile = os.path.join(outfile, path[path.rfind("/")+1:]) outfile = os.path.join(outfile, path[path.rfind("/")+1:])
try: try:
@ -316,18 +333,21 @@ def main():
return 1 return 1
elif command == "cat": elif command == "cat":
outfile = sys.stdout outfile = sys.stdout
parser = OptionParser(usage="usage: %prog cat path\nShow file on the device\n\npath should point to a file on the device and must begin with /,a:/ or b:/") parser = OptionParser(
usage="usage: %prog cat path\nShow file on the device\n\npath should point to a file on the device and must begin with /,a:/ or b:/")
options, args = parser.parse_args(args) options, args = parser.parse_args(args)
if len(args) != 1: if len(args) != 1:
parser.print_help() parser.print_help()
return 1 return 1
if args[0].endswith("/"): path = args[0][:-1] if args[0].endswith("/"):
else: path = args[0] path = args[0][:-1]
else:
path = args[0]
outfile = sys.stdout outfile = sys.stdout
dev.get_file(path, outfile) dev.get_file(path, outfile)
elif command == "rm": elif command == "rm":
parser = OptionParser(usage="usage: %prog rm path\nDelete files from the device\n\npath should point to a file or empty directory on the device "+\ parser = OptionParser(usage="usage: %prog rm path\nDelete files from the device\n\npath should point to a file or empty directory on the device "+
"and must begin with / or card:/\n\n"+\ "and must begin with / or card:/\n\n"+
"rm will DELETE the file. Be very CAREFUL") "rm will DELETE the file. Be very CAREFUL")
options, args = parser.parse_args(args) options, args = parser.parse_args(args)
if len(args) != 1: if len(args) != 1:
@ -335,7 +355,7 @@ def main():
return 1 return 1
dev.rm(args[0]) dev.rm(args[0])
elif command == "touch": elif command == "touch":
parser = OptionParser(usage="usage: %prog touch path\nCreate an empty file on the device\n\npath should point to a file on the device and must begin with /,a:/ or b:/\n\n"+ parser = OptionParser(usage="usage: %prog touch path\nCreate an empty file on the device\n\npath should point to a file on the device and must begin with /,a:/ or b:/\n\n"+ # noqa
"Unfortunately, I cant figure out how to update file times on the device, so if path already exists, touch does nothing") "Unfortunately, I cant figure out how to update file times on the device, so if path already exists, touch does nothing")
options, args = parser.parse_args(args) options, args = parser.parse_args(args)
if len(args) != 1: if len(args) != 1:
@ -358,7 +378,8 @@ def main():
dev.eject() dev.eject()
else: else:
parser.print_help() parser.print_help()
if getattr(dev, 'handle', False): dev.close() if getattr(dev, 'handle', False):
dev.close()
return 1 return 1
except DeviceLocked: except DeviceLocked:
print >> sys.stderr, "The device is locked. Use the --unlock option" print >> sys.stderr, "The device is locked. Use the --unlock option"