/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

Merge bzr.dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006 Canonical Ltd
 
1
# Copyright (C) 2005, 2006, 2007 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
58
58
 
59
59
from bzrlib import (
60
60
    errors,
 
61
    inventory,
61
62
    tree,
62
63
    )
 
64
from bzrlib.branch import Branch
63
65
import bzrlib.config
64
66
from bzrlib.errors import (BzrError, PointlessCommit,
65
67
                           ConflictsInTree,
157
159
            self.config = None
158
160
        
159
161
    def commit(self,
160
 
               branch=DEPRECATED_PARAMETER, message=None,
 
162
               message=None,
161
163
               timestamp=None,
162
164
               timezone=None,
163
165
               committer=None,
171
173
               local=False,
172
174
               reporter=None,
173
175
               config=None,
174
 
               message_callback=None):
 
176
               message_callback=None,
 
177
               recursive='down'):
175
178
        """Commit working copy as a new revision.
176
179
 
177
 
        branch -- the deprecated branch to commit to. New callers should pass in 
178
 
                  working_tree instead
179
 
 
180
180
        message -- the commit message (it or message_callback is required)
181
181
 
182
182
        timestamp -- if not None, seconds-since-epoch for a
198
198
 
199
199
        revprops -- Properties for new revision
200
200
        :param local: Perform a local only commit.
 
201
        :param recursive: If set to 'down', commit in any subtrees that have
 
202
            pending changes of any sort during this commit.
201
203
        """
202
204
        mutter('preparing to commit')
203
205
 
204
 
        if deprecated_passed(branch):
205
 
            symbol_versioning.warn("Commit.commit (branch, ...): The branch parameter is "
206
 
                 "deprecated as of bzr 0.8. Please use working_tree= instead.",
207
 
                 DeprecationWarning, stacklevel=2)
208
 
            self.branch = branch
209
 
            self.work_tree = self.branch.bzrdir.open_workingtree()
210
 
        elif working_tree is None:
211
 
            raise BzrError("One of branch and working_tree must be passed into commit().")
 
206
        if working_tree is None:
 
207
            raise BzrError("working_tree must be passed into commit().")
212
208
        else:
213
209
            self.work_tree = working_tree
214
210
            self.branch = self.work_tree.branch
 
211
            if getattr(self.work_tree, 'requires_rich_root', lambda: False)():
 
212
                if not self.branch.repository.supports_rich_root():
 
213
                    raise errors.RootNotRich()
215
214
        if message_callback is None:
216
215
            if message is not None:
217
216
                if isinstance(message, str):
228
227
        self.rev_id = None
229
228
        self.specific_files = specific_files
230
229
        self.allow_pointless = allow_pointless
 
230
        self.recursive = recursive
 
231
        self.revprops = revprops
 
232
        self.message_callback = message_callback
 
233
        self.timestamp = timestamp
 
234
        self.timezone = timezone
 
235
        self.committer = committer
 
236
        self.specific_files = specific_files
 
237
        self.strict = strict
 
238
        self.verbose = verbose
 
239
        self.local = local
231
240
 
232
241
        if reporter is None and self.reporter is None:
233
242
            self.reporter = NullCommitReporter()
236
245
 
237
246
        self.work_tree.lock_write()
238
247
        self.pb = bzrlib.ui.ui_factory.nested_progress_bar()
 
248
        self.basis_tree = self.work_tree.basis_tree()
 
249
        self.basis_tree.lock_read()
239
250
        try:
240
251
            # Cannot commit with conflicts present.
241
252
            if len(self.work_tree.conflicts())>0:
252
263
                # this is so that we still consier the master branch
253
264
                # - in a checkout scenario the tree may have no
254
265
                # parents but the branch may do.
255
 
                first_tree_parent = None
256
 
            master_last = self.master_branch.last_revision()
257
 
            if (master_last is not None and
258
 
                master_last != first_tree_parent):
259
 
                raise errors.OutOfDateTree(self.work_tree)
