~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/commit.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2010-05-07 08:01:38 UTC
  • mfrom: (5187.2.12 549310-mandatory-whoami)
  • Revision ID: pqm@pqm.ubuntu.com-20100507080138-doe642wej2tu47t5
(parthm) trivial docstring fix to indicate when errors.NoWhoami is raised.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2011 Canonical Ltd
 
1
# Copyright (C) 2005-2010 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
52
52
from bzrlib import (
53
53
    debug,
54
54
    errors,
 
55
    revision,
55
56
    trace,
56
57
    tree,
57
 
    ui,
58
58
    )
59
59
from bzrlib.branch import Branch
60
60
from bzrlib.cleanup import OperationWithCleanups
72
72
from bzrlib.inventory import Inventory, InventoryEntry, make_entry
73
73
from bzrlib import symbol_versioning
74
74
from bzrlib.urlutils import unescape_for_display
 
75
import bzrlib.ui
75
76
 
76
77
 
77
78
class NullCommitReporter(object):
173
174
        self.reporter = reporter
174
175
        self.config = config
175
176
 
176
 
    @staticmethod
177
 
    def update_revprops(revprops, branch, authors=None, author=None,
178
 
                        local=False, possible_master_transports=None):
179
 
        if revprops is None:
180
 
            revprops = {}
181
 
        if possible_master_transports is None:
182
 
            possible_master_transports = []
183
 
        if not 'branch-nick' in revprops:
184
 
            revprops['branch-nick'] = branch._get_nick(
185
 
                local,
186
 
                possible_master_transports)
187
 
        if authors is not None:
188
 
            if author is not None:
189
 
                raise AssertionError('Specifying both author and authors '
190
 
                        'is not allowed. Specify just authors instead')
191
 
            if 'author' in revprops or 'authors' in revprops:
192
 
                # XXX: maybe we should just accept one of them?
193
 
                raise AssertionError('author property given twice')
194
 
            if authors:
195
 
                for individual in authors:
196
 
                    if '\n' in individual:
197
 
                        raise AssertionError('\\n is not a valid character '
198
 
                                'in an author identity')
199
 
                revprops['authors'] = '\n'.join(authors)
200
 
        if author is not None:
201
 
            symbol_versioning.warn('The parameter author was deprecated'
202
 
                   ' in version 1.13. Use authors instead',
203
 
                   DeprecationWarning)
204
 
            if 'author' in revprops or 'authors' in revprops:
205
 
                # XXX: maybe we should just accept one of them?
206
 
                raise AssertionError('author property given twice')
207
 
            if '\n' in author:
208
 
                raise AssertionError('\\n is not a valid character '
209
 
                        'in an author identity')
210
 
            revprops['authors'] = author
211
 
        return revprops
212
 
 
213
177
    def commit(self,
214
178
               message=None,
215
179
               timestamp=None,
228
192
               message_callback=None,
229
193
               recursive='down',
230
194
               exclude=None,
231
 
               possible_master_transports=None,
232
 
               lossy=False):
 
195
               possible_master_transports=None):
233
196
        """Commit working copy as a new revision.
234
197
 
235
198
        :param message: the commit message (it or message_callback is required)
262
225
        :param exclude: None or a list of relative paths to exclude from the
263
226
            commit. Pending changes to excluded files will be ignored by the
264
227
            commit.
265
 
        :param lossy: When committing to a foreign VCS, ignore any
266
 
            data that can not be natively represented.
267
228
        """
268
229
        operation = OperationWithCleanups(self._commit)
269
230
        self.revprops = revprops or {}
285
246
               message_callback=message_callback,
286
247
               recursive=recursive,
287
248
               exclude=exclude,
288
 
               possible_master_transports=possible_master_transports,
289
 
               lossy=lossy)
 
249
               possible_master_transports=possible_master_transports)
290
250
 
291
251
    def _commit(self, operation, message, timestamp, timezone, committer,
292
252
            specific_files, rev_id, allow_pointless, strict, verbose,
293
253
            working_tree, local, reporter, message_callback, recursive,
294
 
            exclude, possible_master_transports, lossy):
 
254
            exclude, possible_master_transports):
295
255
        mutter('preparing to commit')
296
256
 
297
257
        if working_tree is None:
329
289
                minimum_path_selection(specific_files))
330
290
        else:
331
291
            self.specific_files = None
332
 
 
 
292
            
333
293
        self.allow_pointless = allow_pointless
334
294
        self.message_callback = message_callback
335
295
        self.timestamp = timestamp
349
309
            not self.branch.repository._format.supports_tree_reference and
350
310
            (self.branch.repository._format.fast_deltas or
351
311
             len(self.parents) < 2))
