]> arthur.barton.de Git - bup.git/commitdiff
Make "bup meta -tvv" output identical to "bup xstat".
authorRob Browning <rlb@defaultvalue.org>
Sun, 7 Aug 2011 17:01:08 +0000 (18:01 +0100)
committerRob Browning <rlb@defaultvalue.org>
Mon, 15 Oct 2012 02:42:53 +0000 (21:42 -0500)
Move the bits of xstat-cmd.py that generate the detailed metadata
representation to metadata.py and xstat.py to support their use from
both "bup xstat" and "bup meta -tvv".

Add size to detailed metadata description when available.

Signed-off-by: Rob Browning <rlb@defaultvalue.org>
Reviewed-by: Zoran Zaric <zz@zoranzaric.de>
cmd/xstat-cmd.py
lib/bup/metadata.py
lib/bup/xstat.py
t/test-meta.sh

index edd01f676e279080b73a2ccf5ab1ca8207c60b15..11b0b58fd179e4c8a410fa2746fdfd3eaa181289 100755 (executable)
@@ -7,17 +7,6 @@ import sys, stat, errno
 from bup import metadata, options, xstat
 from bup.helpers import handle_ctrl_c, saved_errors, add_error, log
 
-
-def fstimestr(fstime):
-    (s, ns) = xstat.fstime_to_timespec(fstime)
-    if(s < 0):
-        s += 1
-    if ns == 0:
-        return '%d' % s
-    else:
-        return '%d.%09d' % (s, ns)
-
-
 optspec = """
 bup xstat pathinfo [OPTION ...] <PATH ...>
 --
@@ -28,21 +17,7 @@ include-fields= include comma-separated fields (definitive if first)
 """
 
 target_filename = ''
-all_fields = frozenset(['path',
-                        'mode',
-                        'link-target',
-                        'rdev',
-                        'uid',
-                        'gid',
-                        'owner',
-                        'group',
-                        'atime',
-                        'mtime',
-                        'ctime',
-                        'linux-attr',
-                        'linux-xattr',
-                        'posix1e-acl'])
-active_fields = all_fields
+active_fields = metadata.all_fields
 
 handle_ctrl_c()
 
@@ -54,14 +29,14 @@ for flag, value in flags:
     if flag == '--exclude-fields':
         exclude_fields = frozenset(value.split(','))
         for f in exclude_fields:
-            if not f in all_fields:
+            if not f in metadata.all_fields:
                 o.fatal(f + ' is not a valid field name')
         active_fields = active_fields - exclude_fields
         treat_include_fields_as_definitive = False
     elif flag == '--include-fields':
         include_fields = frozenset(value.split(','))
         for f in include_fields:
-            if not f in all_fields:
+            if not f in metadata.all_fields:
                 o.fatal(f + ' is not a valid field name')
         if treat_include_fields_as_definitive:
             active_fields = include_fields
@@ -73,6 +48,7 @@ opt.verbose = opt.verbose or 0
 opt.quiet = opt.quiet or 0
 metadata.verbose = opt.verbose - opt.quiet
 
+first_path = True
 for path in remainder:
     try:
         m = metadata.from_path(path, archive_path = path)
@@ -82,55 +58,11 @@ for path in remainder:
             continue
         else:
             raise
