Browse Source

archive file listing output formatting
Coding style fixup
Add --list-format exmaple to usage examples

Teemu Toivanen 9 years ago
parent
commit
14f0fa6f6a
3 changed files with 87 additions and 10 deletions
  1. 49 10
      borg/archiver.py
  2. 22 0
      borg/helpers.py
  3. 16 0
      docs/usage.rst

+ 49 - 10
borg/archiver.py

@@ -15,7 +15,7 @@ import textwrap
 import traceback
 
 from . import __version__
-from .helpers import Error, location_validator, format_time, format_file_size, \
+from .helpers import Error, location_validator, format_time, format_line, safe_timestamp, format_file_size, \
     parse_pattern, PathPrefixPattern, to_localtime, timestamp, \
     get_cache_dir, get_keys_dir, prune_within, prune_split, \
     Manifest, remove_surrogates, update_excludes, format_archive, check_extension_modules, Statistics, \
@@ -442,6 +442,13 @@ class Archiver:
                 for item in archive.iter_items():
                     print(remove_surrogates(item[b'path']))
             else:
+                longformat="{mode} {user:6} {group:6} {size:8d} {isomtime} {path}{extra}{NEWLINE}"
+                userformat=longformat
+                if args.listformat:
+                    userformat=args.listformat                
+                
+                archive_name=archive.name
+
                 for item in archive.iter_items():
                     mode = stat.filemode(item[b'mode'])
                     type = mode[0]
@@ -451,12 +458,12 @@ class Archiver:
                             size = sum(size for _, size, _ in item[b'chunks'])
                         except KeyError:
                             pass
-                    try:
-                        mtime = datetime.fromtimestamp(bigint_to_int(item[b'mtime']) / 1e9)
-                    except OverflowError:
-                        # likely a broken mtime and datetime did not want to go beyond year 9999
-                        mtime = datetime(9999, 12, 31, 23, 59, 59)
+                    atime=safe_timestamp(item[b'atime'])
+                    ctime=safe_timestamp(item[b'ctime'])
+                    mtime=safe_timestamp(item[b'mtime'])
+                    
                     if b'source' in item:
+                        source = item[b'source']
                         if type == 'l':
                             extra = ' -> %s' % item[b'source']
                         else:
@@ -464,10 +471,40 @@ class Archiver:
                             extra = ' link to %s' % item[b'source']
                     else:
                         extra = ''
-                    print('%s %-6s %-6s %8d %s %s%s' % (
-                        mode, item[b'user'] or item[b'uid'],
-                        item[b'group'] or item[b'gid'], size, format_time(mtime),
-                        remove_surrogates(item[b'path']), extra))
+                        source = ''
+                     
+                    formatdata={
+                        'mode': mode,
+                        'bmode': item[b'mode'],
+                        'type': type,
+                        'source': source,
+                        'linktarget': source,
+                        'user': item[b'user'] or item[b'uid'],
+                        'uid': item[b'uid'],
+                        'group': item[b'group'] or item[b'gid'],
+                        'gid': item[b'gid'],
+                        'size': size,
+                        'isomtime': format_time(mtime),
+                        'mtime': mtime,
+                        'isoctime': format_time(ctime),
+                        'ctime': ctime,
+                        'isoatime': format_time(atime),
+                        'atime': atime,
+                        'path': remove_surrogates(item[b'path']), 
+                        'extra': extra,
+                        'archivename': archive_name,
+                        'SPACE': " ",
+                        'TAB': "\t",
+                        'LF': "\n",
+                        'CR': "\r",
+                        'NEWLINE': os.linesep,
+                        'formatkeys': ()
+                        }
+                    formatdata["formatkeys"]=list(formatdata.keys())
+                    
+
+                    print(format_line(userformat, formatdata), end='')
+
         else:
             for archive_info in manifest.list_archive_infos(sort_by='ts'):
                 if args.prefix and not archive_info.name.startswith(args.prefix):
@@ -1098,6 +1135,8 @@ class Archiver:
         subparser.add_argument('--short', dest='short',
                                action='store_true', default=False,
                                help='only print file/directory names, nothing else')
+        subparser.add_argument('--list-format', dest='listformat', type=str,
+                               help='Format archive listing line')
         subparser.add_argument('-P', '--prefix', dest='prefix', type=str,
                                help='only consider archive names starting with this prefix')
         subparser.add_argument('location', metavar='REPOSITORY_OR_ARCHIVE', nargs='?', default='',

+ 22 - 0
borg/helpers.py

@@ -518,6 +518,28 @@ def dir_is_tagged(path, exclude_caches, exclude_if_present):
                 tag_paths.append(tag_path)
     return tag_paths
 
+def format_line(formatstr, data):
+    """Filter out unwanted properties of str.format(), because "formatstr" 
+    is user provided. 
+    """    
+    try:
+        return(formatstr.format(**data))
+    except KeyError as e:
+        print('Error in lineformat: "{}" - reason "{}"'.format(formatstr, str(e)))
+    except ValueError as e:
+        print('Error in lineformat: "{}" - reason "{}"'.format(formatstr, str(e)))
+    except:
+        print('Line format error')
+        raise   
+    return ''
+
+def safe_timestamp(timedata):    
+    try:
+        return datetime.fromtimestamp(bigint_to_int(timedata) / 1e9)
+    except OverflowError:
+        # likely a broken file time and datetime did not want to go beyond year 9999
+        return datetime(9999, 12, 31, 23, 59, 59)
+
 
 def format_time(t):
     """use ISO-8601 date and time format

+ 16 - 0
docs/usage.rst

@@ -334,7 +334,23 @@ Examples
     -rw-r--r-- root   root       1383 May 22 22:25 etc/ImageMagick-6/colors.xml
     ...
 
+    $ borg list /mnt/backup::archiveA --list-format="{mode} {user:6} {group:6} {size:8d} {isomtime} {path}{extra}{NEWLINE}"
+    drwxrwxr-x user   user          0 Sun, 2015-02-01 11:00:00 .
+    drwxrwxr-x user   user          0 Sun, 2015-02-01 11:00:00 code
+    drwxrwxr-x user   user          0 Sun, 2015-02-01 11:00:00 code/myproject
+    -rw-rw-r-- user   user    1416192 Sun, 2015-02-01 11:00:00 code/myproject/file.ext
+    ...
 
+    # see what is change between archives, based on file modification time, size and file path
+    $ borg list /mnt/backup::archiveA --list-format="{mtime:%s}{TAB}{size}{TAB}{path}{LF}" |sort -n > /tmp/list.archiveA
+    $ borg list /mnt/backup::archiveB --list-format="{mtime:%s}{TAB}{size}{TAB}{path}{LF}" |sort -n > /tmp/list.archiveB
+    $ diff -y /tmp/list.archiveA /tmp/list.archiveB
+    1422781200      0       .                                       1422781200      0       .
+    1422781200      0       code                                    1422781200      0       code
+    1422781200      0       code/myproject                          1422781200      0       code/myproject
+    1422781200      1416192 code/myproject/file.ext               | 1454664653      1416192 code/myproject/file.ext
+    ...
+    
 .. include:: usage/prune.rst.inc
 
 Examples