~bzr-pqm/bzr/bzr.dev

1773.4.1 by Martin Pool
Add pyflakes makefile target; fix many warnings
1
# Copyright (C) 2005, 2006 Canonical Ltd
1666.1.19 by Robert Collins
Introduce a progress bar during commit.
2
# Authors:  Robert Collins <robert.collins@canonical.com>
3
#
4
# This program is free software; you can redistribute it and/or modify
5
# it under the terms of the GNU General Public License as published by
6
# the Free Software Foundation; either version 2 of the License, or
7
# (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU General Public License for more details.
13
#
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, write to the Free Software
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
18
from cStringIO import StringIO
19
import os
20
1773.4.1 by Martin Pool
Add pyflakes makefile target; fix many warnings
21
from bzrlib import branch, bzrdir, errors, ui, workingtree
1666.1.19 by Robert Collins
Introduce a progress bar during commit.
22
from bzrlib.errors import (NotBranchError, NotVersionedError, 
23
                           UnsupportedOperation)
24
from bzrlib.osutils import pathjoin, getcwd, has_symlinks
25
from bzrlib.tests import TestSkipped, TestCase
26
from bzrlib.tests.workingtree_implementations import TestCaseWithWorkingTree
27
from bzrlib.trace import mutter
28
from bzrlib.workingtree import (TreeEntry, TreeDirectory, TreeFile, TreeLink,
29
                                WorkingTree)
30
31
32
class CapturingUIFactory(ui.UIFactory):
33
    """A UI Factory for testing - capture the updates made through it."""
34
35
    def __init__(self):
36
        super(CapturingUIFactory, self).__init__()
37
        self._calls = []
38
        self.depth = 0
39
40
    def clear(self):
41
        """See progress.ProgressBar.clear()."""
42
43
    def clear_term(self):
44
        """See progress.ProgressBar.clear_term()."""
45
46
    def finished(self):
47
        """See progress.ProgressBar.finished()."""
48
        self.depth -= 1
49
50
    def note(self, fmt_string, *args, **kwargs):
51
        """See progress.ProgressBar.note()."""
52
53
    def progress_bar(self):
54
        return self
55
    
56
    def nested_progress_bar(self):
57
        self.depth += 1
58
        return self
59
60
    def update(self, message, count=None, total=None):
61
        """See progress.ProgressBar.update()."""
62
        if self.depth == 1:
63
            self._calls.append(("update", count, total))
64
65
66
class TestCapturingUI(TestCase):
67
68
    def test_nested_ignore_depth_beyond_one(self):
69
        # we only want to capture the first level out progress, not
70
        # want sub-components might do. So we have nested bars ignored.
71
        factory = CapturingUIFactory()
72
        pb1 = factory.nested_progress_bar()
73
        pb1.update('foo', 0, 1)
74
        pb2 = factory.nested_progress_bar()
75
        pb2.update('foo', 0, 1)
76
        pb2.finished()
77
        pb1.finished()
78
        self.assertEqual([("update", 0, 1)], factory._calls)
79
80
81
class TestCommit(TestCaseWithWorkingTree):
82
83
    def test_commit_sets_last_revision(self):
84
        tree = self.make_branch_and_tree('tree')
1773.1.1 by Robert Collins
Teach WorkingTree.commit to return the committed revision id.
85
        committed_id = tree.commit('foo', rev_id='foo', allow_pointless=True)
1666.1.19 by Robert Collins
Introduce a progress bar during commit.
86
        self.assertEqual('foo', tree.last_revision())
1773.1.1 by Robert Collins
Teach WorkingTree.commit to return the committed revision id.
87
        # the commit should have returned the same id we asked for.
88
        self.assertEqual('foo', committed_id)
89
90
    def test_commit_returns_revision_id(self):
91
        tree = self.make_branch_and_tree('.')
92
        committed_id = tree.commit('message', allow_pointless=True)
93
        self.assertTrue(tree.branch.repository.has_revision(committed_id))
94
        self.assertNotEqual(None, committed_id)
1666.1.19 by Robert Collins
Introduce a progress bar during commit.
95
96
    def test_commit_local_unbound(self):
