41 |
41 |
class Rsync:
|
42 |
42 |
"""Wrapper class for the rsync command"""
|
43 |
43 |
|
44 |
|
def __init__(self, src, dest, exclude=[]):
|
45 |
|
"""Create an instance by defining a source, a destinationa and a number
|
46 |
|
of exclude patterns.
|
47 |
|
"""
|
48 |
|
self.src = src
|
49 |
|
self.dest = dest
|
50 |
|
self.exclude = exclude
|
51 |
|
self.options = ['-v']
|
|
44 |
def __init__(self, output):
|
|
45 |
"""Create an instance """
|
|
46 |
self._out = output
|
|
47 |
self._exclude = []
|
|
48 |
self._options = ['-v']
|
52 |
49 |
|
53 |
50 |
def archive(self):
|
54 |
51 |
"""Enable the archive option"""
|
55 |
|
self.options.append('-a')
|
|
52 |
self._options.append('-a')
|
56 |
53 |
return self
|
57 |
54 |
|
58 |
|
def run(self, out):
|
|
55 |
def xattrs(self):
|
|
56 |
"""Preserve extended attributes"""
|
|
57 |
self._options.append('-X')
|
|
58 |
return self
|
|
59 |
|
|
60 |
def hard_links(self):
|
|
61 |
"""Preserve hard links"""
|
|
62 |
self._options.append('-H')
|
|
63 |
return self
|
|
64 |
|
|
65 |
def acls(self):
|
|
66 |
"""Preserve ACLs"""
|
|
67 |
self._options.append('-A')
|
|
68 |
return self
|
|
69 |
|
|
70 |
def sparse(self):
|
|
71 |
"""Handle sparse files efficiently"""
|
|
72 |
self._options.append('-S')
|
|
73 |
return self
|
|
74 |
|
|
75 |
def exclude(self, pattern):
|
|
76 |
"""Add an exclude pattern"""
|
|
77 |
self._exclude.append(pattern)
|
|
78 |
return self
|
|
79 |
|
|
80 |
def reset(self):
|
|
81 |
"""Reset all rsync options"""
|
|
82 |
self._exclude = []
|
|
83 |
self._options = ['-v']
|
|
84 |
|
|
85 |
def run(self, src, dest):
|
59 |
86 |
"""Run the actual command"""
|
60 |
87 |
cmd = []
|
61 |
88 |
cmd.append('rsync')
|
62 |
|
cmd.extend(self.options)
|
63 |
|
for i in self.exclude:
|
|
89 |
cmd.extend(self._options)
|
|
90 |
for i in self._exclude:
|
64 |
91 |
cmd.extend(['--exclude', i])
|
65 |
92 |
|
66 |
|
out.output("Calculating total number of host files ...", False)
|
67 |
|
dry_run = subprocess.Popen(cmd + ['-n', self.src, self.dest],
|
68 |
|
shell=False, stdout=subprocess.PIPE,
|
69 |
|
bufsize=0)
|
|
93 |
self._out.output("Calculating total number of host files ...", False)
|
|
94 |
|
|
95 |
# If you don't specify a destination, rsync will list the source files.
|
|
96 |
dry_run = subprocess.Popen(cmd + [src], shell=False,
|
|
97 |
stdout=subprocess.PIPE, bufsize=0)
|
70 |
98 |
try:
|
71 |
99 |
total = 0
|
72 |
100 |
for line in iter(dry_run.stdout.readline, b''):
|
... | ... | |
76 |
104 |
if dry_run.returncode != 0:
|
77 |
105 |
raise FatalError("rsync failed")
|
78 |
106 |
|
79 |
|
out.success("%d" % total)
|
|
107 |
self._out.success("%d" % total)
|
80 |
108 |
|
81 |
|
progress = out.Progress(total, "Copying files into the image ... ")
|
82 |
|
run = subprocess.Popen(cmd + [self.src, self.dest], shell=False,
|
|
109 |
progress = self._out.Progress(total,
|
|
110 |
"Copying host files into the image ... ")
|
|
111 |
run = subprocess.Popen(cmd + [src, dest], shell=False,
|
83 |
112 |
stdout=subprocess.PIPE, bufsize=0)
|
84 |
113 |
try:
|
85 |
114 |
t = time.time()
|