-#!/usr/bin/env python
+#!/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 PIPE, Popen
+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')
else:
par2_ok = 1
-def parv(lvl):
- if opt.verbose >= lvl:
- if istty2:
- 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)
+ p = subprocess.Popen(('par2', 'create', '-qq', '-t1', canary),
+ stderr=PIPE, stdin=nullf)
+ _, err = p.communicate()
+ parallel = p.returncode == 0
+ if opt.verbose:
+ if err != b'Invalid option specified: -t1\n':
+ log('Unexpected par2 error output\n')
+ log(err)
+ if parallel:
+ log('Assuming par2 supports parallel processing\n')
+ else:
+ log('Assuming par2 does not support parallel processing\n')
+ return parallel
+ 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')
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:
action_result = 'ok'
else:
assert(opt.generate and (not par2_ok or par2_exists))
- if par2_ok:
- action_result = 'exists'
- else:
- action_result = 'skipped'
+ action_result = 'exists' if par2_exists else 'skipped'
if opt.verbose:
- print last, action_result
+ print(last, action_result)
return code
else: # child
try:
sys.exit(do_pack(base, last, par2_exists))
- except Exception, e:
+ except Exception as e:
log('exception: %r\n' % e)
sys.exit(99)