]> arthur.barton.de Git - bup.git/blob - lib/bup/ls.py
Add -n, -A, -F, --file-type, --numeric-ids and detailed -l to "bup ls".
[bup.git] / lib / bup / ls.py
1 """Common code for listing files from a bup repository."""
2 import copy, stat
3 from bup import metadata, options, vfs
4 from helpers import *
5
6
7 def node_info(n, name,
8               show_hash = False,
9               long_fmt = False,
10               classification = None,
11               numeric_ids = False,
12               human_readable = False):
13     """Return a string containing the information to display for the node
14     n.  Classification may be "all", "type", or None.
15
16     """
17     result = ''
18     if show_hash:
19         result += "%s " % n.hash.encode('hex')
20     if long_fmt:
21         meta = copy.copy(n.metadata())
22         meta.size = n.size()
23         result += metadata.summary_str(meta,
24                                        numeric_ids = numeric_ids,
25                                        human_readable = human_readable) + ' '
26     result += name
27     if classification:
28         if n.metadata():
29             mode = n.metadata().mode
30         else:
31             mode = n.mode
32         if stat.S_ISREG(mode):
33             if classification == 'all' \
34                and stat.S_IMODE(mode) & (stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH):
35                 result += '*'
36         elif stat.S_ISDIR(mode):
37             result += '/'
38         elif stat.S_ISLNK(mode):
39             result += '@'
40         elif stat.S_ISFIFO(mode):
41             result += '|'
42         elif stat.S_ISSOCK(mode):
43             result += '='
44     return result
45
46
47 optspec = """
48 %sls [-a] [path...]
49 --
50 s,hash   show hash for each file
51 a,all    show hidden files
52 A,almost-all    show hidden files except . and ..
53 l        use a detailed, long listing format
54 F,classify append type indicator: dir/ sym@ fifo| sock= exec*
55 file-type append type indicator: dir/ sym@ fifo| sock=
56 human-readable    print human readable file sizes (i.e. 3.9K, 4.7M)
57 n,numeric-ids list numeric IDs (user, group, etc.) rather than names
58 """
59
60 def do_ls(args, pwd, default='.', onabort=None, spec_prefix=''):
61     """Output a listing of a file or directory in the bup repository.
62
63     When a long listing is not requested and stdout is attached to a
64     tty, the output is formatted in columns. When not attached to tty
65     (for example when the output is piped to another command), one
66     file is listed per line.
67
68     """
69     if onabort:
70         o = options.Options(optspec % spec_prefix, onabort=onabort)
71     else:
72         o = options.Options(optspec % spec_prefix)
73     (opt, flags, extra) = o.parse(args)
74
75     # Handle order-sensitive options.
76     classification = None
77     show_hidden = None
78     for flag in flags:
79         (option, parameter) = flag
80         if option in ('-F', '--classify'):
81             classification = 'all'
82         elif option == '--file-type':
83             classification = 'type'
84         elif option in ('-a', '--all'):
85             show_hidden = 'all'
86         elif option in ('-A', '--almost-all'):
87             show_hidden = 'almost'
88
89     L = []
90     def output_node_info(node, name):
91         info = node_info(node, name,
92                          show_hash = opt.hash,
93                          long_fmt = opt.l,
94                          classification = classification,
95                          numeric_ids = opt.numeric_ids,
96                          human_readable = opt.human_readable)
97         if not opt.l and istty1:
98             L.append(info)
99         else:
100             print info
101
102     ret = 0
103     for path in (extra or [default]):
104         try:
105             n = pwd.try_resolve(path)
106
107             if stat.S_ISDIR(n.mode):
108                 if show_hidden == 'all':
109                     for implied, name in ((n, '.'), (n.parent, '..')):
110                         output_node_info(implied, name)
111                 for sub in n:
112                     name = sub.name
113                     if show_hidden in ('almost', 'all') \
114                        or not len(name)>1 or not name.startswith('.'):
115                         output_node_info(sub, name)
116             else:
117                 output_node_info(n, path)
118         except vfs.NodeError, e:
119             log('error: %s\n' % e)
120             ret = 1
121
122     if L:
123         sys.stdout.write(columnate(L, ''))
124
125     return ret