/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/commit.py

  • Committer: Robert Collins
  • Date: 2007-09-21 06:10:31 UTC
  • mfrom: (2844 +trunk)
  • mto: (2592.3.144 repository)
  • mto: This revision was merged to the branch mainline in revision 2879.
  • Revision ID: robertc@robertcollins.net-20070921061031-p945q13ra1jjcli2
Merge bzr.dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
68
68
                           ConflictsInTree,
69
69
                           StrictCommitFailed
70
70
                           )
71
 
from bzrlib.osutils import (kind_marker, isdir,isfile, is_inside_any, 
 
71
from bzrlib.osutils import (kind_marker, isdir,isfile, is_inside_any,
72
72
                            is_inside_or_parent_of_any,
 
73
                            minimum_path_selection,
73
74
                            quotefn, sha_file, split_lines)
74
75
from bzrlib.testament import Testament
75
76
from bzrlib.trace import mutter, note, warning, is_quiet
241
242
                               " parameter is required for commit().")
242
243
 
243
244
        self.bound_branch = None
 
245
        self.any_entries_changed = False
 
246
        self.any_entries_deleted = False
244
247
        self.local = local
245
248
        self.master_branch = None
246
249
        self.master_locked = False
247
250
        self.rev_id = None
248
 
        self.specific_files = specific_files
 
251
        if specific_files is not None:
 
252
            self.specific_files = sorted(
 
253
                minimum_path_selection(specific_files))
 
254
        else:
 
255
            self.specific_files = None
 
256
        self.specific_file_ids = None
249
257
        self.allow_pointless = allow_pointless
250
258
        self.revprops = revprops
251
259
        self.message_callback = message_callback
279
287
                self.config = self.branch.get_config()
280
288
 
281
289
            # If provided, ensure the specified files are versioned
282
 
            if specific_files is not None:
283
 
                # Note: We don't actually need the IDs here. This routine
284
 
                # is being called because it raises PathNotVerisonedError
285
 
                # as a side effect of finding the IDs.
 
290
            if self.specific_files is not None:
 
291
                # Note: This routine is being called because it raises
 
292
                # PathNotVerisonedError as a side effect of finding the IDs. We
 
293
                # later use the ids we found as input to the working tree
 
294
                # inventory iterator, so we only consider those ids rather than
 
295
                # examining the whole tree again.
286
296
                # XXX: Dont we have filter_unversioned to do this more
287
297
                # cheaply?
288
 
                tree.find_ids_across_trees(specific_files,
289
 
                                           [self.basis_tree, self.work_tree])
 
298
                self.specific_file_ids = tree.find_ids_across_trees(
 
299
                    specific_files, [self.basis_tree, self.work_tree])
290
300
 
291
301
            # Setup the progress bar. As the number of files that need to be
292
302
            # committed in unknown, progress is reported as stages.
384
394
            return NullCommitReporter()
385
395
        return ReportCommitToLog()
386
396
 
387
 
    def _any_real_changes(self):
388
 
        """Are there real changes between new_inventory and basis?
389
 
 
390
 
        For trees without rich roots, inv.root.revision changes every commit.
391
 
        But if that is the only change, we want to treat it as though there
392
 
        are *no* changes.
393
 
        """
394
 
        new_entries = self.builder.new_inventory.iter_entries()
395
 
        basis_entries = self.basis_inv.iter_entries()
396
 
        new_path, new_root_ie = new_entries.next()
397
 
        basis_path, basis_root_ie = basis_entries.next()
398
 
 
399
 
        # This is a copy of InventoryEntry.__eq__ only leaving out .revision
400
 
        def ie_equal_no_revision(this, other):
401
 
            return ((this.file_id == other.file_id)
402
 
                    and (this.name == other.name)
403
 
                    and (this.symlink_target == other.symlink_target)
404
 
                    and (this.text_sha1 == other.text_sha1)
405
 
                    and (this.text_size == other.text_size)
406
 
                    and (this.text_id == other.text_id)
407
 
                    and (this.parent_id == other.parent_id)
408
 
                    and (this.kind == other.kind)
409
 
                    and (this.executable == other.executable)
410
 
                    and (this.reference_revision == other.reference_revision)
411
 
                    )
412
 
        if not ie_equal_no_revision(new_root_ie, basis_root_ie):
413
 
            return True
414
 
 
415
 
        for new_ie, basis_ie in zip(new_entries, basis_entries):
416
 
            if new_ie != basis_ie:
417
 
                return True
418
 
 
419
 
        # No actual changes present
420
 
        return False
421
 
 
422
397
    def _check_pointless(self):
423
398
        if self.allow_pointless:
424
399
            return
435
410
            return
436
411
        # If length == 1, then we only have the root entry. Which means
437
412
        # that there is no real difference (only the root could be different)
