/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/tests/test_commit.py

  • Committer: John Arbash Meinel
  • Date: 2007-01-24 20:40:20 UTC
  • mfrom: (2242 +trunk)
  • mto: This revision was merged to the branch mainline in revision 2245.
  • Revision ID: john@arbash-meinel.com-20070124204020-szyxbjpn9mzbsks7
[merge] bzr.dev 2242

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005 by Canonical Ltd
2
 
 
 
1
# Copyright (C) 2005, 2006 Canonical Ltd
 
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
5
5
# the Free Software Foundation; either version 2 of the License, or
6
6
# (at your option) any later version.
7
 
 
 
7
#
8
8
# This program is distributed in the hope that it will be useful,
9
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
11
# GNU General Public License for more details.
12
 
 
 
12
#
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
18
import os
19
19
 
20
20
import bzrlib
21
 
from bzrlib.tests import TestCaseWithTransport
 
21
from bzrlib import (
 
22
    errors,
 
23
    lockdir,
 
24
    )
22
25
from bzrlib.branch import Branch
23
26
from bzrlib.bzrdir import BzrDir, BzrDirMetaFormat1
24
 
from bzrlib.workingtree import WorkingTree
25
 
from bzrlib.commit import Commit
 
27
from bzrlib.commit import Commit, NullCommitReporter
26
28
from bzrlib.config import BranchConfig
27
29
from bzrlib.errors import (PointlessCommit, BzrError, SigningFailed, 
28
30
                           LockContention)
 
31
from bzrlib.tests import TestCaseWithTransport
 
32
from bzrlib.workingtree import WorkingTree
29
33
 
30
34
 
31
35
# TODO: Test commit with some added, and added-but-missing files
45
49
        return "bzrlib.ahook bzrlib.ahook"
46
50
 
47
51
 
 
52
class CapturingReporter(NullCommitReporter):
 
53
    """This reporter captures the calls made to it for evaluation later."""
 
54
 
 
55
    def __init__(self):
 
56
        # a list of the calls this received
 
57
        self.calls = []
 
58
 
 
59
    def snapshot_change(self, change, path):
 
60
        self.calls.append(('change', change, path))
 
61
 
 
62
    def deleted(self, file_id):
 
63
        self.calls.append(('deleted', file_id))
 
64
 
 
65
    def missing(self, path):
 
66
        self.calls.append(('missing', path))
 
67
 
 
68
    def renamed(self, change, old_path, new_path):
 
69
        self.calls.append(('renamed', change, old_path, new_path))
 
70
 
 
71
 
48
72
class TestCommit(TestCaseWithTransport):
49
73
 
50
74
    def test_simple_commit(self):
387
411
        bound = master.sprout('bound')
388
412
        wt = bound.open_workingtree()
389
413
        wt.branch.set_bound_location(os.path.realpath('master'))
 
414
 
 
415
        orig_default = lockdir._DEFAULT_TIMEOUT_SECONDS
390
416
        master_branch.lock_write()
391
417
        try:
 
418
            lockdir._DEFAULT_TIMEOUT_SECONDS = 1
392
419
            self.assertRaises(LockContention, wt.commit, 'silly')
393
420
        finally:
 
421
            lockdir._DEFAULT_TIMEOUT_SECONDS = orig_default
394
422
            master_branch.unlock()
 
423
 
 
424
    def test_commit_bound_merge(self):
 
425
        # see bug #43959; commit of a merge in a bound branch fails to push
 
426
        # the new commit into the master
 
427
        master_branch = self.make_branch('master')
 
428
        bound_tree = self.make_branch_and_tree('bound')
 
429
        bound_tree.branch.bind(master_branch)
 
430
 
 
431
        self.build_tree_contents([('bound/content_file', 'initial contents\n')])
 
432
        bound_tree.add(['content_file'])
 
433
        bound_tree.commit(message='woo!')
 
434
 
 
435
        other_bzrdir = master_branch.bzrdir.sprout('other')
 
436
        other_tree = other_bzrdir.open_workingtree()
 
437
 
 
438
        # do a commit to the the other branch changing the content file so
 
439
        # that our commit after merging will have a merged revision in the
 
440
        # content file history.
 
