/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

Faster partial commits by walking less data (Robert Collins)

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
247
248
        self.master_branch = None
248
249
        self.master_locked = False
249
250
        self.rev_id = None
250
 
        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
251
257
        self.allow_pointless = allow_pointless
252
258
        self.recursive = recursive
253
259
        self.revprops = revprops
282
288
                self.config = self.branch.get_config()
283
289
 
284
290
            # If provided, ensure the specified files are versioned
285
 
            if specific_files is not None:
286
 
                # Note: We don't actually need the IDs here. This routine
 
291
            if self.specific_files is not None:
 
292
                # Note: This routine
287
293
                # is being called because it raises PathNotVerisonedError
288
 
                # as a side effect of finding the IDs.
 
294
                # as a side effect of finding the IDs. We later use the ids we
 
295
                # found as input to the working tree inventory iterator, so we
 
296
                # only consider those ids rather than examining the whole tree
 
297
                # again.
289
298
                # XXX: Dont we have filter_unversioned to do this more
290
299
                # cheaply?
291
 
                tree.find_ids_across_trees(specific_files,
292
 
                                           [self.basis_tree, self.work_tree])
 
300
                self.specific_file_ids = tree.find_ids_across_trees(
 
301
                    specific_files, [self.basis_tree, self.work_tree])
293
302
 
294
303
            # Setup the progress bar. As the number of files that need to be
295
304
            # committed in unknown, progress is reported as stages.
639
648
        # recorded in their previous state. For more details, see
640
649
        # https://lists.ubuntu.com/archives/bazaar/2007q3/028476.html.
641
650
        if specific_files:
642
 
            for path, new_ie in self.basis_inv.iter_entries():
643
 
                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:
644
653
                    continue
645
654
                if is_inside_any(specific_files, path):
646
655
                    continue
647
 
                ie = new_ie.copy()
648
 
                ie.revision = None
 
656
                if old_ie.kind == 'directory':
 
657
                    self._next_progress_entry()
 
658
                ie = old_ie.copy()
 
659
                # Note: specific file commits after a merge are currently
 
660
                # prohibited. This test is for sanity/safety in case it's
 
661
                # required after that changes.
 
662
                if len(self.parents) > 1:
 
663
                    ie.revision = None
649
664
                if self.builder.record_entry_contents(ie, self.parent_invs, path,
650
665
                    self.basis_tree):
651
666
                    self.any_entries_changed = True
671
686
        deleted_paths = set()
672
687
        work_inv = self.work_tree.inventory
673
688
        assert work_inv.root is not None
674
 
        entries = work_inv.iter_entries_by_dir()
 
689
        entries = work_inv.iter_entries_by_dir(
 
690
            specific_file_ids=self.specific_file_ids, yield_parents=True)
675
691
        if not self.builder.record_root_entry:
676
692
            entries.next()
677
693
        for path, existing_ie in entries:
681
697
            kind = existing_ie.kind
682
698
            if kind == 'directory':
683
699
                self._next_progress_entry()
684
 
 
685
700
            # Skip files that have been deleted from the working tree.
686
701
            # The deleted files/directories are also recorded so they
687
702
            # can be explicitly unversioned later. Note that when a
689
704
            # deleted files matching that filter.
690
705
            if is_inside_any(deleted_paths, path):
691
706
                continue
692
 
            if not specific_files or is_inside_any(specific_files, path):
693
 
                if not self.work_tree.has_filename(path):
694
 
                    deleted_paths.add(path)
695
 
                    self.reporter.missing(path)
696
 
                    deleted_ids.append(file_id)
697
 
                    continue
 
707
            if not self.work_tree.has_filename(path):
 
708
                deleted_paths.add(path)
 
709
                self.reporter.missing(path)
 
710
                deleted_ids.append(file_id)
 
711
                continue
698
712
            try:
699
713
                kind = self.work_tree.kind(file_id)
700
714
                # TODO: specific_files filtering before nested tree processing
744
758
            report_changes=True):
745
759
        "Record the new inventory entry for a path if any."
746
760
        # mutter('check %s {%s}', path, file_id)
747
 
        if (not specific_files or 
748
 
            is_inside_or_parent_of_any(specific_files, path)):
749
 
                # mutter('%s selected for commit', path)
750
 
                if definitely_changed or existing_ie is None:
751
 
                    ie = inventory.make_entry(kind, name, parent_id, file_id)
752
 
                else:
753
 
                    ie = existing_ie.copy()
754
 
                    ie.revision = None
 
761
        # mutter('%s selected for commit', path)
 
762
        if definitely_changed or existing_ie is None:
 
763
            ie = inventory.make_entry(kind, name, parent_id, file_id)
755
764
        else:
756
 
            # mutter('%s not selected for commit', path)
757
 
            if self.basis_inv.has_id(file_id):
758
 
                ie = self.basis_inv[file_id].copy()
759
 
            else:
760
 
                # this entry is new and not being committed
761
 
                ie = None
762
 
        if ie is not None:
763
 
            if self.builder.record_entry_contents(ie, self.parent_invs,
764
 
                path, self.work_tree):
765
 
                self.any_entries_changed = True
766
 
            if report_changes:
767
 
                self._report_change(ie, path)
 
765
            ie = existing_ie.copy()
 
766
            ie.revision = None
 
767
        if self.builder.record_entry_contents(ie, self.parent_invs, 
 
768
            path, self.work_tree):
 
769
            self.any_entries_changed = True
 
770
        if report_changes:
 
771
            self._report_change(ie, path)
768
772
        return ie
769
773
 
770
774
    def _report_change(self, ie, path):