335
by loafman
patch #6675: Add modelines |
1 |
# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*-
|
2 |
#
|
|
404
by loafman
Add/update copyright statements in all distribution source files |
3 |
# Copyright 2002 Ben Escoto <ben@emerose.org>
|
4 |
# Copyright 2007 Kenneth Loafman <kenneth@loafman.com>
|
|
1
by bescoto
Initial checkin |
5 |
#
|
6 |
# This file is part of duplicity.
|
|
7 |
#
|
|
2
by bescoto
Added full GPL statement in source files at request of Jaime Villate |
8 |
# Duplicity is free software; you can redistribute it and/or modify it
|
9 |
# under the terms of the GNU General Public License as published by the
|
|
476
by loafman
After email voting among known duplicity contributors, |
10 |
# Free Software Foundation; either version 2 of the License, or (at your
|
2
by bescoto
Added full GPL statement in source files at request of Jaime Villate |
11 |
# option) any later version.
|
12 |
#
|
|
13 |
# Duplicity is distributed in the hope that it will be useful, but
|
|
14 |
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
15 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
16 |
# General Public License for more details.
|
|
17 |
#
|
|
18 |
# You should have received a copy of the GNU General Public License
|
|
19 |
# along with duplicity; if not, write to the Free Software Foundation,
|
|
20 |
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
1
by bescoto
Initial checkin |
21 |
|
22 |
"""Manage temporary files"""
|
|
23 |
||
1071
by Kenneth Loafman
* Misc fixes for the following PEP8 issues: |
24 |
import os |
25 |
import sys |
|
1
by bescoto
Initial checkin |
26 |
|
477
by loafman
Normalized include statements and tried to insure that all |
27 |
from duplicity import log |
773
by Kenneth Loafman
- Ignore ENOENT (file missing) errors where it is safe. |
28 |
from duplicity import util |
477
by loafman
Normalized include statements and tried to insure that all |
29 |
from duplicity import path |
30 |
from duplicity import file_naming |
|
31 |
from duplicity import tempdir |
|
521
by loafman
After merge of Checkpoint/Restart. |
32 |
from duplicity import globals |
33 |
from duplicity import gpg |
|
1
by bescoto
Initial checkin |
34 |
|
312
by loafman
Change to one statement per line. |
35 |
|
1
by bescoto
Initial checkin |
36 |
def new_temppath(): |
521
by loafman
After merge of Checkpoint/Restart. |
37 |
"""
|
38 |
Return a new TempPath
|
|
39 |
"""
|
|
304
by loafman
Untabify all files. To compare against previous |
40 |
filename = tempdir.default().mktemp() |
41 |
return TempPath(filename) |
|
1
by bescoto
Initial checkin |
42 |
|
312
by loafman
Change to one statement per line. |
43 |
|
1
by bescoto
Initial checkin |
44 |
class TempPath(path.Path): |
521
by loafman
After merge of Checkpoint/Restart. |
45 |
"""
|
46 |
Path object used as a temporary file
|
|
47 |
"""
|
|
304
by loafman
Untabify all files. To compare against previous |
48 |
def delete(self): |
521
by loafman
After merge of Checkpoint/Restart. |
49 |
"""
|
50 |
Forget and delete
|
|
51 |
"""
|
|
304
by loafman
Untabify all files. To compare against previous |
52 |
path.Path.delete(self) |
53 |
tempdir.default().forget(self.name) |
|
1
by bescoto
Initial checkin |
54 |
|
304
by loafman
Untabify all files. To compare against previous |
55 |
def open_with_delete(self, mode): |
521
by loafman
After merge of Checkpoint/Restart. |
56 |
"""
|
57 |
Returns a fileobj. When that is closed, delete file
|
|
58 |
"""
|
|
304
by loafman
Untabify all files. To compare against previous |
59 |
fh = FileobjHooked(path.Path.open(self, mode)) |
60 |
fh.addhook(self.delete) |
|
61 |
return fh |
|
1
by bescoto
Initial checkin |
62 |
|
312
by loafman
Change to one statement per line. |
63 |
|
864.5.1
by Michael Terry
gracefully handle multiple duplicate base dir entries in the sigtar; avoid writing such entries out |
64 |
def get_fileobj_duppath(dirpath, partname, permname, remname, overwrite=False): |
521
by loafman
After merge of Checkpoint/Restart. |
65 |
"""
|
66 |
Return a file object open for writing, will write to filename
|
|
304
by loafman
Untabify all files. To compare against previous |
67 |
|
68 |
Data will be processed and written to a temporary file. When the
|
|
69 |
return fileobject is closed, rename to final position. filename
|
|
70 |
must be a recognizable duplicity data file.
|
|
71 |
"""
|
|
521
by loafman
After merge of Checkpoint/Restart. |
72 |
if not globals.restart: |
73 |
td = tempdir.TemporaryDirectory(dirpath.name) |
|
74 |
tdpname = td.mktemp() |
|
1033
by Kenneth Loafman
* Source formatted, using PyDev, all source files to fix some easily fixed |
75 |
tdp = TempDupPath(tdpname, parseresults=file_naming.parse(partname)) |
76 |
fh = FileobjHooked(tdp.filtered_open("wb"), tdp=tdp, dirpath=dirpath, |
|
77 |
partname=partname, permname=permname, remname=remname) |
|
521
by loafman
After merge of Checkpoint/Restart. |
78 |
else: |
1033
by Kenneth Loafman
* Source formatted, using PyDev, all source files to fix some easily fixed |
79 |
dp = path.DupPath(dirpath.name, index=(partname,)) |
864.5.1
by Michael Terry
gracefully handle multiple duplicate base dir entries in the sigtar; avoid writing such entries out |
80 |
mode = "ab" |
81 |
if overwrite: |
|
82 |
mode = "wb" |
|
1033
by Kenneth Loafman
* Source formatted, using PyDev, all source files to fix some easily fixed |
83 |
fh = FileobjHooked(dp.filtered_open(mode), tdp=None, dirpath=dirpath, |
84 |
partname=partname, permname=permname, remname=remname) |
|
477
by loafman
Normalized include statements and tried to insure that all |
85 |
|
304
by loafman
Untabify all files. To compare against previous |
86 |
def rename_and_forget(): |
521
by loafman
After merge of Checkpoint/Restart. |
87 |
tdp.rename(dirpath.append(partname)) |
304
by loafman
Untabify all files. To compare against previous |
88 |
td.forget(tdpname) |
89 |
||
521
by loafman
After merge of Checkpoint/Restart. |
90 |
if not globals.restart: |
91 |
fh.addhook(rename_and_forget) |
|
304
by loafman
Untabify all files. To compare against previous |
92 |
|
93 |
return fh |
|
1
by bescoto
Initial checkin |
94 |
|
312
by loafman
Change to one statement per line. |
95 |
|
1
by bescoto
Initial checkin |
96 |
def new_tempduppath(parseresults): |
521
by loafman
After merge of Checkpoint/Restart. |
97 |
"""
|
98 |
Return a new TempDupPath, using settings from parseresults
|
|
99 |
"""
|
|
304
by loafman
Untabify all files. To compare against previous |
100 |
filename = tempdir.default().mktemp() |
1033
by Kenneth Loafman
* Source formatted, using PyDev, all source files to fix some easily fixed |
101 |
return TempDupPath(filename, parseresults=parseresults) |
1
by bescoto
Initial checkin |
102 |
|
312
by loafman
Change to one statement per line. |
103 |
|
1
by bescoto
Initial checkin |
104 |
class TempDupPath(path.DupPath): |
521
by loafman
After merge of Checkpoint/Restart. |
105 |
"""
|
106 |
Like TempPath, but build around DupPath
|
|
107 |
"""
|
|
304
by loafman
Untabify all files. To compare against previous |
108 |
def delete(self): |
521
by loafman
After merge of Checkpoint/Restart. |
109 |
"""
|
110 |
Forget and delete
|
|
111 |
"""
|
|
304
by loafman
Untabify all files. To compare against previous |
112 |
path.DupPath.delete(self) |
113 |
tempdir.default().forget(self.name) |
|
114 |
||
115 |
def filtered_open_with_delete(self, mode): |
|
521
by loafman
After merge of Checkpoint/Restart. |
116 |
"""
|
117 |
Returns a filtered fileobj. When that is closed, delete file
|
|
118 |
"""
|
|
304
by loafman
Untabify all files. To compare against previous |
119 |
fh = FileobjHooked(path.DupPath.filtered_open(self, mode)) |
120 |
fh.addhook(self.delete) |
|
121 |
return fh |
|
122 |
||
1033
by Kenneth Loafman
* Source formatted, using PyDev, all source files to fix some easily fixed |
123 |
def open_with_delete(self, mode="rb"): |
521
by loafman
After merge of Checkpoint/Restart. |
124 |
"""
|
125 |
Returns a fileobj. When that is closed, delete file
|
|
126 |
"""
|
|
1033
by Kenneth Loafman
* Source formatted, using PyDev, all source files to fix some easily fixed |
127 |
assert mode == "rb" # Why write a file and then close it immediately? |
304
by loafman
Untabify all files. To compare against previous |
128 |
fh = FileobjHooked(path.DupPath.open(self, mode)) |
129 |
fh.addhook(self.delete) |
|
130 |
return fh |
|
1
by bescoto
Initial checkin |
131 |
|
312
by loafman
Change to one statement per line. |
132 |
|
1
by bescoto
Initial checkin |
133 |
class FileobjHooked: |
521
by loafman
After merge of Checkpoint/Restart. |
134 |
"""
|
135 |
Simulate a file, but add hook on close
|
|
136 |
"""
|
|
1033
by Kenneth Loafman
* Source formatted, using PyDev, all source files to fix some easily fixed |
137 |
def __init__(self, fileobj, tdp=None, dirpath=None, |
138 |
partname=None, permname=None, remname=None): |
|
521
by loafman
After merge of Checkpoint/Restart. |
139 |
"""
|
140 |
Initializer. fileobj is the file object to simulate
|
|
141 |
"""
|
|
1033
by Kenneth Loafman
* Source formatted, using PyDev, all source files to fix some easily fixed |
142 |
self.fileobj = fileobj # the actual file object |
143 |
self.closed = False # True if closed |
|
144 |
self.hooklist = [] # filled later with thunks to run on close |
|
145 |
self.tdp = tdp # TempDupPath object |
|
146 |
self.dirpath = dirpath # path to directory |
|
147 |
self.partname = partname # partial filename |
|
148 |
self.permname = permname # permanent filename |
|
149 |
self.remname = remname # remote filename |
|
304
by loafman
Untabify all files. To compare against previous |
150 |
|
151 |
def write(self, buf): |
|
521
by loafman
After merge of Checkpoint/Restart. |
152 |
"""
|
153 |
Write fileobj, return result of write()
|
|
154 |
"""
|
|
304
by loafman
Untabify all files. To compare against previous |
155 |
return self.fileobj.write(buf) |
477
by loafman
Normalized include statements and tried to insure that all |
156 |
|
521
by loafman
After merge of Checkpoint/Restart. |
157 |
def flush(self): |
158 |
"""
|
|
159 |
Flush fileobj and force sync.
|
|
160 |
"""
|
|
161 |
self.fileobj.flush() |
|
162 |
os.fsync(self.fileobj.fileno()) |
|
163 |
||
164 |
def to_partial(self): |
|
165 |
"""
|
|
166 |
We have achieved the first checkpoint, make file visible and permanent.
|
|
167 |
"""
|
|
168 |
assert not globals.restart |
|
169 |
self.tdp.rename(self.dirpath.append(self.partname)) |
|
170 |
self.fileobj.flush() |
|
171 |
del self.hooklist[0] |
|
172 |
||
173 |
def to_remote(self): |
|
174 |
"""
|
|
175 |
We have written the last checkpoint, now encrypt or compress
|
|
176 |
and send a copy of it to the remote for final storage.
|
|
177 |
"""
|
|
178 |
pr = file_naming.parse(self.remname) |
|
179 |
src = self.dirpath.append(self.partname) |
|
180 |
tgt = self.dirpath.append(self.remname) |
|
181 |
src_iter = SrcIter(src) |
|
182 |
if pr.compressed: |
|
1033
by Kenneth Loafman
* Source formatted, using PyDev, all source files to fix some easily fixed |
183 |
gpg.GzipWriteFile(src_iter, tgt.name, size=sys.maxsize) |
521
by loafman
After merge of Checkpoint/Restart. |
184 |
elif pr.encrypted: |
1033
by Kenneth Loafman
* Source formatted, using PyDev, all source files to fix some easily fixed |
185 |
gpg.GPGWriteFile(src_iter, tgt.name, globals.gpg_profile, size=sys.maxsize) |
521
by loafman
After merge of Checkpoint/Restart. |
186 |
else: |
674.3.1
by ed
survive spaces in path on local copying with encryption enabled |
187 |
os.system("cp -p \"%s\" \"%s\"" % (src.name, tgt.name)) |
1033
by Kenneth Loafman
* Source formatted, using PyDev, all source files to fix some easily fixed |
188 |
globals.backend.move(tgt) # @UndefinedVariable |
521
by loafman
After merge of Checkpoint/Restart. |
189 |
|
190 |
def to_final(self): |
|
191 |
"""
|
|
192 |
We are finished, rename to final, gzip if needed.
|
|
193 |
"""
|
|
194 |
src = self.dirpath.append(self.partname) |
|
195 |
tgt = self.dirpath.append(self.permname) |
|
196 |
src_iter = SrcIter(src) |
|
197 |
pr = file_naming.parse(self.permname) |
|
198 |
if pr.compressed: |
|
1033
by Kenneth Loafman
* Source formatted, using PyDev, all source files to fix some easily fixed |
199 |
gpg.GzipWriteFile(src_iter, tgt.name, size=sys.maxsize) |
521
by loafman
After merge of Checkpoint/Restart. |
200 |
os.unlink(src.name) |
201 |
else: |
|
202 |
os.rename(src.name, tgt.name) |
|
203 |
||
1033
by Kenneth Loafman
* Source formatted, using PyDev, all source files to fix some easily fixed |
204 |
def read(self, length=-1): |
521
by loafman
After merge of Checkpoint/Restart. |
205 |
"""
|
206 |
Read fileobj, return result of read()
|
|
207 |
"""
|
|
312
by loafman
Change to one statement per line. |
208 |
return self.fileobj.read(length) |
304
by loafman
Untabify all files. To compare against previous |
209 |
|
777.1.1
by Michael Terry
first pass at dropping tarfile |
210 |
def tell(self): |
211 |
"""
|
|
212 |
Returns current location of fileobj
|
|
213 |
"""
|
|
214 |
return self.fileobj.tell() |
|
215 |
||
216 |
def seek(self, offset): |
|
217 |
"""
|
|
218 |
Seeks to a location of fileobj
|
|
219 |
"""
|
|
220 |
return self.fileobj.seek(offset) |
|
221 |
||
304
by loafman
Untabify all files. To compare against previous |
222 |
def close(self): |
521
by loafman
After merge of Checkpoint/Restart. |
223 |
"""
|
224 |
Close fileobj, running hooks right afterwards
|
|
225 |
"""
|
|
304
by loafman
Untabify all files. To compare against previous |
226 |
assert not self.fileobj.close() |
312
by loafman
Change to one statement per line. |
227 |
for hook in self.hooklist: |
228 |
hook() |
|
304
by loafman
Untabify all files. To compare against previous |
229 |
|
230 |
def addhook(self, hook): |
|
521
by loafman
After merge of Checkpoint/Restart. |
231 |
"""
|
232 |
Add hook (function taking no arguments) to run upon closing
|
|
233 |
"""
|
|
304
by loafman
Untabify all files. To compare against previous |
234 |
self.hooklist.append(hook) |
235 |
||
721
by Kenneth Loafman
433591 AttributeError: FileobjHooked instance has no attribute 'name' |
236 |
def get_name(self): |
237 |
"""
|
|
238 |
Return the name of the file
|
|
239 |
"""
|
|
240 |
return self.fileobj.name |
|
241 |
||
242 |
name = property(get_name) |
|
243 |
||
244 |
||
521
by loafman
After merge of Checkpoint/Restart. |
245 |
class Block: |
246 |
"""
|
|
247 |
Data block to return from SrcIter
|
|
248 |
"""
|
|
249 |
def __init__(self, data): |
|
250 |
self.data = data |
|
251 |
||
1070
by Kenneth Loafman
* Misc fixes for the following PEP8 issues: |
252 |
|
521
by loafman
After merge of Checkpoint/Restart. |
253 |
class SrcIter: |
254 |
"""
|
|
255 |
Iterate over source and return Block of data.
|
|
256 |
"""
|
|
257 |
def __init__(self, src): |
|
258 |
self.src = src |
|
259 |
self.fp = src.open("rb") |
|
1070
by Kenneth Loafman
* Misc fixes for the following PEP8 issues: |
260 |
|
902.1.6
by Michael Terry
Fix block-loss when restarting inside a multi-block file due to block sizes being variable |
261 |
def next(self): |
521
by loafman
After merge of Checkpoint/Restart. |
262 |
try: |
902.1.6
by Michael Terry
Fix block-loss when restarting inside a multi-block file due to block sizes being variable |
263 |
res = Block(self.fp.read(self.get_read_size())) |
747.1.1
by Michael Terry
always catch Exceptions, not BaseExceptions |
264 |
except Exception: |
1065
by Kenneth Loafman
* Merged in lp:~angusgr/duplicity/exclude-older-than |
265 |
log.FatalError(_("Failed to read %s: %s") % |
939.3.1
by Michael Terry
Promote filenames to unicode when printing to console and ensure that filenames from backend are bytes |
266 |
(util.ufn(self.src.name), sys.exc_info()), |
521
by loafman
After merge of Checkpoint/Restart. |
267 |
log.ErrorCode.generic) |
268 |
if not res.data: |
|
269 |
self.fp.close() |
|
270 |
raise StopIteration |
|
271 |
return res |
|
1070
by Kenneth Loafman
* Misc fixes for the following PEP8 issues: |
272 |
|
902.1.6
by Michael Terry
Fix block-loss when restarting inside a multi-block file due to block sizes being variable |
273 |
def get_read_size(self): |
274 |
return 128 * 1024 |
|
1070
by Kenneth Loafman
* Misc fixes for the following PEP8 issues: |
275 |
|
521
by loafman
After merge of Checkpoint/Restart. |
276 |
def get_footer(self): |
277 |
return "" |