441
        self.build_tree_contents([('other/content_file', 'change in other\n')])
 
442
        other_tree.commit('change in other')
 
443
 
 
444
        # do a merge into the bound branch from other, and then change the
 
445
        # content file locally to force a new revision (rather than using the
 
446
        # revision from other). This forces extra processing in commit.
 
447
        bound_tree.merge_from_branch(other_tree.branch)
 
448
        self.build_tree_contents([('bound/content_file', 'change in bound\n')])
 
449
 
 
450
        # before #34959 was fixed, this failed with 'revision not present in
 
451
        # weave' when trying to implicitly push from the bound branch to the master
 
452
        bound_tree.commit(message='commit of merge in bound tree')
 
453
 
 
454
    def test_commit_reporting_after_merge(self):
 
455
        # when doing a commit of a merge, the reporter needs to still 
 
456
        # be called for each item that is added/removed/deleted.
 
457
        this_tree = self.make_branch_and_tree('this')
 
458
        # we need a bunch of files and dirs, to perform one action on each.
 
459
        self.build_tree([
 
460
            'this/dirtorename/',
 
461
            'this/dirtoreparent/',
 
462
            'this/dirtoleave/',
 
463
            'this/dirtoremove/',
 
464
            'this/filetoreparent',
 
465
            'this/filetorename',
 
466
            'this/filetomodify',
 
467
            'this/filetoremove',
 
468
            'this/filetoleave']
 
469
            )
 
470
        this_tree.add([
 
471
            'dirtorename',
 
472
            'dirtoreparent',
 
473
            'dirtoleave',
 
474
            'dirtoremove',
 
475
            'filetoreparent',
 
476
            'filetorename',
 
477
            'filetomodify',
 
478
            'filetoremove',
 
479
            'filetoleave']
 
480
            )
 
481
        this_tree.commit('create_files')
 
482
        other_dir = this_tree.bzrdir.sprout('other')
 
483
        other_tree = other_dir.open_workingtree()
 
484
        other_tree.lock_write()
 
485
        # perform the needed actions on the files and dirs.
 
486
        try:
 
487
            other_tree.rename_one('dirtorename', 'renameddir')
 
488
            other_tree.rename_one('dirtoreparent', 'renameddir/reparenteddir')
 
489
            other_tree.rename_one('filetorename', 'renamedfile')
 
490
            other_tree.rename_one('filetoreparent', 'renameddir/reparentedfile')
 
491
            other_tree.remove(['dirtoremove', 'filetoremove'])
 
492
            self.build_tree_contents([
 
493
                ('other/newdir/', ),
 
494
                ('other/filetomodify', 'new content'),
 
495
                ('other/newfile', 'new file content')])
 
496
            other_tree.add('newfile')
 
497
            other_tree.add('newdir/')
 
498
            other_tree.commit('modify all sample files and dirs.')
 
499
        finally:
 
500
            other_tree.unlock()
 
501
        this_tree.merge_from_branch(other_tree.branch)
 
502
        reporter = CapturingReporter()
 
503
        this_tree.commit('do the commit', reporter=reporter)
 
504
        self.assertEqual([
 
505
            ('change', 'unchanged', ''),
 
506
            ('change', 'unchanged', 'dirtoleave'),
 
507
            ('change', 'unchanged', 'filetoleave'),
 
508
            ('change', 'modified', 'filetomodify'),
 
509
            ('change', 'added', 'newdir'),
 
510
            ('change', 'added', 'newfile'),
 
511
            ('renamed', 'renamed', 'dirtorename', 'renameddir'),
 
512
            ('renamed', 'renamed', 'dirtoreparent', 'renameddir/reparenteddir'),
 
513
            ('renamed', 'renamed', 'filetoreparent', 'renameddir/reparentedfile'),
 
514
            ('renamed', 'renamed', 'filetorename', 'renamedfile'),
 
515
            ('deleted', 'dirtoremove'),
 
516
            ('deleted', 'filetoremove'),
 
517
            ],
 
518
            reporter.calls)
 
519
 
 
520
    def test_commit_removals_respects_filespec(self):
 
521
        """Commit respects the specified_files for removals."""
 
522
        tree = self.make_branch_and_tree('.')
 
