~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/commit.py

merge 2.0 branch rev 4647

Show diffs side-by-side

added added

removed removed

Lines of Context:
108
108
    def deleted(self, path):
109
109
        pass
110
110
 
111
 
    def escaped(self, escape_count, message):
112
 
        pass
113
 
 
114
111
    def missing(self, path):
115
112
        pass
116
113
 
153
150
    def deleted(self, path):
154
151
        self._note('deleted %s', path)
155
152
 
156
 
    def escaped(self, escape_count, message):
157
 
        self._note("replaced %d control characters in message", escape_count)
158
 
 
159
153
    def missing(self, path):
160
154
        self._note('missing %s', path)
161
155
 
210
204
        """Commit working copy as a new revision.
211
205
 
212
206
        :param message: the commit message (it or message_callback is required)
 
207
        :param message_callback: A callback: message = message_callback(cmt_obj)
213
208
 
214
209
        :param timestamp: if not None, seconds-since-epoch for a
215
210
            postdated/predated commit.
216
211
 
217
 
        :param specific_files: If true, commit only those files.
 
212
        :param specific_files: If not None, commit only those files. An empty
 
213
            list means 'commit no files'.
218
214
 
219
215
        :param rev_id: If set, use this as the new revision id.
220
216
            Useful for test or import commands that need to tightly
269
265
        self.master_locked = False
270
266
        self.recursive = recursive
271
267
        self.rev_id = None
 
268
        # self.specific_files is None to indicate no filter, or any iterable to
 
269
        # indicate a filter - [] means no files at all, as per iter_changes.
272
270
        if specific_files is not None:
273
271
            self.specific_files = sorted(
274
272
                minimum_path_selection(specific_files))
290
288
        # the command line parameters, and the repository has fast delta
291
289
        # generation. See bug 347649.
292
290
        self.use_record_iter_changes = (
293
 
            not self.specific_files and
294
291
            not self.exclude and 
295
292
            not self.branch.repository._format.supports_tree_reference and
296
293
            (self.branch.repository._format.fast_deltas or
338
335
            self._gather_parents()
339
336
            # After a merge, a selected file commit is not supported.
340
337
            # See 'bzr help merge' for an explanation as to why.
341
 
            if len(self.parents) > 1 and self.specific_files:
 
338
            if len(self.parents) > 1 and self.specific_files is not None:
342
339
                raise errors.CannotCommitSelectedFileMerge(self.specific_files)
343
340
            # Excludes are a form of selected file commit.
344
341
            if len(self.parents) > 1 and self.exclude:
373
370
                # Prompt the user for a commit message if none provided
374
371
                message = message_callback(self)
375
372
                self.message = message
376
 
                self._escape_commit_message()
377
373
 
378
374
                # Add revision data to the local branch
379
375
                self.rev_id = self.builder.commit(self.message)
399
395
            # and now do the commit locally.
400
396
            self.branch.set_last_revision_info(new_revno, self.rev_id)
401
397
 
402
 
            # Make the working tree up to date with the branch
 
398
            # Make the working tree be up to date with the branch. This
 
399
            # includes automatic changes scheduled to be made to the tree, such
 
400
            # as updating its basis and unversioning paths that were missing.
 
401
            self.work_tree.unversion(self.deleted_ids)
403
402
            self._set_progress_stage("Updating the working tree")
404
403
            self.work_tree.update_basis_by_delta(self.rev_id,
405
404
                 self.builder.get_basis_delta())
602
601
        if self.master_locked:
603
602
            self.master_branch.unlock()
604
603
 
605
 
    def _escape_commit_message(self):
606
 
        """Replace xml-incompatible control characters."""
607
 
        # FIXME: RBC 20060419 this should be done by the revision
608
 
        # serialiser not by commit. Then we can also add an unescaper
609
 
        # in the deserializer and start roundtripping revision messages
610
 
        # precisely. See repository_implementations/test_repository.py
611
 
        self.message, escape_count = xml_serializer.escape_invalid_chars(
612
 
            self.message)
613
 
        if escape_count:
614
 
            self.reporter.escaped(escape_count, self.message)
615
 
 
616
604
    def _gather_parents(self):
617
605
        """Record the parents of a merge for merge detection."""
618
606
        # TODO: Make sure that this list doesn't contain duplicate
633
621
        """Update the commit builder with the data about what has changed.
