/b-gtk/fix-viz

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/b-gtk/fix-viz

« back to all changes in this revision

Viewing changes to tests/test_commit.py

  • Committer: Curtis Hovey
  • Date: 2012-01-23 16:38:54 UTC
  • mto: This revision was merged to the branch mainline in revision 772.
  • Revision ID: sinzui.is@verizon.net-20120123163854-czj2d2ebx6nf1s54
Added hooks for testing.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2007 John Arbash Meinel <john@arbash-meinel.com>
 
1
# Copyright (C) 2007, 2008 John Arbash Meinel <john@arbash-meinel.com>
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
18
18
 
19
19
import os
20
20
 
21
 
import gtk
 
21
from gi.repository import Gtk
22
22
 
23
23
from bzrlib import (
 
24
    branch,
24
25
    tests,
25
 
    revision,
 
26
    uncommit,
26
27
    )
27
 
from bzrlib.util import bencode
 
28
try:
 
29
    from bzrlib.tests.features import UnicodeFilenameFeature
 
30
except ImportError: # bzr < 2.5
 
31
    from bzrlib.tests import UnicodeFilenameFeature
 
32
from bzrlib import bencode
28
33
 
29
 
from bzrlib.plugins.gtk import commit
 
34
from bzrlib.plugins.gtk import (
 
35
    commit,
 
36
    commitmsgs,
 
37
    )
 
38
from bzrlib.plugins.gtk.commitmsgs import SavedCommitMessagesManager
30
39
 
31
40
 
32
41
# TODO: All we need is basic ancestry code to test this, we shouldn't need a
38
47
        tree = self.make_branch_and_tree('.')
39
48
        tree.commit('one')
40
49
 
 
50
        self.addCleanup(tree.lock_read().unlock)
41
51
        self.assertIs(None, commit.pending_revisions(tree))
42
52
 
43
53
    def test_pending_revisions_simple(self):
48
58
        tree.merge_from_branch(tree2.branch)
49
59
        self.assertEqual([rev_id1, rev_id2], tree.get_parent_ids())
50
60
 
 
61
        self.addCleanup(tree.lock_read().unlock)
51
62
        pending_revisions = commit.pending_revisions(tree)
52
63
        # One primary merge
53
64
        self.assertEqual(1, len(pending_revisions))
66
77
        tree.merge_from_branch(tree2.branch)
67
78
        self.assertEqual([rev_id1, rev_id4], tree.get_parent_ids())
68
79
 
 
80
        self.addCleanup(tree.lock_read().unlock)
69
81
        pending_revisions = commit.pending_revisions(tree)
70
82
        # One primary merge
71
83
        self.assertEqual(1, len(pending_revisions))
86
98
        rev_id4 = tree3.commit('four')
87
99
        rev_id5 = tree3.commit('five')
88
100
        tree.merge_from_branch(tree2.branch)
89
 
        tree.merge_from_branch(tree3.branch)
 
101
        tree.merge_from_branch(tree3.branch, force=True)
90
102
        self.assertEqual([rev_id1, rev_id3, rev_id5], tree.get_parent_ids())
91
103
 
 
104
        self.addCleanup(tree.lock_read().unlock)
92
105
        pending_revisions = commit.pending_revisions(tree)
93
106
        # Two primary merges
94
107
        self.assertEqual(2, len(pending_revisions))
130
143
        pass # With no widgets, there are no widgets to fill out
131
144
 
132
145
 
 
146
class MockMethod():
 
147
 
 
148
    @classmethod
 
149
    def bind(klass, test_instance, obj, method_name):
 
150
        original_method = getattr(obj, method_name)
 
151
        test_instance.addCleanup(setattr, obj, method_name, original_method)
 
152
        setattr(obj, method_name, klass())
 
153
 
 
154
    def __init__(self):
 
155
        self.called = False
 
156
        self.args = None
 
157
        self.kwargs = None
 
158
 
 
159
    def __call__(self, *args, **kwargs):
 
160
        self.called = True
 
161
        self.args = args
 
162
        self.kwargs = kwargs
 
163
 
 
164
 
133
165
class TestCommitDialogSimple(tests.TestCaseWithTransport):
134
166
 
 
167
    def test_init(self):
 
168
        MockMethod.bind(self, CommitDialogNoWidgets, 'setup_params')
 
169
        MockMethod.bind(self, CommitDialogNoWidgets, 'construct')
 
170
        MockMethod.bind(self, CommitDialogNoWidgets, 'fill_in_data')
 
171
 
 
172
        tree = self.make_branch_and_tree('tree')
 
173
        rev_id = tree.commit('first')
 
174
        dlg = CommitDialogNoWidgets(tree)
 
175
        self.assertIs(tree, dlg._wt)
 
176
        self.assertIs(None, dlg._selected)
 
177
        self.assertTrue(dlg._enable_per_file_commits)
 
178
        self.assertTrue(dlg._commit_all_changes)
 
