21
from cStringIO import StringIO
23
24
from bzrlib.trace import mutter, note
24
from bzrlib.errors import BzrError
25
from bzrlib.errors import BzrError, BzrCheckError
25
26
from bzrlib.inventory import Inventory
26
from bzrlib.osutils import pumpfile, appendpath, fingerprint_file
27
from bzrlib.osutils import appendpath, fingerprint_file
57
58
def has_id(self, file_id):
58
59
return self.inventory.has_id(file_id)
61
def has_or_had_id(self, file_id):
62
if file_id == self.inventory.root.file_id:
64
return self.inventory.has_id(file_id)
60
66
__contains__ = has_id
62
68
def __iter__(self):
65
71
def id2path(self, file_id):
66
72
return self.inventory.id2path(file_id)
74
def kind(self, file_id):
75
raise NotImplementedError("subclasses must implement kind")
68
77
def _get_inventory(self):
69
78
return self._inventory
92
103
"store is probably damaged/corrupt"])
95
def print_file(self, fileid):
96
"""Print file with id `fileid` to stdout."""
106
def print_file(self, file_id):
107
"""Print file with id `file_id` to stdout."""
98
pumpfile(self.get_file(fileid), sys.stdout)
109
sys.stdout.write(self.get_file_text(file_id))
101
112
def export(self, dest, format='dir', root=None):
119
130
or at least passing a description to the constructor.
122
def __init__(self, store, inv):
133
def __init__(self, weave_store, inv, revision_id):
134
self._weave_store = weave_store
124
135
self._inventory = inv
136
self._revision_id = revision_id
138
def get_weave(self, file_id):
139
# FIXME: RevisionTree should be given a branch
140
# not a store, or the store should know the branch.
141
import bzrlib.transactions as transactions
142
return self._weave_store.get_weave(file_id,
143
transactions.PassThroughTransaction())
146
def get_file_lines(self, file_id):
147
ie = self._inventory[file_id]
148
weave = self.get_weave(file_id)
149
return weave.get(ie.revision)
152
def get_file_text(self, file_id):
153
return ''.join(self.get_file_lines(file_id))
126
156
def get_file(self, file_id):
127
ie = self._inventory[file_id]
128
f = self._store[ie.text_id]
129
mutter(" get fileid{%s} from %r" % (file_id, self))
130
self._check_retrieved(ie, f)
157
return StringIO(self.get_file_text(file_id))
133
159
def get_file_size(self, file_id):
134
160
return self._inventory[file_id].text_size
138
164
if ie.kind == "file":
139
165
return ie.text_sha1
167
def is_executable(self, file_id):
168
ie = self._inventory[file_id]
169
if ie.kind != "file":
171
return self._inventory[file_id].executable
141
173
def has_filename(self, filename):
142
174
return bool(self.inventory.path2id(filename))
144
176
def list_files(self):
145
177
# The only files returned by this are those from the version
146
178
for path, entry in self.inventory.iter_entries():
147
yield path, 'V', entry.kind, entry.file_id
179
yield path, 'V', entry.kind, entry.file_id, entry
181
def get_symlink_target(self, file_id):
182
ie = self._inventory[file_id]
183
return ie.symlink_target;
185
def kind(self, file_id):
186
return self._inventory[file_id].kind
150
189
class EmptyTree(Tree):
151
190
def __init__(self):
152
191
self._inventory = Inventory()
193
def get_symlink_target(self, file_id):
154
196
def has_filename(self, filename):
199
def kind(self, file_id):
200
assert self._inventory[file_id].kind == "root_directory"
201
return "root_directory"
157
203
def list_files(self):
158
if False: # just to make it a generator
161
206
def __contains__(self, file_id):
162
207
return file_id in self._inventory
254
297
mutter('export version %r' % tree)
255
298
inv = tree.inventory
256
299
for dp, ie in inv.iter_entries():
258
fullpath = appendpath(dest, dp)
259
if kind == 'directory':
262
pumpfile(tree.get_file(ie.file_id), file(fullpath, 'wb'))
264
raise BzrError("don't know how to export {%s} of kind %r" % (ie.file_id, kind))
265
mutter(" export {%s} kind %s to %s" % (ie.file_id, kind, fullpath))
300
ie.put_on_disk(dest, dp, tree)
266
302
exporters['dir'] = dir_exporter
311
347
inv = tree.inventory
312
348
for dp, ie in inv.iter_entries():
313
349
mutter(" export {%s} kind %s to %s" % (ie.file_id, ie.kind, dest))
314
item = tarfile.TarInfo(os.path.join(root, dp))
315
# TODO: would be cool to actually set it to the timestamp of the
316
# revision it was last changed
318
if ie.kind == 'directory':
319
item.type = tarfile.DIRTYPE
324
elif ie.kind == 'file':
325
item.type = tarfile.REGTYPE
326
fileobj = tree.get_file(ie.file_id)
327
item.size = _find_file_size(fileobj)
330
raise BzrError("don't know how to export {%s} of kind %r" %
331
(ie.file_id, ie.kind))
350
item, fileobj = ie.get_tar_item(root, dp, now, tree)
333
351
ball.addfile(item, fileobj)
335
354
exporters['tar'] = tar_exporter
337
356
def tgz_exporter(tree, dest, root):
341
360
def tbz_exporter(tree, dest, root):
342
361
tar_exporter(tree, dest, root, compression='bz2')
343
362
exporters['tbz2'] = tbz_exporter
346
def _find_file_size(fileobj):
347
offset = fileobj.tell()
350
size = fileobj.tell()
352
# gzip doesn't accept second argument to seek()
356
nread = len(fileobj.read())