3 from calendar import timegm
4 from pipes import quote
5 from subprocess import check_call, check_output
6 from time import strftime, strptime
10 from bup import git, options, vfs
11 from bup.helpers import handle_ctrl_c, log, saved_errors, unlink
15 bup import-duplicity [-n] <duplicity-source-url> <bup-save-name>
17 n,dry-run don't do anything; just print what would be done
22 if isinstance(cmd, basestring):
25 log(' '.join(map(quote, cmd)) + '\n')
28 def exc(cmd, shell=False):
32 check_call(cmd, shell=shell)
34 def exo(cmd, shell=False):
38 return check_output(cmd, shell=shell)
43 o = options.Options(optspec)
44 opt, flags, extra = o.parse(sys.argv[1:])
46 if len(extra) < 1 or not extra[0]:
47 o.fatal('duplicity source URL required')
48 if len(extra) < 2 or not extra[1]:
49 o.fatal('bup destination save name required')
51 o.fatal('too many arguments')
53 source_url, save_name = extra
56 git.check_repo_or_die()
57 top = vfs.RefList(None)
59 tmpdir = tempfile.mkdtemp(prefix='bup-import-dup-')
61 dup = ['duplicity', '--archive-dir', tmpdir + '/dup-cache']
62 restoredir = tmpdir + '/restore'
63 tmpidx = tmpdir + '/index'
65 exo(' '.join(map(quote, dup))
66 + ' collection-status --log-fd=3 %s 3>&1 1>&2' % quote(source_url),
68 # Duplicity output lines of interest look like this (one leading space):
69 # full 20150222T073111Z 1 noenc
70 # inc 20150222T073233Z 1 noenc
72 for line in collection_status.splitlines():
73 if line.startswith(' inc '):
74 assert(len(line) >= len(' inc 20150222T073233Z'))
75 dup_timestamps.append(line[5:21])
76 elif line.startswith(' full '):
77 assert(len(line) >= len(' full 20150222T073233Z'))
78 dup_timestamps.append(line[6:22])
79 for i, dup_ts in enumerate(dup_timestamps):
80 tm = strptime(dup_ts, '%Y%m%dT%H%M%SZ')
81 exc(['rm', '-rf', restoredir])
82 exc(dup + ['restore', '-t', dup_ts, source_url, restoredir])
83 exc([bup, 'index', '-uxf', tmpidx, restoredir])
84 exc([bup, 'save', '--strip', '--date', str(timegm(tm)), '-f', tmpidx,
85 '-n', save_name, restoredir])
87 exc(['rm', '-rf', tmpdir])
90 log('warning: %d errors encountered\n' % len(saved_errors))