/b-gtk/fix-viz

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/b-gtk/fix-viz
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
1
# Copyright (C) 2007 John Arbash Meinel <john@arbash-meinel.com>
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
17
"""Test the Commit functionality."""
18
278.1.16 by John Arbash Meinel
Implement the file changes list on top of _iter_changes rather than
19
import os
20
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
21
import gtk
22
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
23
from bzrlib import (
24
    tests,
25
    revision,
26
    )
278.1.27 by John Arbash Meinel
Add the ability to commit just specific files.
27
from bzrlib.util import bencode
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
28
29
from bzrlib.plugins.gtk import commit
30
31
32
# TODO: All we need is basic ancestry code to test this, we shouldn't need a
33
# TestCaseWithTransport, just a TestCaseWithMemoryTransport or somesuch.
34
35
class TestPendingRevisions(tests.TestCaseWithTransport):
36
37
    def test_pending_revisions_none(self):
38
        tree = self.make_branch_and_tree('.')
39
        tree.commit('one')
40
41
        self.assertIs(None, commit.pending_revisions(tree))
42
43
    def test_pending_revisions_simple(self):
44
        tree = self.make_branch_and_tree('tree')
45
        rev_id1 = tree.commit('one')
46
        tree2 = tree.bzrdir.sprout('tree2').open_workingtree()
47
        rev_id2 = tree2.commit('two')
48
        tree.merge_from_branch(tree2.branch)
49
        self.assertEqual([rev_id1, rev_id2], tree.get_parent_ids())
50
51
        pending_revisions = commit.pending_revisions(tree)
52
        # One primary merge
53
        self.assertEqual(1, len(pending_revisions))
54
        # Revision == rev_id2
55
        self.assertEqual(rev_id2, pending_revisions[0][0].revision_id)
56
        # No children of this revision.
57
        self.assertEqual([], pending_revisions[0][1])
58
59
    def test_pending_revisions_with_children(self):
60
        tree = self.make_branch_and_tree('tree')
61
        rev_id1 = tree.commit('one')
62
        tree2 = tree.bzrdir.sprout('tree2').open_workingtree()
63
        rev_id2 = tree2.commit('two')
64
        rev_id3 = tree2.commit('three')
65
        rev_id4 = tree2.commit('four')
66
        tree.merge_from_branch(tree2.branch)
67
        self.assertEqual([rev_id1, rev_id4], tree.get_parent_ids())
68
69
        pending_revisions = commit.pending_revisions(tree)
70
        # One primary merge
71
        self.assertEqual(1, len(pending_revisions))
72
        # Revision == rev_id2
73
        self.assertEqual(rev_id4, pending_revisions[0][0].revision_id)
74
        # Two children for this revision
75
        self.assertEqual(2, len(pending_revisions[0][1]))
76
        self.assertEqual(rev_id3, pending_revisions[0][1][0].revision_id)
77
        self.assertEqual(rev_id2, pending_revisions[0][1][1].revision_id)
78
79
    def test_pending_revisions_multi_merge(self):
80
        tree = self.make_branch_and_tree('tree')
81
        rev_id1 = tree.commit('one')
82
        tree2 = tree.bzrdir.sprout('tree2').open_workingtree()
83
        rev_id2 = tree2.commit('two')
84
        rev_id3 = tree2.commit('three')
85
        tree3 = tree2.bzrdir.sprout('tree3').open_workingtree()
86
        rev_id4 = tree3.commit('four')
87
        rev_id5 = tree3.commit('five')
88
        tree.merge_from_branch(tree2.branch)
89
        tree.merge_from_branch(tree3.branch)
90
        self.assertEqual([rev_id1, rev_id3, rev_id5], tree.get_parent_ids())
91
92
        pending_revisions = commit.pending_revisions(tree)
93
        # Two primary merges
94
        self.assertEqual(2, len(pending_revisions))
95
        # Revision == rev_id2
96
        self.assertEqual(rev_id3, pending_revisions[0][0].revision_id)
97
        self.assertEqual(rev_id5, pending_revisions[1][0].revision_id)
98
        # One child for the first merge
99
        self.assertEqual(1, len(pending_revisions[0][1]))
100
        self.assertEqual(rev_id2, pending_revisions[0][1][0].revision_id)
101
        # One child for the second merge
102
        self.assertEqual(1, len(pending_revisions[1][1]))
103
        self.assertEqual(rev_id4, pending_revisions[1][1][0].revision_id)
104
105
106
class Test_RevToPendingInfo(tests.TestCaseWithTransport):
107
108
    def test_basic_info(self):
109
        tree = self.make_branch_and_tree('tree')
110
        rev_id = tree.commit('Multiline\ncommit\nmessage',
111
                             committer='Joe Foo <joe@foo.com>',
112
                             timestamp=1191012408.674,
113
                             timezone=-18000
114
                             )
115
        rev = tree.branch.repository.get_revision(rev_id)
116
        rev_dict = commit.CommitDialog._rev_to_pending_info(rev)
117
        self.assertEqual({'committer':'Joe Foo',
118
                          'summary':'Multiline',
119
                          'date':'2007-09-28',
120
                          'revision_id':rev_id,
121
                         }, rev_dict)
122
123
124
class CommitDialogNoWidgets(commit.CommitDialog):
125
126
    def construct(self):
127
        pass # Don't create any widgets here
128
278.1.14 by John Arbash Meinel
Tests that we fill out the pending list correctly.
129
    def fill_in_data(self):
130
        pass # With no widgets, there are no widgets to fill out
131
132
133
class TestCommitDialogSimple(tests.TestCaseWithTransport):
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
134
135
    def test_setup_parameters_no_pending(self):
136
        tree = self.make_branch_and_tree('tree')
137
        rev_id = tree.commit('first')
138
139
        dlg = CommitDialogNoWidgets(tree)
140
        self.assertEqual(rev_id, dlg._basis_tree.get_revision_id())
141
        self.assertIs(None, dlg._pending)
142
        self.assertFalse(dlg._is_checkout)
143
144
    def test_setup_parameters_checkout(self):
145
        tree = self.make_branch_and_tree('tree')
146
        rev_id = tree.commit('first')
147
        tree2 = tree.bzrdir.sprout('tree2').open_workingtree()
148
        tree2.branch.bind(tree.branch)
149
150
        dlg = CommitDialogNoWidgets(tree2)
151
        self.assertEqual(rev_id, dlg._basis_tree.get_revision_id())
152
        self.assertIs(None, dlg._pending)
153
        self.assertTrue(dlg._is_checkout)
154
155
    def test_setup_parameters_pending(self):
