128
131
RENAMED = 'renamed'
129
132
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
149
136
def detect_changes(self, old_entry):
150
137
"""Return a (text_modified, meta_modified) from this to old_entry.
189
176
candidates[ie.revision] = ie
190
177
return candidates
179
@deprecated_method(deprecated_in((1, 6, 0)))
180
def get_tar_item(self, root, dp, now, tree):
181
"""Get a tarfile item and a file stream for its content."""
182
item = tarfile.TarInfo(osutils.pathjoin(root, dp).encode('utf8'))
183
# TODO: would be cool to actually set it to the timestamp of the
184
# revision it was last changed
186
fileobj = self._put_in_tar(item, tree)
192
189
def has_text(self):
193
190
"""Return true if the object this entry represents has textual data.
203
def __init__(self, file_id, name, parent_id):
200
def __init__(self, file_id, name, parent_id, text_id=None):
204
201
"""Create an InventoryEntry
206
203
The filename must be a single component, relative to the
218
215
if '/' in name or '\\' in name:
219
216
raise errors.InvalidEntryName(name=name)
217
self.executable = False
219
self.text_sha1 = None
220
self.text_size = None
220
221
self.file_id = file_id
223
self.text_id = text_id
223
224
self.parent_id = parent_id
225
self.symlink_target = None
226
self.reference_revision = None
225
228
def kind_character(self):
226
229
"""Return a short kind indicator useful for appending to names."""
236
239
raise BzrError("don't know how to export {%s} of kind %r" %
237
240
(self.file_id, self.kind))
242
@deprecated_method(deprecated_in((1, 6, 0)))
243
def put_on_disk(self, dest, dp, tree):
244
"""Create a representation of self on disk in the prefix dest.
246
This is a template method - implement _put_on_disk in subclasses.
248
fullpath = osutils.pathjoin(dest, dp)
249
self._put_on_disk(fullpath, tree)
250
# mutter(" export {%s} kind %s to %s", self.file_id,
251
# self.kind, fullpath)
239
253
def _put_on_disk(self, fullpath, tree):
240
254
"""Put this entry onto disk at fullpath, from tree tree."""
241
255
raise BzrError("don't know how to export {%s} of kind %r" % (self.file_id, self.kind))
400
class RootEntry(InventoryEntry):
402
__slots__ = ['text_sha1', 'text_size', 'file_id', 'name', 'kind',
403
'text_id', 'parent_id', 'children', 'executable',
404
'revision', 'symlink_target', 'reference_revision']
406
def _check(self, checker, rev_id):
407
"""See InventoryEntry._check"""
409
def __init__(self, file_id):
410
self.file_id = file_id
412
self.kind = 'directory'
413
self.parent_id = None
416
symbol_versioning.warn('RootEntry is deprecated as of bzr 0.10.'
417
' Please use InventoryDirectory instead.',
418
DeprecationWarning, stacklevel=2)
420
def __eq__(self, other):
421
if not isinstance(other, RootEntry):
422
return NotImplemented
424
return (self.file_id == other.file_id) \
425
and (self.children == other.children)
386
428
class InventoryDirectory(InventoryEntry):
387
429
"""A directory in an inventory."""
389
__slots__ = ['children']
431
__slots__ = ['text_sha1', 'text_size', 'file_id', 'name', 'kind',
432
'text_id', 'parent_id', 'children', 'executable',
433
'revision', 'symlink_target', 'reference_revision']
393
435
def _check(self, checker, rev_id):
394
436
"""See InventoryEntry._check"""
437
if (self.text_sha1 is not None or self.text_size is not None or
438
self.text_id is not None):
439
checker._report_items.append('directory {%s} has text in revision {%s}'
440
% (self.file_id, rev_id))
395
441
# In non rich root repositories we do not expect a file graph for the
397
443
if self.name == '' and not checker.rich_roots:
413
459
def __init__(self, file_id, name, parent_id):
414
460
super(InventoryDirectory, self).__init__(file_id, name, parent_id)
415
461
self.children = {}
462
self.kind = 'directory'
417
464
def kind_character(self):
418
465
"""See InventoryEntry.kind_character."""
435
482
class InventoryFile(InventoryEntry):
436
483
"""A file in an inventory."""
438
__slots__ = ['text_sha1', 'text_size', 'text_id', 'executable']
442
def __init__(self, file_id, name, parent_id):
443
super(InventoryFile, self).__init__(file_id, name, parent_id)
444
self.text_sha1 = None
445
self.text_size = None
447
self.executable = False
485
__slots__ = ['text_sha1', 'text_size', 'file_id', 'name', 'kind',
486
'text_id', 'parent_id', 'children', 'executable',
487
'revision', 'symlink_target', 'reference_revision']
449
489
def _check(self, checker, tree_revision_id):
450
490
"""See InventoryEntry._check"""
493
533
"""See InventoryEntry.has_text."""
536
def __init__(self, file_id, name, parent_id):
537
super(InventoryFile, self).__init__(file_id, name, parent_id)
496
540
def kind_character(self):
497
541
"""See InventoryEntry.kind_character."""
551
595
class InventoryLink(InventoryEntry):
552
596
"""A file in an inventory."""
554
__slots__ = ['symlink_target']
558
def __init__(self, file_id, name, parent_id):
559
super(InventoryLink, self).__init__(file_id, name, parent_id)
560
self.symlink_target = None
598
__slots__ = ['text_sha1', 'text_size', 'file_id', 'name', 'kind',
599
'text_id', 'parent_id', 'children', 'executable',
600
'revision', 'symlink_target', 'reference_revision']
562
602
def _check(self, checker, tree_revision_id):
563
603
"""See InventoryEntry._check"""
604
if self.text_sha1 is not None or self.text_size is not None or self.text_id is not None:
605
checker._report_items.append(
606
'symlink {%s} has text in revision {%s}'
607
% (self.file_id, tree_revision_id))
564
608
if self.symlink_target is None:
565
609
checker._report_items.append(
566
610
'symlink {%s} has no target in revision {%s}'
604
648
differ = DiffSymlink(old_tree, new_tree, output_to)
605
649
return differ.diff_symlink(old_target, new_target)
651
def __init__(self, file_id, name, parent_id):
652
super(InventoryLink, self).__init__(file_id, name, parent_id)
653
self.kind = 'symlink'
607
655
def kind_character(self):
608
656
"""See InventoryEntry.kind_character."""
642
690
class TreeReference(InventoryEntry):
644
__slots__ = ['reference_revision']
646
692
kind = 'tree-reference'
648
694
def __init__(self, file_id, name, parent_id, revision=None,
1606
1652
# parent_to_children with at least the tree root.)
1608
1654
cache = self._fileid_to_entry_cache
1609
remaining_children = collections.deque(parent_to_children[self.root_id])
1656
remaining_children = collections.deque(parent_to_children[self.root_id])
1658
import pdb; pdb.set_trace()
1610
1660
while remaining_children:
1611
1661
file_id = remaining_children.popleft()
1612
1662
ie = cache[file_id]
2195
2245
class CHKInventoryDirectory(InventoryDirectory):
2196
2246
"""A directory in an inventory."""
2198
__slots__ = ['_children', '_chk_inventory']
2248
__slots__ = ['text_sha1', 'text_size', 'file_id', 'name', 'kind',
2249
'text_id', 'parent_id', '_children', 'executable',
2250
'revision', 'symlink_target', 'reference_revision',
2200
2253
def __init__(self, file_id, name, parent_id, chk_inventory):
2201
2254
# Don't call InventoryDirectory.__init__ - it isn't right for this
2203
2256
InventoryEntry.__init__(self, file_id, name, parent_id)
2204
2257
self._children = None
2258
self.kind = 'directory'
2205
2259
self._chk_inventory = chk_inventory