~bzr-pqm/bzr/bzr.dev

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