156
        tree = self.make_branch_and_tree('tree')
157
        rev_id1 = tree.commit('one')
158
        tree2 = tree.bzrdir.sprout('tree2').open_workingtree()
159
        rev_id2 = tree2.commit('two')
160
        tree.merge_from_branch(tree2.branch)
161
162
        dlg = CommitDialogNoWidgets(tree)
163
        self.assertEqual(rev_id1, dlg._basis_tree.get_revision_id())
164
        self.assertIsNot(None, dlg._pending)
165
        self.assertEqual(1, len(dlg._pending))
166
        self.assertEqual(rev_id2, dlg._pending[0][0].revision_id)
167
168
    def test_setup_parameters_delta(self):
169
        tree = self.make_branch_and_tree('tree')
170
        self.build_tree(['tree/a'])
171
        tree.add(['a'], ['a-id'])
172
173
        dlg = CommitDialogNoWidgets(tree)
278.1.12 by John Arbash Meinel
Delay computing the delta, and clean up some of the diff view names.
174
        self.assertIs(None, dlg._delta)
175
        dlg._compute_delta()
176
278.1.5 by John Arbash Meinel
Starting to flesh out the dialog with actual windows.
177
        delta = dlg._delta
178
        self.assertEqual([], delta.modified)
179
        self.assertEqual([], delta.renamed)
180
        self.assertEqual([], delta.removed)
181
        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.
182
183
184
class TestCommitDialog(tests.TestCaseWithTransport):
185
278.1.25 by John Arbash Meinel
Add the 'Only Commit Locally' checkbox, we may want to put it elsewhere, though.
186
    def test_bound(self):
187
        tree = self.make_branch_and_tree('tree')
188
        rev_id = tree.commit('first')
189
        tree2 = tree.bzrdir.sprout('tree2').open_workingtree()
190
        tree2.branch.bind(tree.branch)
191
192
        # tree is not a checkout
193
        dlg = commit.CommitDialog(tree)
194
        self.assertFalse(dlg._check_local.get_property('visible'))
195
196
        # tree2 is a checkout
197
        dlg2 = commit.CommitDialog(tree2)
198
        self.assertTrue(dlg2._check_local.get_property('visible'))
199
278.1.14 by John Arbash Meinel
Tests that we fill out the pending list correctly.
200
    def test_no_pending(self):
201
        tree = self.make_branch_and_tree('tree')
202
        rev_id1 = tree.commit('one')
203
204
        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.
205
206
        self.assertFalse(dlg._pending_box.get_property('visible'))
207
278.1.17 by John Arbash Meinel
Add a * reference for why you can't change the commit selection.
208
        commit_col = dlg._treeview_files.get_column(0)
209
        self.assertEqual('Commit', commit_col.get_title())
278.1.20 by John Arbash Meinel
We always select the All Files record in the files view,
210
        renderer = commit_col.get_cell_renderers()[0]
278.1.39 by John Arbash Meinel
To disable a checkbox it is set_property('activatable', False),
211
        self.assertTrue(renderer.get_property('activatable'))
278.1.14 by John Arbash Meinel
Tests that we fill out the pending list correctly.
212
278.1.43 by John Arbash Meinel
Finish connecting the 'Commit all changes' radio buttons.
213
        self.assertEqual('Commit all changes',
214
                         dlg._commit_all_files_radio.get_label())
215
        self.assertTrue(dlg._commit_all_files_radio.get_property('sensitive'))
216
        self.assertTrue(dlg._commit_selected_radio.get_property('sensitive'))
217
278.1.14 by John Arbash Meinel
Tests that we fill out the pending list correctly.
218
    def test_pending(self):
219
        tree = self.make_branch_and_tree('tree')
220
        rev_id1 = tree.commit('one')
221
222
        tree2 = tree.bzrdir.sprout('tree2').open_workingtree()
223
        rev_id2 = tree2.commit('two',
224
                               committer='Joe Foo <joe@foo.com>',
225
                               timestamp=1191264271.05,
226
                               timezone=+7200)
227
        tree.merge_from_branch(tree2.branch)
228
229
        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.
230
231
        self.assertTrue(dlg._pending_box.get_property('visible'))
232
278.1.17 by John Arbash Meinel
Add a * reference for why you can't change the commit selection.
233
        commit_col = dlg._treeview_files.get_column(0)
234
        self.assertEqual('Commit*', commit_col.get_title())
278.1.20 by John Arbash Meinel
We always select the All Files record in the files view,
235
        renderer = commit_col.get_cell_renderers()[0]
278.1.39 by John Arbash Meinel
To disable a checkbox it is set_property('activatable', False),
236
        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.
237
278.1.15 by John Arbash Meinel
Hook up the list of modified files.
238
        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.
239
        self.assertEqual([(rev_id2, '2007-10-01', 'Joe Foo', 'two')], values)
240
278.1.43 by John Arbash Meinel
Finish connecting the 'Commit all changes' radio buttons.
241
        self.assertEqual('Commit all changes*',
242
                         dlg._commit_all_files_radio.get_label())
243
        self.assertFalse(dlg._commit_all_files_radio.get_property('sensitive'))
244
        self.assertFalse(dlg._commit_selected_radio.get_property('sensitive'))
245
278.1.14 by John Arbash Meinel
Tests that we fill out the pending list correctly.
246
    def test_pending_multiple(self):
247
        tree = self.make_branch_and_tree('tree')
248
        rev_id1 = tree.commit('one')
249
250
        tree2 = tree.bzrdir.sprout('tree2').open_workingtree()
251
        rev_id2 = tree2.commit('two',
252
                               committer='Joe Foo <joe@foo.com>',
253
                               timestamp=1191264271.05,
254
                               timezone=+7200)
255
        rev_id3 = tree2.commit('three',
256
                               committer='Jerry Foo <jerry@foo.com>',
257
                               timestamp=1191264278.05,
258
                               timezone=+7200)
259
        tree.merge_from_branch(tree2.branch)
260
        tree3 = tree.bzrdir.sprout('tree3').open_workingtree()
261
        rev_id4 = tree3.commit('four',
262
                               committer='Joe Foo <joe@foo.com>',
263
                               timestamp=1191264279.05,
264
                               timezone=+7200)
265
        rev_id5 = tree3.commit('five',
266
                               committer='Jerry Foo <jerry@foo.com>',
267
                               timestamp=1191372278.05,
268
                               timezone=+7200)
269
        tree.merge_from_branch(tree3.branch)
270
271
        dlg = commit.CommitDialog(tree)
272
        # TODO: assert that the pending box is set to show
278.1.15 by John Arbash Meinel
Hook up the list of modified files.
273
        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.
