/b-gtk/fix-viz

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/b-gtk/fix-viz
622.1.2 by John Arbash Meinel
Add tests of RevisionView that it can handle broken file-info properties.
1
# Copyright (C) 2007, 2008 John Arbash Meinel <john@arbash-meinel.com>
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
17
"""Test the Commit functionality."""
18
278.1.16 by John Arbash Meinel
Implement the file changes list on top of _iter_changes rather than
19
import os
20
734.1.1 by Curtis Hovey
Mechanical changes made by pygi.convert.sh.
21
from gi.repository import Gtk
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
22
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
23
from bzrlib import (
635.2.12 by Vincent Ladeuil
Implement commit message saving without modifying bzrlib.
24
    branch,
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
25
    tests,
635.2.8 by Vincent Ladeuil
Start testing patch behavior.
26
    uncommit,
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
27
    )
645 by Jelmer Vernooij
Fix more bencode imports.
28
try:
646 by Jelmer Vernooij
Reorder bencode imports, prefer the new location to prevent deprecation warnings.
29
    from bzrlib import bencode
30
except ImportError:
645 by Jelmer Vernooij
Fix more bencode imports.
31
    from bzrlib.util import bencode
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
32
33
from bzrlib.plugins.gtk import commit
34
35
36
# TODO: All we need is basic ancestry code to test this, we shouldn't need a
37
# TestCaseWithTransport, just a TestCaseWithMemoryTransport or somesuch.
38
39
class TestPendingRevisions(tests.TestCaseWithTransport):
40
41
    def test_pending_revisions_none(self):
42
        tree = self.make_branch_and_tree('.')
43
        tree.commit('one')
44
45
        self.assertIs(None, commit.pending_revisions(tree))
46
47
    def test_pending_revisions_simple(self):
48
        tree = self.make_branch_and_tree('tree')
49
        rev_id1 = tree.commit('one')
50
        tree2 = tree.bzrdir.sprout('tree2').open_workingtree()
51
        rev_id2 = tree2.commit('two')
52
        tree.merge_from_branch(tree2.branch)
53
        self.assertEqual([rev_id1, rev_id2], tree.get_parent_ids())
54
55
        pending_revisions = commit.pending_revisions(tree)
56
        # One primary merge
57
        self.assertEqual(1, len(pending_revisions))
58
        # Revision == rev_id2
59
        self.assertEqual(rev_id2, pending_revisions[0][0].revision_id)
60
        # No children of this revision.
61
        self.assertEqual([], pending_revisions[0][1])
62
63
    def test_pending_revisions_with_children(self):
64
        tree = self.make_branch_and_tree('tree')
65
        rev_id1 = tree.commit('one')
66
        tree2 = tree.bzrdir.sprout('tree2').open_workingtree()
67
        rev_id2 = tree2.commit('two')
68
        rev_id3 = tree2.commit('three')
69
        rev_id4 = tree2.commit('four')
70
        tree.merge_from_branch(tree2.branch)
71
        self.assertEqual([rev_id1, rev_id4], tree.get_parent_ids())
72
73
        pending_revisions = commit.pending_revisions(tree)
74
        # One primary merge
75
        self.assertEqual(1, len(pending_revisions))
76
        # Revision == rev_id2
77
        self.assertEqual(rev_id4, pending_revisions[0][0].revision_id)
78
        # Two children for this revision
79
        self.assertEqual(2, len(pending_revisions[0][1]))
80
        self.assertEqual(rev_id3, pending_revisions[0][1][0].revision_id)
81
        self.assertEqual(rev_id2, pending_revisions[0][1][1].revision_id)
82
83
    def test_pending_revisions_multi_merge(self):
84
        tree = self.make_branch_and_tree('tree')
85
        rev_id1 = tree.commit('one')
86
        tree2 = tree.bzrdir.sprout('tree2').open_workingtree()
87
        rev_id2 = tree2.commit('two')
88
        tree3 = tree2.bzrdir.sprout('tree3').open_workingtree()
500.1.2 by Vincent Ladeuil
Fix third failing test (thanks to jam).
89
        rev_id3 = tree2.commit('three')
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
90
        rev_id4 = tree3.commit('four')
91
        rev_id5 = tree3.commit('five')
92
        tree.merge_from_branch(tree2.branch)
670 by Vincent Ladeuil
Fix regressions in tests about merge being more strict by default.
93
        tree.merge_from_branch(tree3.branch, force=True)
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
94
        self.assertEqual([rev_id1, rev_id3, rev_id5], tree.get_parent_ids())
95
96
        pending_revisions = commit.pending_revisions(tree)
97
        # Two primary merges
98
        self.assertEqual(2, len(pending_revisions))
99
        # Revision == rev_id2
100
        self.assertEqual(rev_id3, pending_revisions[0][0].revision_id)
101
        self.assertEqual(rev_id5, pending_revisions[1][0].revision_id)
102
        # One child for the first merge
103
        self.assertEqual(1, len(pending_revisions[0][1]))
104
        self.assertEqual(rev_id2, pending_revisions[0][1][0].revision_id)
105
        # One child for the second merge
106
        self.assertEqual(1, len(pending_revisions[1][1]))
107
        self.assertEqual(rev_id4, pending_revisions[1][1][0].revision_id)
108
109
110
class Test_RevToPendingInfo(tests.TestCaseWithTransport):
111
112
    def test_basic_info(self):
113
        tree = self.make_branch_and_tree('tree')
114
        rev_id = tree.commit('Multiline\ncommit\nmessage',
115
                             committer='Joe Foo <joe@foo.com>',
116
                             timestamp=1191012408.674,
117
                             timezone=-18000
118
                             )
119
        rev = tree.branch.repository.get_revision(rev_id)
120
        rev_dict = commit.CommitDialog._rev_to_pending_info(rev)
121
        self.assertEqual({'committer':'Joe Foo',
122
                          'summary':'Multiline',
123
                          'date':'2007-09-28',
124
                          'revision_id':rev_id,
125
                         }, rev_dict)
126
127
128
class CommitDialogNoWidgets(commit.CommitDialog):
129
130
    def construct(self):
131
        pass # Don't create any widgets here
132
278.1.14 by John Arbash Meinel
Tests that we fill out the pending list correctly.
133
    def fill_in_data(self):
134
        pass # With no widgets, there are no widgets to fill out
135
136
137
class TestCommitDialogSimple(tests.TestCaseWithTransport):
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
138
139
    def test_setup_parameters_no_pending(self):
140
        tree = self.make_branch_and_tree('tree')
141
        rev_id = tree.commit('first')
142
143
        dlg = CommitDialogNoWidgets(tree)
144
        self.assertEqual(rev_id, dlg._basis_tree.get_revision_id())
145
        self.assertIs(None, dlg._pending)
146
        self.assertFalse(dlg._is_checkout)
147
148
    def test_setup_parameters_checkout(self):
149
        tree = self.make_branch_and_tree('tree')
150
        rev_id = tree.commit('first')
151
        tree2 = tree.bzrdir.sprout('tree2').open_workingtree()
152
        tree2.branch.bind(tree.branch)
153
154
        dlg = CommitDialogNoWidgets(tree2)
155
        self.assertEqual(rev_id, dlg._basis_tree.get_revision_id())
156
        self.assertIs(None, dlg._pending)
157
        self.assertTrue(dlg._is_checkout)
158
159
    def test_setup_parameters_pending(self):
160
        tree = self.make_branch_and_tree('tree')
161
        rev_id1 = tree.commit('one')
162
        tree2 = tree.bzrdir.sprout('tree2').open_workingtree()
163
        rev_id2 = tree2.commit('two')
164
        tree.merge_from_branch(tree2.branch)
165
166
        dlg = CommitDialogNoWidgets(tree)
167
        self.assertEqual(rev_id1, dlg._basis_tree.get_revision_id())
168
        self.assertIsNot(None, dlg._pending)
169
        self.assertEqual(1, len(dlg._pending))
170
        self.assertEqual(rev_id2, dlg._pending[0][0].revision_id)
171
172
    def test_setup_parameters_delta(self):
173
        tree = self.make_branch_and_tree('tree')
174
        self.build_tree(['tree/a'])
175
        tree.add(['a'], ['a-id'])
176
177
        dlg = CommitDialogNoWidgets(tree)
278.1.12 by John Arbash Meinel
Delay computing the delta, and clean up some of the diff view names.
178
        self.assertIs(None, dlg._delta)
179
        dlg._compute_delta()
180
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
181
        delta = dlg._delta
182
        self.assertEqual([], delta.modified)
183
        self.assertEqual([], delta.renamed)
184
        self.assertEqual([], delta.removed)
185
        self.assertEqual([(u'a', 'a-id', 'file')], delta.added)
278.1.14 by John Arbash Meinel
Tests that we fill out the pending list correctly.
186
187
188
class TestCommitDialog(tests.TestCaseWithTransport):
189
278.1.25 by John Arbash Meinel
Add the 'Only Commit Locally' checkbox, we may want to put it elsewhere, though.
190
    def test_bound(self):
191
        tree = self.make_branch_and_tree('tree')
192
        rev_id = tree.commit('first')
193
        tree2 = tree.bzrdir.sprout('tree2').open_workingtree()
194
        tree2.branch.bind(tree.branch)
195
196
        # tree is not a checkout
197
        dlg = commit.CommitDialog(tree)
198
        self.assertFalse(dlg._check_local.get_property('visible'))
199
200
        # tree2 is a checkout
201
        dlg2 = commit.CommitDialog(tree2)
202
        self.assertTrue(dlg2._check_local.get_property('visible'))
203
278.1.14 by John Arbash Meinel
Tests that we fill out the pending list correctly.
204
    def test_no_pending(self):
205
        tree = self.make_branch_and_tree('tree')
206
        rev_id1 = tree.commit('one')