97
        # using the library api to do a local commit on unbound branches is 
98
        # also an error
99
        tree = self.make_branch_and_tree('tree')
100
        self.assertRaises(errors.LocalRequiresBoundBranch,
101
                          tree.commit,
102
                          'foo',
103
                          local=True)
104
 
105
    def test_local_commit_ignores_master(self):
106
        # a --local commit does not require access to the master branch
107
        # at all, or even for it to exist.
108
        # we test this by setting up a bound branch and then corrupting
109
        # the master.
110
        master = self.make_branch('master')
111
        tree = self.make_branch_and_tree('tree')
112
        try:
113
            tree.branch.bind(master)
114
        except errors.UpgradeRequired:
115
            # older format.
116
            return
117
        master.bzrdir.transport.put('branch-format', StringIO('garbage'))
118
        del master
119
        # check its corrupted.
120
        self.assertRaises(errors.UnknownFormatError,
121
                          bzrdir.BzrDir.open,
122
                          'master')
123
        tree.commit('foo', rev_id='foo', local=True)
124
 
125
    def test_local_commit_does_not_push_to_master(self):
126
        # a --local commit does not require access to the master branch
127
        # at all, or even for it to exist.
128
        # we test that even when its available it does not push to it.
129
        master = self.make_branch('master')
130
        tree = self.make_branch_and_tree('tree')
131
        try:
132
            tree.branch.bind(master)
133
        except errors.UpgradeRequired:
134
            # older format.
135
            return
136
        tree.commit('foo', rev_id='foo', local=True)
137
        self.failIf(master.repository.has_revision('foo'))
138
        self.assertEqual(None, master.last_revision())
139
        
140
1740.3.10 by Jelmer Vernooij
Fix some minor issues pointed out by j-a-m.
141
class TestCommitProgress(TestCaseWithWorkingTree):
1666.1.19 by Robert Collins
Introduce a progress bar during commit.
142
    
143
    def restoreDefaults(self):
144
        ui.ui_factory = self.old_ui_factory
145
146
    def test_commit_progress_steps(self):
147
        # during commit we one progress update for every entry in the 
148
        # inventory, and then one for the inventory, and one for the
149
        # inventory, and one for the revision insertions.
150
        # first we need a test commit to do. Lets setup a branch with 
151
        # 3 files, and alter one in a selected-file commit. This exercises
152
        # a number of cases quickly. We should also test things like 
153
        # selective commits which excludes newly added files.
154
        tree = self.make_branch_and_tree('.')
155
        self.build_tree(['a', 'b', 'c'])
156
        tree.add(['a', 'b', 'c'])
157
        tree.commit('first post')
158
        f = file('b', 'wt')
159
        f.write('new content')
160
        f.close()
161
        # set a progress bar that captures the calls so we can see what is 
162
        # emitted
163
        self.old_ui_factory = ui.ui_factory
164
        self.addCleanup(self.restoreDefaults)
165
        factory = CapturingUIFactory()
166
        ui.ui_factory = factory
167
        # TODO RBC 20060421 it would be nice to merge the reporter output
168
        # into the factory for this test - just make the test ui factory
169
        # pun as a reporter. Then we can check the ordering is right.
170
        tree.commit('second post', specific_files=['b'])
1740.3.10 by Jelmer Vernooij
Fix some minor issues pointed out by j-a-m.
171
        # 9 steps: 1 for rev, 2 for inventory, 1 for finishing. 2 for root
172
        # and 6 for inventory files.
173
        # 2 steps don't trigger an update, as 'a' and 'c' are not 
174
        # committed.
1666.1.19 by Robert Collins
Introduce a progress bar during commit.
175
        self.assertEqual(
1740.3.10 by Jelmer Vernooij
Fix some minor issues pointed out by j-a-m.
176
            [("update", 0, 9),
177
             ("update", 1, 9),
178
             ("update", 2, 9),
179
             ("update", 3, 9),
180
             ("update", 4, 9),
181
             ("update", 5, 9),
182
             ("update", 6, 9),
183
             ("update", 7, 9)],
1666.1.19 by Robert Collins
Introduce a progress bar during commit.
184
            factory._calls
185
           )