1
# Copyright (C) 2007, 2008 John Arbash Meinel <john@arbash-meinel.com>
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.
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.
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
17
"""Test the Commit functionality."""
21
from gi.repository import Gtk
29
from bzrlib.tests.features import UnicodeFilenameFeature
30
except ImportError: # bzr < 2.5
31
from bzrlib.tests import UnicodeFilenameFeature
33
from bzrlib import bencode
35
from bzrlib.util import bencode
37
from bzrlib.plugins.gtk import (
43
# TODO: All we need is basic ancestry code to test this, we shouldn't need a
44
# TestCaseWithTransport, just a TestCaseWithMemoryTransport or somesuch.
46
class TestPendingRevisions(tests.TestCaseWithTransport):
48
def test_pending_revisions_none(self):
49
tree = self.make_branch_and_tree('.')
52
self.addCleanup(tree.lock_read().unlock)
53
self.assertIs(None, commit.pending_revisions(tree))
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())
63
self.addCleanup(tree.lock_read().unlock)
64
pending_revisions = commit.pending_revisions(tree)
66
self.assertEqual(1, len(pending_revisions))
68
self.assertEqual(rev_id2, pending_revisions[0][0].revision_id)
69
# No children of this revision.
70
self.assertEqual([], pending_revisions[0][1])
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())
82
self.addCleanup(tree.lock_read().unlock)
83
pending_revisions = commit.pending_revisions(tree)
85
self.assertEqual(1, len(pending_revisions))
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)
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()
99
rev_id3 = tree2.commit('three')
100
rev_id4 = tree3.commit('four')
101
rev_id5 = tree3.commit('five')
102
tree.merge_from_branch(tree2.branch)
103
tree.merge_from_branch(tree3.branch, force=True)
104
self.assertEqual([rev_id1, rev_id3, rev_id5], tree.get_parent_ids())
106
self.addCleanup(tree.lock_read().unlock)
107
pending_revisions = commit.pending_revisions(tree)
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)
121
class Test_RevToPendingInfo(tests.TestCaseWithTransport):
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,
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',
135
'revision_id':rev_id,
139
class CommitDialogNoWidgets(commit.CommitDialog):
142
pass # Don't create any widgets here
144
def fill_in_data(self):
145
pass # With no widgets, there are no widgets to fill out
148
class TestCommitDialogSimple(tests.TestCaseWithTransport):
150
def test_setup_parameters_no_pending(self):
151
tree = self.make_branch_and_tree('tree')
152
rev_id = tree.commit('first')
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)
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)
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)
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)
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)
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'])
188
dlg = CommitDialogNoWidgets(tree)
189
self.assertIs(None, 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)
199
class TestCommitDialog(tests.TestCaseWithTransport):
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)
207
# tree is not a checkout
208
dlg = commit.CommitDialog(tree)
209
self.assertFalse(dlg._check_local.get_property('visible'))
211
# tree2 is a checkout
212
dlg2 = commit.CommitDialog(tree2)
213
self.assertTrue(dlg2._check_local.get_property('visible'))
215
def test_no_pending(self):
216
tree = self.make_branch_and_tree('tree')
217
rev_id1 = tree.commit('one')
219
dlg = commit.CommitDialog(tree)
221
self.assertFalse(dlg._pending_box.get_property('visible'))
223
commit_col = dlg._treeview_files.get_column(0)
224
self.assertEqual('Commit', commit_col.get_title())
225
renderer = commit_col.get_cells()[0]
226
self.assertTrue(renderer.get_property('activatable'))
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'))
233
def test_pending(self):
234
tree = self.make_branch_and_tree('tree')
235
rev_id1 = tree.commit('one')
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,
242
tree.merge_from_branch(tree2.branch)
244
dlg = commit.CommitDialog(tree)
246
self.assertTrue(dlg._pending_box.get_property('visible'))
248
commit_col = dlg._treeview_files.get_column(0)
249
self.assertEqual('Commit*', commit_col.get_title())
250
renderer = commit_col.get_cells()[0]
251
self.assertFalse(renderer.get_property('activatable'))
253
values = [(r[0], r[1], r[2], r[3]) for r in dlg._pending_store]
254
self.assertEqual([(rev_id2, '2007-10-01', 'Joe Foo', 'two')], values)
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'))
261
def test_pending_multiple(self):
262
tree = self.make_branch_and_tree('tree')
263
rev_id1 = tree.commit('one')
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,
270
rev_id3 = tree2.commit('three',
271
committer='Jerry Foo <jerry@foo.com>',
272
timestamp=1191264278.05,
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,
280
rev_id5 = tree3.commit('five',
281
committer='Jerry Foo <jerry@foo.com>',
282
timestamp=1191372278.05,
284
tree.merge_from_branch(tree3.branch, force=True)
286
dlg = commit.CommitDialog(tree)
287
# TODO: assert that the pending box is set to show
288
values = [(r[0], r[1], r[2], r[3]) for r in dlg._pending_store]
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'),
295
def test_filelist_added(self):
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'])
300
dlg = commit.CommitDialog(tree)
301
values = [(r[0], r[1], r[2], r[3], r[4]) for r in dlg._files_store]
302
self.assertEqual([(None, None, True, 'All Files', ''),
303
('a-id', 'a', True, 'a', 'added'),
304
('b-id', 'b', True, 'b/', 'added'),
305
('c-id', 'b/c', True, 'b/c', 'added'),
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')
314
tree.rename_one('b', 'd')
315
tree.rename_one('a', 'd/a')
317
dlg = commit.CommitDialog(tree)
318
values = [(r[0], r[1], r[2], r[3], r[4]) for r in dlg._files_store]
319
self.assertEqual([(None, None, True, 'All Files', ''),
320
('b-id', 'd', True, 'b/ => d/', 'renamed'),
321
('a-id', 'd/a', True, 'a => d/a', 'renamed'),
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')
330
self.build_tree_contents([('tree/a', 'new contents for a\n')])
332
dlg = commit.CommitDialog(tree)
333
values = [(r[0], r[1], r[2], r[3], r[4]) for r in dlg._files_store]
334
self.assertEqual([(None, None, True, 'All Files', ''),
335
('a-id', 'a', True, 'a', 'modified'),
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')
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'),
349
# 'c' is not considered renamed, because only its parent was moved, it
350
# stayed in the same directory
352
dlg = commit.CommitDialog(tree)
353
values = [(r[0], r[1], r[2], r[3], r[4]) for r in dlg._files_store]
354
self.assertEqual([(None, None, True, 'All Files', ''),
355
('b-id', 'd', True, 'b/ => d/', 'renamed'),
356
('a-id', 'd/a', True, 'a => d/a', 'renamed and modified'),
357
('c-id', 'd/c', True, 'd/c', 'modified'),
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'])
367
self.build_tree(['tree/a/'])
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
371
# tree.rename_one('b', 'c')
372
# os.remove('tree/c')
373
# self.build_tree(['tree/c/'])
375
dlg = commit.CommitDialog(tree)
376
values = [(r[0], r[1], r[2], r[3], r[4]) for r in dlg._files_store]
377
self.assertEqual([(None, None, True, 'All Files', ''),
378
('a-id', 'a', True, 'a => a/', 'kind changed'),
379
# ('b-id', 'c', True, 'b => c/', 'renamed and modified'),
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'])
389
tree.remove('b', force=True)
391
dlg = commit.CommitDialog(tree)
392
values = [(r[0], r[1], r[2], r[3], r[4]) for r in dlg._files_store]
393
self.assertEqual([(None, None, True, 'All Files', ''),
394
('a-id', 'a', True, 'a', 'removed'),
395
('b-id', 'b', True, 'b/', 'removed'),
397
# All Files should be selected
399
(Gtk.TreePath(path=0), None), dlg._treeview_files.get_cursor())
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'])
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'),
412
# This file should also be selected in the file list, rather than the
413
# 'All Files' selection
415
(Gtk.TreePath(path=1), None), dlg._treeview_files.get_cursor())
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'])
423
self.build_tree_contents([('tree/a', 'new contents for a\n')])
426
dlg = commit.CommitDialog(tree)
427
diff_buffer = dlg._diff_view.buffer
428
text = diff_buffer.get_text(diff_buffer.get_start_iter(),
429
diff_buffer.get_end_iter(),
430
True).splitlines(True)
432
self.assertEqual("=== modified file 'a'\n", text[0])
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")
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])
442
self.assertEqual("=== removed file 'b'\n", text[7])
443
self.assertContainsRe(text[8],
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])
448
self.assertEqual('\n', text[12])
450
self.assertEqual('Diff for All Files', dlg._diff_label.get_text())
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'])
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)
462
dlg._commit_selected_radio.set_active(True)
463
self.assertTrue(checked_col.get_property('visible'))
464
self.assertFalse(dlg._commit_all_changes)
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')
469
tree.branch.get_config().set_user_option('per_file_commits', 'true')
470
self.build_tree(['tree/a', 'tree/b'])
471
tree.add(['a', 'b'], ['a-id', 'b-id'])
473
dlg = commit.CommitDialog(tree)
474
diff_buffer = dlg._diff_view.buffer
475
self.assertEqual('Diff for All Files', dlg._diff_label.get_text())
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'))
481
dlg._treeview_files.set_cursor(
482
Gtk.TreePath(path=1), None, False)
483
self.assertEqual('Diff for a', dlg._diff_label.get_text())
484
text = diff_buffer.get_text(diff_buffer.get_start_iter(),
485
diff_buffer.get_end_iter(),
486
True).splitlines(True)
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])
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'))
500
dlg._treeview_files.set_cursor(
501
Gtk.TreePath(path=2), None, False)
502
self.assertEqual('Diff for b', dlg._diff_label.get_text())
503
text = diff_buffer.get_text(diff_buffer.get_start_iter(),
504
diff_buffer.get_end_iter(),
505
True).splitlines(True)
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])
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'))
519
dlg._treeview_files.set_cursor(
520
Gtk.TreePath(path=0), None, False)
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'))
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')
530
tree.branch.get_config().set_user_option('per_file_commits', 'true')
531
self.build_tree(['tree/a', 'tree/b/'])
532
tree.add(['a', 'b'], ['a-id', 'b-id'])
535
buf = dlg._file_message_text_view.get_buffer()
537
buf.get_start_iter(), buf.get_end_iter(), True)
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)
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())
550
dlg._treeview_files.set_cursor(
551
Gtk.TreePath(path=1), None, False)
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())
558
self.assertEqual('', get_saved_text(1))
559
dlg._set_file_commit_message('Some text\nfor a\n')
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))
564
dlg._treeview_files.set_cursor(
565
Gtk.TreePath(path=2), None, False)
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())
572
self.assertEqual('', get_saved_text(2))
573
dlg._set_file_commit_message('More text\nfor b\n')
574
# Now switch back to 'a'. The message should be saved, and the buffer
575
# should be updated with the other text
576
dlg._treeview_files.set_cursor(
577
Gtk.TreePath(path=1), None, False)
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())
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'])
591
dlg = commit.CommitDialog(tree)
592
self.assertEqual([(None, None, True),
595
], [(r[0], r[1], r[2]) for r in dlg._files_store])
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)
603
# renderer = column.get_cells()[0]
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),
610
], [(r[0], r[1], r[2]) for r in dlg._files_store])
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])
619
dlg._toggle_commit(None, 2, dlg._files_store)
620
self.assertEqual([(None, None, False),
621
('a-id', 'a', False),
623
], [(r[0], r[1], r[2]) for r in dlg._files_store])
625
dlg._toggle_commit(None, 0, dlg._files_store)
626
self.assertEqual([(None, None, True),
629
], [(r[0], r[1], r[2]) for r in dlg._files_store])
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'])
636
dlg = commit.CommitDialog(tree)
637
self.assertEqual((['a', 'b'], []), dlg._get_specific_files())
639
dlg._commit_selected_radio.set_active(True)
640
dlg._toggle_commit(None, 0, dlg._files_store)
641
self.assertEqual(([], []), dlg._get_specific_files())
643
dlg._toggle_commit(None, 1, dlg._files_store)
644
self.assertEqual((['a'], []), dlg._get_specific_files())
646
def test_specific_files_with_messages(self):
647
tree = self.make_branch_and_tree('tree')
648
tree.branch.get_config().set_user_option('per_file_commits', 'true')
649
self.build_tree(['tree/a_file', 'tree/b_dir/'])
650
tree.add(['a_file', 'b_dir'], ['1a-id', '0b-id'])
652
dlg = commit.CommitDialog(tree)
653
dlg._commit_selected_radio.set_active(True)
654
self.assertEqual((['a_file', 'b_dir'], []), dlg._get_specific_files())
656
dlg._treeview_files.set_cursor(
657
Gtk.TreePath(path=1), None, False)
658
dlg._set_file_commit_message('Test\nmessage\nfor a_file\n')
659
dlg._treeview_files.set_cursor(
660
Gtk.TreePath(path=2), None, False)
661
dlg._set_file_commit_message('message\nfor b_dir\n')
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())
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())
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'])
682
dlg = commit.CommitDialog(tree)
683
dlg._commit_selected_radio.set_active(True)
684
self.assertEqual((['a_file', 'b_dir'], []), dlg._get_specific_files())
686
dlg._treeview_files.set_cursor(
687
Gtk.TreePath(path=1), None, False)
688
dlg._set_file_commit_message('Test\r\nmessage\rfor a_file\n')
689
dlg._treeview_files.set_cursor(
690
Gtk.TreePath(path=2), None, False)
691
dlg._set_file_commit_message('message\r\nfor\nb_dir\r')
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())
701
class QuestionHelpers(object):
703
def _set_question_yes(self, dlg):
704
"""Set the dialog to answer YES to any questions."""
706
def _question_yes(*args, **kwargs):
707
self.questions.append(args)
708
self.questions.append('YES')
709
return Gtk.ResponseType.YES
710
dlg._question_dialog = _question_yes
712
def _set_question_no(self, dlg):
713
"""Set the dialog to answer NO to any questions."""
715
def _question_no(*args, **kwargs):
716
self.questions.append(args)
717
self.questions.append('NO')
718
return Gtk.ResponseType.NO
719
dlg._question_dialog = _question_no
722
class TestCommitDialog_Commit(tests.TestCaseWithTransport, QuestionHelpers):
723
"""Tests on the actual 'commit' button being pushed."""
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')
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)
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')
742
last_rev = tree2.last_revision()
743
self.assertEqual(last_rev, dlg.committed_revision_id)
744
self.assertEqual(rev_id1, tree.branch.last_revision())
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')
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')
758
rev = tree.branch.repository.get_revision(tree.last_revision())
759
self.assertEqual('Commit\nmessage\nfoo\n', rev.message)
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')
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)
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')
778
last_rev = tree2.last_revision()
779
self.assertEqual(last_rev, dlg.committed_revision_id)
780
self.assertEqual(last_rev, tree.branch.last_revision())
782
def test_commit_empty_message(self):
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')
788
tree.add(['b'], ['b-id'])
790
dlg = commit.CommitDialog(tree)
791
self._set_question_no(dlg)
794
[('Commit with an empty message?',
795
'You can describe your commit intent in the message.'),
798
# By saying NO, nothing should be committed.
799
self.assertEqual(rev_id, tree.last_revision())
800
self.assertIs(None, dlg.committed_revision_id)
801
self.assertTrue(dlg._global_message_text_view.get_property('is-focus'))
803
self._set_question_yes(dlg)
807
[('Commit with an empty message?',
808
'You can describe your commit intent in the message.'),
811
committed = tree.last_revision()
812
self.assertNotEqual(rev_id, committed)
813
self.assertEqual(committed, dlg.committed_revision_id)
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'])
820
dlg = commit.CommitDialog(tree)
821
dlg._set_global_commit_message('Some text\n')
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)
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')
836
dlg = commit.CommitDialog(tree)
837
dlg._set_global_commit_message('Some text\n')
839
self._set_question_no(dlg)
842
self.assertIs(None, dlg.committed_revision_id)
843
self.assertEqual(rev_id1, tree.last_revision())
845
[('Commit with no changes?',
846
'There are no changes in the working tree.'
847
' Do you want to commit anyway?'),
851
self._set_question_yes(dlg)
854
rev_id2 = tree.last_revision()
855
self.assertEqual(rev_id2, dlg.committed_revision_id)
856
self.assertNotEqual(rev_id1, rev_id2)
858
[('Commit with no changes?',
859
'There are no changes in the working tree.'
860
' Do you want to commit anyway?'),
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'])
871
dlg = commit.CommitDialog(tree)
872
dlg._set_global_commit_message('Some text\n')
873
self._set_question_no(dlg)
877
self.assertIs(None, dlg.committed_revision_id)
878
self.assertEqual(rev_id1, tree.last_revision())
880
[("Commit with unknowns?",
881
"Unknown files exist in the working tree. Commit anyway?"),
885
self._set_question_yes(dlg)
888
rev_id2 = tree.last_revision()
889
self.assertNotEqual(rev_id1, rev_id2)
890
self.assertEqual(rev_id2, dlg.committed_revision_id)
892
[("Commit with unknowns?",
893
"Unknown files exist in the working tree. Commit anyway?"),
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'])
903
dlg = commit.CommitDialog(tree)
904
dlg._commit_selected_radio.set_active(True) # enable partial
905
dlg._toggle_commit(None, 2, dlg._files_store) # unset 'b'
907
dlg._set_global_commit_message('Committing just "a"\n')
910
rev_id2 = dlg.committed_revision_id
911
self.assertIsNot(None, rev_id2)
912
self.assertEqual(rev_id2, tree.last_revision())
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)
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'])
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'
930
# Switch back to committing all changes
931
dlg._commit_all_files_radio.set_active(True)
933
dlg._set_global_commit_message('Committing everything\n')
936
rev_id2 = dlg.committed_revision_id
937
self.assertIsNot(None, rev_id2)
938
self.assertEqual(rev_id2, tree.last_revision())
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)
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'])
951
dlg = commit.CommitDialog(tree)
952
dlg._set_global_commit_message('Simple commit\n')
955
rev = tree.branch.repository.get_revision(dlg.committed_revision_id)
956
self.failIf('file-info' in rev.properties)
958
def test_commit_disabled_messages(self):
959
tree = self.make_branch_and_tree('tree')
960
rev_id1 = tree.commit('one')
962
self.build_tree(['tree/a', 'tree/b'])
963
tree.add(['a', 'b'], ['a-id', 'b-id'])
965
dlg = commit.CommitDialog(tree)
966
self.assertFalse(dlg._file_message_expander.get_property('visible'))
967
self.assertEqual('Commit Message',
968
dlg._global_message_label.get_text())
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'))
973
self.assertEqual('Global Commit Message',
974
dlg._global_message_label.get_text())
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'))
979
self.assertEqual('Global Commit Message',
980
dlg._global_message_label.get_text())
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'))
985
self.assertEqual('Global Commit Message',
986
dlg._global_message_label.get_text())
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'))
991
self.assertEqual('Commit Message',
992
dlg._global_message_label.get_text())
994
def test_commit_specific_files_with_messages(self):
995
tree = self.make_branch_and_tree('tree')
996
tree.branch.get_config().set_user_option('per_file_commits', 'true')
997
rev_id1 = tree.commit('one')
998
self.build_tree(['tree/a', 'tree/b'])
999
tree.add(['a', 'b'], ['a-id', 'b-id'])
1001
dlg = commit.CommitDialog(tree)
1002
dlg._commit_selected_radio.set_active(True) # enable partial
1003
dlg._treeview_files.set_cursor(
1004
Gtk.TreePath(path=1), None, False)
1005
dlg._set_file_commit_message('Message for A\n')
1006
dlg._treeview_files.set_cursor(
1007
Gtk.TreePath(path=2), None, False)
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"')
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']
1019
self.assertEqual(u'ld7:file_id4:a-id'
1020
'7:message14:Message for A\n'
1024
self.assertEqual([{'path':'a', 'file_id':'a-id',
1025
'message':'Message for A\n'},],
1026
bencode.bdecode(file_info.encode('UTF-8')))
1028
def test_commit_messages_after_merge(self):
1029
tree = self.make_branch_and_tree('tree')
1030
tree.branch.get_config().set_user_option('per_file_commits', 'true')
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')
1037
tree.merge_from_branch(tree2.branch)
1039
dlg = commit.CommitDialog(tree)
1040
dlg._treeview_files.set_cursor(
1041
Gtk.TreePath(path=1), None, False) # 'a'
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')
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']
1054
self.assertEqual(u'ld7:file_id4:a-id'
1055
'7:message14:Message for A\n'
1059
self.assertEqual([{'path':'a', 'file_id':'a-id',
1060
'message':'Message for A\n'},],
1061
bencode.bdecode(file_info.encode('UTF-8')))
1063
def test_commit_unicode_messages(self):
1064
self.requireFeature(UnicodeFilenameFeature)
1066
tree = self.make_branch_and_tree('tree')
1067
tree.branch.get_config().set_user_option('per_file_commits', 'true')
1068
self.build_tree(['tree/a', u'tree/\u03a9'])
1069
tree.add(['a', u'\u03a9'], ['a-id', 'omega-id'])
1071
dlg = commit.CommitDialog(tree)
1072
dlg._treeview_files.set_cursor(
1073
Gtk.TreePath(path=1), None, False) # 'a'
1074
dlg._set_file_commit_message(u'Test \xfan\xecc\xf6de\n')
1075
dlg._treeview_files.set_cursor(
1076
Gtk.TreePath(path=2), None, False) # omega
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')
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())
1089
rev = tree.branch.repository.get_revision(dlg.committed_revision_id)
1090
file_info = rev.properties['file-info'].encode('UTF-8')
1091
value = ('ld7:file_id4:a-id'
1092
'7:message16:Test \xc3\xban\xc3\xacc\xc3\xb6de\n'
1095
'd7:file_id8:omega-id'
1096
'7:message29:\xce\xa9 is the end of all things.\n'
1100
self.assertEqual(value, file_info)
1101
file_info_decoded = bencode.bdecode(file_info)
1102
for d in file_info_decoded:
1103
d['path'] = d['path'].decode('UTF-8')
1104
d['message'] = d['message'].decode('UTF-8')
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)
1113
class TestSanitizeMessage(tests.TestCase):
1115
def assertSanitize(self, expected, original):
1116
self.assertEqual(expected,
1117
commit._sanitize_and_decode_message(original))
1119
def test_untouched(self):
1120
self.assertSanitize('foo\nbar\nbaz\n', 'foo\nbar\nbaz\n')
1122
def test_converts_cr_to_lf(self):
1123
self.assertSanitize('foo\nbar\nbaz\n', 'foo\rbar\rbaz\r')
1125
def test_converts_crlf_to_lf(self):
1126
self.assertSanitize('foo\nbar\nbaz\n', 'foo\r\nbar\r\nbaz\r\n')
1128
def test_converts_mixed_to_lf(self):
1129
self.assertSanitize('foo\nbar\nbaz\n', 'foo\r\nbar\rbaz\n')
1132
class TestSavedCommitMessages(tests.TestCaseWithTransport):
1135
super(TestSavedCommitMessages, self).setUp()
1137
branch.Branch.hooks.install_named_hook(
1138
'post_uncommit', commitmsgs.save_commit_messages, None)
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)]
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')}
1149
def _get_commit_message(self):
1150
return self.config.get_user_option('gtk_global_commit_message')
1152
def _get_file_commit_messages(self):
1153
return self.config.get_user_option('gtk_file_commit_messages')
1156
class TestUncommitHook(TestSavedCommitMessages):
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'])
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',
1170
revprops=self._get_file_info_revprops(3))
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())
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())
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())
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())
1200
class TestReusingSavedCommitMessages(TestSavedCommitMessages, QuestionHelpers):
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'),])
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)
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())
1230
def test_messages_are_reloaded(self):
1231
dlg = self._get_commit_dialog(self.tree)
1232
self.assertEquals(u'two', dlg._get_global_commit_message())
1233
self.assertEquals(([u'a', u'b'],
1235
'file_id': 'a-id', 'message': 'a msg 2',},
1237
'file_id': 'b-id', 'message': 'b msg 2',}],),
1238
dlg._get_specific_files())
1240
def test_messages_are_consumed(self):
1241
dlg = self._get_commit_dialog(self.tree)
1243
self.assertEquals(u'', self._get_commit_message())
1244
self.assertEquals(u'de', self._get_file_commit_messages())
1246
def test_messages_are_saved_on_cancel_if_required(self):
1247
dlg = self._get_commit_dialog(self.tree)
1248
self._set_question_yes(dlg) # Save messages
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())
1254
def test_messages_are_cleared_on_cancel_if_required(self):
1255
dlg = self._get_commit_dialog(self.tree)
1256
self._set_question_no(dlg) # Don't save messages
1258
self.assertEquals(u'', self._get_commit_message())
1259
self.assertEquals(u'de',
1260
self._get_file_commit_messages())