207
208
        dlg = commit.CommitDialog(tree)
278.1.25 by John Arbash Meinel
Add the 'Only Commit Locally' checkbox, we may want to put it elsewhere, though.
209
210
        self.assertFalse(dlg._pending_box.get_property('visible'))
211
278.1.17 by John Arbash Meinel
Add a * reference for why you can't change the commit selection.
212
        commit_col = dlg._treeview_files.get_column(0)
213
        self.assertEqual('Commit', commit_col.get_title())
734.1.20 by Curtis Hovey
col.get_cell_renderers => col.get_cells.
214
        renderer = commit_col.get_cells()[0]
278.1.39 by John Arbash Meinel
To disable a checkbox it is set_property('activatable', False),
215
        self.assertTrue(renderer.get_property('activatable'))
278.1.14 by John Arbash Meinel
Tests that we fill out the pending list correctly.
216
278.1.43 by John Arbash Meinel
Finish connecting the 'Commit all changes' radio buttons.
217
        self.assertEqual('Commit all changes',
218
                         dlg._commit_all_files_radio.get_label())
219
        self.assertTrue(dlg._commit_all_files_radio.get_property('sensitive'))
220
        self.assertTrue(dlg._commit_selected_radio.get_property('sensitive'))
221
278.1.14 by John Arbash Meinel
Tests that we fill out the pending list correctly.
222
    def test_pending(self):
223
        tree = self.make_branch_and_tree('tree')
224
        rev_id1 = tree.commit('one')
225
226
        tree2 = tree.bzrdir.sprout('tree2').open_workingtree()
227
        rev_id2 = tree2.commit('two',
228
                               committer='Joe Foo <joe@foo.com>',
229
                               timestamp=1191264271.05,
230
                               timezone=+7200)
231
        tree.merge_from_branch(tree2.branch)
232
233
        dlg = commit.CommitDialog(tree)
278.1.25 by John Arbash Meinel
Add the 'Only Commit Locally' checkbox, we may want to put it elsewhere, though.
234
235
        self.assertTrue(dlg._pending_box.get_property('visible'))
236
278.1.17 by John Arbash Meinel
Add a * reference for why you can't change the commit selection.
237
        commit_col = dlg._treeview_files.get_column(0)
238
        self.assertEqual('Commit*', commit_col.get_title())
734.1.20 by Curtis Hovey
col.get_cell_renderers => col.get_cells.
239
        renderer = commit_col.get_cells()[0]
278.1.39 by John Arbash Meinel
To disable a checkbox it is set_property('activatable', False),
240
        self.assertFalse(renderer.get_property('activatable'))
278.1.17 by John Arbash Meinel
Add a * reference for why you can't change the commit selection.
241
278.1.15 by John Arbash Meinel
Hook up the list of modified files.
242
        values = [(r[0], r[1], r[2], r[3]) for r in dlg._pending_store]
278.1.14 by John Arbash Meinel
Tests that we fill out the pending list correctly.
243
        self.assertEqual([(rev_id2, '2007-10-01', 'Joe Foo', 'two')], values)
244
278.1.43 by John Arbash Meinel
Finish connecting the 'Commit all changes' radio buttons.
245
        self.assertEqual('Commit all changes*',
246
                         dlg._commit_all_files_radio.get_label())
247
        self.assertFalse(dlg._commit_all_files_radio.get_property('sensitive'))
248
        self.assertFalse(dlg._commit_selected_radio.get_property('sensitive'))
249
278.1.14 by John Arbash Meinel
Tests that we fill out the pending list correctly.
250
    def test_pending_multiple(self):
251
        tree = self.make_branch_and_tree('tree')
252
        rev_id1 = tree.commit('one')
253
254
        tree2 = tree.bzrdir.sprout('tree2').open_workingtree()
255
        rev_id2 = tree2.commit('two',
256
                               committer='Joe Foo <joe@foo.com>',
257
                               timestamp=1191264271.05,
258
                               timezone=+7200)
259
        rev_id3 = tree2.commit('three',
260
                               committer='Jerry Foo <jerry@foo.com>',
261
                               timestamp=1191264278.05,
262
                               timezone=+7200)
263
        tree.merge_from_branch(tree2.branch)
264
        tree3 = tree.bzrdir.sprout('tree3').open_workingtree()
265
        rev_id4 = tree3.commit('four',
266
                               committer='Joe Foo <joe@foo.com>',
267
                               timestamp=1191264279.05,
268
                               timezone=+7200)
269
        rev_id5 = tree3.commit('five',
270
                               committer='Jerry Foo <jerry@foo.com>',
271
                               timestamp=1191372278.05,
272
                               timezone=+7200)
670 by Vincent Ladeuil
Fix regressions in tests about merge being more strict by default.
273
        tree.merge_from_branch(tree3.branch, force=True)
278.1.14 by John Arbash Meinel
Tests that we fill out the pending list correctly.
274
275
        dlg = commit.CommitDialog(tree)
276
        # TODO: assert that the pending box is set to show
278.1.15 by John Arbash Meinel
Hook up the list of modified files.
277
        values = [(r[0], r[1], r[2], r[3]) for r in dlg._pending_store]
278.1.14 by John Arbash Meinel
Tests that we fill out the pending list correctly.
278
        self.assertEqual([(rev_id3, '2007-10-01', 'Jerry Foo', 'three'),
279
                          (rev_id2, '2007-10-01', 'Joe Foo', 'two'),
280
                          (rev_id5, '2007-10-03', 'Jerry Foo', 'five'),
281
                          (rev_id4, '2007-10-01', 'Joe Foo', 'four'),
282
                         ], values)
278.1.15 by John Arbash Meinel
Hook up the list of modified files.
283
278.1.16 by John Arbash Meinel
Implement the file changes list on top of _iter_changes rather than
284
    def test_filelist_added(self):
278.1.15 by John Arbash Meinel
Hook up the list of modified files.
285
        tree = self.make_branch_and_tree('tree')
286
        self.build_tree(['tree/a', 'tree/b/', 'tree/b/c'])
287
        tree.add(['a', 'b', 'b/c'], ['a-id', 'b-id', 'c-id'])
288
289
        dlg = commit.CommitDialog(tree)
290
        values = [(r[0], r[1], r[2], r[3], r[4]) for r in dlg._files_store]
278.1.20 by John Arbash Meinel
We always select the All Files record in the files view,
291
        self.assertEqual([(None, None, True, 'All Files', ''),
292
                          ('a-id', 'a', True, 'a', 'added'),
278.1.15 by John Arbash Meinel
Hook up the list of modified files.
293
                          ('b-id', 'b', True, 'b/', 'added'),
294
                          ('c-id', 'b/c', True, 'b/c', 'added'),
295
                         ], values)
278.1.16 by John Arbash Meinel
Implement the file changes list on top of _iter_changes rather than
296
297
    def test_filelist_renamed(self):
298
        tree = self.make_branch_and_tree('tree')
299
        self.build_tree(['tree/a', 'tree/b/', 'tree/b/c'])
300
        tree.add(['a', 'b', 'b/c'], ['a-id', 'b-id', 'c-id'])
301
        rev_id1 = tree.commit('one')
302
303
        tree.rename_one('b', 'd')
304
        tree.rename_one('a', 'd/a')
305
306
        dlg = commit.CommitDialog(tree)
307
        values = [(r[0], r[1], r[2], r[3], r[4]) for r in dlg._files_store]
278.1.20 by John Arbash Meinel
We always select the All Files record in the files view,
308
        self.assertEqual([(None, None, True, 'All Files', ''),
309
                          ('b-id', 'd', True, 'b/ => d/', 'renamed'),
278.1.16 by John Arbash Meinel
Implement the file changes list on top of _iter_changes rather than
310
                          ('a-id', 'd/a', True, 'a => d/a', 'renamed'),
311
                         ], values)
312
313
    def test_filelist_modified(self):
314
        tree = self.make_branch_and_tree('tree')
315
        self.build_tree(['tree/a'])
316
        tree.add(['a'], ['a-id'])
317
        rev_id1 = tree.commit('one')
318
319
        self.build_tree_contents([('tree/a', 'new contents for a\n')])
320
321
        dlg = commit.CommitDialog(tree)
322
        values = [(r[0], r[1], r[2], r[3], r[4]) for r in dlg._files_store]
278.1.20 by John Arbash Meinel
We always select the All Files record in the files view,
323
        self.assertEqual([(None, None, True, 'All Files', ''),
324
                          ('a-id', 'a', True, 'a', 'modified'),
278.1.16 by John Arbash Meinel
Implement the file changes list on top of _iter_changes rather than
325
                         ], values)
326
327
    def test_filelist_renamed_and_modified(self):
328
        tree = self.make_branch_and_tree('tree')
329
        self.build_tree(['tree/a', 'tree/b/', 'tree/b/c'])
330
        tree.add(['a', 'b', 'b/c'], ['a-id', 'b-id', 'c-id'])
331
        rev_id1 = tree.commit('one')
332
333
        tree.rename_one('b', 'd')
334
        tree.rename_one('a', 'd/a')
335
        self.build_tree_contents([('tree/d/a', 'new contents for a\n'),
336
                                  ('tree/d/c', 'new contents for c\n'),
337
                                 ])
338
        # 'c' is not considered renamed, because only its parent was moved, it
339
        # stayed in the same directory
340
341
        dlg = commit.CommitDialog(tree)
342
        values = [(r[0], r[1], r[2], r[3], r[4]) for r in dlg._files_store]
278.1.20 by John Arbash Meinel
We always select the All Files record in the files view,
343
        self.assertEqual([(None, None, True, 'All Files', ''),
344
                          ('b-id', 'd', True, 'b/ => d/', 'renamed'),
278.1.16 by John Arbash Meinel
Implement the file changes list on top of _iter_changes rather than
345
                          ('a-id', 'd/a', True, 'a => d/a', 'renamed and modified'),
346
                          ('c-id', 'd/c', True, 'd/c', 'modified'),
347
                         ], values)