-    if 'path' in active_fields:
-        print 'path:', m.path
-    if 'mode' in active_fields:
-        print 'mode: %s (%s)' % (oct(m.mode),
-                                 xstat.mode_str(m.mode))
-    if 'link-target' in active_fields and stat.S_ISLNK(m.mode):
-        print 'link-target:', m.symlink_target
-    if 'rdev' in active_fields:
-        print 'rdev:', m.rdev
-    if 'uid' in active_fields:
-        print 'uid:', m.uid
-    if 'gid' in active_fields:
-        print 'gid:', m.gid
-    if 'owner' in active_fields:
-        print 'owner:', m.owner
-    if 'group' in active_fields:
-        print 'group:', m.group
-    if 'atime' in active_fields:
-        # If we don't have utimensat, that means we have to use
-        # utime(), and utime() has no way to set the mtime/atime of a
-        # symlink.  Thus, the mtime/atime of a symlink is meaningless,
-        # so let's not report it.  (That way scripts comparing
-        # before/after won't trigger.)
-        if xstat.lutime or not stat.S_ISLNK(m.mode):
-            print 'atime: ' + fstimestr(m.atime)
-        else:
-            print 'atime: 0'
-    if 'mtime' in active_fields:
-        if xstat.lutime or not stat.S_ISLNK(m.mode):
-            print 'mtime: ' + fstimestr(m.mtime)
-        else:
-            print 'mtime: 0'
-    if 'ctime' in active_fields:
-        print 'ctime: ' + fstimestr(m.ctime)
-    if 'linux-attr' in active_fields and m.linux_attr:
-        print 'linux-attr:', hex(m.linux_attr)
-    if 'linux-xattr' in active_fields and m.linux_xattr:
-        for name, value in m.linux_xattr:
-            print 'linux-xattr: %s -> %s' % (name, repr(value))
-    if 'posix1e-acl' in active_fields and m.posix1e_acl and metadata.posix1e:
-        flags = metadata.posix1e.TEXT_ABBREVIATE
-        if stat.S_ISDIR(m.mode):
-            acl = m.posix1e_acl[0]
-            default_acl = m.posix1e_acl[2]
-            print acl.to_any_text('posix1e-acl: ', '\n', flags)
-            print acl.to_any_text('posix1e-acl-default: ', '\n', flags)
-        else:
-            acl = m.posix1e_acl[0]
-            print acl.to_any_text('posix1e-acl: ', '\n', flags)
+    if metadata.verbose >= 0:
+        if not first_path:
+            print
+        print metadata.detailed_str(m, active_fields)
+        first_path = False
 
 if saved_errors:
     log('WARNING: %d errors encountered.\n' % len(saved_errors))
index c76a25f51eaed4141254d20f0dc6dc2b6e55d30d..4f9e162b5cb9adcd50b622d9b545bc1b00a25d55 100644 (file)
@@ -4,7 +4,7 @@
 #
 # This code is covered under the terms of the GNU Library General
 # Public License as described in the bup LICENSE file.
-import errno, os, sys, stat, pwd, grp, struct, re
+import errno, os, sys, stat, time, pwd, grp, struct, re
 from cStringIO import StringIO
 from bup import vint, xstat
 from bup.drecurse import recursive_dirlist
@@ -690,6 +690,88 @@ def _set_up_path(meta, create_symlinks=True):
             meta.create_path(meta.path, create_symlinks=create_symlinks)
 
 