179
        self.assertIs(None, dlg.committed_revision_id)
 
180
        self.assertIs(None, dlg._last_selected_file)
 
181
        self.assertIsInstance(
 
182
            dlg._saved_commit_messages_manager, SavedCommitMessagesManager)
 
183
        self.assertTrue(CommitDialogNoWidgets.setup_params.called)
 
184
        self.assertTrue(CommitDialogNoWidgets.construct.called)
 
185
        self.assertTrue(CommitDialogNoWidgets.fill_in_data.called)
 
186
 
135
187
    def test_setup_parameters_no_pending(self):
136
188
        tree = self.make_branch_and_tree('tree')
137
189
        rev_id = tree.commit('first')
180
232
        self.assertEqual([], delta.removed)
181
233
        self.assertEqual([(u'a', 'a-id', 'file')], delta.added)
182
234
 
 
235
    def test_on_treeview_files_cursor_changed_no_selection(self):
 
236
        MockMethod.bind(self, CommitDialogNoWidgets, '_update_per_file_info')
 
237
        tree = self.make_branch_and_tree('tree')
 
238
        rev_id = tree.commit('first')
 
239
        dlg = CommitDialogNoWidgets(tree)
 
240
        treeview = Gtk.TreeView()
 
241
        dlg._on_treeview_files_cursor_changed(treeview)
 
242
        self.assertFalse(CommitDialogNoWidgets._update_per_file_info.called)
 
243
 
 
244
    def test_on_treeview_files_cursor_changed_with_destroyed_treeview(self):
 
245
        MockMethod.bind(self, CommitDialogNoWidgets, '_update_per_file_info')
 
246
        tree = self.make_branch_and_tree('tree')
 
247
        rev_id = tree.commit('first')
 
248
        dlg = CommitDialogNoWidgets(tree)
 
249
        treeview = Gtk.TreeView()
 
250
        treeview.destroy()
 
251
        dlg._on_treeview_files_cursor_changed(treeview)
 
252
        self.assertFalse(CommitDialogNoWidgets._update_per_file_info.called)
 
253
 
183
254
 
184
255
class TestCommitDialog(tests.TestCaseWithTransport):
185
256
 
207
278
 
208
279
        commit_col = dlg._treeview_files.get_column(0)
209
280
        self.assertEqual('Commit', commit_col.get_title())
210
 
        renderer = commit_col.get_cell_renderers()[0]
 
281
        renderer = commit_col.get_cells()[0]
211
282
        self.assertTrue(renderer.get_property('activatable'))
212
283
 
213
284
        self.assertEqual('Commit all changes',
232
303
 
233
304
        commit_col = dlg._treeview_files.get_column(0)
234
305
        self.assertEqual('Commit*', commit_col.get_title())
235
 
        renderer = commit_col.get_cell_renderers()[0]
 
306
        renderer = commit_col.get_cells()[0]
236
307
        self.assertFalse(renderer.get_property('activatable'))
237
308
 
238
309
        values = [(r[0], r[1], r[2], r[3]) for r in dlg._pending_store]
266
337
                               committer='Jerry Foo <jerry@foo.com>',
267
338
                               timestamp=1191372278.05,
268
339
                               timezone=+7200)
269
 
        tree.merge_from_branch(tree3.branch)
 
340
        tree.merge_from_branch(tree3.branch, force=True)
270
341
 
271
342
        dlg = commit.CommitDialog(tree)
272
343
        # TODO: assert that the pending box is set to show
284
355
 
285
356
        dlg = commit.CommitDialog(tree)
286
357
        values = [(r[0], r[1], r[2], r[3], r[4]) for r in dlg._files_store]