274
        self.assertEqual([(rev_id3, '2007-10-01', 'Jerry Foo', 'three'),
275
                          (rev_id2, '2007-10-01', 'Joe Foo', 'two'),
276
                          (rev_id5, '2007-10-03', 'Jerry Foo', 'five'),
277
                          (rev_id4, '2007-10-01', 'Joe Foo', 'four'),
278
                         ], values)
278.1.15 by John Arbash Meinel
Hook up the list of modified files.
279
278.1.16 by John Arbash Meinel
Implement the file changes list on top of _iter_changes rather than
280
    def test_filelist_added(self):
278.1.15 by John Arbash Meinel
Hook up the list of modified files.
281
        tree = self.make_branch_and_tree('tree')
282
        self.build_tree(['tree/a', 'tree/b/', 'tree/b/c'])
283
        tree.add(['a', 'b', 'b/c'], ['a-id', 'b-id', 'c-id'])
284
285
        dlg = commit.CommitDialog(tree)
286
        values = [(r[0], r[1], r[2], r[3], r[4]) for r in dlg._files_store]
278.1.20 by John Arbash Meinel
We always select the All Files record in the files view,
287
        self.assertEqual([(None, None, True, 'All Files', ''),
288
                          ('a-id', 'a', True, 'a', 'added'),
278.1.15 by John Arbash Meinel
Hook up the list of modified files.
289
                          ('b-id', 'b', True, 'b/', 'added'),
290
                          ('c-id', 'b/c', True, 'b/c', 'added'),
291
                         ], values)
278.1.16 by John Arbash Meinel
Implement the file changes list on top of _iter_changes rather than
292
293
    def test_filelist_renamed(self):
294
        tree = self.make_branch_and_tree('tree')
295
        self.build_tree(['tree/a', 'tree/b/', 'tree/b/c'])
296
        tree.add(['a', 'b', 'b/c'], ['a-id', 'b-id', 'c-id'])
297
        rev_id1 = tree.commit('one')
298
299
        tree.rename_one('b', 'd')
300
        tree.rename_one('a', 'd/a')
301
302
        dlg = commit.CommitDialog(tree)
303
        values = [(r[0], r[1], r[2], r[3], r[4]) for r in dlg._files_store]
