~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: 2007-02-27 22:08:46 UTC
  • mfrom: (2227.4.1 bzr.78026)
  • Revision ID: pqm@pqm.ubuntu.com-20070227220846-8cce3b2986915092
CapitalizeĀ rocksĀ output

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
16
 
17
17
 
18
 
# XXX: Can we do any better about making interrupted commits change
19
 
# nothing?  
20
 
 
21
 
# TODO: Separate 'prepare' phase where we find a list of potentially
22
 
# committed files.  We then can then pause the commit to prompt for a
23
 
# commit message, knowing the summary will be the same as what's
24
 
# actually used for the commit.  (But perhaps simpler to simply get
25
 
# the tree status, then use that for a selective commit?)
26
 
 
27
18
# The newly committed revision is going to have a shape corresponding
28
19
# to that of the working inventory.  Files that are not in the
29
20
# working tree and that were in the predecessor are reported as
55
46
# merges from, then it should still be reported as newly added
56
47
# relative to the basis revision.
57
48
 
58
 
# TODO: Do checks that the tree can be committed *before* running the 
59
 
# editor; this should include checks for a pointless commit and for 
60
 
# unknown or missing files.
61
 
 
62
 
# TODO: If commit fails, leave the message in a file somewhere.
63
 
 
64
49
# TODO: Change the parameter 'rev_id' to 'revision_id' to be consistent with
65
50
# the rest of the code; add a deprecation of the old name.
66
51
 
73
58
 
74
59
from bzrlib import (
75
60
    errors,
 
61
    inventory,
76
62
    tree,
77
63
    )
 
64
from bzrlib.branch import Branch
78
65
import bzrlib.config
79
66
from bzrlib.errors import (BzrError, PointlessCommit,
80
67
                           ConflictsInTree,
92
79
        deprecated_function,
93
80
        DEPRECATED_PARAMETER)
94
81
from bzrlib.workingtree import WorkingTree
 
82
import bzrlib.ui
95
83
 
96
84
 
97
85
class NullCommitReporter(object):
184
172
               working_tree=None,
185
173
               local=False,
186
174
               reporter=None,
187
 
               config=None):
 
175
               config=None,
 
176
               message_callback=None):