348
349
    def test_filelist_kind_changed(self):
350
        tree = self.make_branch_and_tree('tree')
351
        self.build_tree(['tree/a', 'tree/b'])
352
        tree.add(['a', 'b'], ['a-id', 'b-id'])
353
        tree.commit('one')
354
355
        os.remove('tree/a')
356
        self.build_tree(['tree/a/'])
278.1.17 by John Arbash Meinel
Add a * reference for why you can't change the commit selection.
357
        # XXX:  This is technically valid, and the file list handles it fine,
358
        #       but 'show_diff_trees()' does not, so we skip this part of the
359
        #       test for now.
360
        # tree.rename_one('b', 'c')
361
        # os.remove('tree/c')
362
        # self.build_tree(['tree/c/'])
278.1.16 by John Arbash Meinel
Implement the file changes list on top of _iter_changes rather than
363
364
        dlg = commit.CommitDialog(tree)
365
        values = [(r[0], r[1], r[2], r[3], r[4]) for r in dlg._files_store]
278.1.20 by John Arbash Meinel
We always select the All Files record in the files view,
366
        self.assertEqual([(None, None, True, 'All Files', ''),
367
                          ('a-id', 'a', True, 'a => a/', 'kind changed'),
278.1.17 by John Arbash Meinel
Add a * reference for why you can't change the commit selection.
368
                          # ('b-id', 'c', True, 'b => c/', 'renamed and modified'),
278.1.16 by John Arbash Meinel
Implement the file changes list on top of _iter_changes rather than
369
                         ], values)
370
371
    def test_filelist_removed(self):
372
        tree = self.make_branch_and_tree('tree')
373
        self.build_tree(['tree/a', 'tree/b/'])
374
        tree.add(['a', 'b'], ['a-id', 'b-id'])
375
        tree.commit('one')
376
377
        os.remove('tree/a')
378
        tree.remove('b', force=True)
379
380
        dlg = commit.CommitDialog(tree)
381
        values = [(r[0], r[1], r[2], r[3], r[4]) for r in dlg._files_store]
278.1.20 by John Arbash Meinel
We always select the All Files record in the files view,
382
        self.assertEqual([(None, None, True, 'All Files', ''),
383
                          ('a-id', 'a', True, 'a', 'removed'),
278.1.16 by John Arbash Meinel
Implement the file changes list on top of _iter_changes rather than
384
                          ('b-id', 'b', True, 'b/', 'removed'),
385
                         ], values)
278.1.35 by John Arbash Meinel
Make use of the 'selected' parameter to CommitDialog.
386
        # All Files should be selected
734.1.23 by Curtis Hovey
Always pass a Gtk.TreePath instead of an int or tuple.
387
        self.assertEqual(
388
            (Gtk.TreePath(path=0), None), dlg._treeview_files.get_cursor())
278.1.35 by John Arbash Meinel
Make use of the 'selected' parameter to CommitDialog.
389
390
    def test_filelist_with_selected(self):
391
        tree = self.make_branch_and_tree('tree')
392
        self.build_tree(['tree/a', 'tree/b/'])
393
        tree.add(['a', 'b'], ['a-id', 'b-id'])
394
395
        dlg = commit.CommitDialog(tree, selected='a')
396
        values = [(r[0], r[1], r[2], r[3], r[4]) for r in dlg._files_store]
397
        self.assertEqual([(None, None, False, 'All Files', ''),
398
                          ('a-id', 'a', True, 'a', 'added'),
399
                          ('b-id', 'b', False, 'b/', 'added'),
400
                         ], values)
401
        # This file should also be selected in the file list, rather than the
402
        # 'All Files' selection
734.1.23 by Curtis Hovey
Always pass a Gtk.TreePath instead of an int or tuple.
403
        self.assertEqual(
404
            (Gtk.TreePath(path=1), None), dlg._treeview_files.get_cursor())
278.1.18 by John Arbash Meinel
Start checking the diff view is correct.
405
406
    def test_diff_view(self):
407
        tree = self.make_branch_and_tree('tree')
408
        self.build_tree(['tree/a', 'tree/b'])
409
        tree.add(['a', 'b'], ['a-id', 'b-id'])
410
        tree.commit('one')
411
412
        self.build_tree_contents([('tree/a', 'new contents for a\n')])
413
        tree.remove('b')
414
415
        dlg = commit.CommitDialog(tree)
416
        diff_buffer = dlg._diff_view.buffer
417
        text = diff_buffer.get_text(diff_buffer.get_start_iter(),
734.1.7 by Curtis Hovey
Updated buffer.getText() calls and ModifierType enums.
418
                                    diff_buffer.get_end_iter(),
419
                                    True).splitlines(True)
278.1.18 by John Arbash Meinel
Start checking the diff view is correct.
420
483 by Jelmer Vernooij
Fix diff test.
421
        self.assertEqual("=== modified file 'a'\n", text[0])
278.1.18 by John Arbash Meinel
Start checking the diff view is correct.
422
        self.assertContainsRe(text[1],
423
            r"--- a\t\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d [+-]\d\d\d\d")
483 by Jelmer Vernooij
Fix diff test.
424
        self.assertContainsRe(text[2],
425
            r"\+\+\+ a\t\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d [+-]\d\d\d\d")
426
        self.assertEqual('@@ -1,1 +1,1 @@\n', text[3])
427
        self.assertEqual('-contents of tree/a\n', text[4])
428
        self.assertEqual('+new contents for a\n', text[5])
429
        self.assertEqual('\n', text[6])
430
431
        self.assertEqual("=== removed file 'b'\n", text[7])
278.1.18 by John Arbash Meinel
Start checking the diff view is correct.
432
        self.assertContainsRe(text[8],
483 by Jelmer Vernooij
Fix diff test.
433
            r"--- b\t\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d [+-]\d\d\d\d")
434
        self.assertEqual('+++ b\t1970-01-01 00:00:00 +0000\n', text[9])
435
        self.assertEqual('@@ -1,1 +0,0 @@\n', text[10])
436
        self.assertEqual('-contents of tree/b\n', text[11])
278.1.18 by John Arbash Meinel
Start checking the diff view is correct.
437
        self.assertEqual('\n', text[12])
438
278.1.20 by John Arbash Meinel
We always select the All Files record in the files view,
439
        self.assertEqual('Diff for All Files', dlg._diff_label.get_text())
278.1.19 by John Arbash Meinel
Test what happens when a specific file is selected.
440
278.1.43 by John Arbash Meinel
Finish connecting the 'Commit all changes' radio buttons.
441
    def test_commit_partial_toggle(self):
442
        tree = self.make_branch_and_tree('tree')
443
        self.build_tree(['tree/a', 'tree/b'])
444
        tree.add(['a', 'b'], ['a-id', 'b-id'])
445
446
        dlg = commit.CommitDialog(tree)
447
        checked_col = dlg._treeview_files.get_column(0)
448
        self.assertFalse(checked_col.get_property('visible'))
449
        self.assertTrue(dlg._commit_all_changes)
450
451
        dlg._commit_selected_radio.set_active(True)
452
        self.assertTrue(checked_col.get_property('visible'))
453
        self.assertFalse(dlg._commit_all_changes)
454
278.1.19 by John Arbash Meinel
Test what happens when a specific file is selected.
455
    def test_file_selection(self):
456
        """Several things should happen when a file has been selected."""
457
        tree = self.make_branch_and_tree('tree')
278.1.33 by John Arbash Meinel
Only enable the per-file dialog if 'per_file_commits' is enabled in the config.
458
        tree.branch.get_config().set_user_option('per_file_commits', 'true')
278.1.19 by John Arbash Meinel
Test what happens when a specific file is selected.
459
        self.build_tree(['tree/a', 'tree/b'])
460
        tree.add(['a', 'b'], ['a-id', 'b-id'])
461
462
        dlg = commit.CommitDialog(tree)
463
        diff_buffer = dlg._diff_view.buffer
278.1.20 by John Arbash Meinel
We always select the All Files record in the files view,
464
        self.assertEqual('Diff for All Files', dlg._diff_label.get_text())
278.1.21 by John Arbash Meinel
Start tracking the per-file commit messages.
465
        self.assertEqual('File commit message',
466
                         dlg._file_message_expander.get_label())
467
        self.assertFalse(dlg._file_message_expander.get_expanded())
468
        self.assertFalse(dlg._file_message_expander.get_property('sensitive'))
278.1.19 by John Arbash Meinel
Test what happens when a specific file is selected.
469
734.1.23 by Curtis Hovey
Always pass a Gtk.TreePath instead of an int or tuple.
470
        dlg._treeview_files.set_cursor(
471
            Gtk.TreePath(path=1), None, False)
278.1.19 by John Arbash Meinel
Test what happens when a specific file is selected.
472
        self.assertEqual('Diff for a', dlg._diff_label.get_text())
473
        text = diff_buffer.get_text(diff_buffer.get_start_iter(),
734.1.7 by Curtis Hovey
Updated buffer.getText() calls and ModifierType enums.
474
                                    diff_buffer.get_end_iter(),
475
                                    True).splitlines(True)
278.1.19 by John Arbash Meinel
Test what happens when a specific file is selected.
476
        self.assertEqual("=== added file 'a'\n", text[0])
477
        self.assertContainsRe(text[1],
478
            r"--- a\t\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d [+-]\d\d\d\d")
479
        self.assertContainsRe(text[2],
480
            r"\+\+\+ a\t\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d [+-]\d\d\d\d")
481
        self.assertEqual('@@ -0,0 +1,1 @@\n', text[3])
482
        self.assertEqual('+contents of tree/a\n', text[4])
