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):
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
136
162
def get_file_sha1(self, file_id):
137
163
ie = self._inventory[file_id]
164
if ie.kind == "file":
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
140
173
def has_filename(self, filename):
141
174
return bool(self.inventory.path2id(filename))
143
176
def list_files(self):
144
177
# The only files returned by this are those from the version
145
178
for path, entry in self.inventory.iter_entries():
146
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
149
189
class EmptyTree(Tree):
150
190
def __init__(self):
151
191
self._inventory = Inventory()
193
def get_symlink_target(self, file_id):
153
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"
156
203
def list_files(self):
157
if False: # just to make it a generator
206
def __contains__(self, file_id):
207
return file_id in self._inventory
209
def get_file_sha1(self, file_id):
210
assert self._inventory[file_id].kind == "root_directory"
162
214
######################################################################
245
mutter('export version %r' % tree)
297
mutter('export version %r', tree)
246
298
inv = tree.inventory
247
299
for dp, ie in inv.iter_entries():
249
fullpath = appendpath(dest, dp)
250
if kind == 'directory':
253
pumpfile(tree.get_file(ie.file_id), file(fullpath, 'wb'))
255
raise BzrError("don't know how to export {%s} of kind %r" % (ie.file_id, kind))
256
mutter(" export {%s} kind %s to %s" % (ie.file_id, kind, fullpath))
300
ie.put_on_disk(dest, dp, tree)
257
302
exporters['dir'] = dir_exporter
298
343
ball = tarfile.open(dest, 'w:' + compression)
299
344
except tarfile.CompressionError, e:
300
345
raise BzrError(str(e))
301
mutter('export version %r' % tree)
346
mutter('export version %r', tree)
302
347
inv = tree.inventory
303
348
for dp, ie in inv.iter_entries():
304
mutter(" export {%s} kind %s to %s" % (ie.file_id, ie.kind, dest))
305
item = tarfile.TarInfo(os.path.join(root, dp))
306
# TODO: would be cool to actually set it to the timestamp of the
307
# revision it was last changed
309
if ie.kind == 'directory':
310
item.type = tarfile.DIRTYPE
315
elif ie.kind == 'file':
316
item.type = tarfile.REGTYPE
317
fileobj = tree.get_file(ie.file_id)
318
item.size = _find_file_size(fileobj)
321
raise BzrError("don't know how to export {%s} of kind %r" %
322
(ie.file_id, ie.kind))
349
mutter(" export {%s} kind %s to %s", ie.file_id, ie.kind, dest)
350
item, fileobj = ie.get_tar_item(root, dp, now, tree)
324
351
ball.addfile(item, fileobj)
326
354
exporters['tar'] = tar_exporter
328
356
def tgz_exporter(tree, dest, root):
332
360
def tbz_exporter(tree, dest, root):
333
361
tar_exporter(tree, dest, root, compression='bz2')
334
362
exporters['tbz2'] = tbz_exporter
337
def _find_file_size(fileobj):
338
offset = fileobj.tell()
341
size = fileobj.tell()
343
# gzip doesn't accept second argument to seek()
347
nread = len(fileobj.read())