/b-gtk/fix-viz

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