483
        self.assertEqual('\n', text[5])
278.1.21 by John Arbash Meinel
Start tracking the per-file commit messages.
484
        self.assertEqual('Commit message for a',
485
                         dlg._file_message_expander.get_label())
486
        self.assertTrue(dlg._file_message_expander.get_expanded())
487
        self.assertTrue(dlg._file_message_expander.get_property('sensitive'))
278.1.19 by John Arbash Meinel
Test what happens when a specific file is selected.
488
734.1.23 by Curtis Hovey
Always pass a Gtk.TreePath instead of an int or tuple.
489
        dlg._treeview_files.set_cursor(
490
            Gtk.TreePath(path=2), None, False)
278.1.19 by John Arbash Meinel
Test what happens when a specific file is selected.
491
        self.assertEqual('Diff for b', dlg._diff_label.get_text())
492
        text = diff_buffer.get_text(diff_buffer.get_start_iter(),
734.1.7 by Curtis Hovey
Updated buffer.getText() calls and ModifierType enums.
493
                                    diff_buffer.get_end_iter(),
494
                                    True).splitlines(True)
278.1.19 by John Arbash Meinel
Test what happens when a specific file is selected.
495
        self.assertEqual("=== added file 'b'\n", text[0])
496
        self.assertContainsRe(text[1],
497
            r"--- b\t\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d [+-]\d\d\d\d")
498
        self.assertContainsRe(text[2],
499
            r"\+\+\+ b\t\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d [+-]\d\d\d\d")
500
        self.assertEqual('@@ -0,0 +1,1 @@\n', text[3])
501
        self.assertEqual('+contents of tree/b\n', text[4])
502
        self.assertEqual('\n', text[5])
278.1.21 by John Arbash Meinel
Start tracking the per-file commit messages.
503
        self.assertEqual('Commit message for b',
504
                         dlg._file_message_expander.get_label())
505
        self.assertTrue(dlg._file_message_expander.get_expanded())
506
        self.assertTrue(dlg._file_message_expander.get_property('sensitive'))
507
734.1.23 by Curtis Hovey
Always pass a Gtk.TreePath instead of an int or tuple.
508
        dlg._treeview_files.set_cursor(
509
            Gtk.TreePath(path=0), None, False)
278.1.21 by John Arbash Meinel
Start tracking the per-file commit messages.
510
        self.assertEqual('Diff for All Files', dlg._diff_label.get_text())
511
        self.assertEqual('File commit message',
512
                         dlg._file_message_expander.get_label())
513
        self.assertFalse(dlg._file_message_expander.get_expanded())
514
        self.assertFalse(dlg._file_message_expander.get_property('sensitive'))
515
516
    def test_file_selection_message(self):
517
        """Selecting a file should bring up its commit message."""
518
        tree = self.make_branch_and_tree('tree')
278.1.33 by John Arbash Meinel
Only enable the per-file dialog if 'per_file_commits' is enabled in the config.
519
        tree.branch.get_config().set_user_option('per_file_commits', 'true')
278.1.21 by John Arbash Meinel
Start tracking the per-file commit messages.
520
        self.build_tree(['tree/a', 'tree/b/'])
521
        tree.add(['a', 'b'], ['a-id', 'b-id'])
522
523
        def get_file_text():
524
            buf = dlg._file_message_text_view.get_buffer()
734.1.7 by Curtis Hovey
Updated buffer.getText() calls and ModifierType enums.
525
            return buf.get_text(
526
                buf.get_start_iter(), buf.get_end_iter(), True)
278.1.21 by John Arbash Meinel
Start tracking the per-file commit messages.
527
528
        def get_saved_text(path):
529
            """Get the saved text for a given record."""
530
            return dlg._files_store.get_value(dlg._files_store.get_iter(path), 5)
531
532
        dlg = commit.CommitDialog(tree)
533
        self.assertEqual('File commit message',
534
                         dlg._file_message_expander.get_label())
535
        self.assertFalse(dlg._file_message_expander.get_expanded())
536
        self.assertFalse(dlg._file_message_expander.get_property('sensitive'))
537
        self.assertEqual('', get_file_text())
538
734.1.23 by Curtis Hovey
Always pass a Gtk.TreePath instead of an int or tuple.
539
        dlg._treeview_files.set_cursor(
540
            Gtk.TreePath(path=1), None, False)
278.1.21 by John Arbash Meinel
Start tracking the per-file commit messages.
541
        self.assertEqual('Commit message for a',
542
                         dlg._file_message_expander.get_label())
543
        self.assertTrue(dlg._file_message_expander.get_expanded())
544
        self.assertTrue(dlg._file_message_expander.get_property('sensitive'))
545
        self.assertEqual('', get_file_text())
546
547
        self.assertEqual('', get_saved_text(1))
278.1.27 by John Arbash Meinel
Add the ability to commit just specific files.
548
        dlg._set_file_commit_message('Some text\nfor a\n')
278.1.21 by John Arbash Meinel
Start tracking the per-file commit messages.
549
        dlg._save_current_file_message()
550
        # We should have updated the ListStore with the new file commit info
551
        self.assertEqual('Some text\nfor a\n', get_saved_text(1))
552
734.1.23 by Curtis Hovey
Always pass a Gtk.TreePath instead of an int or tuple.
553
        dlg._treeview_files.set_cursor(
554
            Gtk.TreePath(path=2), None, False)
278.1.21 by John Arbash Meinel
Start tracking the per-file commit messages.
555
        self.assertEqual('Commit message for b/',
556
                         dlg._file_message_expander.get_label())
557
        self.assertTrue(dlg._file_message_expander.get_expanded())
558
        self.assertTrue(dlg._file_message_expander.get_property('sensitive'))
559
        self.assertEqual('', get_file_text())
560
561
        self.assertEqual('', get_saved_text(2))
278.1.27 by John Arbash Meinel
Add the ability to commit just specific files.
562
        dlg._set_file_commit_message('More text\nfor b\n')
278.1.21 by John Arbash Meinel
Start tracking the per-file commit messages.
563
        # Now switch back to 'a'. The message should be saved, and the buffer
564
        # should be updated with the other text
734.1.23 by Curtis Hovey
Always pass a Gtk.TreePath instead of an int or tuple.
565
        dlg._treeview_files.set_cursor(
566
            Gtk.TreePath(path=1), None, False)
278.1.21 by John Arbash Meinel
Start tracking the per-file commit messages.
567
        self.assertEqual('More text\nfor b\n', get_saved_text(2))
568
        self.assertEqual('Commit message for a',
569
                         dlg._file_message_expander.get_label())
570
        self.assertTrue(dlg._file_message_expander.get_expanded())
571
        self.assertTrue(dlg._file_message_expander.get_property('sensitive'))
572
        self.assertEqual('Some text\nfor a\n', get_file_text())
278.1.20 by John Arbash Meinel
We always select the All Files record in the files view,
573
574
    def test_toggle_all_files(self):
575
        """When checking the All Files entry, it should toggle all fields"""
576
        tree = self.make_branch_and_tree('tree')
577
        self.build_tree(['tree/a', 'tree/b/'])
578
        tree.add(['a', 'b'], ['a-id', 'b-id'])
579
580
        dlg = commit.CommitDialog(tree)
581
        self.assertEqual([(None, None, True),
582
                          ('a-id', 'a', True),
583
                          ('b-id', 'b', True),
584
                         ], [(r[0], r[1], r[2]) for r in dlg._files_store])
585
586
        # TODO: jam 20071002 I'm not sure how to exactly trigger a toggle, it
587
        #       looks like we need to call renderer.activate() and pass an
588
        #       event and widget, and lots of other stuff I'm not sure what to
589
        #       do with. So instead, we just call toggle directly, and assume
590
        #       that toggle is hooked in correctly
591
        # column = dlg._treeview_files.get_column(0)
734.1.20 by Curtis Hovey
col.get_cell_renderers => col.get_cells.
592
        # renderer = column.get_cells()[0]
278.1.20 by John Arbash Meinel
We always select the All Files record in the files view,
593
594
        # Toggle a single entry should set just that entry to False
595
        dlg._toggle_commit(None, 1, dlg._files_store)
596
        self.assertEqual([(None, None, True),
597
                          ('a-id', 'a', False),
598
                          ('b-id', 'b', True),
599
                         ], [(r[0], r[1], r[2]) for r in dlg._files_store])
600
601
        # Toggling the main entry should set all entries
602
        dlg._toggle_commit(None, 0, dlg._files_store)
603
        self.assertEqual([(None, None, False),
604
                          ('a-id', 'a', False),
605
                          ('b-id', 'b', False),
606
                         ], [(r[0], r[1], r[2]) for r in dlg._files_store])
607
608
        dlg._toggle_commit(None, 2, dlg._files_store)
609
        self.assertEqual([(None, None, False),
610
                          ('a-id', 'a', False),
611
                          ('b-id', 'b', True),
612
                         ], [(r[0], r[1], r[2]) for r in dlg._files_store])
613
614
        dlg._toggle_commit(None, 0, dlg._files_store)
615
        self.assertEqual([(None, None, True),
616
                          ('a-id', 'a', True),
617
                          ('b-id', 'b', True),
618
                         ], [(r[0], r[1], r[2]) for r in dlg._files_store])
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
619
278.1.27 by John Arbash Meinel
Add the ability to commit just specific files.
620
    def test_specific_files(self):
621
        tree = self.make_branch_and_tree('tree')
622
        self.build_tree(['tree/a', 'tree/b/'])
623
        tree.add(['a', 'b'], ['a-id', 'b-id'])
624
625
        dlg = commit.CommitDialog(tree)
626
        self.assertEqual((['a', 'b'], []), dlg._get_specific_files())
627
278.1.43 by John Arbash Meinel
Finish connecting the 'Commit all changes' radio buttons.
628
        dlg._commit_selected_radio.set_active(True)