260
 
    
 
266
                first_tree_parent = bzrlib.revision.NULL_REVISION
 
267
            old_revno, master_last = self.master_branch.last_revision_info()
 
268
            if master_last != first_tree_parent:
 
269
                if master_last != bzrlib.revision.NULL_REVISION:
 
270
                    raise errors.OutOfDateTree(self.work_tree)
 
271
            if self.branch.repository.has_revision(first_tree_parent):
 
272
                new_revno = old_revno + 1
 
273
            else:
 
274
                # ghost parents never appear in revision history.
 
275
                new_revno = 1
261
276
            if strict:
262
277
                # raise an exception as soon as we find a single unknown.
263
278
                for unknown in self.work_tree.unknowns():
267
282
                self.config = self.branch.get_config()
268
283
 
269
284
            self.work_inv = self.work_tree.inventory
270
 
            self.basis_tree = self.work_tree.basis_tree()
271
285
            self.basis_inv = self.basis_tree.inventory
272
286
            if specific_files is not None:
273
287
                # Ensure specified files are versioned
274
288
                # (We don't actually need the ids here)
275
 
                tree.find_ids_across_trees(specific_files, 
 
289
                # XXX: Dont we have filter_unversioned to do this more
 
290
                # cheaply?
 
291
                tree.find_ids_across_trees(specific_files,
276
292
                                           [self.basis_tree, self.work_tree])
277
293
            # one to finish, one for rev and inventory, and one for each
278
294
            # inventory entry, and the same for the new inventory.
287
303
                raise NotImplementedError('selected-file commit of merges is not supported yet: files %r',
288
304
                        self.specific_files)
289
305
            
290
 
            self.builder = self.branch.get_commit_builder(self.parents, 
 
306
            self.builder = self.branch.get_commit_builder(self.parents,
291
307
                self.config, timestamp, timezone, committer, revprops, rev_id)
292
308
            
293
309
            self._remove_deleted()
321
337
                # now the master has the revision data
322
338
                # 'commit' to the master first so a timeout here causes the local
323
339
                # branch to be out of date
324
 
                self.master_branch.append_revision(self.rev_id)
 
340
                self.master_branch.set_last_revision_info(new_revno,
 
341
                                                          self.rev_id)
325
342
 
326
343
            # and now do the commit locally.
327
 
            self.branch.append_revision(self.rev_id)
 
344
            self.branch.set_last_revision_info(new_revno, self.rev_id)
328
345
 
329
346
            rev_tree = self.builder.revision_tree()
330
347
            self.work_tree.set_parent_trees([(self.rev_id, rev_tree)])
331
348
            # now the work tree is up to date with the branch
332
349
            
333
 
            self.reporter.completed(self.branch.revno(), self.rev_id)
 
350
            self.reporter.completed(new_revno, self.rev_id)
 
351
            # old style commit hooks - should be deprecated ? (obsoleted in
 
352
            # 0.15)
334
353
            if self.config.post_commit() is not None:
335
354
                hooks = self.config.post_commit().split(' ')
336
355
                # this would be nicer with twisted.python.reflect.namedAny
339
358
                                  {'branch':self.branch,
340
359
                                   'bzrlib':bzrlib,
341
360
                                   'rev_id':self.rev_id})
 
361
            # new style commit hooks:
 
362
            if not self.bound_branch:
 
363
                hook_master = self.branch
 
364
                hook_local = None
 
365
            else:
 
366
                hook_master = self.master_branch
 
367
                hook_local = self.branch
 
368
            # With bound branches, when the master is behind the local branch,
 
369
            # the 'old_revno' and old_revid values here are incorrect.
 
370
            # XXX: FIXME ^. RBC 20060206
 
371
            if self.parents:
 
372
                old_revid = self.parents[0]
 
373
            else:
 
374
                old_revid = bzrlib.revision.NULL_REVISION
 
375
            for hook in Branch.hooks['post_commit']:
 
376
                hook(hook_local, hook_master, old_revno, old_revid, new_revno,
 
377
                    self.rev_id)
342
378
            self._emit_progress_update()
343
379
        finally:
344
380
            self._cleanup()
367
403
                    and (this.parent_id == other.parent_id)
368
404
                    and (this.kind == other.kind)
369
405
                    and (this.executable == other.executable)
 
406
                    and (this.reference_revision == other.reference_revision)
370
407
                    )
