forked from ostreedev/ostree-releng-scripts
-
Notifications
You must be signed in to change notification settings - Fork 0
/
rsync-repos
executable file
·52 lines (46 loc) · 2.12 KB
/
rsync-repos
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#!/usr/bin/env python
#
# Use rsync to intelligently sync OSTree repositories. This
# avoids a few race conditions and issues that could otherwise
# occur if one simply does the whole repository in a single run.
#
# Known issues:
# - Ignores the fact that detached metadata (e.g. GPG signatures)
# can be updated asynchronously.
#
# Copyright 2016 Colin Walters <[email protected]>
# Licensed under the new-BSD license (http://www.opensource.org/licenses/bsd-license.php)
import os, sys, subprocess, argparse, shlex
def fatal(msg):
print >>sys.stderr, msg
sys.exit(1)
parser = argparse.ArgumentParser()
parser.add_argument("--src", help="Source path",
action='store', required=True)
parser.add_argument("--dest", help="Destination path",
action='store', required=True)
parser.add_argument("--rsync-opts", help="Additional rsync options (parsed via shell)",
action='store', default=None)
parser.add_argument("--rsync-opt", help="Additional (single) rsync option",
action='append', default=[])
args = parser.parse_args()
OBJECTS_AND_DELTAS = ['/objects', '/objects/**', '/deltas', '/deltas/**']
# We rsync in reverse data dependence order - the summary and refs
# point to objects + deltas. Our first pass over the objects doesn't
# perform any deletions, as that would create race conditions. We
# do handle deletions for refs and summary.
# Finally, we handle any deletions for objects and deltas.
RSYNC_ORDERING = [(OBJECTS_AND_DELTAS, ['--ignore-existing']),
(['/refs', '/refs/**', '/summary', '/summary.sig'], ['--delete', '--ignore-missing-args']),
(OBJECTS_AND_DELTAS, ['--ignore-existing', '--delete'])]
for (paths, opts) in RSYNC_ORDERING:
argv = ['rsync', '-rlpt']
for path in paths:
argv.append('--include=' + path)
argv.extend(['--exclude=*', args.src, args.dest])
argv.extend(opts)
if args.rsync_opts is not None:
argv.extend(shlex.split(args.rsync_opts))
argv.extend(args.rsync_opt)
print("Executing: {}".format(subprocess.list2cmdline(argv)))
subprocess.check_call(argv)