278.1.27 by John Arbash Meinel
Add the ability to commit just specific files.
629
        dlg._toggle_commit(None, 0, dlg._files_store)
630
        self.assertEqual(([], []), dlg._get_specific_files())
631
632
        dlg._toggle_commit(None, 1, dlg._files_store)
633
        self.assertEqual((['a'], []), dlg._get_specific_files())
634
635
    def test_specific_files_with_messages(self):
636
        tree = self.make_branch_and_tree('tree')
278.1.33 by John Arbash Meinel
Only enable the per-file dialog if 'per_file_commits' is enabled in the config.
637
        tree.branch.get_config().set_user_option('per_file_commits', 'true')
278.1.27 by John Arbash Meinel
Add the ability to commit just specific files.
638
        self.build_tree(['tree/a_file', 'tree/b_dir/'])
639
        tree.add(['a_file', 'b_dir'], ['1a-id', '0b-id'])
640
641
        dlg = commit.CommitDialog(tree)
278.1.43 by John Arbash Meinel
Finish connecting the 'Commit all changes' radio buttons.
642
        dlg._commit_selected_radio.set_active(True)
278.1.27 by John Arbash Meinel
Add the ability to commit just specific files.
643
        self.assertEqual((['a_file', 'b_dir'], []), dlg._get_specific_files())
644
734.1.23 by Curtis Hovey
Always pass a Gtk.TreePath instead of an int or tuple.
645
        dlg._treeview_files.set_cursor(
646
            Gtk.TreePath(path=1), None, False)
278.1.27 by John Arbash Meinel
Add the ability to commit just specific files.
647
        dlg._set_file_commit_message('Test\nmessage\nfor a_file\n')
734.1.23 by Curtis Hovey
Always pass a Gtk.TreePath instead of an int or tuple.
648
        dlg._treeview_files.set_cursor(
649
            Gtk.TreePath(path=2), None, False)
278.1.27 by John Arbash Meinel
Add the ability to commit just specific files.
650
        dlg._set_file_commit_message('message\nfor b_dir\n')
651
652
        self.assertEqual((['a_file', 'b_dir'],
653
                          [{'path':'a_file', 'file_id':'1a-id',
654
                            'message':'Test\nmessage\nfor a_file\n'},
655
                           {'path':'b_dir', 'file_id':'0b-id',
656
                            'message':'message\nfor b_dir\n'},
657
                          ]), dlg._get_specific_files())
658
659
        dlg._toggle_commit(None, 1, dlg._files_store)
660
        self.assertEqual((['b_dir'],
661
                          [{'path':'b_dir', 'file_id':'0b-id',
662
                            'message':'message\nfor b_dir\n'},
663
                          ]), dlg._get_specific_files())
664
622.1.1 by John Arbash Meinel
Ensure that per-file commit messages and global commit messages get sanitized.
665
    def test_specific_files_sanitizes_messages(self):
666
        tree = self.make_branch_and_tree('tree')
667
        tree.branch.get_config().set_user_option('per_file_commits', 'true')
668
        self.build_tree(['tree/a_file', 'tree/b_dir/'])
669
        tree.add(['a_file', 'b_dir'], ['1a-id', '0b-id'])
670
671
        dlg = commit.CommitDialog(tree)
672
        dlg._commit_selected_radio.set_active(True)
673
        self.assertEqual((['a_file', 'b_dir'], []), dlg._get_specific_files())
674
734.1.23 by Curtis Hovey
Always pass a Gtk.TreePath instead of an int or tuple.
675
        dlg._treeview_files.set_cursor(
676
            Gtk.TreePath(path=1), None, False)
622.1.1 by John Arbash Meinel
Ensure that per-file commit messages and global commit messages get sanitized.
677
        dlg._set_file_commit_message('Test\r\nmessage\rfor a_file\n')
734.1.23 by Curtis Hovey
Always pass a Gtk.TreePath instead of an int or tuple.
678
        dlg._treeview_files.set_cursor(
679
            Gtk.TreePath(path=2), None, False)
622.1.1 by John Arbash Meinel
Ensure that per-file commit messages and global commit messages get sanitized.
680
        dlg._set_file_commit_message('message\r\nfor\nb_dir\r')
681
682
        self.assertEqual((['a_file', 'b_dir'],
683
                          [{'path':'a_file', 'file_id':'1a-id',
684
                            'message':'Test\nmessage\nfor a_file\n'},
685
                           {'path':'b_dir', 'file_id':'0b-id',
686
                            'message':'message\nfor\nb_dir\n'},
687
                          ]), dlg._get_specific_files())
688
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
689
635.2.10 by Vincent Ladeuil
Complete tests around saved commit messages.
690
class QuestionHelpers(object):
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
691
278.1.26 by John Arbash Meinel
Handle pointless commits and trees with unknown files.
692
    def _set_question_yes(self, dlg):
693
        """Set the dialog to answer YES to any questions."""
694
        self.questions = []
606 by Vincent Ladeuil
Fix gtk dialogs popping up and asking for input during selftest.
695
        def _question_yes(*args, **kwargs):
278.1.26 by John Arbash Meinel
Handle pointless commits and trees with unknown files.
696
            self.questions.append(args)
697
            self.questions.append('YES')
734.1.1 by Curtis Hovey
Mechanical changes made by pygi.convert.sh.
698
            return Gtk.ResponseType.YES
278.1.26 by John Arbash Meinel
Handle pointless commits and trees with unknown files.
699
        dlg._question_dialog = _question_yes
700
701
    def _set_question_no(self, dlg):
702
        """Set the dialog to answer NO to any questions."""
703
        self.questions = []
606 by Vincent Ladeuil
Fix gtk dialogs popping up and asking for input during selftest.
704
        def _question_no(*args, **kwargs):
278.1.26 by John Arbash Meinel
Handle pointless commits and trees with unknown files.
705
            self.questions.append(args)
706
            self.questions.append('NO')
734.1.1 by Curtis Hovey
Mechanical changes made by pygi.convert.sh.
707
            return Gtk.ResponseType.NO
278.1.26 by John Arbash Meinel
Handle pointless commits and trees with unknown files.
708
        dlg._question_dialog = _question_no
709
635.2.10 by Vincent Ladeuil
Complete tests around saved commit messages.
710
711
class TestCommitDialog_Commit(tests.TestCaseWithTransport, QuestionHelpers):
712
    """Tests on the actual 'commit' button being pushed."""
713
278.1.25 by John Arbash Meinel
Add the 'Only Commit Locally' checkbox, we may want to put it elsewhere, though.
714
    def test_bound_commit_local(self):
715
        tree = self.make_branch_and_tree('tree')
716
        self.build_tree(['tree/a'])
717
        tree.add(['a'], ['a-id'])
718
        rev_id1 = tree.commit('one')
719
720
        tree2 = tree.bzrdir.sprout('tree2').open_workingtree()
721
        self.build_tree(['tree2/b'])
722
        tree2.add(['b'], ['b-id'])
723
        tree2.branch.bind(tree.branch)
724
725
        dlg = commit.CommitDialog(tree2)
726
        # With the check box set, it should only effect the local branch
727
        dlg._check_local.set_active(True)
728
        dlg._set_global_commit_message('Commit message\n')
729
        dlg._do_commit()
730
731
        last_rev = tree2.last_revision()
732
        self.assertEqual(last_rev, dlg.committed_revision_id)
733
        self.assertEqual(rev_id1, tree.branch.last_revision())
734
622.1.1 by John Arbash Meinel
Ensure that per-file commit messages and global commit messages get sanitized.
735
    def test_commit_global_sanitizes_message(self):
736
        tree = self.make_branch_and_tree('tree')
737
        self.build_tree(['tree/a'])
738
        tree.add(['a'], ['a-id'])
739
        rev_id1 = tree.commit('one')
740
741
        self.build_tree(['tree/b'])
742
        tree.add(['b'], ['b-id'])
743
        dlg = commit.CommitDialog(tree)
744
        # With the check box set, it should only effect the local branch
745
        dlg._set_global_commit_message('Commit\r\nmessage\rfoo\n')
746
        dlg._do_commit()
747
        rev = tree.branch.repository.get_revision(tree.last_revision())
748
        self.assertEqual('Commit\nmessage\nfoo\n', rev.message)
749
278.1.25 by John Arbash Meinel
Add the 'Only Commit Locally' checkbox, we may want to put it elsewhere, though.
750
    def test_bound_commit_both(self):
751
        tree = self.make_branch_and_tree('tree')
752
        self.build_tree(['tree/a'])
753
        tree.add(['a'], ['a-id'])
754
        rev_id1 = tree.commit('one')
755
756
        tree2 = tree.bzrdir.sprout('tree2').open_workingtree()
757
        self.build_tree(['tree2/b'])
758
        tree2.add(['b'], ['b-id'])
759
        tree2.branch.bind(tree.branch)
760
761
        dlg = commit.CommitDialog(tree2)
762
        # With the check box set, it should only effect the local branch
763
        dlg._check_local.set_active(False)
764
        dlg._set_global_commit_message('Commit message\n')
765
        dlg._do_commit()
766
767
        last_rev = tree2.last_revision()
768
        self.assertEqual(last_rev, dlg.committed_revision_id)
769
        self.assertEqual(last_rev, tree.branch.last_revision())
770
606 by Vincent Ladeuil
Fix gtk dialogs popping up and asking for input during selftest.
771
    def test_commit_empty_message(self):
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
772
        tree = self.make_branch_and_tree('tree')
773
        self.build_tree(['tree/a', 'tree/b'])
774
        tree.add(['a'], ['a-id'])
775
        rev_id = tree.commit('one')
776
777
        tree.add(['b'], ['b-id'])
778
779
        dlg = commit.CommitDialog(tree)