371
408
        if not ie_equal_no_revision(new_root_ie, basis_root_ie):
372
409
            return True
428
465
        #       to local.
429
466
        
430
467
        # Make sure the local branch is identical to the master
431
 
        master_rh = self.master_branch.revision_history()
432
 
        local_rh = self.branch.revision_history()
433
 
        if local_rh != master_rh:
 
468
        master_info = self.master_branch.last_revision_info()
 
469
        local_info = self.branch.last_revision_info()
 
470
        if local_info != master_info:
434
471
            raise errors.BoundBranchOutOfDate(self.branch,
435
472
                    self.master_branch)
436
473
 
443
480
    def _cleanup(self):
444
481
        """Cleanup any open locks, progress bars etc."""
445
482
        cleanups = [self._cleanup_bound_branch,
 
483
                    self.basis_tree.unlock,
446
484
                    self.work_tree.unlock,
447
485
                    self.pb.finished]
448
486
        found_exception = None
498
536
        # TODO: Make sure that this list doesn't contain duplicate 
499
537
        # entries and the order is preserved when doing this.
500
538
        self.parents = self.work_tree.get_parent_ids()
501
 
        self.parent_invs = []
502
 
        for revision in self.parents:
 
539
        self.parent_invs = [self.basis_inv]
 
540
        for revision in self.parents[1:]:
503
541
            if self.branch.repository.has_revision(revision):
504
542
                mutter('commit parent revision {%s}', revision)
505
543
                inventory = self.branch.repository.get_inventory(revision)
560
598
        for path, new_ie in entries:
561
599
            self._emit_progress_update()
562
600
            file_id = new_ie.file_id
 
601
            try:
 
602
                kind = self.work_tree.kind(file_id)
 
603
                if kind == 'tree-reference' and self.recursive == 'down':
 
604
                    # nested tree: commit in it
 
605
                    sub_tree = WorkingTree.open(self.work_tree.abspath(path))
 
606
                    # FIXME: be more comprehensive here:
 
607
                    # this works when both trees are in --trees repository,
 
608
                    # but when both are bound to a different repository,
 
609
                    # it fails; a better way of approaching this is to 
 
610
                    # finally implement the explicit-caches approach design
 
611
                    # a while back - RBC 20070306.
 
612
                    if (sub_tree.branch.repository.bzrdir.root_transport.base
 
613
                        ==
 
614
                        self.work_tree.branch.repository.bzrdir.root_transport.base):
 
615
                        sub_tree.branch.repository = \
 
616
                            self.work_tree.branch.repository
 
617
                    try:
 
618
                        sub_tree.commit(message=None, revprops=self.revprops,
 
619
                            recursive=self.recursive,
 
620
                            message_callback=self.message_callback,
 
621
                            timestamp=self.timestamp, timezone=self.timezone,
 
622
                            committer=self.committer,
 
623
                            allow_pointless=self.allow_pointless,
 
624
                            strict=self.strict, verbose=self.verbose,
 
625
                            local=self.local, reporter=self.reporter)
 
626
                    except errors.PointlessCommit:
 
627
                        pass
 
628
                if kind != new_ie.kind:
 
629
                    new_ie = inventory.make_entry(kind, new_ie.name,
 
630
                                                  new_ie.parent_id, file_id)
 
631
            except errors.NoSuchFile:
 
632
                pass
563
633
            # mutter('check %s {%s}', path, file_id)
564
634
            if (not self.specific_files or 
565
635
                is_inside_or_parent_of_any(self.specific_files, path)):