+all_fields = frozenset(['path',
+                        'mode',
+                        'link-target',
+                        'rdev',
+                        'size',
+                        'uid',
+                        'gid',
+                        'owner',
+                        'group',
+                        'atime',
+                        'mtime',
+                        'ctime',
+                        'linux-attr',
+                        'linux-xattr',
+                        'posix1e-acl'])
+
+
+def detailed_str(meta, fields = None):
+    # FIXME: should optional fields be omitted, or empty i.e. "rdev:
+    # 0", "link-target:", etc.
+    if not fields:
+        fields = all_fields
+
+    result = []
+    if 'path' in fields:
+        result.append('path: ' + meta.path)
+    if 'mode' in fields:
+        result.append('mode: %s (%s)' % (oct(meta.mode),
+                                         xstat.mode_str(meta.mode)))
+    if 'link-target' in fields and stat.S_ISLNK(meta.mode):
+        result.append('link-target: ' + meta.symlink_target)
+    if 'rdev' in fields:
+        if meta.rdev:
+            result.append('rdev: %d,%d' % (os.major(meta.rdev),
+                                           os.minor(meta.rdev)))
+        else:
+            result.append('rdev: 0')
+    if 'size' in fields and meta.size:
+        result.append('size: ' + str(meta.size))
+    if 'uid' in fields:
+        result.append('uid: ' + str(meta.uid))
+    if 'gid' in fields:
+        result.append('gid: ' + str(meta.gid))
+    if 'owner' in fields:
+        result.append('owner: ' + meta.owner)
+    if 'group' in fields:
+        result.append('group: ' + meta.group)
+    if 'atime' in fields:
+        # If we don't have xstat.lutime, that means we have to use
+        # utime(), and utime() has no way to set the mtime/atime of a
+        # symlink.  Thus, the mtime/atime of a symlink is meaningless,
+        # so let's not report it.  (That way scripts comparing
+        # before/after won't trigger.)
+        if xstat.lutime or not stat.S_ISLNK(meta.mode):
+            result.append('atime: ' + xstat.fstime_to_sec_str(meta.atime))
+        else:
+            result.append('atime: 0')
+    if 'mtime' in fields:
+        if xstat.lutime or not stat.S_ISLNK(meta.mode):
+            result.append('mtime: ' + xstat.fstime_to_sec_str(meta.mtime))
+        else:
+            result.append('mtime: 0')
+    if 'ctime' in fields:
+        result.append('ctime: ' + xstat.fstime_to_sec_str(meta.ctime))
+    if 'linux-attr' in fields and meta.linux_attr:
+        result.append('linux-attr: ' + hex(meta.linux_attr))
+    if 'linux-xattr' in fields and meta.linux_xattr:
+        for name, value in meta.linux_xattr:
+            result.append('linux-xattr: %s -> %s' % (name, repr(value)))
+    if 'posix1e-acl' in fields and meta.posix1e_acl and posix1e:
+        flags = posix1e.TEXT_ABBREVIATE
+        if stat.S_ISDIR(meta.mode):
+            acl = meta.posix1e_acl[0]
+            default_acl = meta.posix1e_acl[2]
+            result.append(acl.to_any_text('posix1e-acl: ', '\n', flags))
+            result.append(acl.to_any_text('posix1e-acl-default: ', '\n', flags))
+        else:
+            acl = meta.posix1e_acl[0]
+            result.append(acl.to_any_text('posix1e-acl: ', '\n', flags))
+    return '\n'.join(result)
+
+
 class _ArchiveIterator:
     def next(self):
         try:
@@ -705,10 +787,19 @@ class _ArchiveIterator:
 
 
 def display_archive(file):
-    for meta in _ArchiveIterator(file):
-        if verbose:
-            print meta.path # FIXME
-        else:
+    if verbose > 1:
+        first_item = True
+        for meta in _ArchiveIterator(file):
+            if not first_item:
+                print
+            print detailed_str(meta)
+            first_item = False
+    elif verbose >= 0:
+        for meta in _ArchiveIterator(file):
+            if not meta.path:
+                print >> sys.stderr, \
+                    'bup: cannot list path for metadata without path'
+                sys.exit(1)
             print meta.path
 
 
index 7fcbe8aa8414a1f0fee3769a9ec5e8f110d89f2f..be6f0620fa3ac76689cd07877e9f9c206602d373 100644 (file)
@@ -38,6 +38,16 @@ def fstime_to_timespec(ns):
     return nsecs_to_timespec(ns)
 
 
+def fstime_to_sec_str(fstime):
+    (s, ns) = fstime_to_timespec(fstime)
+    if(s < 0):
+        s += 1
+    if ns == 0:
+        return '%d' % s
+    else:
+        return '%d.%09d' % (s, ns)
+
+
 if _have_bup_utime_ns:
     def utime(path, times):
         """Times must be provided as (atime_ns, mtime_ns)."""
index 5ce48d55d0e80ec8cf49800938691d8c59a84d57..e94a85b3258276e8ad8af89429792b93093d1cd1 100755 (executable)
@@ -20,7 +20,7 @@ genstat()
     (
         export PATH="$TOP:$PATH" # pick up bup
         # Skip atime (test elsewhere) to avoid the observer effect.
-        find . | sort | xargs bup xstat --exclude-fields ctime,atime
+        find . | sort | xargs bup xstat --exclude-fields ctime,atime,size
     )
 }