131
128
RENAMED = 'renamed'
132
129
MODIFIED_AND_RENAMED = 'modified and renamed'
131
__slots__ = ['file_id', 'revision', 'parent_id', 'name']
133
# Attributes that all InventoryEntry instances are expected to have, but
134
# that don't vary for all kinds of entry. (e.g. symlink_target is only
135
# relevant to InventoryLink, so there's no reason to make every
136
# InventoryFile instance allocate space to hold a value for it.)
137
# Attributes that only vary for files: executable, text_sha1, text_size,
143
# Attributes that only vary for symlinks: symlink_target
144
symlink_target = None
145
# Attributes that only vary for tree-references: reference_revision
146
reference_revision = None
136
149
def detect_changes(self, old_entry):
137
150
"""Return a (text_modified, meta_modified) from this to old_entry.
190
def __init__(self, file_id, name, parent_id, text_id=None):
203
def __init__(self, file_id, name, parent_id):
191
204
"""Create an InventoryEntry
193
206
The filename must be a single component, relative to the
205
218
if '/' in name or '\\' in name:
206
219
raise errors.InvalidEntryName(name=name)
207
self.executable = False
220
self.file_id = file_id
208
221
self.revision = None
209
self.text_sha1 = None
210
self.text_size = None
211
self.file_id = file_id
213
self.text_id = text_id
214
223
self.parent_id = parent_id
215
self.symlink_target = None
216
self.reference_revision = None
218
225
def kind_character(self):
219
226
"""Return a short kind indicator useful for appending to names."""
222
229
known_kinds = ('file', 'directory', 'symlink')
224
def _put_in_tar(self, item, tree):
225
"""populate item for stashing in a tar, and return the content stream.
227
If no content is available, return None.
229
raise BzrError("don't know how to export {%s} of kind %r" %
230
(self.file_id, self.kind))
232
def _put_on_disk(self, fullpath, tree):
233
"""Put this entry onto disk at fullpath, from tree tree."""
234
raise BzrError("don't know how to export {%s} of kind %r" % (self.file_id, self.kind))
236
231
def sorted_children(self):
237
232
return sorted(self.children.items())
379
374
class InventoryDirectory(InventoryEntry):
380
375
"""A directory in an inventory."""
382
__slots__ = ['text_sha1', 'text_size', 'file_id', 'name', 'kind',
383
'text_id', 'parent_id', 'children', 'executable',
384
'revision', 'symlink_target', 'reference_revision']
377
__slots__ = ['children']
386
381
def _check(self, checker, rev_id):
387
382
"""See InventoryEntry._check"""
388
if (self.text_sha1 is not None or self.text_size is not None or
389
self.text_id is not None):
390
checker._report_items.append('directory {%s} has text in revision {%s}'
391
% (self.file_id, rev_id))
392
383
# In non rich root repositories we do not expect a file graph for the
394
385
if self.name == '' and not checker.rich_roots:
410
401
def __init__(self, file_id, name, parent_id):
411
402
super(InventoryDirectory, self).__init__(file_id, name, parent_id)
412
403
self.children = {}
413
self.kind = 'directory'
415
405
def kind_character(self):
416
406
"""See InventoryEntry.kind_character."""
419
def _put_in_tar(self, item, tree):
420
"""See InventoryEntry._put_in_tar."""
421
item.type = tarfile.DIRTYPE
428
def _put_on_disk(self, fullpath, tree):
429
"""See InventoryEntry._put_on_disk."""
433
410
class InventoryFile(InventoryEntry):
434
411
"""A file in an inventory."""
436
__slots__ = ['text_sha1', 'text_size', 'file_id', 'name', 'kind',
437
'text_id', 'parent_id', 'children', 'executable',
438
'revision', 'symlink_target', 'reference_revision']
413
__slots__ = ['text_sha1', 'text_size', 'text_id', 'executable']
417
def __init__(self, file_id, name, parent_id):
418
super(InventoryFile, self).__init__(file_id, name, parent_id)
419
self.text_sha1 = None
420
self.text_size = None
422
self.executable = False
440
424
def _check(self, checker, tree_revision_id):
441
425
"""See InventoryEntry._check"""
484
468
"""See InventoryEntry.has_text."""
487
def __init__(self, file_id, name, parent_id):
488
super(InventoryFile, self).__init__(file_id, name, parent_id)
491
471
def kind_character(self):
492
472
"""See InventoryEntry.kind_character."""
495
def _put_in_tar(self, item, tree):
496
"""See InventoryEntry._put_in_tar."""
497
item.type = tarfile.REGTYPE
498
fileobj = tree.get_file(self.file_id)
499
item.size = self.text_size
500
if tree.is_executable(self.file_id):
506
def _put_on_disk(self, fullpath, tree):
507
"""See InventoryEntry._put_on_disk."""
508
osutils.pumpfile(tree.get_file(self.file_id), file(fullpath, 'wb'))
509
if tree.is_executable(self.file_id):
510
os.chmod(fullpath, 0755)
512
475
def _read_tree_state(self, path, work_tree):
513
476
"""See InventoryEntry._read_tree_state."""
514
477
self.text_sha1 = work_tree.get_file_sha1(self.file_id, path=path)
546
509
class InventoryLink(InventoryEntry):
547
510
"""A file in an inventory."""
549
__slots__ = ['text_sha1', 'text_size', 'file_id', 'name', 'kind',
550
'text_id', 'parent_id', 'children', 'executable',
551
'revision', 'symlink_target', 'reference_revision']
512
__slots__ = ['symlink_target']
516
def __init__(self, file_id, name, parent_id):
517
super(InventoryLink, self).__init__(file_id, name, parent_id)
518
self.symlink_target = None
553
520
def _check(self, checker, tree_revision_id):
554
521
"""See InventoryEntry._check"""
555
if self.text_sha1 is not None or self.text_size is not None or self.text_id is not None:
556
checker._report_items.append(
557
'symlink {%s} has text in revision {%s}'
558
% (self.file_id, tree_revision_id))
559
522
if self.symlink_target is None:
560
523
checker._report_items.append(
561
524
'symlink {%s} has no target in revision {%s}'
599
562
differ = DiffSymlink(old_tree, new_tree, output_to)
600
563
return differ.diff_symlink(old_target, new_target)
602
def __init__(self, file_id, name, parent_id):
603
super(InventoryLink, self).__init__(file_id, name, parent_id)
604
self.kind = 'symlink'
606
565
def kind_character(self):
607
566
"""See InventoryEntry.kind_character."""
610
def _put_in_tar(self, item, tree):
611
"""See InventoryEntry._put_in_tar."""
612
item.type = tarfile.SYMTYPE
616
item.linkname = self.symlink_target
619
def _put_on_disk(self, fullpath, tree):
620
"""See InventoryEntry._put_on_disk."""
622
os.symlink(self.symlink_target, fullpath)
624
raise BzrError("Failed to create symlink %r -> %r, error: %s" % (fullpath, self.symlink_target, e))
626
569
def _read_tree_state(self, path, work_tree):
627
570
"""See InventoryEntry._read_tree_state."""
628
571
self.symlink_target = work_tree.get_symlink_target(self.file_id)
641
584
class TreeReference(InventoryEntry):
586
__slots__ = ['reference_revision']
643
588
kind = 'tree-reference'
645
590
def __init__(self, file_id, name, parent_id, revision=None,
2192
2134
class CHKInventoryDirectory(InventoryDirectory):
2193
2135
"""A directory in an inventory."""
2195
__slots__ = ['text_sha1', 'text_size', 'file_id', 'name', 'kind',
2196
'text_id', 'parent_id', '_children', 'executable',
2197
'revision', 'symlink_target', 'reference_revision',
2137
__slots__ = ['_children', '_chk_inventory']
2200
2139
def __init__(self, file_id, name, parent_id, chk_inventory):
2201
2140
# Don't call InventoryDirectory.__init__ - it isn't right for this
2203
2142
InventoryEntry.__init__(self, file_id, name, parent_id)
2204
2143
self._children = None
2205
self.kind = 'directory'
2206
2144
self._chk_inventory = chk_inventory