352
 
        self.pb = ui.ui_factory.nested_progress_bar()
 
312
        self.pb = bzrlib.ui.ui_factory.nested_progress_bar()
353
313
        operation.add_cleanup(self.pb.finished)
354
314
        self.basis_revid = self.work_tree.last_revision()
355
315
        self.basis_tree = self.work_tree.basis_tree()
383
343
        self.pb_stage_count = 0
384
344
        self.pb_stage_total = 5
385
345
        if self.bound_branch:
386
 
            # 2 extra stages: "Uploading data to master branch" and "Merging
387
 
            # tags to master branch"
388
 
            self.pb_stage_total += 2
 
346
            self.pb_stage_total += 1
389
347
        self.pb.show_pct = False
390
348
        self.pb.show_spinner = False
391
349
        self.pb.show_eta = False
403
361
 
404
362
        # Collect the changes
405
363
        self._set_progress_stage("Collecting changes", counter=True)
406
 
        self._lossy = lossy
407
364
        self.builder = self.branch.get_commit_builder(self.parents,
408
 
            self.config, timestamp, timezone, committer, self.revprops,
409
 
            rev_id, lossy=lossy)
410
 
        if not self.builder.supports_record_entry_contents and self.exclude:
411
 
            self.builder.abort()
412
 
            raise errors.ExcludesUnsupported(self.branch.repository)
 
365
            self.config, timestamp, timezone, committer, self.revprops, rev_id)
413
366
 
414
367
        try:
415
368
            self.builder.will_record_deletes()
442
395
        except Exception, e:
443
396
            mutter("aborting commit write group because of exception:")
444
397
            trace.log_exception_quietly()
 
398
            note("aborting commit write group: %r" % (e,))
445
399
            self.builder.abort()
446
400
            raise
447
401
 
453
407
            self._set_progress_stage("Uploading data to master branch")
454
408
            # 'commit' to the master first so a timeout here causes the
455
409
            # local branch to be out of date
456
 
            (new_revno, self.rev_id) = self.master_branch.import_last_revision_info_and_tags(
457
 
                self.branch, new_revno, self.rev_id, lossy=lossy)
458
 
            if lossy:
459
 
                self.branch.fetch(self.master_branch, self.rev_id)
 
410
            self.master_branch.import_last_revision_info(
 
411
                self.branch.repository, new_revno, self.rev_id)
460
412
 
461
413
        # and now do the commit locally.
462
414
        self.branch.set_last_revision_info(new_revno, self.rev_id)
463
415
 
464
 
        # Merge local tags to remote
465
 
        if self.bound_branch:
466
 
            self._set_progress_stage("Merging tags to master branch")
467
 
            tag_updates, tag_conflicts = self.branch.tags.merge_to(
468
 
                self.master_branch.tags)
469
 
            if tag_conflicts:
470
 
                warning_lines = ['    ' + name for name, _, _ in tag_conflicts]
471
 
                note("Conflicting tags in bound branch:\n" +
472
 
                    "\n".join(warning_lines))
473
 
 
474
416
        # Make the working tree be up to date with the branch. This
475
417
        # includes automatic changes scheduled to be made to the tree, such
476
418
        # as updating its basis and unversioning paths that were missing.
494
436
        # A merge with no effect on files
495
437
        if len(self.parents) > 1:
496
438
            return
 
439
        # TODO: we could simplify this by using self.builder.basis_delta.
 
440
 
 
441
        # The initial commit adds a root directory, but this in itself is not
 
442
        # a worthwhile commit.
 
443
        if (self.basis_revid == revision.NULL_REVISION and
 
444
            ((self.builder.new_inventory is not None and
 
445
             len(self.builder.new_inventory) == 1) or
 
446
            len(self.builder._basis_delta) == 1)):
 
447
            raise PointlessCommit()
497
448
        if self.builder.any_changes():
498
449
            return
499
450
        raise PointlessCommit()
695
646
                # Reset the new path (None) and new versioned flag (False)
696
647
                change = (change[0], (change[1][0], None), change[2],
697
648
                    (change[3][0], False)) + change[4:]
698
 
                new_path = change[1][1]
699
 
                versioned = False
700
649
            elif kind == 'tree-reference':
701
650
                if self.recursive == 'down':
702
651
                    self._commit_nested_tree(change[0], change[1][1])
726
675
        if self.specific_files or self.exclude:
727
676
            specific_files = self.specific_files or []
728
677
            for path, old_ie in self.basis_inv.iter_entries():
729
 
                if self.builder.new_inventory.has_id(old_ie.file_id):
 
678
                if old_ie.file_id in self.builder.new_inventory:
730
679
                    # already added - skip.
731
680
                    continue
732
681
                if (is_inside_any(specific_files, path)