113
113
>>> i.id2path('2326')
114
114
'src/wibble/wibble.c'
117
# Constants returned by describe_change()
119
# TODO: These should probably move to some kind of FileChangeDescription
120
# class; that's like what's inside a TreeDelta but we want to be able to
121
# generate them just for one file at a time.
123
MODIFIED_AND_RENAMED = 'modified and renamed'
117
125
__slots__ = ['text_sha1', 'text_size', 'file_id', 'name', 'kind',
118
126
'text_id', 'parent_id', 'children', 'executable',
353
361
"""Clone this inventory entry."""
354
362
raise NotImplementedError
356
def _describe_snapshot_change(self, previous_entries):
357
"""Describe how this entry will have changed in a new commit.
359
:param previous_entries: Dictionary from revision_id to inventory entry.
361
:returns: One-word description: "merged", "added", "renamed", "modified".
365
def describe_change(old_entry, new_entry):
366
"""Describe the change between old_entry and this.
368
This smells of being an InterInventoryEntry situation, but as its
369
the first one, we're making it a static method for now.
371
An entry with a different parent, or different name is considered
372
to be renamed. Reparenting is an internal detail.
373
Note that renaming the parent does not trigger a rename for the
363
# XXX: This assumes that the file *has* changed -- it should probably
364
# be fused with whatever does that detection. Why not just a single
365
# thing to compare the entries?
367
# TODO: Return some kind of object describing all the possible
368
# dimensions that can change, not just a string. That can then give
369
# both old and new names for renames, etc.
371
if len(previous_entries) > 1:
373
elif len(previous_entries) == 0:
376
# TODO: Perhaps return an object rather than just a string
377
if old_entry is new_entry:
378
# also the case of both being None
380
elif old_entry is None:
375
the_parent, = previous_entries.values()
376
if self.parent_id != the_parent.parent_id:
377
# actually, moved to another directory
379
elif self.name != the_parent.name:
382
elif new_entry is None:
384
text_modified, meta_modified = new_entry.detect_changes(old_entry)
385
if text_modified or meta_modified:
389
# TODO 20060511 (mbp, rbc) factor out 'detect_rename' here.
390
if old_entry.parent_id != new_entry.parent_id:
392
elif old_entry.name != new_entry.name:
396
if renamed and not modified:
397
return InventoryEntry.RENAMED
398
if modified and not renamed:
400
if modified and renamed:
401
return InventoryEntry.MODIFIED_AND_RENAMED
383
404
def __repr__(self):
384
405
return ("%s(%r, %r, parent_id=%r)"
420
441
mutter('new revision {%s} for {%s}', revision, self.file_id)
421
442
self.revision = revision
422
change = self._describe_snapshot_change(previous_entries)
423
443
self._snapshot_text(previous_entries, work_tree, weave_store,
427
446
def _snapshot_text(self, file_parents, work_tree, weave_store, transaction):
428
447
"""Record the 'text' of this entry, whatever form that takes.