188
177
        """Commit working copy as a new revision.
189
178
 
190
179
        branch -- the deprecated branch to commit to. New callers should pass in 
191
180
                  working_tree instead
192
181
 
193
 
        message -- the commit message, a mandatory parameter
 
182
        message -- the commit message (it or message_callback is required)
194
183
 
195
184
        timestamp -- if not None, seconds-since-epoch for a
196
185
             postdated/predated commit.
225
214
        else:
226
215
            self.work_tree = working_tree
227
216
            self.branch = self.work_tree.branch
228
 
        if message is None:
229
 
            raise BzrError("The message keyword parameter is required for commit().")
 
217
        if message_callback is None:
 
218
            if message is not None:
 
219
                if isinstance(message, str):
 
220
                    message = message.decode(bzrlib.user_encoding)
 
221
                message_callback = lambda x: message
 
222
            else:
 
223
                raise BzrError("The message or message_callback keyword"
 
224
                               " parameter is required for commit().")
230
225
 
231
226
        self.bound_branch = None
232
227
        self.local = local
259
254
                # this is so that we still consier the master branch
260
255
                # - in a checkout scenario the tree may have no
261
256
                # parents but the branch may do.
262
 
                first_tree_parent = None
263
 
            master_last = self.master_branch.last_revision()
264
 
            if (master_last is not None and
265
 
                master_last != first_tree_parent):
266
 
                raise errors.OutOfDateTree(self.work_tree)
267
 
    
 
257
                first_tree_parent = bzrlib.revision.NULL_REVISION
 
258
            old_revno, master_last = self.master_branch.last_revision_info()
 
259
            if master_last != first_tree_parent:
 
260
                if master_last != bzrlib.revision.NULL_REVISION:
 
261
                    raise errors.OutOfDateTree(self.work_tree)
 
262
            if self.branch.repository.has_revision(first_tree_parent):
 
263
                new_revno = old_revno + 1
 
264
            else:
 
265
                # ghost parents never appear in revision history.
 
266
                new_revno = 1
268
267
            if strict:
269
268
                # raise an exception as soon as we find a single unknown.
270
269
                for unknown in self.work_tree.unknowns():
272
271
                   
273
272
            if self.config is None:
274
273
                self.config = self.branch.get_config()
275
 
      
276
 
            if isinstance(message, str):
277
 
                message = message.decode(bzrlib.user_encoding)
278
 
            assert isinstance(message, unicode), type(message)
279
 
            self.message = message
280
 
            self._escape_commit_message()
281
274
 
282
275
            self.work_inv = self.work_tree.inventory
283
276
            self.basis_tree = self.work_tree.basis_tree()
317
310
            # that commit will succeed.
318
311
            self.builder.finish_inventory()
319
312
            self._emit_progress_update()
 
313
            message = message_callback(self)
 
314
            assert isinstance(message, unicode), type(message)
 
315
            self.message = message
 
316
            self._escape_commit_message()
 
317
 
320
318
            self.rev_id = self.builder.commit(self.message)
321
319
            self._emit_progress_update()
322
320
            # revision data is in the local branch now.
329
327
                # now the master has the revision data
330
328
                # 'commit' to the master first so a timeout here causes the local
331
329
                # branch to be out of date
332
 
                self.master_branch.append_revision(self.rev_id)
 
330
                self.master_branch.set_last_revision_info(new_revno,
 
331
                                                          self.rev_id)
333
332
 
334
333
            # and now do the commit locally.
335
 
            self.branch.append_revision(self.rev_id)
 
334
            self.branch.set_last_revision_info(new_revno, self.rev_id)
336
335
 
337
336
            rev_tree = self.builder.revision_tree()
338
337
            self.work_tree.set_parent_trees([(self.rev_id, rev_tree)])
339
338
            # now the work tree is up to date with the branch
340
339
            
341
 
            self.reporter.completed(self.branch.revno(), self.rev_id)
 
340
            self.reporter.completed(new_revno, self.rev_id)
 
341
            # old style commit hooks - should be deprecated ? (obsoleted in
 
342
            # 0.15)
342
343
            if self.config.post_commit() is not None:
343
344
                hooks = self.config.post_commit().split(' ')
344
345
                # this would be nicer with twisted.python.reflect.namedAny
347
348
                                  {'branch':self.branch,
348
349
                                   'bzrlib':bzrlib,
349
350
                                   'rev_id':self.rev_id})
 
351
            # new style commit hooks:
 
352
            if not self.bound_branch:
 
353
                hook_master = self.branch
 
354
                hook_local = None
 
355
            else:
 
356
                hook_master = self.master_branch
 
357
                hook_local = self.branch
 
358
            # With bound branches, when the master is behind the local branch,
 
359
            # the 'old_revno' and old_revid values here are incorrect.
 
360
            # XXX: FIXME ^. RBC 20060206
 
361
            if self.parents:
 
362
                old_revid = self.parents[0]
 
363
            else:
 
364
                old_revid = bzrlib.revision.NULL_REVISION
 
365
            for hook in Branch.hooks['post_commit']:
 
366
                hook(hook_local, hook_master, old_revno, old_revid, new_revno,
 
367
                    self.rev_id)
350
368
            self._emit_progress_update()
351
369
        finally:
352
370
            self._cleanup()
436
454
        #       to local.
437
455
        
438
456
        # Make sure the local branch is identical to the master
439
 
        master_rh = self.master_branch.revision_history()
440
 
        local_rh = self.branch.revision_history()
441
 
        if local_rh != master_rh:
 
457
        master_info = self.master_branch.last_revision_info()
 
458
        local_info = self.branch.last_revision_info()
 
459
        if local_info != master_info:
442
460
            raise errors.BoundBranchOutOfDate(self.branch,
443
461
                    self.master_branch)
444
462
 
506
524
        # TODO: Make sure that this list doesn't contain duplicate 
507
525
        # entries and the order is preserved when doing this.
508
526
        self.parents = self.work_tree.get_parent_ids()
509
 
        self.parent_invs = []
510
 
        for revision in self.parents:
 
527
        self.parent_invs = [self.basis_inv]
 
528
        for revision in self.parents[1:]:
511
529
            if self.branch.repository.has_revision(revision):
512
530
                mutter('commit parent revision {%s}', revision)
513
531
                inventory = self.branch.repository.get_inventory(revision)
568
586
        for path, new_ie in entries:
569
587
            self._emit_progress_update()
570
588
            file_id = new_ie.file_id
 
589
            try:
 
590
                kind = self.work_tree.kind(file_id)
 
591
                if kind != new_ie.kind:
 
592
                    new_ie = inventory.make_entry(kind, new_ie.name,
 
593
                                                  new_ie.parent_id, file_id)
 
594
            except errors.NoSuchFile:
 
595
                pass
571
596
            # mutter('check %s {%s}', path, file_id)
572
597
            if (not self.specific_files or 
573
598
                is_inside_or_parent_of_any(self.specific_files, path)):