17
17
"""Tree classes, representing directory at point in time.
21
from cStringIO import StringIO
20
from osutils import pumpfile, appendpath, fingerprint_file
22
from bzrlib.trace import mutter, note
23
from bzrlib.errors import BzrError
24
from bzrlib.trace import mutter, note
25
from bzrlib.errors import BzrError, BzrCheckError
26
from bzrlib.inventory import Inventory
27
from bzrlib.osutils import appendpath, fingerprint_file
69
66
def _get_inventory(self):
70
67
return self._inventory
72
def get_file_by_path(self, path):
73
return self.get_file(self._inventory.path2id(path))
75
69
inventory = property(_get_inventory,
76
70
doc="Inventory of this Tree")
78
72
def _check_retrieved(self, ie, f):
81
73
fp = fingerprint_file(f)
95
87
"store is probably damaged/corrupt"])
98
def print_file(self, file_id):
99
"""Print file with id `file_id` to stdout."""
90
def print_file(self, fileid):
91
"""Print file with id `fileid` to stdout."""
101
sys.stdout.write(self.get_file_text(file_id))
104
def export(self, dest, format='dir', root=None):
93
pumpfile(self.get_file(fileid), sys.stdout)
96
def export(self, dest, format='dir'):
105
97
"""Export this tree."""
107
99
exporter = exporters[format]
109
from bzrlib.errors import BzrCommandError
110
101
raise BzrCommandError("export format %r not supported" % format)
111
exporter(self, dest, root)
122
113
or at least passing a description to the constructor.
125
def __init__(self, weave_store, inv, revision_id):
126
self._weave_store = weave_store
116
def __init__(self, store, inv):
127
118
self._inventory = inv
128
self._revision_id = revision_id
130
def get_weave(self, file_id):
131
# FIXME: RevisionTree should be given a branch
132
# not a store, or the store should know the branch.
133
import bzrlib.transactions as transactions
134
return self._weave_store.get_weave(file_id,
135
transactions.PassThroughTransaction())
138
def get_file_lines(self, file_id):
139
ie = self._inventory[file_id]
140
weave = self.get_weave(file_id)
141
return weave.get(ie.revision)
144
def get_file_text(self, file_id):
145
return ''.join(self.get_file_lines(file_id))
148
120
def get_file(self, file_id):
149
return StringIO(self.get_file_text(file_id))
121
ie = self._inventory[file_id]
122
f = self._store[ie.text_id]
123
mutter(" get fileid{%s} from %r" % (file_id, self))
124
self._check_retrieved(ie, f)
151
127
def get_file_size(self, file_id):
152
128
return self._inventory[file_id].text_size
154
130
def get_file_sha1(self, file_id):
155
131
ie = self._inventory[file_id]
156
if ie.kind == "file":
159
def is_executable(self, file_id):
160
return self._inventory[file_id].executable
162
134
def has_filename(self, filename):
163
135
return bool(self.inventory.path2id(filename))
165
137
def list_files(self):
166
138
# The only files returned by this are those from the version
167
139
for path, entry in self.inventory.iter_entries():
168
yield path, 'V', entry.kind, entry.file_id, entry
170
def get_symlink_target(self, file_id):
171
ie = self._inventory[file_id]
172
return ie.symlink_target;
140
yield path, 'V', entry.kind, entry.file_id
175
143
class EmptyTree(Tree):
176
144
def __init__(self):
145
from bzrlib.inventory import Inventory
177
146
self._inventory = Inventory()
179
def get_symlink_target(self, file_id):
182
148
def has_filename(self, filename):
185
151
def list_files(self):
152
if False: # just to make it a generator
188
def __contains__(self, file_id):
189
return file_id in self._inventory
191
def get_file_sha1(self, file_id):
192
assert self._inventory[file_id].kind == "root_directory"
196
157
######################################################################
262
223
######################################################################
265
def dir_exporter(tree, dest, root):
226
def dir_exporter(tree, dest):
266
227
"""Export this tree to a new directory.
268
229
`dest` should not exist, and will be created holding the
279
240
mutter('export version %r' % tree)
280
241
inv = tree.inventory
281
242
for dp, ie in inv.iter_entries():
282
ie.put_on_disk(dest, dp, tree)
244
fullpath = appendpath(dest, dp)
245
if kind == 'directory':
248
pumpfile(tree.get_file(ie.file_id), file(fullpath, 'wb'))
250
raise BzrError("don't know how to export {%s} of kind %r" % (ie.file_id, kind))
251
mutter(" export {%s} kind %s to %s" % (ie.file_id, kind, fullpath))
284
252
exporters['dir'] = dir_exporter
288
256
except ImportError:
291
def get_root_name(dest):
292
"""Get just the root name for a tarball.
294
>>> get_root_name('mytar.tar')
296
>>> get_root_name('mytar.tar.bz2')
298
>>> get_root_name('tar.tar.tar.tgz')
300
>>> get_root_name('bzr-0.0.5.tar.gz')
302
>>> get_root_name('a/long/path/mytar.tgz')
304
>>> get_root_name('../parent/../dir/other.tbz2')
307
endings = ['.tar', '.tar.gz', '.tgz', '.tar.bz2', '.tbz2']
308
dest = os.path.basename(dest)
310
if dest.endswith(end):
311
return dest[:-len(end)]
313
def tar_exporter(tree, dest, root, compression=None):
259
def tar_exporter(tree, dest, compression=None):
314
260
"""Export this tree to a new tar file.
316
262
`dest` will be created holding the contents of this tree; if it
319
265
from time import time
321
267
compression = str(compression or '')
323
root = get_root_name(dest)
325
269
ball = tarfile.open(dest, 'w:' + compression)
326
270
except tarfile.CompressionError, e:
329
273
inv = tree.inventory
330
274
for dp, ie in inv.iter_entries():
331
275
mutter(" export {%s} kind %s to %s" % (ie.file_id, ie.kind, dest))
332
item, fileobj = ie.get_tar_item(root, dp, now, tree)
276
item = tarfile.TarInfo(dp)
277
# TODO: would be cool to actually set it to the timestamp of the
278
# revision it was last changed
280
if ie.kind == 'directory':
281
item.type = tarfile.DIRTYPE
286
elif ie.kind == 'file':
287
item.type = tarfile.REGTYPE
288
fileobj = tree.get_file(ie.file_id)
289
item.size = _find_file_size(fileobj)
292
raise BzrError("don't know how to export {%s} of kind %r" %
293
(ie.file_id, ie.kind))
333
295
ball.addfile(item, fileobj)
336
297
exporters['tar'] = tar_exporter
338
def tgz_exporter(tree, dest, root):
339
tar_exporter(tree, dest, root, compression='gz')
299
def tgz_exporter(tree, dest):
300
tar_exporter(tree, dest, compression='gz')
340
301
exporters['tgz'] = tgz_exporter
342
def tbz_exporter(tree, dest, root):
343
tar_exporter(tree, dest, root, compression='bz2')
303
def tbz_exporter(tree, dest):
304
tar_exporter(tree, dest, compression='bz2')
344
305
exporters['tbz2'] = tbz_exporter
308
def _find_file_size(fileobj):
309
offset = fileobj.tell()
312
size = fileobj.tell()
314
# gzip doesn't accept second argument to seek()
318
nread = len(fileobj.read())