278.1.26 by John Arbash Meinel
Handle pointless commits and trees with unknown files.
780
        self._set_question_no(dlg)
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
781
        dlg._do_commit()
782
        self.assertEqual(
783
            [('Commit with an empty message?',
784
              'You can describe your commit intent in the message.'),
785
              'NO',
278.1.26 by John Arbash Meinel
Handle pointless commits and trees with unknown files.
786
            ], self.questions)
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
787
        # By saying NO, nothing should be committed.
788
        self.assertEqual(rev_id, tree.last_revision())
789
        self.assertIs(None, dlg.committed_revision_id)
278.1.25 by John Arbash Meinel
Add the 'Only Commit Locally' checkbox, we may want to put it elsewhere, though.
790
        self.assertTrue(dlg._global_message_text_view.get_property('is-focus'))
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
791
278.1.26 by John Arbash Meinel
Handle pointless commits and trees with unknown files.
792
        self._set_question_yes(dlg)
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
793
794
        dlg._do_commit()
795
        self.assertEqual(
796
            [('Commit with an empty message?',
797
              'You can describe your commit intent in the message.'),
278.1.26 by John Arbash Meinel
Handle pointless commits and trees with unknown files.
798
              'YES',
799
            ], self.questions)
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
800
        committed = tree.last_revision()
801
        self.assertNotEqual(rev_id, committed)
802
        self.assertEqual(committed, dlg.committed_revision_id)
803
804
    def test_initial_commit(self):
805
        tree = self.make_branch_and_tree('tree')
806
        self.build_tree(['tree/a'])
807
        tree.add(['a'], ['a-id'])
808
809
        dlg = commit.CommitDialog(tree)
278.1.25 by John Arbash Meinel
Add the 'Only Commit Locally' checkbox, we may want to put it elsewhere, though.
810
        dlg._set_global_commit_message('Some text\n')
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
811
        dlg._do_commit()
812
813
        last_rev = tree.last_revision()
814
        self.assertEqual(last_rev, dlg.committed_revision_id)
815
        rev = tree.branch.repository.get_revision(last_rev)
816
        self.assertEqual(last_rev, rev.revision_id)
817
        self.assertEqual('Some text\n', rev.message)
278.1.26 by John Arbash Meinel
Handle pointless commits and trees with unknown files.
818
819
    def test_pointless_commit(self):
820
        tree = self.make_branch_and_tree('tree')
821
        self.build_tree(['tree/a'])
822
        tree.add(['a'], ['a-id'])
823
        rev_id1 = tree.commit('one')
824
825
        dlg = commit.CommitDialog(tree)
826
        dlg._set_global_commit_message('Some text\n')
827
828
        self._set_question_no(dlg)
829
        dlg._do_commit()
830
831
        self.assertIs(None, dlg.committed_revision_id)
832
        self.assertEqual(rev_id1, tree.last_revision())
833
        self.assertEqual(
834
            [('Commit with no changes?',
835
              'There are no changes in the working tree.'
836
              ' Do you want to commit anyway?'),
837
              'NO',
838
            ], self.questions)
839
840
        self._set_question_yes(dlg)
841
        dlg._do_commit()
842
843
        rev_id2 = tree.last_revision()
844
        self.assertEqual(rev_id2, dlg.committed_revision_id)
845
        self.assertNotEqual(rev_id1, rev_id2)
846
        self.assertEqual(
847
            [('Commit with no changes?',
848
              'There are no changes in the working tree.'
849
              ' Do you want to commit anyway?'),
850
              'YES',
851
            ], self.questions)
852
853
    def test_unknowns(self):
854
        """We should check if there are unknown files."""
855
        tree = self.make_branch_and_tree('tree')
856
        rev_id1 = tree.commit('one')
857
        self.build_tree(['tree/a', 'tree/b'])
858
        tree.add(['a'], ['a-id'])
859
860
        dlg = commit.CommitDialog(tree)
861
        dlg._set_global_commit_message('Some text\n')
862
        self._set_question_no(dlg)
863
864
        dlg._do_commit()
865
866
        self.assertIs(None, dlg.committed_revision_id)
867
        self.assertEqual(rev_id1, tree.last_revision())
868
        self.assertEqual(
869
            [("Commit with unknowns?",
870
              "Unknown files exist in the working tree. Commit anyway?"),
871
              "NO",
872
            ], self.questions)
873
874
        self._set_question_yes(dlg)
875
        dlg._do_commit()
876
877
        rev_id2 = tree.last_revision()
878
        self.assertNotEqual(rev_id1, rev_id2)
879
        self.assertEqual(rev_id2, dlg.committed_revision_id)
880
        self.assertEqual(
881
            [("Commit with unknowns?",
882
              "Unknown files exist in the working tree. Commit anyway?"),
883
              "YES",
884
            ], self.questions)
885
278.1.27 by John Arbash Meinel
Add the ability to commit just specific files.
886
    def test_commit_specific_files(self):
887
        tree = self.make_branch_and_tree('tree')
888
        rev_id1 = tree.commit('one')
889
        self.build_tree(['tree/a', 'tree/b'])
890
        tree.add(['a', 'b'], ['a-id', 'b-id'])
891
892
        dlg = commit.CommitDialog(tree)
278.1.43 by John Arbash Meinel
Finish connecting the 'Commit all changes' radio buttons.
893
        dlg._commit_selected_radio.set_active(True) # enable partial
278.1.27 by John Arbash Meinel
Add the ability to commit just specific files.
894
        dlg._toggle_commit(None, 2, dlg._files_store) # unset 'b'
895
896
        dlg._set_global_commit_message('Committing just "a"\n')
897
        dlg._do_commit()
898
899
        rev_id2 = dlg.committed_revision_id
900
        self.assertIsNot(None, rev_id2)
901
        self.assertEqual(rev_id2, tree.last_revision())
902
903
        rt = tree.branch.repository.revision_tree(rev_id2)
904
        entries = [(path, ie.file_id) for path, ie in rt.iter_entries_by_dir()
905
                                       if path] # Ignore the root entry
906
        self.assertEqual([('a', 'a-id')], entries)
907
278.1.43 by John Arbash Meinel
Finish connecting the 'Commit all changes' radio buttons.
908
    def test_commit_partial_no_partial(self):
909
        """Ignore the checkboxes if committing all files."""
910
        tree = self.make_branch_and_tree('tree')
911
        rev_id1 = tree.commit('one')
912
        self.build_tree(['tree/a', 'tree/b'])
913
        tree.add(['a', 'b'], ['a-id', 'b-id'])
914
915
        dlg = commit.CommitDialog(tree)
916
        dlg._commit_selected_radio.set_active(True) # enable partial
917
        dlg._toggle_commit(None, 2, dlg._files_store) # unset 'b'
918
919
        # Switch back to committing all changes
920
        dlg._commit_all_files_radio.set_active(True)
921
922
        dlg._set_global_commit_message('Committing everything\n')
923
        dlg._do_commit()
924
925
        rev_id2 = dlg.committed_revision_id
926
        self.assertIsNot(None, rev_id2)
927
        self.assertEqual(rev_id2, tree.last_revision())
928
929
        rt = tree.branch.repository.revision_tree(rev_id2)
930
        entries = [(path, ie.file_id) for path, ie in rt.iter_entries_by_dir()
931
                                       if path] # Ignore the root entry
932
        self.assertEqual([('a', 'a-id'), ('b', 'b-id')], entries)
933
278.1.27 by John Arbash Meinel
Add the ability to commit just specific files.
934
    def test_commit_no_messages(self):
935
        tree = self.make_branch_and_tree('tree')
936
        rev_id1 = tree.commit('one')
937
        self.build_tree(['tree/a', 'tree/b'])
938
        tree.add(['a', 'b'], ['a-id', 'b-id'])
939
940
        dlg = commit.CommitDialog(tree)
941
        dlg._set_global_commit_message('Simple commit\n')
942
        dlg._do_commit()
943
944
        rev = tree.branch.repository.get_revision(dlg.committed_revision_id)
945
        self.failIf('file-info' in rev.properties)
946
278.1.33 by John Arbash Meinel
Only enable the per-file dialog if 'per_file_commits' is enabled in the config.
947
    def test_commit_disabled_messages(self):
948
        tree = self.make_branch_and_tree('tree')
949
        rev_id1 = tree.commit('one')
950
951
        self.build_tree(['tree/a', 'tree/b'])
952
        tree.add(['a', 'b'], ['a-id', 'b-id'])
953
954
        dlg = commit.CommitDialog(tree)
955
        self.assertFalse(dlg._file_message_expander.get_property('visible'))
278.1.38 by John Arbash Meinel
Add tests that when per-file messages are disabled
956
        self.assertEqual('Commit Message',
957
                         dlg._global_message_label.get_text())
278.1.33 by John Arbash Meinel
Only enable the per-file dialog if 'per_file_commits' is enabled in the config.
958
959
        tree.branch.get_config().set_user_option('per_file_commits', 'true')
960
        dlg = commit.CommitDialog(tree)
961
        self.assertTrue(dlg._file_message_expander.get_property('visible'))
278.1.38 by John Arbash Meinel
Add tests that when per-file messages are disabled
962
        self.assertEqual('Global Commit Message',
963
                         dlg._global_message_label.get_text())
278.1.33 by John Arbash Meinel
Only enable the per-file dialog if 'per_file_commits' is enabled in the config.
964
965
        tree.branch.get_config().set_user_option('per_file_commits', 'on')
966
        dlg = commit.CommitDialog(tree)
967
        self.assertTrue(dlg._file_message_expander.get_property('visible'))
278.1.38 by John Arbash Meinel
Add tests that when per-file messages are disabled
968
        self.assertEqual('Global Commit Message',
969
                         dlg._global_message_label.get_text())
