20
20
from sets import Set
21
import os.path, os, fnmatch
21
import os.path, os, fnmatch, time
23
from osutils import pumpfile, compare_files, filesize, quotefn, sha_file, \
23
from osutils import pumpfile, filesize, quotefn, sha_file, \
24
24
joinpath, splitpath, appendpath, isdir, isfile, file_kind, fingerprint_file
26
26
from stat import S_ISREG, S_ISDIR, ST_MODE, ST_SIZE
28
from inventory import Inventory
29
from trace import mutter, note
30
from errors import bailout
28
from bzrlib.inventory import Inventory
29
from bzrlib.trace import mutter, note
30
from bzrlib.errors import BzrError
36
38
"""Abstract file tree.
38
40
There are several subclasses:
86
84
if ie.text_size != None:
87
85
if ie.text_size != fp['size']:
88
bailout("mismatched size for file %r in %r" % (ie.file_id, self._store),
86
raise BzrError("mismatched size for file %r in %r" % (ie.file_id, self._store),
89
87
["inventory expects %d bytes" % ie.text_size,
90
88
"file is actually %d bytes" % fp['size'],
91
89
"store is probably damaged/corrupt"])
93
91
if ie.text_sha1 != fp['sha1']:
94
bailout("wrong SHA-1 for file %r in %r" % (ie.file_id, self._store),
92
raise BzrError("wrong SHA-1 for file %r in %r" % (ie.file_id, self._store),
95
93
["inventory expects %s" % ie.text_sha1,
96
94
"file is actually %s" % fp['sha1'],
97
95
"store is probably damaged/corrupt"])
103
101
pumpfile(self.get_file(fileid), sys.stdout)
106
def export(self, dest):
107
"""Export this tree to a new directory.
109
`dest` should not exist, and will be created holding the
110
contents of this tree.
112
TODO: To handle subdirectories we need to create the
115
:note: If the export fails, the destination directory will be
116
left in a half-assed state.
119
mutter('export version %r' % self)
121
for dp, ie in inv.iter_entries():
123
fullpath = appendpath(dest, dp)
124
if kind == 'directory':
127
pumpfile(self.get_file(ie.file_id), file(fullpath, 'wb'))
129
bailout("don't know how to export {%s} of kind %r" % (ie.file_id, kind))
130
mutter(" export {%s} kind %s to %s" % (ie.file_id, kind, fullpath))
104
def export(self, dest, format='dir'):
105
"""Export this tree."""
107
exporter = exporters[format]
109
raise BzrCommandError("export format %r not supported" % format)
245
225
if old_name != new_name:
246
226
yield (old_name, new_name)
230
######################################################################
233
def dir_exporter(tree, dest):
234
"""Export this tree to a new directory.
236
`dest` should not exist, and will be created holding the
237
contents of this tree.
239
TODO: To handle subdirectories we need to create the
242
:note: If the export fails, the destination directory will be
243
left in a half-assed state.
246
mutter('export version %r' % tree)
248
for dp, ie in inv.iter_entries():
250
fullpath = appendpath(dest, dp)
251
if kind == 'directory':
254
pumpfile(tree.get_file(ie.file_id), file(fullpath, 'wb'))
256
raise BzrError("don't know how to export {%s} of kind %r" % (ie.file_id, kind))
257
mutter(" export {%s} kind %s to %s" % (ie.file_id, kind, fullpath))
258
exporters['dir'] = dir_exporter
265
def tar_exporter(tree, dest, compression=None):
266
"""Export this tree to a new tar file.
268
`dest` will be created holding the contents of this tree; if it
269
already exists, it will be clobbered, like with "tar -c".
272
compression = str(compression or '')
274
ball = tarfile.open(dest, 'w:' + compression)
275
except tarfile.CompressionError, e:
276
raise BzrError(str(e))
277
mutter('export version %r' % tree)
279
for dp, ie in inv.iter_entries():
280
mutter(" export {%s} kind %s to %s" % (ie.file_id, ie.kind, dest))
281
item = tarfile.TarInfo(dp)
282
# TODO: would be cool to actually set it to the timestamp of the
283
# revision it was last changed
285
if ie.kind == 'directory':
286
item.type = tarfile.DIRTYPE
291
elif ie.kind == 'file':
292
item.type = tarfile.REGTYPE
293
fileobj = tree.get_file(ie.file_id)
294
item.size = _find_file_size(fileobj)
297
raise BzrError("don't know how to export {%s} of kind %r" %
298
(ie.file_id, ie.kind))
300
ball.addfile(item, fileobj)
302
exporters['tar'] = tar_exporter
304
def tgz_exporter(tree, dest):
305
tar_exporter(tree, dest, compression='gz')
306
exporters['tgz'] = tgz_exporter
308
def tbz_exporter(tree, dest):
309
tar_exporter(tree, dest, compression='bz2')
310
exporters['tbz2'] = tbz_exporter
313
def _find_file_size(fileobj):
314
offset = fileobj.tell()
317
size = fileobj.tell()
319
# gzip doesn't accept second argument to seek()
323
nread = len(fileobj.read())