634
622
        """
635
623
        exclude = self.exclude
636
 
        specific_files = self.specific_files or []
 
624
        specific_files = self.specific_files
637
625
        mutter("Selecting files for commit with filter %s", specific_files)
638
626
 
639
627
        self._check_strict()
640
628
        if self.use_record_iter_changes:
641
 
            iter_changes = self.work_tree.iter_changes(self.basis_tree)
 
629
            iter_changes = self.work_tree.iter_changes(self.basis_tree,
 
630
                specific_files=specific_files)
642
631
            iter_changes = self._filter_iter_changes(iter_changes)
643
632
            for file_id, path, fs_hash in self.builder.record_iter_changes(
644
633
                self.work_tree, self.basis_revid, iter_changes):
697
686
                            reporter.snapshot_change('modified', new_path)
698
687
            self._next_progress_entry()
699
688
        # Unversion IDs that were found to be deleted
700
 
        self.work_tree.unversion(deleted_ids)
 
689
        self.deleted_ids = deleted_ids
701
690
 
702
691
    def _record_unselected(self):
703
692
        # If specific files are selected, then all un-selected files must be
816
805
                # _update_builder_with_changes.
817
806
                continue
818
807
            content_summary = self.work_tree.path_content_summary(path)
 
808
            kind = content_summary[0]
819
809
            # Note that when a filter of specific files is given, we must only
820
810
            # skip/record deleted files matching that filter.
821
811
            if not specific_files or is_inside_any(specific_files, path):
822
 
                if content_summary[0] == 'missing':
 
812
                if kind == 'missing':
823
813
                    if not deleted_paths:
824
814
                        # path won't have been split yet.
825
815
                        path_segments = splitpath(path)
832
822
                    continue
833
823
            # TODO: have the builder do the nested commit just-in-time IF and
834
824
            # only if needed.
835
 
            if content_summary[0] == 'tree-reference':
 
825
            if kind == 'tree-reference':
836
826
                # enforce repository nested tree policy.
837
827
                if (not self.work_tree.supports_tree_reference() or
838
828
                    # repository does not support it either.
839
829
                    not self.branch.repository._format.supports_tree_reference):
840
 
                    content_summary = ('directory',) + content_summary[1:]
841
 
            kind = content_summary[0]
842
 
            # TODO: specific_files filtering before nested tree processing
843
 
            if kind == 'tree-reference':
844
 
                if self.recursive == 'down':
 
830
                    kind = 'directory'
 
831
                    content_summary = (kind, None, None, None)
 
832
                elif self.recursive == 'down':
845
833
                    nested_revision_id = self._commit_nested_tree(
846
834
                        file_id, path)
847
 
                    content_summary = content_summary[:3] + (
848
 
                        nested_revision_id,)
 
835
                    content_summary = (kind, None, None, nested_revision_id)
849
836
                else:
850
 
                    content_summary = content_summary[:3] + (
851
 
                        self.work_tree.get_reference_revision(file_id),)
 
837
                    nested_revision_id = self.work_tree.get_reference_revision(file_id)
 
838
                    content_summary = (kind, None, None, nested_revision_id)
852
839
 
853
840
            # Record an entry for this item
854
841
            # Note: I don't particularly want to have the existing_ie
860
847
                content_summary)
861
848
 
862
849
        # Unversion IDs that were found to be deleted
863
 
        self.work_tree.unversion(deleted_ids)
 
850
        self.deleted_ids = deleted_ids
864
851
 
865
852
    def _commit_nested_tree(self, file_id, path):
866
853
        "Commit a nested tree."