278.1.33 by John Arbash Meinel
Only enable the per-file dialog if 'per_file_commits' is enabled in the config.
970
971
        tree.branch.get_config().set_user_option('per_file_commits', 'y')
972
        dlg = commit.CommitDialog(tree)
973
        self.assertTrue(dlg._file_message_expander.get_property('visible'))
278.1.38 by John Arbash Meinel
Add tests that when per-file messages are disabled
974
        self.assertEqual('Global Commit Message',
975
                         dlg._global_message_label.get_text())
278.1.33 by John Arbash Meinel
Only enable the per-file dialog if 'per_file_commits' is enabled in the config.
976
977
        tree.branch.get_config().set_user_option('per_file_commits', 'n')
978
        dlg = commit.CommitDialog(tree)
979
        self.assertFalse(dlg._file_message_expander.get_property('visible'))
278.1.38 by John Arbash Meinel
Add tests that when per-file messages are disabled
980
        self.assertEqual('Commit Message',
981
                         dlg._global_message_label.get_text())
278.1.33 by John Arbash Meinel
Only enable the per-file dialog if 'per_file_commits' is enabled in the config.
982
278.1.27 by John Arbash Meinel
Add the ability to commit just specific files.
983
    def test_commit_specific_files_with_messages(self):
984
        tree = self.make_branch_and_tree('tree')
278.1.33 by John Arbash Meinel
Only enable the per-file dialog if 'per_file_commits' is enabled in the config.
985
        tree.branch.get_config().set_user_option('per_file_commits', 'true')
278.1.27 by John Arbash Meinel
Add the ability to commit just specific files.
986
        rev_id1 = tree.commit('one')
987
        self.build_tree(['tree/a', 'tree/b'])
988
        tree.add(['a', 'b'], ['a-id', 'b-id'])
989
990
        dlg = commit.CommitDialog(tree)
278.1.43 by John Arbash Meinel
Finish connecting the 'Commit all changes' radio buttons.
991
        dlg._commit_selected_radio.set_active(True) # enable partial
734.1.23 by Curtis Hovey
Always pass a Gtk.TreePath instead of an int or tuple.
992
        dlg._treeview_files.set_cursor(
993
            Gtk.TreePath(path=1), None, False)
278.1.27 by John Arbash Meinel
Add the ability to commit just specific files.
994
        dlg._set_file_commit_message('Message for A\n')
734.1.23 by Curtis Hovey
Always pass a Gtk.TreePath instead of an int or tuple.
995
        dlg._treeview_files.set_cursor(
996
            Gtk.TreePath(path=2), None, False)
278.1.27 by John Arbash Meinel
Add the ability to commit just specific files.
997
        dlg._set_file_commit_message('Message for B\n')
998
        dlg._toggle_commit(None, 2, dlg._files_store) # unset 'b'
999
        dlg._set_global_commit_message('Commit just "a"')
1000
1001
        dlg._do_commit()
1002
1003
        rev_id2 = dlg.committed_revision_id
1004
        self.assertEqual(rev_id2, tree.last_revision())
1005
        rev = tree.branch.repository.get_revision(rev_id2)
1006
        self.assertEqual('Commit just "a"', rev.message)
1007
        file_info = rev.properties['file-info']
662 by Vincent Ladeuil
Fix test failures.
1008
        self.assertEqual(u'ld7:file_id4:a-id'
1009
                         '7:message14:Message for A\n'
1010
                         '4:path1:a'
1011
                         'ee',
1012
                         file_info)
278.1.27 by John Arbash Meinel
Add the ability to commit just specific files.
1013
        self.assertEqual([{'path':'a', 'file_id':'a-id',
662 by Vincent Ladeuil
Fix test failures.
1014
                           'message':'Message for A\n'},],
1015
                         bencode.bdecode(file_info.encode('UTF-8')))
278.1.28 by John Arbash Meinel
Ensure that we can set per-file messages even during a merge.
1016
1017
    def test_commit_messages_after_merge(self):
1018
        tree = self.make_branch_and_tree('tree')
278.1.33 by John Arbash Meinel
Only enable the per-file dialog if 'per_file_commits' is enabled in the config.
1019
        tree.branch.get_config().set_user_option('per_file_commits', 'true')
278.1.28 by John Arbash Meinel
Ensure that we can set per-file messages even during a merge.
1020
        rev_id1 = tree.commit('one')
1021
        tree2 = tree.bzrdir.sprout('tree2').open_workingtree()
1022
        self.build_tree(['tree2/a', 'tree2/b'])
1023
        tree2.add(['a', 'b'], ['a-id', 'b-id'])
1024
        rev_id2 = tree2.commit('two')
1025
1026
        tree.merge_from_branch(tree2.branch)
1027
1028
        dlg = commit.CommitDialog(tree)
734.1.23 by Curtis Hovey
Always pass a Gtk.TreePath instead of an int or tuple.
1029
        dlg._treeview_files.set_cursor(
1030
            Gtk.TreePath(path=1), None, False) # 'a'
278.1.28 by John Arbash Meinel
Ensure that we can set per-file messages even during a merge.
1031
        dlg._set_file_commit_message('Message for A\n')
1032
        # No message for 'B'
1033
        dlg._set_global_commit_message('Merging from "tree2"\n')
1034
1035
        dlg._do_commit()
1036
1037
        rev_id3 = dlg.committed_revision_id
1038
        self.assertEqual(rev_id3, tree.last_revision())
1039
        rev = tree.branch.repository.get_revision(rev_id3)
1040
        self.assertEqual('Merging from "tree2"\n', rev.message)
1041
        self.assertEqual([rev_id1, rev_id2], rev.parent_ids)
1042
        file_info = rev.properties['file-info']
662 by Vincent Ladeuil
Fix test failures.
1043
        self.assertEqual(u'ld7:file_id4:a-id'
1044
                         '7:message14:Message for A\n'
1045
                         '4:path1:a'
1046
                         'ee',
1047
                         file_info)
278.1.28 by John Arbash Meinel
Ensure that we can set per-file messages even during a merge.
1048
        self.assertEqual([{'path':'a', 'file_id':'a-id',
662 by Vincent Ladeuil
Fix test failures.
1049
                           'message':'Message for A\n'},],
1050
                         bencode.bdecode(file_info.encode('UTF-8')))
278.1.29 by John Arbash Meinel
Start testing with Unicode data.
1051
1052
    def test_commit_unicode_messages(self):
500.1.1 by Vincent Ladeuil
Fix test failing after a feature rename in bzr.
1053
        self.requireFeature(tests.UnicodeFilenameFeature)
278.1.29 by John Arbash Meinel
Start testing with Unicode data.
1054
1055
        tree = self.make_branch_and_tree('tree')
278.1.33 by John Arbash Meinel
Only enable the per-file dialog if 'per_file_commits' is enabled in the config.
1056
        tree.branch.get_config().set_user_option('per_file_commits', 'true')
278.1.29 by John Arbash Meinel
Start testing with Unicode data.
1057
        self.build_tree(['tree/a', u'tree/\u03a9'])
1058
        tree.add(['a', u'\u03a9'], ['a-id', 'omega-id'])
1059
1060
        dlg = commit.CommitDialog(tree)
734.1.23 by Curtis Hovey
Always pass a Gtk.TreePath instead of an int or tuple.
1061
        dlg._treeview_files.set_cursor(
1062
            Gtk.TreePath(path=1), None, False) # 'a'
278.1.29 by John Arbash Meinel
Start testing with Unicode data.
1063
        dlg._set_file_commit_message(u'Test \xfan\xecc\xf6de\n')
734.1.23 by Curtis Hovey
Always pass a Gtk.TreePath instead of an int or tuple.
1064
        dlg._treeview_files.set_cursor(
1065
            Gtk.TreePath(path=2), None, False) # omega
278.1.29 by John Arbash Meinel
Start testing with Unicode data.
1066
        dlg._set_file_commit_message(u'\u03a9 is the end of all things.\n')
1067
        dlg._set_global_commit_message(u'\u03a9 and \xfan\xecc\xf6de\n')
1068
1069
        self.assertEqual(([u'a', u'\u03a9'],
1070
                          [{'path':'a', 'file_id':'a-id',
1071
                            'message':'Test \xc3\xban\xc3\xacc\xc3\xb6de\n'},
1072
                           {'path':'\xce\xa9', 'file_id':'omega-id',
1073
                            'message':'\xce\xa9 is the end of all things.\n'},
1074
                          ]), dlg._get_specific_files())
1075
1076
        dlg._do_commit()
1077
1078
        rev = tree.branch.repository.get_revision(dlg.committed_revision_id)
278.1.31 by John Arbash Meinel
We can make bencode work again by a simple decode/encode step.
1079
        file_info = rev.properties['file-info'].encode('UTF-8')
278.1.29 by John Arbash Meinel
Start testing with Unicode data.
1080
        value = ('ld7:file_id4:a-id'
1081
                   '7:message16:Test \xc3\xban\xc3\xacc\xc3\xb6de\n'
1082
                   '4:path1:a'
1083
                  'e'
1084
                  'd7:file_id8:omega-id'
1085
                   '7:message29:\xce\xa9 is the end of all things.\n'
1086
                   '4:path2:\xce\xa9'
1087
                  'e'
1088
                 'e')
1089
        self.assertEqual(value, file_info)
1090
        file_info_decoded = bencode.bdecode(file_info)
1091
        for d in file_info_decoded:
278.1.31 by John Arbash Meinel
We can make bencode work again by a simple decode/encode step.
1092
            d['path'] = d['path'].decode('UTF-8')
1093
            d['message'] = d['message'].decode('UTF-8')
