]> arthur.barton.de Git - bup.git/blobdiff - cmd/fsck-cmd.py
fsck: only specify -t1 when par2 appears to support it
[bup.git] / cmd / fsck-cmd.py
index aa78d88320af16624f1ccd8d59e9fad3ba6fa6e3..8ba698c9d159388407e4e256554eb822cdcb8582 100755 (executable)
@@ -1,13 +1,24 @@
-#!/usr/bin/env python
-import sys, os, glob, subprocess, time
+#!/bin/sh
+"""": # -*-python-*-
+bup_python="$(dirname "$0")/bup-python" || exit $?
+exec "$bup_python" "$0" ${1+"$@"}
+"""
+# end of bup preamble
+
+from __future__ import absolute_import, print_function
+import sys, os, glob, subprocess
+from shutil import rmtree
+from subprocess import call
+from tempfile import mkdtemp
+
 from bup import options, git
-from bup.helpers import *
+from bup.helpers import Sha1, chunkyreader, istty2, log, progress
 
 par2_ok = 0
 nullf = open('/dev/null')
 
 def debug(s):
-    if opt.verbose:
+    if opt.verbose > 1:
         log(s)
 
 def run(argv):
@@ -34,24 +45,45 @@ def par2_setup():
     else:
         par2_ok = 1
 
-def parv(lvl):
-    if opt.verbose >= lvl:
-        if istty:
-            return []
-        else:
-            return ['-q']
+def is_par2_parallel():
+    # A true result means it definitely allows -t1; a false result is
+    # technically inconclusive, but likely means no.
+    tmpdir = mkdtemp(prefix="bup-fsck")
+    try:
+        canary = tmpdir + '/canary'
+        with open(canary, 'w') as f:
+            print('canary', file=f)
+        rc = call(('par2', 'create', '-qq', '-t1', canary))
+        return rc == 0
+    finally:
+        rmtree(tmpdir)
+
+_par2_parallel = None
+
+def par2(action, args, verb_floor=0):
+    global _par2_parallel
+    if _par2_parallel is None:
+        _par2_parallel = is_par2_parallel()
+    cmd = ['par2', action]
+    if opt.verbose >= verb_floor and not istty2:
+        cmd.append('-q')
     else:
-        return ['-qq']
+        cmd.append('-qq')
+    if _par2_parallel:
+        cmd.append('-t1')
+    cmd.extend(args)
+    return run(cmd)
 
 def par2_generate(base):
-    return run(['par2', 'create', '-n1', '-c200'] + parv(2)
-               + ['--', base, base+'.pack', base+'.idx'])
+    return par2('create',
+                ['-n1', '-c200', '--', base, base + '.pack', base + '.idx'],
+                verb_floor=2)
 
 def par2_verify(base):
-    return run(['par2', 'verify'] + parv(3) + ['--', base])
+    return par2('verify', ['--', base], verb_floor=3)
 
 def par2_repair(base):
-    return run(['par2', 'repair'] + parv(2) + ['--', base])
+    return par2('repair', ['--', base], verb_floor=2)
 
 def quick_verify(base):
     f = open(base + '.pack', 'rb')
@@ -71,15 +103,15 @@ def git_verify(base):
     if opt.quick:
         try:
             quick_verify(base)
-        except Exception, e:
-            debug('error: %s\n' % e)
+        except Exception as e:
+            log('error: %s\n' % e)
             return 1
         return 0
     else:
         return run(['git', 'verify-pack', '--', base])
     
     
-def do_pack(base, last):
+def do_pack(base, last, par2_exists):
     code = 0
     if par2_ok and par2_exists and (opt.repair or not opt.generate):
         vresult = par2_verify(base)
@@ -87,34 +119,41 @@ def do_pack(base, last):
             if opt.repair:
                 rresult = par2_repair(base)
                 if rresult != 0:
-                    print '%s par2 repair: failed (%d)' % (last, rresult)
+                    action_result = 'failed'
+                    log('%s par2 repair: failed (%d)\n' % (last, rresult))
                     code = rresult
                 else:
-                    print '%s par2 repair: succeeded (0)' % last
+                    action_result = 'repaired'
+                    log('%s par2 repair: succeeded (0)\n' % last)
                     code = 100
             else:
-                print '%s par2 verify: failed (%d)' % (last, vresult)
+                action_result = 'failed'
+                log('%s par2 verify: failed (%d)\n' % (last, vresult))
                 code = vresult
         else:
-            print '%s ok' % last
+            action_result = 'ok'
     elif not opt.generate or (par2_ok and not par2_exists):
         gresult = git_verify(base)
         if gresult != 0:
-            print '%s git verify: failed (%d)' % (last, gresult)
+            action_result = 'failed'
+            log('%s git verify: failed (%d)\n' % (last, gresult))
             code = gresult
         else:
             if par2_ok and opt.generate:
                 presult = par2_generate(base)
                 if presult != 0:
-                    print '%s par2 create: failed (%d)' % (last, presult)
+                    action_result = 'failed'
+                    log('%s par2 create: failed (%d)\n' % (last, presult))
                     code = presult
                 else:
-                    print '%s ok' % last
+                    action_result = 'generated'
             else:
-                print '%s ok' % last
+                action_result = 'ok'
     else:
         assert(opt.generate and (not par2_ok or par2_exists))
-        debug('    skipped: par2 file already generated.\n')
+        action_result = 'exists' if par2_exists else 'skipped'
+    if opt.verbose:
+        print(last, action_result)
     return code
 
 
@@ -129,7 +168,7 @@ j,jobs=     run 'n' jobs in parallel
 par2-ok     immediately return 0 if par2 is ok, 1 if not
 disable-par2  ignore par2 even if it is available
 """
-o = options.Options('bup fsck', optspec)
+o = options.Options(optspec)
 (opt, flags, extra) = o.parse(sys.argv[1:])
 
 par2_setup()
@@ -172,7 +211,7 @@ for name in extra:
         progress('fsck (%d/%d)\r' % (count, len(extra)))
     
     if not opt.jobs:
-        nc = do_pack(base, last)
+        nc = do_pack(base, last, par2_exists)
         code = code or nc
         count += 1
     else:
@@ -188,8 +227,8 @@ for name in extra:
             outstanding[pid] = 1
         else: # child
             try:
-                sys.exit(do_pack(base, last))
-            except Exception, e:
+                sys.exit(do_pack(base, last, par2_exists))
+            except Exception as e:
                 log('exception: %r\n' % e)
                 sys.exit(99)
                 
@@ -203,6 +242,6 @@ while len(outstanding):
     if not opt.verbose:
         progress('fsck (%d/%d)\r' % (count, len(extra)))
 
-if not opt.verbose and istty:
-    log('fsck done.           \n')
+if istty2:
+    debug('fsck done.           \n')
 sys.exit(code)