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