278.1.29 by John Arbash Meinel
Start testing with Unicode data.
1094
1095
        self.assertEqual([{'path':u'a', 'file_id':'a-id',
1096
                           'message':u'Test \xfan\xecc\xf6de\n'},
1097
                          {'path':u'\u03a9', 'file_id':'omega-id',
1098
                           'message':u'\u03a9 is the end of all things.\n'},
1099
                         ], file_info_decoded)
622.1.1 by John Arbash Meinel
Ensure that per-file commit messages and global commit messages get sanitized.
1100
1101
1102
class TestSanitizeMessage(tests.TestCase):
1103
1104
    def assertSanitize(self, expected, original):
1105
        self.assertEqual(expected,
1106
                         commit._sanitize_and_decode_message(original))
1107
1108
    def test_untouched(self):
1109
        self.assertSanitize('foo\nbar\nbaz\n', 'foo\nbar\nbaz\n')
1110
1111
    def test_converts_cr_to_lf(self):
1112
        self.assertSanitize('foo\nbar\nbaz\n', 'foo\rbar\rbaz\r')
1113
1114
    def test_converts_crlf_to_lf(self):
1115
        self.assertSanitize('foo\nbar\nbaz\n', 'foo\r\nbar\r\nbaz\r\n')
1116
1117
    def test_converts_mixed_to_lf(self):
1118
        self.assertSanitize('foo\nbar\nbaz\n', 'foo\r\nbar\rbaz\n')
635.2.8 by Vincent Ladeuil
Start testing patch behavior.
1119
1120
635.2.10 by Vincent Ladeuil
Complete tests around saved commit messages.
1121
class TestSavedCommitMessages(tests.TestCaseWithTransport):
635.2.9 by Vincent Ladeuil
Tests completed for uncommit.
1122
635.2.12 by Vincent Ladeuil
Implement commit message saving without modifying bzrlib.
1123
    def setUp(self):
1124
        super(TestSavedCommitMessages, self).setUp()
1125
        # Install our hook
1126
        branch.Branch.hooks.install_named_hook(
1127
            'post_uncommit', commit.save_commit_messages, None)
1128
635.2.9 by Vincent Ladeuil
Tests completed for uncommit.
1129
    def _get_file_info_dict(self, rank):
1130
        file_info = [dict(path='a', file_id='a-id', message='a msg %d' % rank),
1131
                     dict(path='b', file_id='b-id', message='b msg %d' % rank)]
1132
        return file_info
1133
1134
    def _get_file_info_revprops(self, rank):
1135
        file_info_prop = self._get_file_info_dict(rank)
1136
        return {'file-info': bencode.bencode(file_info_prop).decode('UTF-8')}
1137
1138
    def _get_commit_message(self):
1139
        return self.config.get_user_option('gtk_global_commit_message')
1140
1141
    def _get_file_commit_messages(self):
1142
        return self.config.get_user_option('gtk_file_commit_messages')
1143
635.2.10 by Vincent Ladeuil
Complete tests around saved commit messages.
1144
1145
class TestUncommitHook(TestSavedCommitMessages):
1146
1147
    def setUp(self):
1148
        super(TestUncommitHook, self).setUp()
1149
        self.tree = self.make_branch_and_tree('tree')
1150
        self.config = self.tree.branch.get_config()
1151
        self.build_tree(['tree/a', 'tree/b'])
1152
        self.tree.add(['a'], ['a-id'])
1153
        self.tree.add(['b'], ['b-id'])
635.2.12 by Vincent Ladeuil
Implement commit message saving without modifying bzrlib.
1154
        rev1 = self.tree.commit('one', rev_id='one-id',
1155
                                revprops=self._get_file_info_revprops(1))
1156
        rev2 = self.tree.commit('two', rev_id='two-id',
1157
                                revprops=self._get_file_info_revprops(2))
1158
        rev3 = self.tree.commit('three', rev_id='three-id',
635.2.10 by Vincent Ladeuil
Complete tests around saved commit messages.
1159
                                revprops=self._get_file_info_revprops(3))
1160
635.2.9 by Vincent Ladeuil
Tests completed for uncommit.
1161
    def test_uncommit_one_by_one(self):
1162
        uncommit.uncommit(self.tree.branch, tree=self.tree)
1163
        self.assertEquals(u'three', self._get_commit_message())
1164
        self.assertEquals(u'd4:a-id7:a msg 34:b-id7:b msg 3e',
1165
                          self._get_file_commit_messages())
1166
1167
        uncommit.uncommit(self.tree.branch, tree=self.tree)
1168
        self.assertEquals(u'two\n******\nthree', self._get_commit_message())
1169
        self.assertEquals(u'd4:a-id22:a msg 2\n******\na msg 3'
1170
                          '4:b-id22:b msg 2\n******\nb msg 3e',
1171
                          self._get_file_commit_messages())
1172
1173
        uncommit.uncommit(self.tree.branch, tree=self.tree)
1174
        self.assertEquals(u'one\n******\ntwo\n******\nthree',
1175
                          self._get_commit_message())
1176
        self.assertEquals(u'd4:a-id37:a msg 1\n******\na msg 2\n******\na msg 3'
1177
                          '4:b-id37:b msg 1\n******\nb msg 2\n******\nb msg 3e',
1178
                          self._get_file_commit_messages())
1179
1180
    def test_uncommit_all_at_once(self):
1181
        uncommit.uncommit(self.tree.branch, tree=self.tree, revno=1)
1182
        self.assertEquals(u'one\n******\ntwo\n******\nthree',
1183
                          self._get_commit_message())
1184
        self.assertEquals(u'd4:a-id37:a msg 1\n******\na msg 2\n******\na msg 3'
1185
                          '4:b-id37:b msg 1\n******\nb msg 2\n******\nb msg 3e',
1186
                          self._get_file_commit_messages())
635.2.10 by Vincent Ladeuil
Complete tests around saved commit messages.
1187
1188
1189
class TestReusingSavedCommitMessages(TestSavedCommitMessages, QuestionHelpers):
1190
1191
    def setUp(self):
1192
        super(TestReusingSavedCommitMessages, self).setUp()
1193
        self.tree = self.make_branch_and_tree('tree')
1194
        self.config = self.tree.branch.get_config()
1195
        self.config.set_user_option('per_file_commits', 'true')
1196
        self.build_tree(['tree/a', 'tree/b'])
1197
        self.tree.add(['a'], ['a-id'])
1198
        self.tree.add(['b'], ['b-id'])
1199
        rev1 = self.tree.commit('one', revprops=self._get_file_info_revprops(1))
1200
        rev2 = self.tree.commit('two', revprops=self._get_file_info_revprops(2))
1201
        uncommit.uncommit(self.tree.branch, tree=self.tree)
1202
        self.build_tree_contents([('tree/a', 'new a content\n'),
1203
                                  ('tree/b', 'new b content'),])
1204
635.2.11 by Vincent Ladeuil
Fix a leaking dialog windows appearing during the test suite.
1205
    def _get_commit_dialog(self, tree):
1206
        # Ensure we will never use a dialog that can actually prompt the user
1207
        # during the test suite. Test *can* and *should* override with the
1208
        # correct question dialog type.
1209
        dlg = commit.CommitDialog(tree)
1210
        self._set_question_no(dlg)
1211
        return dlg
1212
635.2.10 by Vincent Ladeuil
Complete tests around saved commit messages.
1213
    def test_setup_saved_messages(self):
1214
        # Check the initial setup
1215
        self.assertEquals(u'two', self._get_commit_message())
1216
        self.assertEquals(u'd4:a-id7:a msg 24:b-id7:b msg 2e',
1217
                          self._get_file_commit_messages())
1218
1219
    def test_messages_are_reloaded(self):
635.2.11 by Vincent Ladeuil
Fix a leaking dialog windows appearing during the test suite.
1220
        dlg = self._get_commit_dialog(self.tree)
635.2.10 by Vincent Ladeuil
Complete tests around saved commit messages.
1221
        self.assertEquals(u'two', dlg._get_global_commit_message())
1222
        self.assertEquals(([u'a', u'b'],
1223
                           [{ 'path': 'a',
1224
                             'file_id': 'a-id', 'message': 'a msg 2',},
1225
                           {'path': 'b',
1226
                            'file_id': 'b-id', 'message': 'b msg 2',}],),
1227
                          dlg._get_specific_files())
1228
1229
    def test_messages_are_consumed(self):
635.2.11 by Vincent Ladeuil
Fix a leaking dialog windows appearing during the test suite.
1230
        dlg = self._get_commit_dialog(self.tree)
635.2.10 by Vincent Ladeuil
Complete tests around saved commit messages.
1231
        dlg._do_commit()
1232
        self.assertEquals(u'', self._get_commit_message())
1233
        self.assertEquals(u'de', self._get_file_commit_messages())
1234
1235
    def test_messages_are_saved_on_cancel_if_required(self):
635.2.11 by Vincent Ladeuil
Fix a leaking dialog windows appearing during the test suite.
1236
        dlg = self._get_commit_dialog(self.tree)
635.2.10 by Vincent Ladeuil
Complete tests around saved commit messages.
1237
        self._set_question_yes(dlg) # Save messages
1238
        dlg._do_cancel()
1239
        self.assertEquals(u'two', self._get_commit_message())
1240
        self.assertEquals(u'd4:a-id7:a msg 24:b-id7:b msg 2e',
1241
                          self._get_file_commit_messages())
1242
1243
    def test_messages_are_cleared_on_cancel_if_required(self):
635.2.11 by Vincent Ladeuil
Fix a leaking dialog windows appearing during the test suite.
1244
        dlg = self._get_commit_dialog(self.tree)
635.2.10 by Vincent Ladeuil
Complete tests around saved commit messages.
1245
        self._set_question_no(dlg) # Don't save messages
1246
        dlg._do_cancel()
1247
        self.assertEquals(u'', self._get_commit_message())
1248
        self.assertEquals(u'de',
1249
                          self._get_file_commit_messages())