523
        self.build_tree(['a', 'b'])
 
524
        tree.add(['a', 'b'])
 
525
        tree.commit('added a, b')
 
526
        tree.remove(['a', 'b'])
 
527
        tree.commit('removed a', specific_files='a')
 
528
        basis = tree.basis_tree().inventory
 
529
        self.assertIs(None, basis.path2id('a'))
 
530
        self.assertFalse(basis.path2id('b') is None)
 
531
 
 
532
    def test_commit_saves_1ms_timestamp(self):
 
533
        """Passing in a timestamp is saved with 1ms resolution"""
 
534
        tree = self.make_branch_and_tree('.')
 
535
        self.build_tree(['a'])
 
536
        tree.add('a')
 
537
        tree.commit('added a', timestamp=1153248633.4186721, timezone=0,
 
538
                    rev_id='a1')
 
539
 
 
540
        rev = tree.branch.repository.get_revision('a1')
 
541
        self.assertEqual(1153248633.419, rev.timestamp)
 
542
 
 
543
    def test_commit_has_1ms_resolution(self):
 
544
        """Allowing commit to generate the timestamp also has 1ms resolution"""
 
545
        tree = self.make_branch_and_tree('.')
 
546
        self.build_tree(['a'])
 
547
        tree.add('a')
 
548
        tree.commit('added a', rev_id='a1')
 
549
 
 
550
        rev = tree.branch.repository.get_revision('a1')
 
551
        timestamp = rev.timestamp
 
552
        timestamp_1ms = round(timestamp, 3)
 
553
        self.assertEqual(timestamp_1ms, timestamp)
 
554
 
 
555
    def test_commit_unversioned_specified(self):
 
556
        """Commit should raise if specified files isn't in basis or worktree"""
 
557
        tree = self.make_branch_and_tree('.')
 
558
        self.assertRaises(errors.PathsNotVersionedError, tree.commit, 
 
559
                          'message', specific_files=['bogus'])
 
560
 
 
561
    class Callback(object):
 
562
        
 
563
        def __init__(self, message, testcase):
 
564
            self.called = False
 
565
            self.message = message
 
566
            self.testcase = testcase
 
567
 
 
568
        def __call__(self, commit_obj):
 
569
            self.called = True
 
570
            self.testcase.assertTrue(isinstance(commit_obj, Commit))
 
571
            return self.message
 
572
 
 
573
    def test_commit_callback(self):
 
574
        """Commit should invoke a callback to get the message"""
 
575
 
 
576
        tree = self.make_branch_and_tree('.')
 
577
        try:
 
578
            tree.commit()
 
579
        except Exception, e:
 
580
            self.assertTrue(isinstance(e, BzrError))
 
581
            self.assertEqual('The message or message_callback keyword'
 
582
                             ' parameter is required for commit().', str(e))
 
583
        else:
 
584
            self.fail('exception not raised')
 
585
        cb = self.Callback(u'commit 1', self)
 
586
        tree.commit(message_callback=cb)
 
587
        self.assertTrue(cb.called)
 
588
        repository = tree.branch.repository
 
589
        message = repository.get_revision(tree.last_revision()).message
 
590
        self.assertEqual('commit 1', message)
 
591
 
 
592
    def test_no_callback_pointless(self):
 
593
        """Callback should not be invoked for pointless commit"""
 
594
        tree = self.make_branch_and_tree('.')
 
595
        cb = self.Callback(u'commit 2', self)
 
596
        self.assertRaises(PointlessCommit, tree.commit, message_callback=cb, 
 
597
                          allow_pointless=False)
 
598
        self.assertFalse(cb.called)
 
599
 
 
600
    def test_no_callback_netfailure(self):
 
601
        """Callback should not be invoked if connectivity fails"""
 
602
        tree = self.make_branch_and_tree('.')
 
603
        cb = self.Callback(u'commit 2', self)
 
604
        repository = tree.branch.repository
 
605
        # simulate network failure
 
606
        def raise_(self, arg, arg2):
 
607
            raise errors.NoSuchFile('foo')
 
608
        repository.add_inventory = raise_
 
609
        self.assertRaises(errors.NoSuchFile, tree.commit, message_callback=cb)
 
610
        self.assertFalse(cb.called)