278.1.20 by John Arbash Meinel
We always select the All Files record in the files view,
304
        self.assertEqual([(None, None, True, 'All Files', ''),
305
                          ('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
306
                          ('a-id', 'd/a', True, 'a => d/a', 'renamed'),
307
                         ], values)
308
309
    def test_filelist_modified(self):
310
        tree = self.make_branch_and_tree('tree')
311
        self.build_tree(['tree/a'])
312
        tree.add(['a'], ['a-id'])
313
        rev_id1 = tree.commit('one')
314
315
        self.build_tree_contents([('tree/a', 'new contents for a\n')])
316
317
        dlg = commit.CommitDialog(tree)
318
        values = [(r[0], r[1], r[2], r[3], r[4]) for r in dlg._files_store]
278.1.20 by John Arbash Meinel
We always select the All Files record in the files view,
319
        self.assertEqual([(None, None, True, 'All Files', ''),
320
                          ('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
321
                         ], values)
322
323
    def test_filelist_renamed_and_modified(self):
324
        tree = self.make_branch_and_tree('tree')
325
        self.build_tree(['tree/a', 'tree/b/', 'tree/b/c'])
326
        tree.add(['a', 'b', 'b/c'], ['a-id', 'b-id', 'c-id'])
327
        rev_id1 = tree.commit('one')
328
329
        tree.rename_one('b', 'd')
330
        tree.rename_one('a', 'd/a')
331
        self.build_tree_contents([('tree/d/a', 'new contents for a\n'),
332
                                  ('tree/d/c', 'new contents for c\n'),
333
                                 ])
334
        # 'c' is not considered renamed, because only its parent was moved, it
335
        # stayed in the same directory
336
337
        dlg = commit.CommitDialog(tree)
338
        values = [(r[0], r[1], r[2], r[3], r[4]) for r in dlg._files_store]
278.1.20 by John Arbash Meinel
We always select the All Files record in the files view,
339
        self.assertEqual([(None, None, True, 'All Files', ''),
340
                          ('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
341
                          ('a-id', 'd/a', True, 'a => d/a', 'renamed and modified'),
342
                          ('c-id', 'd/c', True, 'd/c', 'modified'),
343
                         ], values)
344
345
    def test_filelist_kind_changed(self):
346
        tree = self.make_branch_and_tree('tree')
347
        self.build_tree(['tree/a', 'tree/b'])
348
        tree.add(['a', 'b'], ['a-id', 'b-id'])
349
        tree.commit('one')
350
351
        os.remove('tree/a')
352
        self.build_tree(['tree/a/'])
278.1.17 by John Arbash Meinel
Add a * reference for why you can't change the commit selection.
353
        # XXX:  This is technically valid, and the file list handles it fine,
354
        #       but 'show_diff_trees()' does not, so we skip this part of the
355
        #       test for now.
356
        # tree.rename_one('b', 'c')
357
        # os.remove('tree/c')
358
        # self.build_tree(['tree/c/'])
278.1.16 by John Arbash Meinel
Implement the file changes list on top of _iter_changes rather than
359
360
        dlg = commit.CommitDialog(tree)
361
        values = [(r[0], r[1], r[2], r[3], r[4]) for r in dlg._files_store]
278.1.20 by John Arbash Meinel
We always select the All Files record in the files view,
362
        self.assertEqual([(None, None, True, 'All Files', ''),
363
                          ('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.
364
                          # ('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
365
                         ], values)
366
367
    def test_filelist_removed(self):
368
        tree = self.make_branch_and_tree('tree')
369
        self.build_tree(['tree/a', 'tree/b/'])
370
        tree.add(['a', 'b'], ['a-id', 'b-id'])
371
        tree.commit('one')
372
373
        os.remove('tree/a')
374
        tree.remove('b', force=True)
375
376
        dlg = commit.CommitDialog(tree)
377
        values = [(r[0], r[1], r[2], r[3], r[4]) for r in dlg._files_store]
278.1.20 by John Arbash Meinel
We always select the All Files record in the files view,
378
        self.assertEqual([(None, None, True, 'All Files', ''),
379
                          ('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
380
                          ('b-id', 'b', True, 'b/', 'removed'),
381
                         ], values)
278.1.35 by John Arbash Meinel
Make use of the 'selected' parameter to CommitDialog.
382
        # All Files should be selected
383
        self.assertEqual(((0,), None), dlg._treeview_files.get_cursor())
384
385
    def test_filelist_with_selected(self):
386
        tree = self.make_branch_and_tree('tree')
387
        self.build_tree(['tree/a', 'tree/b/'])
388
        tree.add(['a', 'b'], ['a-id', 'b-id'])
389
390
        dlg = commit.CommitDialog(tree, selected='a')
391
        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', ''),
393
                          ('a-id', 'a', True, 'a', 'added'),
394
                          ('b-id', 'b', False, 'b/', 'added'),
395
                         ], values)
396
        # This file should also be selected in the file list, rather than the
397
        # 'All Files' selection
398
        self.assertEqual(((1,), None), dlg._treeview_files.get_cursor())
278.1.18 by John Arbash Meinel
Start checking the diff view is correct.
399
400
    def test_diff_view(self):
401
        tree = self.make_branch_and_tree('tree')
402
        self.build_tree(['tree/a', 'tree/b'])
403
        tree.add(['a', 'b'], ['a-id', 'b-id'])
404
        tree.commit('one')
405
406
        self.build_tree_contents([('tree/a', 'new contents for a\n')])
407
        tree.remove('b')
408
409
        dlg = commit.CommitDialog(tree)
410
        diff_buffer = dlg._diff_view.buffer
411
        text = diff_buffer.get_text(diff_buffer.get_start_iter(),
412
                                    diff_buffer.get_end_iter()).splitlines(True)
413
414
        self.assertEqual("=== removed file 'b'\n", text[0])
415
        self.assertContainsRe(text[1],
416
            r"--- b\t\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d [+-]\d\d\d\d")
417
        self.assertEqual('+++ b\t1970-01-01 00:00:00 +0000\n', text[2])
418
        self.assertEqual('@@ -1,1 +0,0 @@\n', text[3])
419
        self.assertEqual('-contents of tree/b\n', text[4])
420
        self.assertEqual('\n', text[5])
421
422
        self.assertEqual("=== modified file 'a'\n", text[6])
423
        self.assertContainsRe(text[7],
424
            r"--- a\t\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d [+-]\d\d\d\d")
425
        self.assertContainsRe(text[8],
426
            r"\+\+\+ a\t\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d [+-]\d\d\d\d")
427
        self.assertEqual('@@ -1,1 +1,1 @@\n', text[9])
428
        self.assertEqual('-contents of tree/a\n', text[10])
429
        self.assertEqual('+new contents for a\n', text[11])
430
        self.assertEqual('\n', text[12])
431
278.1.20 by John Arbash Meinel
We always select the All Files record in the files view,
432
        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.
433
278.1.43 by John Arbash Meinel
Finish connecting the 'Commit all changes' radio buttons.
434
    def test_commit_partial_toggle(self):
435
        tree = self.make_branch_and_tree('tree')
436
        self.build_tree(['tree/a', 'tree/b'])
437
        tree.add(['a', 'b'], ['a-id', 'b-id'])
438
439
        dlg = commit.CommitDialog(tree)
440
        checked_col = dlg._treeview_files.get_column(0)
441
        self.assertFalse(checked_col.get_property('visible'))
442
        self.assertTrue(dlg._commit_all_changes)
443
444
        dlg._commit_selected_radio.set_active(True)
445
        self.assertTrue(checked_col.get_property('visible'))
446
        self.assertFalse(dlg._commit_all_changes)
447
278.1.19 by John Arbash Meinel
Test what happens when a specific file is selected.
448
    def test_file_selection(self):
449
        """Several things should happen when a file has been selected."""
450
        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.
451
        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.
452
        self.build_tree(['tree/a', 'tree/b'])
453
        tree.add(['a', 'b'], ['a-id', 'b-id'])
454
455
        dlg = commit.CommitDialog(tree)
456
        diff_buffer = dlg._diff_view.buffer
278.1.20 by John Arbash Meinel
We always select the All Files record in the files view,
457
        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.
458
        self.assertEqual('File commit message',
459
                         dlg._file_message_expander.get_label())
460
        self.assertFalse(dlg._file_message_expander.get_expanded())
461
        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.
462
278.1.20 by John Arbash Meinel
We always select the All Files record in the files view,
463
        dlg._treeview_files.set_cursor((1,))
278.1.19 by John Arbash Meinel
Test what happens when a specific file is selected.
464
        self.assertEqual('Diff for a', dlg._diff_label.get_text())
465
        text = diff_buffer.get_text(diff_buffer.get_start_iter(),
466
                                    diff_buffer.get_end_iter()).splitlines(True)
467
        self.assertEqual("=== added file 'a'\n", text[0])
468
        self.assertContainsRe(text[1],
469
            r"--- a\t\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d [+-]\d\d\d\d")
470
        self.assertContainsRe(text[2],
471
            r"\+\+\+ a\t\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d [+-]\d\d\d\d")
472
        self.assertEqual('@@ -0,0 +1,1 @@\n', text[3])
473
        self.assertEqual('+contents of tree/a\n', text[4])
474
        self.assertEqual('\n', text[5])
278.1.21 by John Arbash Meinel
Start tracking the per-file commit messages.
475
        self.assertEqual('Commit message for a',
476
                         dlg._file_message_expander.get_label())
477
        self.assertTrue(dlg._file_message_expander.get_expanded())
478
        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.
479
278.1.20 by John Arbash Meinel
We always select the All Files record in the files view,
480
        dlg._treeview_files.set_cursor((2,))
278.1.19 by John Arbash Meinel
Test what happens when a specific file is selected.
481
        self.assertEqual('Diff for b', dlg._diff_label.get_text())
482
        text = diff_buffer.get_text(diff_buffer.get_start_iter(),
483
                                    diff_buffer.get_end_iter()).splitlines(True)
484
        self.assertEqual("=== added file 'b'\n", text[0])
485
        self.assertContainsRe(text[1],
486
            r"--- b\t\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d [+-]\d\d\d\d")
487
        self.assertContainsRe(text[2],
488
            r"\+\+\+ b\t\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d [+-]\d\d\d\d")
489
        self.assertEqual('@@ -0,0 +1,1 @@\n', text[3])
490
        self.assertEqual('+contents of tree/b\n', text[4])
491
        self.assertEqual('\n', text[5])
278.1.21 by John Arbash Meinel
Start tracking the per-file commit messages.
492
        self.assertEqual('Commit message for b',
493
                         dlg._file_message_expander.get_label())
494
        self.assertTrue(dlg._file_message_expander.get_expanded())
495
        self.assertTrue(dlg._file_message_expander.get_property('sensitive'))
496
497
        dlg._treeview_files.set_cursor((0,))
498
        self.assertEqual('Diff for All Files', dlg._diff_label.get_text())
499
        self.assertEqual('File commit message',
500
                         dlg._file_message_expander.get_label())
501
        self.assertFalse(dlg._file_message_expander.get_expanded())
502
        self.assertFalse(dlg._file_message_expander.get_property('sensitive'))
503
504
    def test_file_selection_message(self):
505
        """Selecting a file should bring up its commit message."""
506
        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.
507
        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.
508
        self.build_tree(['tree/a', 'tree/b/'])
509
        tree.add(['a', 'b'], ['a-id', 'b-id'])
510
511
        def get_file_text():
512
            buf = dlg._file_message_text_view.get_buffer()
513
            return buf.get_text(buf.get_start_iter(), buf.get_end_iter())
514
515
        def get_saved_text(path):
516
            """Get the saved text for a given record."""
517
            return dlg._files_store.get_value(dlg._files_store.get_iter(path), 5)
518
519
        dlg = commit.CommitDialog(tree)
520
        self.assertEqual('File commit message',
521
                         dlg._file_message_expander.get_label())
522
        self.assertFalse(dlg._file_message_expander.get_expanded())
523
        self.assertFalse(dlg._file_message_expander.get_property('sensitive'))
524
        self.assertEqual('', get_file_text())
525
526
        dlg._treeview_files.set_cursor((1,))
527
        self.assertEqual('Commit message for a',
528
                         dlg._file_message_expander.get_label())
529
        self.assertTrue(dlg._file_message_expander.get_expanded())
530
        self.assertTrue(dlg._file_message_expander.get_property('sensitive'))
531
        self.assertEqual('', get_file_text())
532
533
        self.assertEqual('', get_saved_text(1))
278.1.27 by John Arbash Meinel
Add the ability to commit just specific files.
534
        dlg._set_file_commit_message('Some text\nfor a\n')
278.1.21 by John Arbash Meinel
Start tracking the per-file commit messages.
535
        dlg._save_current_file_message()
536
        # We should have updated the ListStore with the new file commit info
537
        self.assertEqual('Some text\nfor a\n', get_saved_text(1))
538
539
        dlg._treeview_files.set_cursor((2,))
540
        self.assertEqual('Commit message for b/',
541
                         dlg._file_message_expander.get_label())
542
        self.assertTrue(dlg._file_message_expander.get_expanded())
543
        self.assertTrue(dlg._file_message_expander.get_property('sensitive'))
544
        self.assertEqual('', get_file_text())
545
546
        self.assertEqual('', get_saved_text(2))
278.1.27 by John Arbash Meinel
Add the ability to commit just specific files.
547
        dlg._set_file_commit_message('More text\nfor b\n')
278.1.21 by John Arbash Meinel
Start tracking the per-file commit messages.
548
        # Now switch back to 'a'. The message should be saved, and the buffer
549
        # should be updated with the other text
550
        dlg._treeview_files.set_cursor((1,))
551
        self.assertEqual('More text\nfor b\n', get_saved_text(2))
552
        self.assertEqual('Commit message for a',
553
                         dlg._file_message_expander.get_label())
554
        self.assertTrue(dlg._file_message_expander.get_expanded())
555
        self.assertTrue(dlg._file_message_expander.get_property('sensitive'))
556
        self.assertEqual('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,
557
558
    def test_toggle_all_files(self):
559
        """When checking the All Files entry, it should toggle all fields"""
560
        tree = self.make_branch_and_tree('tree')
561
        self.build_tree(['tree/a', 'tree/b/'])
562
        tree.add(['a', 'b'], ['a-id', 'b-id'])
563
564
        dlg = commit.CommitDialog(tree)
565
        self.assertEqual([(None, None, True),
566
                          ('a-id', 'a', True),
567
                          ('b-id', 'b', True),
568
                         ], [(r[0], r[1], r[2]) for r in dlg._files_store])
569
570
        # TODO: jam 20071002 I'm not sure how to exactly trigger a toggle, it
571
        #       looks like we need to call renderer.activate() and pass an
572
        #       event and widget, and lots of other stuff I'm not sure what to
573
        #       do with. So instead, we just call toggle directly, and assume
574
        #       that toggle is hooked in correctly
575
        # column = dlg._treeview_files.get_column(0)
576
        # renderer = column.get_cell_renderers()[0]
577
578
        # Toggle a single entry should set just that entry to False
579
        dlg._toggle_commit(None, 1, dlg._files_store)
580
        self.assertEqual([(None, None, True),
581
                          ('a-id', 'a', False),
582
                          ('b-id', 'b', True),
583
                         ], [(r[0], r[1], r[2]) for r in dlg._files_store])
584
585
        # Toggling the main entry should set all entries
586
        dlg._toggle_commit(None, 0, dlg._files_store)
587
        self.assertEqual([(None, None, False),
588
                          ('a-id', 'a', False),
589
                          ('b-id', 'b', False),
590
                         ], [(r[0], r[1], r[2]) for r in dlg._files_store])
591
592
        dlg._toggle_commit(None, 2, dlg._files_store)
593
        self.assertEqual([(None, None, False),
594
                          ('a-id', 'a', False),
595
                          ('b-id', 'b', True),
596
                         ], [(r[0], r[1], r[2]) for r in dlg._files_store])
597
598
        dlg._toggle_commit(None, 0, dlg._files_store)
599
        self.assertEqual([(None, None, True),
600
                          ('a-id', 'a', True),
601
                          ('b-id', 'b', True),
602
                         ], [(r[0], r[1], r[2]) for r in dlg._files_store])
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
603
278.1.27 by John Arbash Meinel
Add the ability to commit just specific files.
604
    def test_specific_files(self):
605
        tree = self.make_branch_and_tree('tree')
606
        self.build_tree(['tree/a', 'tree/b/'])
607
        tree.add(['a', 'b'], ['a-id', 'b-id'])
608
609
        dlg = commit.CommitDialog(tree)
610
        self.assertEqual((['a', 'b'], []), dlg._get_specific_files())
611
278.1.43 by John Arbash Meinel
Finish connecting the 'Commit all changes' radio buttons.
612
        dlg._commit_selected_radio.set_active(True)
278.1.27 by John Arbash Meinel
Add the ability to commit just specific files.
613
        dlg._toggle_commit(None, 0, dlg._files_store)
614
        self.assertEqual(([], []), dlg._get_specific_files())
615
616
        dlg._toggle_commit(None, 1, dlg._files_store)
617
        self.assertEqual((['a'], []), dlg._get_specific_files())
618
619
    def test_specific_files_with_messages(self):
620
        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.
621
        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.
622
        self.build_tree(['tree/a_file', 'tree/b_dir/'])
623
        tree.add(['a_file', 'b_dir'], ['1a-id', '0b-id'])
624
625
        dlg = commit.CommitDialog(tree)
278.1.43 by John Arbash Meinel
Finish connecting the 'Commit all changes' radio buttons.
626
        dlg._commit_selected_radio.set_active(True)
278.1.27 by John Arbash Meinel
Add the ability to commit just specific files.
627
        self.assertEqual((['a_file', 'b_dir'], []), dlg._get_specific_files())
628
629
        dlg._treeview_files.set_cursor((1,))
630
        dlg._set_file_commit_message('Test\nmessage\nfor a_file\n')
631
        dlg._treeview_files.set_cursor((2,))
632
        dlg._set_file_commit_message('message\nfor b_dir\n')
633
634
        self.assertEqual((['a_file', 'b_dir'],
635
                          [{'path':'a_file', 'file_id':'1a-id',
636
                            'message':'Test\nmessage\nfor a_file\n'},
637
                           {'path':'b_dir', 'file_id':'0b-id',
638
                            'message':'message\nfor b_dir\n'},
639
                          ]), dlg._get_specific_files())
640
641
        dlg._toggle_commit(None, 1, dlg._files_store)
642
        self.assertEqual((['b_dir'],
643
                          [{'path':'b_dir', 'file_id':'0b-id',
644
                            'message':'message\nfor b_dir\n'},
645
                          ]), dlg._get_specific_files())
646
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
647
648
class TestCommitDialog_Commit(tests.TestCaseWithTransport):
649
    """Tests on the actual 'commit' button being pushed."""
650
278.1.26 by John Arbash Meinel
Handle pointless commits and trees with unknown files.
651
    def _set_question_yes(self, dlg):
652
        """Set the dialog to answer YES to any questions."""
653
        self.questions = []
654
        def _question_yes(*args):
655
            self.questions.append(args)
656
            self.questions.append('YES')
657
            return gtk.RESPONSE_YES
658
        dlg._question_dialog = _question_yes
659
660
    def _set_question_no(self, dlg):
661
        """Set the dialog to answer NO to any questions."""
662
        self.questions = []
663
        def _question_no(*args):
664
            self.questions.append(args)
665
            self.questions.append('NO')
666
            return gtk.RESPONSE_NO
667
        dlg._question_dialog = _question_no
668
278.1.25 by John Arbash Meinel
Add the 'Only Commit Locally' checkbox, we may want to put it elsewhere, though.
669
    def test_bound_commit_local(self):
670
        tree = self.make_branch_and_tree('tree')
671
        self.build_tree(['tree/a'])
672
        tree.add(['a'], ['a-id'])
673
        rev_id1 = tree.commit('one')
674
675
        tree2 = tree.bzrdir.sprout('tree2').open_workingtree()
676
        self.build_tree(['tree2/b'])
677
        tree2.add(['b'], ['b-id'])
678
        tree2.branch.bind(tree.branch)
679
680
        dlg = commit.CommitDialog(tree2)
681
        # With the check box set, it should only effect the local branch
682
        dlg._check_local.set_active(True)
683
        dlg._set_global_commit_message('Commit message\n')
684
        dlg._do_commit()
685
686
        last_rev = tree2.last_revision()
687
        self.assertEqual(last_rev, dlg.committed_revision_id)
688
        self.assertEqual(rev_id1, tree.branch.last_revision())
689
690
    def test_bound_commit_both(self):
691
        tree = self.make_branch_and_tree('tree')
692
        self.build_tree(['tree/a'])
693
        tree.add(['a'], ['a-id'])
694
        rev_id1 = tree.commit('one')
695
696
        tree2 = tree.bzrdir.sprout('tree2').open_workingtree()
697
        self.build_tree(['tree2/b'])
698
        tree2.add(['b'], ['b-id'])
699
        tree2.branch.bind(tree.branch)
700
701
        dlg = commit.CommitDialog(tree2)
702
        # With the check box set, it should only effect the local branch
703
        dlg._check_local.set_active(False)
704
        dlg._set_global_commit_message('Commit message\n')
705
        dlg._do_commit()
706
707
        last_rev = tree2.last_revision()
708
        self.assertEqual(last_rev, dlg.committed_revision_id)
709
        self.assertEqual(last_rev, tree.branch.last_revision())
710
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
711
    def test_commit_no_message(self):
712
        tree = self.make_branch_and_tree('tree')
713
        self.build_tree(['tree/a', 'tree/b'])
714
        tree.add(['a'], ['a-id'])
715
        rev_id = tree.commit('one')
716
717
        tree.add(['b'], ['b-id'])
718
719
        dlg = commit.CommitDialog(tree)
278.1.26 by John Arbash Meinel
Handle pointless commits and trees with unknown files.
720
        self._set_question_no(dlg)
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
721
        dlg._do_commit()
722
        self.assertEqual(
723
            [('Commit with an empty message?',
724
              'You can describe your commit intent in the message.'),
725
              'NO',
278.1.26 by John Arbash Meinel
Handle pointless commits and trees with unknown files.
726
            ], self.questions)
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
727
        # By saying NO, nothing should be committed.
728
        self.assertEqual(rev_id, tree.last_revision())
729
        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.
730
        self.assertTrue(dlg._global_message_text_view.get_property('is-focus'))
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
731
278.1.26 by John Arbash Meinel
Handle pointless commits and trees with unknown files.
732
        self._set_question_yes(dlg)
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
733
734
        dlg._do_commit()
735
        self.assertEqual(
736
            [('Commit with an empty message?',
737
              'You can describe your commit intent in the message.'),
278.1.26 by John Arbash Meinel
Handle pointless commits and trees with unknown files.
738
              'YES',
739
            ], self.questions)
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
740
        committed = tree.last_revision()
741
        self.assertNotEqual(rev_id, committed)
742
        self.assertEqual(committed, dlg.committed_revision_id)
743
744
    def test_initial_commit(self):
745
        tree = self.make_branch_and_tree('tree')
746
        self.build_tree(['tree/a'])
747
        tree.add(['a'], ['a-id'])
748
749
        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.
750
        dlg._set_global_commit_message('Some text\n')
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
751
        dlg._do_commit()
752
753
        last_rev = tree.last_revision()
754
        self.assertEqual(last_rev, dlg.committed_revision_id)
755
        rev = tree.branch.repository.get_revision(last_rev)
756
        self.assertEqual(last_rev, rev.revision_id)
757
        self.assertEqual('Some text\n', rev.message)
278.1.26 by John Arbash Meinel
Handle pointless commits and trees with unknown files.
758
759
    def test_pointless_commit(self):
760
        tree = self.make_branch_and_tree('tree')
761
        self.build_tree(['tree/a'])
762
        tree.add(['a'], ['a-id'])
763
        rev_id1 = tree.commit('one')
764
765
        dlg = commit.CommitDialog(tree)
766
        dlg._set_global_commit_message('Some text\n')
767
768
        self._set_question_no(dlg)
769
        dlg._do_commit()
770
771
        self.assertIs(None, dlg.committed_revision_id)
772
        self.assertEqual(rev_id1, tree.last_revision())
773
        self.assertEqual(
774
            [('Commit with no changes?',
775
              'There are no changes in the working tree.'
776
              ' Do you want to commit anyway?'),
777
              'NO',
778
            ], self.questions)
779
780
        self._set_question_yes(dlg)
781
        dlg._do_commit()
782
783
        rev_id2 = tree.last_revision()
784
        self.assertEqual(rev_id2, dlg.committed_revision_id)
785
        self.assertNotEqual(rev_id1, rev_id2)
786
        self.assertEqual(
787
            [('Commit with no changes?',
788
              'There are no changes in the working tree.'
789
              ' Do you want to commit anyway?'),
790
              'YES',
791
            ], self.questions)
792
793
    def test_unknowns(self):
794
        """We should check if there are unknown files."""
795
        tree = self.make_branch_and_tree('tree')
796
        rev_id1 = tree.commit('one')
797
        self.build_tree(['tree/a', 'tree/b'])
798
        tree.add(['a'], ['a-id'])
799
800
        dlg = commit.CommitDialog(tree)
801
        dlg._set_global_commit_message('Some text\n')
802
        self._set_question_no(dlg)
803
804
        dlg._do_commit()
805
806
        self.assertIs(None, dlg.committed_revision_id)
807
        self.assertEqual(rev_id1, tree.last_revision())
808
        self.assertEqual(
809
            [("Commit with unknowns?",
810
              "Unknown files exist in the working tree. Commit anyway?"),
811
              "NO",
812
            ], self.questions)
813
814
        self._set_question_yes(dlg)
815
        dlg._do_commit()
816
817
        rev_id2 = tree.last_revision()
818
        self.assertNotEqual(rev_id1, rev_id2)
819
        self.assertEqual(rev_id2, dlg.committed_revision_id)
820
        self.assertEqual(
821
            [("Commit with unknowns?",
822
              "Unknown files exist in the working tree. Commit anyway?"),
823
              "YES",
824
            ], self.questions)
825
278.1.27 by John Arbash Meinel
Add the ability to commit just specific files.
826
    def test_commit_specific_files(self):
827
        tree = self.make_branch_and_tree('tree')
828
        rev_id1 = tree.commit('one')
829
        self.build_tree(['tree/a', 'tree/b'])
830
        tree.add(['a', 'b'], ['a-id', 'b-id'])
831
832
        dlg = commit.CommitDialog(tree)
278.1.43 by John Arbash Meinel
Finish connecting the 'Commit all changes' radio buttons.
833
        dlg._commit_selected_radio.set_active(True) # enable partial
278.1.27 by John Arbash Meinel
Add the ability to commit just specific files.
834
        dlg._toggle_commit(None, 2, dlg._files_store) # unset 'b'
835
836
        dlg._set_global_commit_message('Committing just "a"\n')
837
        dlg._do_commit()
838
839
        rev_id2 = dlg.committed_revision_id
840
        self.assertIsNot(None, rev_id2)
841
        self.assertEqual(rev_id2, tree.last_revision())
842
843
        rt = tree.branch.repository.revision_tree(rev_id2)
844
        entries = [(path, ie.file_id) for path, ie in rt.iter_entries_by_dir()
845
                                       if path] # Ignore the root entry
846
        self.assertEqual([('a', 'a-id')], entries)
847
278.1.43 by John Arbash Meinel
Finish connecting the 'Commit all changes' radio buttons.
848
    def test_commit_partial_no_partial(self):
849
        """Ignore the checkboxes if committing all files."""
850
        tree = self.make_branch_and_tree('tree')
851
        rev_id1 = tree.commit('one')
852
        self.build_tree(['tree/a', 'tree/b'])
853
        tree.add(['a', 'b'], ['a-id', 'b-id'])
854
855
        dlg = commit.CommitDialog(tree)
856
        dlg._commit_selected_radio.set_active(True) # enable partial
857
        dlg._toggle_commit(None, 2, dlg._files_store) # unset 'b'
858
859
        # Switch back to committing all changes
860
        dlg._commit_all_files_radio.set_active(True)
861
862
        dlg._set_global_commit_message('Committing everything\n')
863
        dlg._do_commit()
864
865
        rev_id2 = dlg.committed_revision_id
866
        self.assertIsNot(None, rev_id2)
867
        self.assertEqual(rev_id2, tree.last_revision())
868
869
        rt = tree.branch.repository.revision_tree(rev_id2)
870
        entries = [(path, ie.file_id) for path, ie in rt.iter_entries_by_dir()
871
                                       if path] # Ignore the root entry
872
        self.assertEqual([('a', 'a-id'), ('b', 'b-id')], entries)
873
278.1.27 by John Arbash Meinel
Add the ability to commit just specific files.
874
    def test_commit_no_messages(self):
875
        tree = self.make_branch_and_tree('tree')
876
        rev_id1 = tree.commit('one')
877
        self.build_tree(['tree/a', 'tree/b'])
878
        tree.add(['a', 'b'], ['a-id', 'b-id'])
879
880
        dlg = commit.CommitDialog(tree)
881
        dlg._set_global_commit_message('Simple commit\n')
882
        dlg._do_commit()
883
884
        rev = tree.branch.repository.get_revision(dlg.committed_revision_id)
885
        self.failIf('file-info' in rev.properties)
886
278.1.33 by John Arbash Meinel
Only enable the per-file dialog if 'per_file_commits' is enabled in the config.
887
    def test_commit_disabled_messages(self):
888
        tree = self.make_branch_and_tree('tree')
889
        rev_id1 = tree.commit('one')
890
891
        self.build_tree(['tree/a', 'tree/b'])
892
        tree.add(['a', 'b'], ['a-id', 'b-id'])
893
894
        dlg = commit.CommitDialog(tree)
895
        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
896
        self.assertEqual('Commit Message',
897
                         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.
898
899
        tree.branch.get_config().set_user_option('per_file_commits', 'true')
900
        dlg = commit.CommitDialog(tree)
901
        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
902
        self.assertEqual('Global Commit Message',
903
                         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.
904
905
        tree.branch.get_config().set_user_option('per_file_commits', 'on')
906
        dlg = commit.CommitDialog(tree)
907
        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
908
        self.assertEqual('Global Commit Message',
909
                         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.
910
911
        tree.branch.get_config().set_user_option('per_file_commits', 'y')
912
        dlg = commit.CommitDialog(tree)
913
        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
914
        self.assertEqual('Global Commit Message',
915
                         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.
916
917
        tree.branch.get_config().set_user_option('per_file_commits', 'n')
918
        dlg = commit.CommitDialog(tree)
919
        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
920
        self.assertEqual('Commit Message',
921
                         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.
922
278.1.27 by John Arbash Meinel
Add the ability to commit just specific files.
923
    def test_commit_specific_files_with_messages(self):
924
        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.
925
        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.
926
        rev_id1 = tree.commit('one')
927
        self.build_tree(['tree/a', 'tree/b'])
928
        tree.add(['a', 'b'], ['a-id', 'b-id'])
929
930
        dlg = commit.CommitDialog(tree)
278.1.43 by John Arbash Meinel
Finish connecting the 'Commit all changes' radio buttons.
931
        dlg._commit_selected_radio.set_active(True) # enable partial
278.1.27 by John Arbash Meinel
Add the ability to commit just specific files.
932
        dlg._treeview_files.set_cursor((1,))
933
        dlg._set_file_commit_message('Message for A\n')
934
        dlg._treeview_files.set_cursor((2,))
935
        dlg._set_file_commit_message('Message for B\n')
936
        dlg._toggle_commit(None, 2, dlg._files_store) # unset 'b'
937
        dlg._set_global_commit_message('Commit just "a"')
938
939
        dlg._do_commit()
940
941
        rev_id2 = dlg.committed_revision_id
942
        self.assertEqual(rev_id2, tree.last_revision())
943
        rev = tree.branch.repository.get_revision(rev_id2)
944
        self.assertEqual('Commit just "a"', rev.message)
945
        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)
950
        self.assertEqual([{'path':'a', 'file_id':'a-id',
951
                           'message':'Message for A\n'},
952
                         ], bencode.bdecode(file_info))
278.1.28 by John Arbash Meinel
Ensure that we can set per-file messages even during a merge.
953
954
    def test_commit_messages_after_merge(self):
955
        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.
956
        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.
957
        rev_id1 = tree.commit('one')
958
        tree2 = tree.bzrdir.sprout('tree2').open_workingtree()
959
        self.build_tree(['tree2/a', 'tree2/b'])
960
        tree2.add(['a', 'b'], ['a-id', 'b-id'])
961
        rev_id2 = tree2.commit('two')
962
963
        tree.merge_from_branch(tree2.branch)
964
965
        dlg = commit.CommitDialog(tree)
966
        dlg._treeview_files.set_cursor((1,)) # 'a'
967
        dlg._set_file_commit_message('Message for A\n')
968
        # No message for 'B'
969
        dlg._set_global_commit_message('Merging from "tree2"\n')
970
971
        dlg._do_commit()
972
973
        rev_id3 = dlg.committed_revision_id
974
        self.assertEqual(rev_id3, tree.last_revision())
975
        rev = tree.branch.repository.get_revision(rev_id3)
976
        self.assertEqual('Merging from "tree2"\n', rev.message)
977
        self.assertEqual([rev_id1, rev_id2], rev.parent_ids)
978
        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)
983
        self.assertEqual([{'path':'a', 'file_id':'a-id',
984
                           'message':'Message for A\n'},
985
                         ], bencode.bdecode(file_info))
278.1.29 by John Arbash Meinel
Start testing with Unicode data.
986
987
    def test_commit_unicode_messages(self):
988
        from bzrlib.tests.test_diff import UnicodeFilename
989
        self.requireFeature(UnicodeFilename)
990
991
        tree = self.make_branch_and_tree('tree')
278.1.33 by John Arbash Meinel
Only enable the per-file dialog if 'per_file_commits' is enabled in the config.
992
        tree.branch.get_config().set_user_option('per_file_commits', 'true')
278.1.29 by John Arbash Meinel
Start testing with Unicode data.
993
        self.build_tree(['tree/a', u'tree/\u03a9'])
994
        tree.add(['a', u'\u03a9'], ['a-id', 'omega-id'])
995
996
        dlg = commit.CommitDialog(tree)
997
        dlg._treeview_files.set_cursor((1,)) # 'a'
998
        dlg._set_file_commit_message(u'Test \xfan\xecc\xf6de\n')
999
        dlg._treeview_files.set_cursor((2,)) # omega
1000
        dlg._set_file_commit_message(u'\u03a9 is the end of all things.\n')
1001
        dlg._set_global_commit_message(u'\u03a9 and \xfan\xecc\xf6de\n')
1002
1003
        self.assertEqual(([u'a', u'\u03a9'],
1004
                          [{'path':'a', 'file_id':'a-id',
1005
                            'message':'Test \xc3\xban\xc3\xacc\xc3\xb6de\n'},
1006
                           {'path':'\xce\xa9', 'file_id':'omega-id',
1007
                            'message':'\xce\xa9 is the end of all things.\n'},
1008
                          ]), dlg._get_specific_files())
1009
1010
        dlg._do_commit()
1011
1012
        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.
1013
        file_info = rev.properties['file-info'].encode('UTF-8')
278.1.29 by John Arbash Meinel
Start testing with Unicode data.
1014
        value = ('ld7:file_id4:a-id'
1015
                   '7:message16:Test \xc3\xban\xc3\xacc\xc3\xb6de\n'
1016
                   '4:path1:a'
1017
                  'e'
1018
                  'd7:file_id8:omega-id'
1019
                   '7:message29:\xce\xa9 is the end of all things.\n'
1020
                   '4:path2:\xce\xa9'
1021
                  'e'
1022
                 'e')
1023
        self.assertEqual(value, file_info)
1024
        file_info_decoded = bencode.bdecode(file_info)
1025
        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.
1026
            d['path'] = d['path'].decode('UTF-8')
1027
            d['message'] = d['message'].decode('UTF-8')
278.1.29 by John Arbash Meinel
Start testing with Unicode data.
1028
1029
        self.assertEqual([{'path':u'a', 'file_id':'a-id',
1030
                           'message':u'Test \xfan\xecc\xf6de\n'},
1031
                          {'path':u'\u03a9', 'file_id':'omega-id',
1032
                           'message':u'\u03a9 is the end of all things.\n'},
1033
                         ], file_info_decoded)