438
 
        if (len(self.builder.new_inventory) != 1 and self._any_real_changes()):
 
413
        if len(self.builder.new_inventory) != 1 and (self.any_entries_changed
 
414
            or self.any_entries_deleted):
439
415
            return
440
416
        raise PointlessCommit()
441
417
 
672
648
        # recorded in their previous state. For more details, see
673
649
        # https://lists.ubuntu.com/archives/bazaar/2007q3/028476.html.
674
650
        if specific_files:
675
 
            for path, new_ie in self.basis_inv.iter_entries():
676
 
                if new_ie.file_id in self.builder.new_inventory:
 
651
            for path, old_ie in self.basis_inv.iter_entries():
 
652
                if old_ie.file_id in self.builder.new_inventory:
677
653
                    # already added - skip.
678
654
                    continue
679
655
                if is_inside_any(specific_files, path):
680
656
                    # was inside the selected path, if not present it has been
681
657
                    # deleted so skip.
682
658
                    continue
 
659
                if old_ie.kind == 'directory':
 
660
                    self._next_progress_entry()
683
661
                # not in final inv yet, was not in the selected files, so is an
684
662
                # entry to be preserved unaltered.
685
 
                ie = new_ie.copy()
686
 
                self.builder.record_entry_contents(ie, self.parent_invs, path,
687
 
                                                   self.basis_tree, None)
 
663
                ie = old_ie.copy()
 
664
                # Note: specific file commits after a merge are currently
 
665
                # prohibited. This test is for sanity/safety in case it's
 
666
                # required after that changes.
 
667
                if len(self.parents) > 1:
 
668
                    ie.revision = None
 
669
                if self.builder.record_entry_contents(ie, self.parent_invs, path,
 
670
                    self.basis_tree, None):
 
671
                    self.any_entries_changed = True
688
672
 
 
673
        # note that deletes have occurred
 
674
        if set(self.basis_inv._byid.keys()) - set(self.builder.new_inventory._byid.keys()):
 
675
            self.any_entries_deleted = True
689
676
        # Report what was deleted.
690
 
        if self.reporter.is_verbose():
 
677
        if self.any_entries_deleted and self.reporter.is_verbose():
691
678
            for path, ie in self.basis_inv.iter_entries():
692
679
                if ie.file_id not in self.builder.new_inventory:
693
680
                    self.reporter.deleted(path)
704
691
        deleted_paths = set()
705
692
        work_inv = self.work_tree.inventory
706
693
        assert work_inv.root is not None
707
 
        entries = work_inv.iter_entries()
708
694
        # XXX: Note that entries may have the wrong kind.
 
695
        entries = work_inv.iter_entries_by_dir(
 
696
            specific_file_ids=self.specific_file_ids, yield_parents=True)
709
697
        if not self.builder.record_root_entry:
710
698
            entries.next()
711
699
        for path, existing_ie in entries:
715
703
            kind = existing_ie.kind
716
704
            if kind == 'directory':
717
705
                self._next_progress_entry()
718
 
 
719
706
            # Skip files that have been deleted from the working tree.
720
707
            # The deleted files/directories are also recorded so they
721
708
            # can be explicitly unversioned later. Note that when a
794
781
        content_summary):
795
782
        "Record the new inventory entry for a path if any."
796
783
        # mutter('check %s {%s}', path, file_id)
797
 
        if (not specific_files or 
798
 
            is_inside_or_parent_of_any(specific_files, path)):
799
 
                # mutter('%s selected for commit', path)
800
 
                if definitely_changed or existing_ie is None:
801
 
                    ie = inventory.make_entry(kind, name, parent_id, file_id)
802
 
                else:
803
 
                    ie = existing_ie.copy()
804
 
                    ie.revision = None
 
784
        # mutter('%s selected for commit', path)
 
785
        if definitely_changed or existing_ie is None:
 
786
            ie = inventory.make_entry(kind, name, parent_id, file_id)
805
787
        else:
806
 
            # mutter('%s not selected for commit', path)
807
 
            if self.basis_inv.has_id(file_id):
808
 
                ie = self.basis_inv[file_id].copy()
809
 
            else:
810
 
                # this entry is new and not being committed
811
 
                ie = None
812
 
        if ie is not None:
813
 
            self.builder.record_entry_contents(ie, self.parent_invs,
814
 
                path, self.work_tree, content_summary)
815
 
            if report_changes:
816
 
                self._report_change(ie, path)
 
788
            ie = existing_ie.copy()
 
789
            ie.revision = None
 
790
        if self.builder.record_entry_contents(ie, self.parent_invs,
 
791
            path, self.work_tree, content_summary):
 
792
            self.any_entries_changed = True
 
793
        if report_changes:
 
794
            self._report_change(ie, path)
817
795
        return ie
818
796
 
819
797
    def _report_change(self, ie, path):