287
 
        self.assertEqual([(None, None, True, 'All Files', ''),
 
358
        self.assertEqual([("", "", True, 'All Files', ''),
288
359
                          ('a-id', 'a', True, 'a', 'added'),
289
360
                          ('b-id', 'b', True, 'b/', 'added'),
290
361
                          ('c-id', 'b/c', True, 'b/c', 'added'),
301
372
 
302
373
        dlg = commit.CommitDialog(tree)
303
374
        values = [(r[0], r[1], r[2], r[3], r[4]) for r in dlg._files_store]
304
 
        self.assertEqual([(None, None, True, 'All Files', ''),
 
375
        self.assertEqual([("", "", True, 'All Files', ''),
305
376
                          ('b-id', 'd', True, 'b/ => d/', 'renamed'),
306
377
                          ('a-id', 'd/a', True, 'a => d/a', 'renamed'),
307
378
                         ], values)
316
387
 
317
388
        dlg = commit.CommitDialog(tree)
318
389
        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', ''),
 
390
        self.assertEqual([("", "", True, 'All Files', ''),
320
391
                          ('a-id', 'a', True, 'a', 'modified'),
321
392
                         ], values)
322
393
 
336
407
 
337
408
        dlg = commit.CommitDialog(tree)
338
409
        values = [(r[0], r[1], r[2], r[3], r[4]) for r in dlg._files_store]
339
 
        self.assertEqual([(None, None, True, 'All Files', ''),
 
410
        self.assertEqual([("", "", True, 'All Files', ''),
340
411
                          ('b-id', 'd', True, 'b/ => d/', 'renamed'),
341
412
                          ('a-id', 'd/a', True, 'a => d/a', 'renamed and modified'),
342
413
                          ('c-id', 'd/c', True, 'd/c', 'modified'),
359
430
 
360
431
        dlg = commit.CommitDialog(tree)
361
432
        values = [(r[0], r[1], r[2], r[3], r[4]) for r in dlg._files_store]
362
 
        self.assertEqual([(None, None, True, 'All Files', ''),
 
433
        self.assertEqual([("", "", True, 'All Files', ''),
363
434
                          ('a-id', 'a', True, 'a => a/', 'kind changed'),
364
435
                          # ('b-id', 'c', True, 'b => c/', 'renamed and modified'),
365
436
                         ], values)
375
446
 
376
447
        dlg = commit.CommitDialog(tree)
377
448
        values = [(r[0], r[1], r[2], r[3], r[4]) for r in dlg._files_store]
378
 
        self.assertEqual([(None, None, True, 'All Files', ''),
 
449
        self.assertEqual([("", "", True, 'All Files', ''),
379
450
                          ('a-id', 'a', True, 'a', 'removed'),
380
451
                          ('b-id', 'b', True, 'b/', 'removed'),
381
452
                         ], values)
382
453
        # All Files should be selected
383
 
        self.assertEqual(((0,), None), dlg._treeview_files.get_cursor())
 
454
        self.assertEqual(
 
455
            (Gtk.TreePath(path=0), None), dlg._treeview_files.get_cursor())
384
456
 
385
457
    def test_filelist_with_selected(self):
386
458
        tree = self.make_branch_and_tree('tree')
389
461
 
390
462
        dlg = commit.CommitDialog(tree, selected='a')
391
463
        values = [(r[0], r[1], r[2], r[3], r[4]) for r in dlg._files_store]
392
 
        self.assertEqual([(None, None, False, 'All Files', ''),
 
464
        self.assertEqual([("", "", False, 'All Files', ''),
393
465
                          ('a-id', 'a', True, 'a', 'added'),
394
466
                          ('b-id', 'b', False, 'b/', 'added'),
395
467
                         ], values)
396
468
        # This file should also be selected in the file list, rather than the
397
469
        # 'All Files' selection
398
 
        self.assertEqual(((1,), None), dlg._treeview_files.get_cursor())
 
470
        self.assertEqual(
 
471
            (Gtk.TreePath(path=1), None), dlg._treeview_files.get_cursor())
399
472
 
400
473
    def test_diff_view(self):
401
474
        tree = self.make_branch_and_tree('tree')
409
482
        dlg = commit.CommitDialog(tree)
410
483
        diff_buffer = dlg._diff_view.buffer
411
484
        text = diff_buffer.get_text(diff_buffer.get_start_iter(),
412
 
                                    diff_buffer.get_end_iter()).splitlines(True)
 
485
                                    diff_buffer.get_end_iter(),
 
486
                                    True).splitlines(True)
413
487
 
414
488
        self.assertEqual("=== modified file 'a'\n", text[0])
415
489
        self.assertContainsRe(text[1],
460
534
        self.assertFalse(dlg._file_message_expander.get_expanded())
461
535
        self.assertFalse(dlg._file_message_expander.get_property('sensitive'))
462
536
 
463
 
        dlg._treeview_files.set_cursor((1,))
 
537
        dlg._treeview_files.set_cursor(
 
538
            Gtk.TreePath(path=1), None, False)
464
539
        self.assertEqual('Diff for a', dlg._diff_label.get_text())
465
540
        text = diff_buffer.get_text(diff_buffer.get_start_iter(),
466
 
                                    diff_buffer.get_end_iter()).splitlines(True)
 
541
                                    diff_buffer.get_end_iter(),
 
542
                                    True).splitlines(True)
467
543
        self.assertEqual("=== added file 'a'\n", text[0])
468
544
        self.assertContainsRe(text[1],
469
545
            r"--- a\t\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d [+-]\d\d\d\d")
477
553
        self.assertTrue(dlg._file_message_expander.get_expanded())
478
554
        self.assertTrue(dlg._file_message_expander.get_property('sensitive'))
479
555
 
480
 
        dlg._treeview_files.set_cursor((2,))
 
556
        dlg._treeview_files.set_cursor(
 
557
            Gtk.TreePath(path=2), None, False)
481
558
        self.assertEqual('Diff for b', dlg._diff_label.get_text())
482
559
        text = diff_buffer.get_text(diff_buffer.get_start_iter(),
483
 
                                    diff_buffer.get_end_iter()).splitlines(True)
 
560
                                    diff_buffer.get_end_iter(),
 
561
                                    True).splitlines(True)
484
562
        self.assertEqual("=== added file 'b'\n", text[0])
485
563
        self.assertContainsRe(text[1],
486
564
            r"--- b\t\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d [+-]\d\d\d\d")
494
572
        self.assertTrue(dlg._file_message_expander.get_expanded())
495
573
        self.assertTrue(dlg._file_message_expander.get_property('sensitive'))
496
574
 
497
 
        dlg._treeview_files.set_cursor((0,))
 
575
        dlg._treeview_files.set_cursor(
 
576
            Gtk.TreePath(path=0), None, False)
498
577
        self.assertEqual('Diff for All Files', dlg._diff_label.get_text())
499
578
        self.assertEqual('File commit message',
500
579
                         dlg._file_message_expander.get_label())
510
589
 
511
590
        def get_file_text():
512
591
            buf = dlg._file_message_text_view.get_buffer()
513
 
            return buf.get_text(buf.get_start_iter(), buf.get_end_iter())
 
592
            return buf.get_text(
 
593
                buf.get_start_iter(), buf.get_end_iter(), True)
514
594
 
515
595
        def get_saved_text(path):
516
596
            """Get the saved text for a given record."""
523
603
        self.assertFalse(dlg._file_message_expander.get_property('sensitive'))
524
604
        self.assertEqual('', get_file_text())
525
605
 
526
 
        dlg._treeview_files.set_cursor((1,))
 
606
        dlg._treeview_files.set_cursor(
 
607
            Gtk.TreePath(path=1), None, False)
527
608
        self.assertEqual('Commit message for a',
528
609
                         dlg._file_message_expander.get_label())
529
610
        self.assertTrue(dlg._file_message_expander.get_expanded())
536
617
        # We should have updated the ListStore with the new file commit info
537
618
        self.assertEqual('Some text\nfor a\n', get_saved_text(1))
538
619
 
539
 
        dlg._treeview_files.set_cursor((2,))
 
620
        dlg._treeview_files.set_cursor(
 
621
            Gtk.TreePath(path=2), None, False)
540
622
        self.assertEqual('Commit message for b/',
541
623
                         dlg._file_message_expander.get_label())
542
624
        self.assertTrue(dlg._file_message_expander.get_expanded())
547
629
        dlg._set_file_commit_message('More text\nfor b\n')
548
630
        # Now switch back to 'a'. The message should be saved, and the buffer
549
631
        # should be updated with the other text
550
 
        dlg._treeview_files.set_cursor((1,))
 
632
        dlg._treeview_files.set_cursor(
 
633
            Gtk.TreePath(path=1), None, False)
551
634
        self.assertEqual('More text\nfor b\n', get_saved_text(2))
552
635
        self.assertEqual('Commit message for a',
553
636
                         dlg._file_message_expander.get_label())
562
645
        tree.add(['a', 'b'], ['a-id', 'b-id'])
563
646
 
564
647
        dlg = commit.CommitDialog(tree)
565
 
        self.assertEqual([(None, None, True),
 
648
        self.assertEqual([("", "", True),
566
649
                          ('a-id', 'a', True),
567
650
                          ('b-id', 'b', True),
568
651
                         ], [(r[0], r[1], r[2]) for r in dlg._files_store])
573
656
        #       do with. So instead, we just call toggle directly, and assume
574
657
        #       that toggle is hooked in correctly
575
658
        # column = dlg._treeview_files.get_column(0)
576
 
        # renderer = column.get_cell_renderers()[0]
 
659
        # renderer = column.get_cells()[0]
577
660
 
578
661
        # Toggle a single entry should set just that entry to False
579
662
        dlg._toggle_commit(None, 1, dlg._files_store)
580
 
        self.assertEqual([(None, None, True),
 
663
        self.assertEqual([("", "", True),
581
664
                          ('a-id', 'a', False),
582
665
                          ('b-id', 'b', True),
583
666
                         ], [(r[0], r[1], r[2]) for r in dlg._files_store])
584
667
 
585
668
        # Toggling the main entry should set all entries
586
669
        dlg._toggle_commit(None, 0, dlg._files_store)
587
 
        self.assertEqual([(None, None, False),
 
670
        self.assertEqual([("", "", False),
588
671
                          ('a-id', 'a', False),
589
672
                          ('b-id', 'b', False),
590
673
                         ], [(r[0], r[1], r[2]) for r in dlg._files_store])
591
674
 
592
675
        dlg._toggle_commit(None, 2, dlg._files_store)
593
 
        self.assertEqual([(None, None, False),
 
676
        self.assertEqual([("", "", False),
594
677
                          ('a-id', 'a', False),
595
678
                          ('b-id', 'b', True),
596
679
                         ], [(r[0], r[1], r[2]) for r in dlg._files_store])
597
680
 
598
681
        dlg._toggle_commit(None, 0, dlg._files_store)
599
 
        self.assertEqual([(None, None, True),
 
682
        self.assertEqual([("", "", True),
600
683
                          ('a-id', 'a', True),
601
684
                          ('b-id', 'b', True),
602
685
                         ], [(r[0], r[1], r[2]) for r in dlg._files_store])
626
709
        dlg._commit_selected_radio.set_active(True)
627
710
        self.assertEqual((['a_file', 'b_dir'], []), dlg._get_specific_files())
628
711
 
629
 
        dlg._treeview_files.set_cursor((1,))
 
712
        dlg._treeview_files.set_cursor(
 
713
            Gtk.TreePath(path=1), None, False)
630
714
        dlg._set_file_commit_message('Test\nmessage\nfor a_file\n')
631
 
        dlg._treeview_files.set_cursor((2,))
 
715
        dlg._treeview_files.set_cursor(
 
716
            Gtk.TreePath(path=2), None, False)
632
717
        dlg._set_file_commit_message('message\nfor b_dir\n')
633
718
 
634
719
        self.assertEqual((['a_file', 'b_dir'],
644
729
                            'message':'message\nfor b_dir\n'},
645
730
                          ]), dlg._get_specific_files())
646
731
 
647
 
 
648
 
class TestCommitDialog_Commit(tests.TestCaseWithTransport):
649
 
    """Tests on the actual 'commit' button being pushed."""
 
732
    def test_specific_files_sanitizes_messages(self):
 
733
        tree = self.make_branch_and_tree('tree')
 
734
        tree.branch.get_config().set_user_option('per_file_commits', 'true')
 
735
        self.build_tree(['tree/a_file', 'tree/b_dir/'])
 
736
        tree.add(['a_file', 'b_dir'], ['1a-id', '0b-id'])
 
737
 
 
738
        dlg = commit.CommitDialog(tree)
 
739
        dlg._commit_selected_radio.set_active(True)
 
740
        self.assertEqual((['a_file', 'b_dir'], []), dlg._get_specific_files())
 
741
 
 
742
        dlg._treeview_files.set_cursor(
 
743
            Gtk.TreePath(path=1), None, False)
 
744
        dlg._set_file_commit_message('Test\r\nmessage\rfor a_file\n')
 
745
        dlg._treeview_files.set_cursor(
 
746
            Gtk.TreePath(path=2), None, False)
 
747
        dlg._set_file_commit_message('message\r\nfor\nb_dir\r')
 
748
 
 
749
        self.assertEqual((['a_file', 'b_dir'],
 
750
                          [{'path':'a_file', 'file_id':'1a-id',
 
751
                            'message':'Test\nmessage\nfor a_file\n'},
 
752
                           {'path':'b_dir', 'file_id':'0b-id',
 
753
                            'message':'message\nfor\nb_dir\n'},
 
754
                          ]), dlg._get_specific_files())
 
755
 
 
756
 
 
757
class QuestionHelpers(object):
650
758
 
651
759
    def _set_question_yes(self, dlg):
652
760
        """Set the dialog to answer YES to any questions."""
653
761
        self.questions = []
654
 
        def _question_yes(*args):
 
762
        def _question_yes(*args, **kwargs):
655
763
            self.questions.append(args)
656
764
            self.questions.append('YES')
657
 
            return gtk.RESPONSE_YES
 
765
            return Gtk.ResponseType.YES
658
766
        dlg._question_dialog = _question_yes
659
767
 
660
768
    def _set_question_no(self, dlg):
661
769
        """Set the dialog to answer NO to any questions."""
662
770
        self.questions = []
663
 
        def _question_no(*args):
 
771
        def _question_no(*args, **kwargs):
664
772
            self.questions.append(args)
665
773
            self.questions.append('NO')
666
 
            return gtk.RESPONSE_NO
 
774
            return Gtk.ResponseType.NO
667
775
        dlg._question_dialog = _question_no
668
776
 
 
777
 
 
778
class TestCommitDialog_Commit(tests.TestCaseWithTransport, QuestionHelpers):
 
779
    """Tests on the actual 'commit' button being pushed."""
 
780
 
669
781
    def test_bound_commit_local(self):
670
782
        tree = self.make_branch_and_tree('tree')
671
783
        self.build_tree(['tree/a'])
687
799
        self.assertEqual(last_rev, dlg.committed_revision_id)
688
800
        self.assertEqual(rev_id1, tree.branch.last_revision())
689
801
 
 
802
    def test_commit_global_sanitizes_message(self):
 
803
        tree = self.make_branch_and_tree('tree')
 
804
        self.build_tree(['tree/a'])
 
805
        tree.add(['a'], ['a-id'])
 
806
        rev_id1 = tree.commit('one')
 
807
 
 
808
        self.build_tree(['tree/b'])
 
809
        tree.add(['b'], ['b-id'])
 
810
        dlg = commit.CommitDialog(tree)
 
811
        # With the check box set, it should only effect the local branch
 
812
        dlg._set_global_commit_message('Commit\r\nmessage\rfoo\n')
 
813
        dlg._do_commit()
 
814
        rev = tree.branch.repository.get_revision(tree.last_revision())
 
815
        self.assertEqual('Commit\nmessage\nfoo\n', rev.message)
 
816
 
690
817
    def test_bound_commit_both(self):
691
818
        tree = self.make_branch_and_tree('tree')
692
819
        self.build_tree(['tree/a'])
708
835
        self.assertEqual(last_rev, dlg.committed_revision_id)
709
836
        self.assertEqual(last_rev, tree.branch.last_revision())
710
837
 
711
 
    def test_commit_no_message(self):
 
838
    def test_commit_empty_message(self):
712
839
        tree = self.make_branch_and_tree('tree')
713
840
        self.build_tree(['tree/a', 'tree/b'])
714
841
        tree.add(['a'], ['a-id'])
929
1056
 
930
1057
        dlg = commit.CommitDialog(tree)
931
1058
        dlg._commit_selected_radio.set_active(True) # enable partial
932
 
        dlg._treeview_files.set_cursor((1,))
 
1059
        dlg._treeview_files.set_cursor(
 
1060
            Gtk.TreePath(path=1), None, False)
933
1061
        dlg._set_file_commit_message('Message for A\n')
934
 
        dlg._treeview_files.set_cursor((2,))
 
1062
        dlg._treeview_files.set_cursor(
 
1063
            Gtk.TreePath(path=2), None, False)
935
1064
        dlg._set_file_commit_message('Message for B\n')
936
1065
        dlg._toggle_commit(None, 2, dlg._files_store) # unset 'b'
937
1066
        dlg._set_global_commit_message('Commit just "a"')
943
1072
        rev = tree.branch.repository.get_revision(rev_id2)
944
1073
        self.assertEqual('Commit just "a"', rev.message)
945
1074
        file_info = rev.properties['file-info']
946
 
        self.assertEqual('ld7:file_id4:a-id'
947
 
                           '7:message14:Message for A\n'
948
 
                           '4:path1:a'
949
 
                         'ee', file_info)
 
1075
        self.assertEqual(u'ld7:file_id4:a-id'
 
1076
                         '7:message14:Message for A\n'
 
1077
                         '4:path1:a'
 
1078
                         'ee',
 
1079
                         file_info)
950
1080
        self.assertEqual([{'path':'a', 'file_id':'a-id',
951
 
                           'message':'Message for A\n'},
952
 
                         ], bencode.bdecode(file_info))
 
1081
                           'message':'Message for A\n'},],
 
1082
                         bencode.bdecode(file_info.encode('UTF-8')))
953
1083
 
954
1084
    def test_commit_messages_after_merge(self):
955
1085
        tree = self.make_branch_and_tree('tree')
963
1093
        tree.merge_from_branch(tree2.branch)
964
1094
 
965
1095
        dlg = commit.CommitDialog(tree)
966
 
        dlg._treeview_files.set_cursor((1,)) # 'a'
 
1096
        dlg._treeview_files.set_cursor(
 
1097
            Gtk.TreePath(path=1), None, False) # 'a'
967
1098
        dlg._set_file_commit_message('Message for A\n')
968
1099
        # No message for 'B'
969
1100
        dlg._set_global_commit_message('Merging from "tree2"\n')
976
1107
        self.assertEqual('Merging from "tree2"\n', rev.message)
977
1108
        self.assertEqual([rev_id1, rev_id2], rev.parent_ids)
978
1109
        file_info = rev.properties['file-info']
979
 
        self.assertEqual('ld7:file_id4:a-id'
980
 
                           '7:message14:Message for A\n'
981
 
                           '4:path1:a'
982
 
                         'ee', file_info)
 
1110
        self.assertEqual(u'ld7:file_id4:a-id'
 
1111
                         '7:message14:Message for A\n'
 
1112
                         '4:path1:a'
 
1113
                         'ee',
 
1114
                         file_info)
983
1115
        self.assertEqual([{'path':'a', 'file_id':'a-id',
984
 
                           'message':'Message for A\n'},
985
 
                         ], bencode.bdecode(file_info))
 
1116
                           'message':'Message for A\n'},],
 
1117
                         bencode.bdecode(file_info.encode('UTF-8')))
986
1118
 
987
1119
    def test_commit_unicode_messages(self):
988
 
        self.requireFeature(tests.UnicodeFilenameFeature)
 
1120
        self.requireFeature(UnicodeFilenameFeature)
989
1121
 
990
1122
        tree = self.make_branch_and_tree('tree')
991
1123
        tree.branch.get_config().set_user_option('per_file_commits', 'true')
993
1125
        tree.add(['a', u'\u03a9'], ['a-id', 'omega-id'])
994
1126
 
995
1127
        dlg = commit.CommitDialog(tree)
996
 
        dlg._treeview_files.set_cursor((1,)) # 'a'
 
1128
        dlg._treeview_files.set_cursor(
 
1129
            Gtk.TreePath(path=1), None, False) # 'a'
997
1130
        dlg._set_file_commit_message(u'Test \xfan\xecc\xf6de\n')
998
 
        dlg._treeview_files.set_cursor((2,)) # omega
 
1131
        dlg._treeview_files.set_cursor(
 
1132
            Gtk.TreePath(path=2), None, False) # omega
999
1133
        dlg._set_file_commit_message(u'\u03a9 is the end of all things.\n')
1000
1134
        dlg._set_global_commit_message(u'\u03a9 and \xfan\xecc\xf6de\n')
1001
1135
 
1030
1164
                          {'path':u'\u03a9', 'file_id':'omega-id',
1031
1165
                           'message':u'\u03a9 is the end of all things.\n'},
1032
1166
                         ], file_info_decoded)
 
1167
 
 
1168
 
 
1169
class TestSanitizeMessage(tests.TestCase):
 
1170
 
 
1171
    def assertSanitize(self, expected, original):
 
1172
        self.assertEqual(expected,
 
1173
                         commit._sanitize_and_decode_message(original))
 
1174
 
 
1175
    def test_untouched(self):
 
1176
        self.assertSanitize('foo\nbar\nbaz\n', 'foo\nbar\nbaz\n')
 
1177
 
 
1178
    def test_converts_cr_to_lf(self):
 
1179
        self.assertSanitize('foo\nbar\nbaz\n', 'foo\rbar\rbaz\r')
 
1180
 
 
1181
    def test_converts_crlf_to_lf(self):
 
1182
        self.assertSanitize('foo\nbar\nbaz\n', 'foo\r\nbar\r\nbaz\r\n')
 
1183
 
 
1184
    def test_converts_mixed_to_lf(self):
 
1185
        self.assertSanitize('foo\nbar\nbaz\n', 'foo\r\nbar\rbaz\n')
 
1186
 
 
1187
 
 
1188
class TestSavedCommitMessages(tests.TestCaseWithTransport):
 
1189
 
 
1190
    def setUp(self):
 
1191
        super(TestSavedCommitMessages, self).setUp()
 
1192
        # Install our hook
 
1193
        branch.Branch.hooks.install_named_hook(
 
1194
            'post_uncommit', commitmsgs.save_commit_messages, None)
 
1195
 
 
1196
    def _get_file_info_dict(self, rank):
 
1197
        file_info = [dict(path='a', file_id='a-id', message='a msg %d' % rank),
 
1198
                     dict(path='b', file_id='b-id', message='b msg %d' % rank)]
 
1199
        return file_info
 
1200
 
 
1201
    def _get_file_info_revprops(self, rank):
 
1202
        file_info_prop = self._get_file_info_dict(rank)
 
1203
        return {'file-info': bencode.bencode(file_info_prop).decode('UTF-8')}
 
1204
 
 
1205
    def _get_commit_message(self):
 
1206
        return self.config.get_user_option('gtk_global_commit_message')
 
1207
 
 
1208
    def _get_file_commit_messages(self):
 
1209
        return self.config.get_user_option('gtk_file_commit_messages')
 
1210
 
 
1211
 
 
1212
class TestUncommitHook(TestSavedCommitMessages):
 
1213
 
 
1214
    def setUp(self):
 
1215
        super(TestUncommitHook, self).setUp()
 
1216
        self.tree = self.make_branch_and_tree('tree')
 
1217
        self.config = self.tree.branch.get_config()
 
1218
        self.build_tree(['tree/a', 'tree/b'])
 
1219
        self.tree.add(['a'], ['a-id'])
 
1220
        self.tree.add(['b'], ['b-id'])
 
1221
        rev1 = self.tree.commit('one', rev_id='one-id',
 
1222
                                revprops=self._get_file_info_revprops(1))
 
1223
        rev2 = self.tree.commit('two', rev_id='two-id',
 
1224
                                revprops=self._get_file_info_revprops(2))
 
1225
        rev3 = self.tree.commit('three', rev_id='three-id',
 
1226
                                revprops=self._get_file_info_revprops(3))
 
1227
 
 
1228
    def test_uncommit_one_by_one(self):
 
1229
        uncommit.uncommit(self.tree.branch, tree=self.tree)
 
1230
        self.assertEquals(u'three', self._get_commit_message())
 
1231
        self.assertEquals(u'd4:a-id7:a msg 34:b-id7:b msg 3e',
 
1232
                          self._get_file_commit_messages())
 
1233
 
 
1234
        uncommit.uncommit(self.tree.branch, tree=self.tree)
 
1235
        self.assertEquals(u'two\n******\nthree', self._get_commit_message())
 
1236
        self.assertEquals(u'd4:a-id22:a msg 2\n******\na msg 3'
 
1237
                          '4:b-id22:b msg 2\n******\nb msg 3e',
 
1238
                          self._get_file_commit_messages())
 
1239
 
 
1240
        uncommit.uncommit(self.tree.branch, tree=self.tree)
 
1241
        self.assertEquals(u'one\n******\ntwo\n******\nthree',
 
1242
                          self._get_commit_message())
 
1243
        self.assertEquals(u'd4:a-id37:a msg 1\n******\na msg 2\n******\na msg 3'
 
1244
                          '4:b-id37:b msg 1\n******\nb msg 2\n******\nb msg 3e',
 
1245
                          self._get_file_commit_messages())
 
1246
 
 
1247
    def test_uncommit_all_at_once(self):
 
1248
        uncommit.uncommit(self.tree.branch, tree=self.tree, revno=1)
 
1249
        self.assertEquals(u'one\n******\ntwo\n******\nthree',
 
1250
                          self._get_commit_message())
 
1251
        self.assertEquals(u'd4:a-id37:a msg 1\n******\na msg 2\n******\na msg 3'
 
1252
                          '4:b-id37:b msg 1\n******\nb msg 2\n******\nb msg 3e',
 
1253
                          self._get_file_commit_messages())
 
1254
 
 
1255
 
 
1256
class TestReusingSavedCommitMessages(TestSavedCommitMessages, QuestionHelpers):
 
1257
 
 
1258
    def setUp(self):
 
1259
        super(TestReusingSavedCommitMessages, self).setUp()
 
1260
        self.tree = self.make_branch_and_tree('tree')
 
1261
        self.config = self.tree.branch.get_config()
 
1262
        self.config.set_user_option('per_file_commits', 'true')
 
1263
        self.build_tree(['tree/a', 'tree/b'])
 
1264
        self.tree.add(['a'], ['a-id'])
 
1265
        self.tree.add(['b'], ['b-id'])
 
1266
        rev1 = self.tree.commit('one', revprops=self._get_file_info_revprops(1))
 
1267
        rev2 = self.tree.commit('two', revprops=self._get_file_info_revprops(2))
 
1268
        uncommit.uncommit(self.tree.branch, tree=self.tree)
 
1269
        self.build_tree_contents([('tree/a', 'new a content\n'),
 
1270
                                  ('tree/b', 'new b content'),])
 
1271
 
 
1272
    def _get_commit_dialog(self, tree):
 
1273
        # Ensure we will never use a dialog that can actually prompt the user
 
1274
        # during the test suite. Test *can* and *should* override with the
 
1275
        # correct question dialog type.
 
1276
        dlg = commit.CommitDialog(tree)
 
1277
        self._set_question_no(dlg)
 
1278
        return dlg
 
1279
 
 
1280
    def test_setup_saved_messages(self):
 
1281
        # Check the initial setup
 
1282
        self.assertEquals(u'two', self._get_commit_message())
 
1283
        self.assertEquals(u'd4:a-id7:a msg 24:b-id7:b msg 2e',
 
1284
                          self._get_file_commit_messages())
 
1285
 
 
1286
    def test_messages_are_reloaded(self):
 
1287
        dlg = self._get_commit_dialog(self.tree)
 
1288
        self.assertEquals(u'two', dlg._get_global_commit_message())
 
1289
        self.assertEquals(([u'a', u'b'],
 
1290
                           [{ 'path': 'a',
 
1291
                             'file_id': 'a-id', 'message': 'a msg 2',},
 
1292
                           {'path': 'b',
 
1293
                            'file_id': 'b-id', 'message': 'b msg 2',}],),
 
1294
                          dlg._get_specific_files())
 
1295
 
 
1296
    def test_messages_are_consumed(self):
 
1297
        dlg = self._get_commit_dialog(self.tree)
 
1298
        dlg._do_commit()
 
1299
        self.assertEquals(u'', self._get_commit_message())
 
1300
        self.assertEquals(u'de', self._get_file_commit_messages())
 
1301
 
 
1302
    def test_messages_are_saved_on_cancel_if_required(self):
 
1303
        dlg = self._get_commit_dialog(self.tree)
 
1304
        self._set_question_yes(dlg) # Save messages
 
1305
        dlg._do_cancel()
 
1306
        self.assertEquals(u'two', self._get_commit_message())
 
1307
        self.assertEquals(u'd4:a-id7:a msg 24:b-id7:b msg 2e',
 
1308
                          self._get_file_commit_messages())
 
1309
 
 
1310
    def test_messages_are_cleared_on_cancel_if_required(self):
 
1311
        dlg = self._get_commit_dialog(self.tree)
 
1312
        self._set_question_no(dlg) # Don't save messages
 
1313
        dlg._do_cancel()
 
1314
        self.assertEquals(u'', self._get_commit_message())
 
1315
        self.assertEquals(u'de',
 
1316
                          self._get_file_commit_messages())