~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/inventory.py

(mbp) 0.8.1 fixes

Show diffs side-by-side

added added

removed removed

Lines of Context:
113
113
    >>> i.id2path('2326')
114
114
    'src/wibble/wibble.c'
115
115
    """
 
116
 
 
117
    # Constants returned by describe_change()
 
118
    #
 
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.
 
122
    RENAMED = 'renamed'
 
123
    MODIFIED_AND_RENAMED = 'modified and renamed'
116
124
    
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
355
363
 
356
 
    def _describe_snapshot_change(self, previous_entries):
357
 
        """Describe how this entry will have changed in a new commit.
358
 
 
359
 
        :param previous_entries: Dictionary from revision_id to inventory entry.
360
 
 
361
 
        :returns: One-word description: "merged", "added", "renamed", "modified".
 
364
    @staticmethod
 
365
    def describe_change(old_entry, new_entry):
 
366
        """Describe the change between old_entry and this.
 
367
        
 
368
        This smells of being an InterInventoryEntry situation, but as its
 
369
        the first one, we're making it a static method for now.
 
370
 
 
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
 
374
        child entry itself.
362
375
        """
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?
366
 
        #
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.
370
 
        #
371
 
        if len(previous_entries) > 1:
372
 
            return 'merged'
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
 
379
            return 'unchanged'
 
380
        elif old_entry is None:
374
381
            return 'added'
375
 
        the_parent, = previous_entries.values()
376
 
        if self.parent_id != the_parent.parent_id:
377
 
            # actually, moved to another directory
378
 
            return 'renamed'
379
 
        elif self.name != the_parent.name:
380
 
            return 'renamed'
381
 
        return 'modified'
 
382
        elif new_entry is None:
 
383
            return 'removed'
 
384
        text_modified, meta_modified = new_entry.detect_changes(old_entry)
 
385
        if text_modified or meta_modified:
 
386
            modified = True
 
387
        else:
 
388
            modified = False
 
389
        # TODO 20060511 (mbp, rbc) factor out 'detect_rename' here.
 
390
        if old_entry.parent_id != new_entry.parent_id:
 
391
            renamed = True
 
392
        elif old_entry.name != new_entry.name:
 
393
            renamed = True
 
394
        else:
 
395
            renamed = False
 
396
        if renamed and not modified:
 
397
            return InventoryEntry.RENAMED
 
398
        if modified and not renamed:
 
399
            return 'modified'
 
400
        if modified and renamed:
 
401
            return InventoryEntry.MODIFIED_AND_RENAMED
 
402
        return 'unchanged'
382
403
 
383
404
    def __repr__(self):
384
405
        return ("%s(%r, %r, parent_id=%r)"
419
440
        """
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,
424
444
                            transaction)
425
 
        return change
426
445
 
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.
656
675
        self.text_sha1 = None
657
676
        self.executable = None
658
677
 
659
 
    def _snapshot_text(self, file_parents, work_tree, weave_store, transaction):
 
678
    def _snapshot_text(self, file_parents, work_tree, versionedfile_store, transaction):
660
679
        """See InventoryEntry._snapshot_text."""
661
 
        mutter('storing file {%s} in revision {%s}',
662
 
               self.file_id, self.revision)
 
680
        mutter('storing text of file {%s} in revision {%s} into %r',
 
681
               self.file_id, self.revision, versionedfile_store)
663
682
        # special case to avoid diffing on renames or 
664
683
        # reparenting
665
684
        if (len(file_parents) == 1
666
685
            and self.text_sha1 == file_parents.values()[0].text_sha1
667
686
            and self.text_size == file_parents.values()[0].text_size):
668
687
            previous_ie = file_parents.values()[0]
669
 
            versionedfile = weave_store.get_weave(self.file_id, transaction)
 
688
            versionedfile = versionedfile_store.get_weave(self.file_id, transaction)
670
689
            versionedfile.clone_text(self.revision, previous_ie.revision, file_parents.keys())
671
690
        else:
672
691
            new_lines = work_tree.get_file(self.file_id).readlines()
673
 
            self._add_text_to_weave(new_lines, file_parents.keys(), weave_store,
 
692
            self._add_text_to_weave(new_lines, file_parents.keys(), versionedfile_store,
674
693
                                    transaction)
675
694
            self.text_sha1 = sha_strings(new_lines)
676
695
            self.text_size = sum(map(len, new_lines))