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