/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]
211
        self.assertTrue(renderer.get_active())
278.1.14 by John Arbash Meinel
Tests that we fill out the pending list correctly.
212
213
    def test_pending(self):
214
        tree = self.make_branch_and_tree('tree')
215
        rev_id1 = tree.commit('one')
216
217
        tree2 = tree.bzrdir.sprout('tree2').open_workingtree()
218
        rev_id2 = tree2.commit('two',
219
                               committer='Joe Foo <joe@foo.com>',
220
                               timestamp=1191264271.05,
221
                               timezone=+7200)
222
        tree.merge_from_branch(tree2.branch)
223
224
        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.
225
226
        self.assertTrue(dlg._pending_box.get_property('visible'))
227
278.1.17 by John Arbash Meinel
Add a * reference for why you can't change the commit selection.
228
        commit_col = dlg._treeview_files.get_column(0)
229
        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,
230
        renderer = commit_col.get_cell_renderers()[0]
231
        self.assertFalse(renderer.get_active())
278.1.17 by John Arbash Meinel
Add a * reference for why you can't change the commit selection.
232
278.1.15 by John Arbash Meinel
Hook up the list of modified files.
233
        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.
234
        self.assertEqual([(rev_id2, '2007-10-01', 'Joe Foo', 'two')], values)
235
236
    def test_pending_multiple(self):
237
        tree = self.make_branch_and_tree('tree')
238
        rev_id1 = tree.commit('one')
239
240
        tree2 = tree.bzrdir.sprout('tree2').open_workingtree()
241
        rev_id2 = tree2.commit('two',
242
                               committer='Joe Foo <joe@foo.com>',
243
                               timestamp=1191264271.05,
244
                               timezone=+7200)
245
        rev_id3 = tree2.commit('three',
246
                               committer='Jerry Foo <jerry@foo.com>',
247
                               timestamp=1191264278.05,
248
                               timezone=+7200)
249
        tree.merge_from_branch(tree2.branch)
250
        tree3 = tree.bzrdir.sprout('tree3').open_workingtree()
251
        rev_id4 = tree3.commit('four',
252
                               committer='Joe Foo <joe@foo.com>',
253
                               timestamp=1191264279.05,
254
                               timezone=+7200)
255
        rev_id5 = tree3.commit('five',
256
                               committer='Jerry Foo <jerry@foo.com>',
257
                               timestamp=1191372278.05,
258
                               timezone=+7200)
259
        tree.merge_from_branch(tree3.branch)
260
261
        dlg = commit.CommitDialog(tree)
262
        # TODO: assert that the pending box is set to show
278.1.15 by John Arbash Meinel
Hook up the list of modified files.
263
        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.
264
        self.assertEqual([(rev_id3, '2007-10-01', 'Jerry Foo', 'three'),
265
                          (rev_id2, '2007-10-01', 'Joe Foo', 'two'),
266
                          (rev_id5, '2007-10-03', 'Jerry Foo', 'five'),
267
                          (rev_id4, '2007-10-01', 'Joe Foo', 'four'),
268
                         ], values)
278.1.15 by John Arbash Meinel
Hook up the list of modified files.
269
278.1.16 by John Arbash Meinel
Implement the file changes list on top of _iter_changes rather than
270
    def test_filelist_added(self):
278.1.15 by John Arbash Meinel
Hook up the list of modified files.
271
        tree = self.make_branch_and_tree('tree')
272
        self.build_tree(['tree/a', 'tree/b/', 'tree/b/c'])
273
        tree.add(['a', 'b', 'b/c'], ['a-id', 'b-id', 'c-id'])
274
275
        dlg = commit.CommitDialog(tree)
276
        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,
277
        self.assertEqual([(None, None, True, 'All Files', ''),
278
                          ('a-id', 'a', True, 'a', 'added'),
278.1.15 by John Arbash Meinel
Hook up the list of modified files.
279
                          ('b-id', 'b', True, 'b/', 'added'),
280
                          ('c-id', 'b/c', True, 'b/c', 'added'),
281
                         ], values)
278.1.16 by John Arbash Meinel
Implement the file changes list on top of _iter_changes rather than
282
283
    def test_filelist_renamed(self):
284
        tree = self.make_branch_and_tree('tree')
285
        self.build_tree(['tree/a', 'tree/b/', 'tree/b/c'])
286
        tree.add(['a', 'b', 'b/c'], ['a-id', 'b-id', 'c-id'])
287
        rev_id1 = tree.commit('one')
288
289
        tree.rename_one('b', 'd')
290
        tree.rename_one('a', 'd/a')
291
292
        dlg = commit.CommitDialog(tree)
293
        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,
294
        self.assertEqual([(None, None, True, 'All Files', ''),
295
                          ('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
296
                          ('a-id', 'd/a', True, 'a => d/a', 'renamed'),
297
                         ], values)
298
299
    def test_filelist_modified(self):
300
        tree = self.make_branch_and_tree('tree')
301
        self.build_tree(['tree/a'])
302
        tree.add(['a'], ['a-id'])
303
        rev_id1 = tree.commit('one')
304
305
        self.build_tree_contents([('tree/a', 'new contents for a\n')])
306
307
        dlg = commit.CommitDialog(tree)
308
        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,
309
        self.assertEqual([(None, None, True, 'All Files', ''),
310
                          ('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
311
                         ], values)
312
313
    def test_filelist_renamed_and_modified(self):
314
        tree = self.make_branch_and_tree('tree')
315
        self.build_tree(['tree/a', 'tree/b/', 'tree/b/c'])
316
        tree.add(['a', 'b', 'b/c'], ['a-id', 'b-id', 'c-id'])
317
        rev_id1 = tree.commit('one')
318
319
        tree.rename_one('b', 'd')
320
        tree.rename_one('a', 'd/a')
321
        self.build_tree_contents([('tree/d/a', 'new contents for a\n'),
322
                                  ('tree/d/c', 'new contents for c\n'),
323
                                 ])
324
        # 'c' is not considered renamed, because only its parent was moved, it
325
        # stayed in the same directory
326
327
        dlg = commit.CommitDialog(tree)
328
        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,
329
        self.assertEqual([(None, None, True, 'All Files', ''),
330
                          ('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
331
                          ('a-id', 'd/a', True, 'a => d/a', 'renamed and modified'),
332
                          ('c-id', 'd/c', True, 'd/c', 'modified'),
333
                         ], values)
334
335
    def test_filelist_kind_changed(self):
336
        tree = self.make_branch_and_tree('tree')
337
        self.build_tree(['tree/a', 'tree/b'])
338
        tree.add(['a', 'b'], ['a-id', 'b-id'])
339
        tree.commit('one')
340
341
        os.remove('tree/a')
342
        self.build_tree(['tree/a/'])
278.1.17 by John Arbash Meinel
Add a * reference for why you can't change the commit selection.
343
        # XXX:  This is technically valid, and the file list handles it fine,
344
        #       but 'show_diff_trees()' does not, so we skip this part of the
345
        #       test for now.
346
        # tree.rename_one('b', 'c')
347
        # os.remove('tree/c')
348
        # self.build_tree(['tree/c/'])
278.1.16 by John Arbash Meinel
Implement the file changes list on top of _iter_changes rather than
349
350
        dlg = commit.CommitDialog(tree)
351
        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,
352
        self.assertEqual([(None, None, True, 'All Files', ''),
353
                          ('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.
354
                          # ('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
355
                         ], values)
356
357
    def test_filelist_removed(self):
358
        tree = self.make_branch_and_tree('tree')
359
        self.build_tree(['tree/a', 'tree/b/'])
360
        tree.add(['a', 'b'], ['a-id', 'b-id'])
361
        tree.commit('one')
362
363
        os.remove('tree/a')
364
        tree.remove('b', force=True)
365
366
        dlg = commit.CommitDialog(tree)
367
        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,
368
        self.assertEqual([(None, None, True, 'All Files', ''),
369
                          ('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
370
                          ('b-id', 'b', True, 'b/', 'removed'),
371
                         ], values)
278.1.35 by John Arbash Meinel
Make use of the 'selected' parameter to CommitDialog.
372
        # All Files should be selected
373
        self.assertEqual(((0,), None), dlg._treeview_files.get_cursor())
374
375
    def test_filelist_with_selected(self):
376
        tree = self.make_branch_and_tree('tree')
377
        self.build_tree(['tree/a', 'tree/b/'])
378
        tree.add(['a', 'b'], ['a-id', 'b-id'])
379
380
        dlg = commit.CommitDialog(tree, selected='a')
381
        values = [(r[0], r[1], r[2], r[3], r[4]) for r in dlg._files_store]
382
        self.assertEqual([(None, None, False, 'All Files', ''),
383
                          ('a-id', 'a', True, 'a', 'added'),
384
                          ('b-id', 'b', False, 'b/', 'added'),
385
                         ], values)
386
        # This file should also be selected in the file list, rather than the
387
        # 'All Files' selection
388
        self.assertEqual(((1,), None), dlg._treeview_files.get_cursor())
278.1.18 by John Arbash Meinel
Start checking the diff view is correct.
389
390
    def test_diff_view(self):
391
        tree = self.make_branch_and_tree('tree')
392
        self.build_tree(['tree/a', 'tree/b'])
393
        tree.add(['a', 'b'], ['a-id', 'b-id'])
394
        tree.commit('one')
395
396
        self.build_tree_contents([('tree/a', 'new contents for a\n')])
397
        tree.remove('b')
398
399
        dlg = commit.CommitDialog(tree)
400
        diff_buffer = dlg._diff_view.buffer
401
        text = diff_buffer.get_text(diff_buffer.get_start_iter(),
402
                                    diff_buffer.get_end_iter()).splitlines(True)
403
404
        self.assertEqual("=== removed file 'b'\n", text[0])
405
        self.assertContainsRe(text[1],
406
            r"--- b\t\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d [+-]\d\d\d\d")
407
        self.assertEqual('+++ b\t1970-01-01 00:00:00 +0000\n', text[2])
408
        self.assertEqual('@@ -1,1 +0,0 @@\n', text[3])
409
        self.assertEqual('-contents of tree/b\n', text[4])
410
        self.assertEqual('\n', text[5])
411
412
        self.assertEqual("=== modified file 'a'\n", text[6])
413
        self.assertContainsRe(text[7],
414
            r"--- a\t\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d [+-]\d\d\d\d")
415
        self.assertContainsRe(text[8],
416
            r"\+\+\+ a\t\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d [+-]\d\d\d\d")
417
        self.assertEqual('@@ -1,1 +1,1 @@\n', text[9])
418
        self.assertEqual('-contents of tree/a\n', text[10])
419
        self.assertEqual('+new contents for a\n', text[11])
420
        self.assertEqual('\n', text[12])
421
278.1.20 by John Arbash Meinel
We always select the All Files record in the files view,
422
        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.
423
424
    def test_file_selection(self):
425
        """Several things should happen when a file has been selected."""
426
        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.
427
        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.
428
        self.build_tree(['tree/a', 'tree/b'])
429
        tree.add(['a', 'b'], ['a-id', 'b-id'])
430
431
        dlg = commit.CommitDialog(tree)
432
        diff_buffer = dlg._diff_view.buffer
278.1.20 by John Arbash Meinel
We always select the All Files record in the files view,
433
        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.
434
        self.assertEqual('File commit message',
435
                         dlg._file_message_expander.get_label())
436
        self.assertFalse(dlg._file_message_expander.get_expanded())
437
        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.
438
278.1.20 by John Arbash Meinel
We always select the All Files record in the files view,
439
        dlg._treeview_files.set_cursor((1,))
278.1.19 by John Arbash Meinel
Test what happens when a specific file is selected.
440
        self.assertEqual('Diff for a', dlg._diff_label.get_text())
441
        text = diff_buffer.get_text(diff_buffer.get_start_iter(),
442
                                    diff_buffer.get_end_iter()).splitlines(True)
443
        self.assertEqual("=== added file 'a'\n", text[0])
444
        self.assertContainsRe(text[1],
445
            r"--- a\t\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d [+-]\d\d\d\d")
446
        self.assertContainsRe(text[2],
447
            r"\+\+\+ a\t\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d [+-]\d\d\d\d")
448
        self.assertEqual('@@ -0,0 +1,1 @@\n', text[3])
449
        self.assertEqual('+contents of tree/a\n', text[4])
450
        self.assertEqual('\n', text[5])
278.1.21 by John Arbash Meinel
Start tracking the per-file commit messages.
451
        self.assertEqual('Commit message for a',
452
                         dlg._file_message_expander.get_label())
453
        self.assertTrue(dlg._file_message_expander.get_expanded())
454
        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.
455
278.1.20 by John Arbash Meinel
We always select the All Files record in the files view,
456
        dlg._treeview_files.set_cursor((2,))
278.1.19 by John Arbash Meinel
Test what happens when a specific file is selected.
457
        self.assertEqual('Diff for b', dlg._diff_label.get_text())
458
        text = diff_buffer.get_text(diff_buffer.get_start_iter(),
459
                                    diff_buffer.get_end_iter()).splitlines(True)
460
        self.assertEqual("=== added file 'b'\n", text[0])
461
        self.assertContainsRe(text[1],
462
            r"--- b\t\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d [+-]\d\d\d\d")
463
        self.assertContainsRe(text[2],
464
            r"\+\+\+ b\t\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d [+-]\d\d\d\d")
465
        self.assertEqual('@@ -0,0 +1,1 @@\n', text[3])
466
        self.assertEqual('+contents of tree/b\n', text[4])
467
        self.assertEqual('\n', text[5])
278.1.21 by John Arbash Meinel
Start tracking the per-file commit messages.
468
        self.assertEqual('Commit message for b',
469
                         dlg._file_message_expander.get_label())
470
        self.assertTrue(dlg._file_message_expander.get_expanded())
471
        self.assertTrue(dlg._file_message_expander.get_property('sensitive'))
472
473
        dlg._treeview_files.set_cursor((0,))
474
        self.assertEqual('Diff for All Files', dlg._diff_label.get_text())
475
        self.assertEqual('File commit message',
476
                         dlg._file_message_expander.get_label())
477
        self.assertFalse(dlg._file_message_expander.get_expanded())
478
        self.assertFalse(dlg._file_message_expander.get_property('sensitive'))
479
480
    def test_file_selection_message(self):
481
        """Selecting a file should bring up its commit message."""
482
        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.
483
        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.
484
        self.build_tree(['tree/a', 'tree/b/'])
485
        tree.add(['a', 'b'], ['a-id', 'b-id'])
486
487
        def get_file_text():
488
            buf = dlg._file_message_text_view.get_buffer()
489
            return buf.get_text(buf.get_start_iter(), buf.get_end_iter())
490
491
        def get_saved_text(path):
492
            """Get the saved text for a given record."""
493
            return dlg._files_store.get_value(dlg._files_store.get_iter(path), 5)
494
495
        dlg = commit.CommitDialog(tree)
496
        self.assertEqual('File commit message',
497
                         dlg._file_message_expander.get_label())
498
        self.assertFalse(dlg._file_message_expander.get_expanded())
499
        self.assertFalse(dlg._file_message_expander.get_property('sensitive'))
500
        self.assertEqual('', get_file_text())
501
502
        dlg._treeview_files.set_cursor((1,))
503
        self.assertEqual('Commit message for a',
504
                         dlg._file_message_expander.get_label())
505
        self.assertTrue(dlg._file_message_expander.get_expanded())
506
        self.assertTrue(dlg._file_message_expander.get_property('sensitive'))
507
        self.assertEqual('', get_file_text())
508
509
        self.assertEqual('', get_saved_text(1))
278.1.27 by John Arbash Meinel
Add the ability to commit just specific files.
510
        dlg._set_file_commit_message('Some text\nfor a\n')
278.1.21 by John Arbash Meinel
Start tracking the per-file commit messages.
511
        dlg._save_current_file_message()
512
        # We should have updated the ListStore with the new file commit info
513
        self.assertEqual('Some text\nfor a\n', get_saved_text(1))
514
515
        dlg._treeview_files.set_cursor((2,))
516
        self.assertEqual('Commit message for b/',
517
                         dlg._file_message_expander.get_label())
518
        self.assertTrue(dlg._file_message_expander.get_expanded())
519
        self.assertTrue(dlg._file_message_expander.get_property('sensitive'))
520
        self.assertEqual('', get_file_text())
521
522
        self.assertEqual('', get_saved_text(2))
278.1.27 by John Arbash Meinel
Add the ability to commit just specific files.
523
        dlg._set_file_commit_message('More text\nfor b\n')
278.1.21 by John Arbash Meinel
Start tracking the per-file commit messages.
524
        # Now switch back to 'a'. The message should be saved, and the buffer
525
        # should be updated with the other text
526
        dlg._treeview_files.set_cursor((1,))
527
        self.assertEqual('More text\nfor b\n', get_saved_text(2))
528
        self.assertEqual('Commit message for a',
529
                         dlg._file_message_expander.get_label())
530
        self.assertTrue(dlg._file_message_expander.get_expanded())
531
        self.assertTrue(dlg._file_message_expander.get_property('sensitive'))
532
        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,
533
534
    def test_toggle_all_files(self):
535
        """When checking the All Files entry, it should toggle all fields"""
536
        tree = self.make_branch_and_tree('tree')
537
        self.build_tree(['tree/a', 'tree/b/'])
538
        tree.add(['a', 'b'], ['a-id', 'b-id'])
539
540
        dlg = commit.CommitDialog(tree)
541
        self.assertEqual([(None, None, True),
542
                          ('a-id', 'a', True),
543
                          ('b-id', 'b', True),
544
                         ], [(r[0], r[1], r[2]) for r in dlg._files_store])
545
546
        # TODO: jam 20071002 I'm not sure how to exactly trigger a toggle, it
547
        #       looks like we need to call renderer.activate() and pass an
548
        #       event and widget, and lots of other stuff I'm not sure what to
549
        #       do with. So instead, we just call toggle directly, and assume
550
        #       that toggle is hooked in correctly
551
        # column = dlg._treeview_files.get_column(0)
552
        # renderer = column.get_cell_renderers()[0]
553
554
        # Toggle a single entry should set just that entry to False
555
        dlg._toggle_commit(None, 1, dlg._files_store)
556
        self.assertEqual([(None, None, True),
557
                          ('a-id', 'a', False),
558
                          ('b-id', 'b', True),
559
                         ], [(r[0], r[1], r[2]) for r in dlg._files_store])
560
561
        # Toggling the main entry should set all entries
562
        dlg._toggle_commit(None, 0, dlg._files_store)
563
        self.assertEqual([(None, None, False),
564
                          ('a-id', 'a', False),
565
                          ('b-id', 'b', False),
566
                         ], [(r[0], r[1], r[2]) for r in dlg._files_store])
567
568
        dlg._toggle_commit(None, 2, dlg._files_store)
569
        self.assertEqual([(None, None, False),
570
                          ('a-id', 'a', False),
571
                          ('b-id', 'b', True),
572
                         ], [(r[0], r[1], r[2]) for r in dlg._files_store])
573
574
        dlg._toggle_commit(None, 0, dlg._files_store)
575
        self.assertEqual([(None, None, True),
576
                          ('a-id', 'a', True),
577
                          ('b-id', 'b', True),
578
                         ], [(r[0], r[1], r[2]) for r in dlg._files_store])
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
579
278.1.27 by John Arbash Meinel
Add the ability to commit just specific files.
580
    def test_specific_files(self):
581
        tree = self.make_branch_and_tree('tree')
582
        self.build_tree(['tree/a', 'tree/b/'])
583
        tree.add(['a', 'b'], ['a-id', 'b-id'])
584
585
        dlg = commit.CommitDialog(tree)
586
        self.assertEqual((['a', 'b'], []), dlg._get_specific_files())
587
588
        dlg._toggle_commit(None, 0, dlg._files_store)
589
        self.assertEqual(([], []), dlg._get_specific_files())
590
591
        dlg._toggle_commit(None, 1, dlg._files_store)
592
        self.assertEqual((['a'], []), dlg._get_specific_files())
593
594
    def test_specific_files_with_messages(self):
595
        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.
596
        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.
597
        self.build_tree(['tree/a_file', 'tree/b_dir/'])
598
        tree.add(['a_file', 'b_dir'], ['1a-id', '0b-id'])
599
600
        dlg = commit.CommitDialog(tree)
601
        self.assertEqual((['a_file', 'b_dir'], []), dlg._get_specific_files())
602
603
        dlg._treeview_files.set_cursor((1,))
604
        dlg._set_file_commit_message('Test\nmessage\nfor a_file\n')
605
        dlg._treeview_files.set_cursor((2,))
606
        dlg._set_file_commit_message('message\nfor b_dir\n')
607
608
        self.assertEqual((['a_file', 'b_dir'],
609
                          [{'path':'a_file', 'file_id':'1a-id',
610
                            'message':'Test\nmessage\nfor a_file\n'},
611
                           {'path':'b_dir', 'file_id':'0b-id',
612
                            'message':'message\nfor b_dir\n'},
613
                          ]), dlg._get_specific_files())
614
615
        dlg._toggle_commit(None, 1, dlg._files_store)
616
        self.assertEqual((['b_dir'],
617
                          [{'path':'b_dir', 'file_id':'0b-id',
618
                            'message':'message\nfor b_dir\n'},
619
                          ]), dlg._get_specific_files())
620
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
621
622
class TestCommitDialog_Commit(tests.TestCaseWithTransport):
623
    """Tests on the actual 'commit' button being pushed."""
624
278.1.26 by John Arbash Meinel
Handle pointless commits and trees with unknown files.
625
    def _set_question_yes(self, dlg):
626
        """Set the dialog to answer YES to any questions."""
627
        self.questions = []
628
        def _question_yes(*args):
629
            self.questions.append(args)
630
            self.questions.append('YES')
631
            return gtk.RESPONSE_YES
632
        dlg._question_dialog = _question_yes
633
634
    def _set_question_no(self, dlg):
635
        """Set the dialog to answer NO to any questions."""
636
        self.questions = []
637
        def _question_no(*args):
638
            self.questions.append(args)
639
            self.questions.append('NO')
640
            return gtk.RESPONSE_NO
641
        dlg._question_dialog = _question_no
642
278.1.25 by John Arbash Meinel
Add the 'Only Commit Locally' checkbox, we may want to put it elsewhere, though.
643
    def test_bound_commit_local(self):
644
        tree = self.make_branch_and_tree('tree')
645
        self.build_tree(['tree/a'])
646
        tree.add(['a'], ['a-id'])
647
        rev_id1 = tree.commit('one')
648
649
        tree2 = tree.bzrdir.sprout('tree2').open_workingtree()
650
        self.build_tree(['tree2/b'])
651
        tree2.add(['b'], ['b-id'])
652
        tree2.branch.bind(tree.branch)
653
654
        dlg = commit.CommitDialog(tree2)
655
        # With the check box set, it should only effect the local branch
656
        dlg._check_local.set_active(True)
657
        dlg._set_global_commit_message('Commit message\n')
658
        dlg._do_commit()
659
660
        last_rev = tree2.last_revision()
661
        self.assertEqual(last_rev, dlg.committed_revision_id)
662
        self.assertEqual(rev_id1, tree.branch.last_revision())
663
664
    def test_bound_commit_both(self):
665
        tree = self.make_branch_and_tree('tree')
666
        self.build_tree(['tree/a'])
667
        tree.add(['a'], ['a-id'])
668
        rev_id1 = tree.commit('one')
669
670
        tree2 = tree.bzrdir.sprout('tree2').open_workingtree()
671
        self.build_tree(['tree2/b'])
672
        tree2.add(['b'], ['b-id'])
673
        tree2.branch.bind(tree.branch)
674
675
        dlg = commit.CommitDialog(tree2)
676
        # With the check box set, it should only effect the local branch
677
        dlg._check_local.set_active(False)
678
        dlg._set_global_commit_message('Commit message\n')
679
        dlg._do_commit()
680
681
        last_rev = tree2.last_revision()
682
        self.assertEqual(last_rev, dlg.committed_revision_id)
683
        self.assertEqual(last_rev, tree.branch.last_revision())
684
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
685
    def test_commit_no_message(self):
686
        tree = self.make_branch_and_tree('tree')
687
        self.build_tree(['tree/a', 'tree/b'])
688
        tree.add(['a'], ['a-id'])
689
        rev_id = tree.commit('one')
690
691
        tree.add(['b'], ['b-id'])
692
693
        dlg = commit.CommitDialog(tree)
278.1.26 by John Arbash Meinel
Handle pointless commits and trees with unknown files.
694
        self._set_question_no(dlg)
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
695
        dlg._do_commit()
696
        self.assertEqual(
697
            [('Commit with an empty message?',
698
              'You can describe your commit intent in the message.'),
699
              'NO',
278.1.26 by John Arbash Meinel
Handle pointless commits and trees with unknown files.
700
            ], self.questions)
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
701
        # By saying NO, nothing should be committed.
702
        self.assertEqual(rev_id, tree.last_revision())
703
        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.
704
        self.assertTrue(dlg._global_message_text_view.get_property('is-focus'))
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
705
278.1.26 by John Arbash Meinel
Handle pointless commits and trees with unknown files.
706
        self._set_question_yes(dlg)
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
707
708
        dlg._do_commit()
709
        self.assertEqual(
710
            [('Commit with an empty message?',
711
              'You can describe your commit intent in the message.'),
278.1.26 by John Arbash Meinel
Handle pointless commits and trees with unknown files.
712
              'YES',
713
            ], self.questions)
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
714
        committed = tree.last_revision()
715
        self.assertNotEqual(rev_id, committed)
716
        self.assertEqual(committed, dlg.committed_revision_id)
717
718
    def test_initial_commit(self):
719
        tree = self.make_branch_and_tree('tree')
720
        self.build_tree(['tree/a'])
721
        tree.add(['a'], ['a-id'])
722
723
        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.
724
        dlg._set_global_commit_message('Some text\n')
278.1.23 by John Arbash Meinel
Beginning to support actual commit.
725
        dlg._do_commit()
726
727
        last_rev = tree.last_revision()
728
        self.assertEqual(last_rev, dlg.committed_revision_id)
729
        rev = tree.branch.repository.get_revision(last_rev)
730
        self.assertEqual(last_rev, rev.revision_id)
731
        self.assertEqual('Some text\n', rev.message)
278.1.26 by John Arbash Meinel
Handle pointless commits and trees with unknown files.
732
733
    def test_pointless_commit(self):
734
        tree = self.make_branch_and_tree('tree')
735
        self.build_tree(['tree/a'])
736
        tree.add(['a'], ['a-id'])
737
        rev_id1 = tree.commit('one')
738
739
        dlg = commit.CommitDialog(tree)
740
        dlg._set_global_commit_message('Some text\n')
741
742
        self._set_question_no(dlg)
743
        dlg._do_commit()
744
745
        self.assertIs(None, dlg.committed_revision_id)
746
        self.assertEqual(rev_id1, tree.last_revision())
747
        self.assertEqual(
748
            [('Commit with no changes?',
749
              'There are no changes in the working tree.'
750
              ' Do you want to commit anyway?'),
751
              'NO',
752
            ], self.questions)
753
754
        self._set_question_yes(dlg)
755
        dlg._do_commit()
756
757
        rev_id2 = tree.last_revision()
758
        self.assertEqual(rev_id2, dlg.committed_revision_id)
759
        self.assertNotEqual(rev_id1, rev_id2)
760
        self.assertEqual(
761
            [('Commit with no changes?',
762
              'There are no changes in the working tree.'
763
              ' Do you want to commit anyway?'),
764
              'YES',
765
            ], self.questions)
766
767
    def test_unknowns(self):
768
        """We should check if there are unknown files."""
769
        tree = self.make_branch_and_tree('tree')
770
        rev_id1 = tree.commit('one')
771
        self.build_tree(['tree/a', 'tree/b'])
772
        tree.add(['a'], ['a-id'])
773
774
        dlg = commit.CommitDialog(tree)
775
        dlg._set_global_commit_message('Some text\n')
776
        self._set_question_no(dlg)
777
778
        dlg._do_commit()
779
780
        self.assertIs(None, dlg.committed_revision_id)
781
        self.assertEqual(rev_id1, tree.last_revision())
782
        self.assertEqual(
783
            [("Commit with unknowns?",
784
              "Unknown files exist in the working tree. Commit anyway?"),
785
              "NO",
786
            ], self.questions)
787
788
        self._set_question_yes(dlg)
789
        dlg._do_commit()
790
791
        rev_id2 = tree.last_revision()
792
        self.assertNotEqual(rev_id1, rev_id2)
793
        self.assertEqual(rev_id2, dlg.committed_revision_id)
794
        self.assertEqual(
795
            [("Commit with unknowns?",
796
              "Unknown files exist in the working tree. Commit anyway?"),
797
              "YES",
798
            ], self.questions)
799
278.1.27 by John Arbash Meinel
Add the ability to commit just specific files.
800
    def test_commit_specific_files(self):
801
        tree = self.make_branch_and_tree('tree')
802
        rev_id1 = tree.commit('one')
803
        self.build_tree(['tree/a', 'tree/b'])
804
        tree.add(['a', 'b'], ['a-id', 'b-id'])
805
806
        dlg = commit.CommitDialog(tree)
807
        dlg._toggle_commit(None, 2, dlg._files_store) # unset 'b'
808
809
        dlg._set_global_commit_message('Committing just "a"\n')
810
        dlg._do_commit()
811
812
        rev_id2 = dlg.committed_revision_id
813
        self.assertIsNot(None, rev_id2)
814
        self.assertEqual(rev_id2, tree.last_revision())
815
816
        rt = tree.branch.repository.revision_tree(rev_id2)
817
        entries = [(path, ie.file_id) for path, ie in rt.iter_entries_by_dir()
818
                                       if path] # Ignore the root entry
819
        self.assertEqual([('a', 'a-id')], entries)
820
821
    def test_commit_no_messages(self):
822
        tree = self.make_branch_and_tree('tree')
823
        rev_id1 = tree.commit('one')
824
        self.build_tree(['tree/a', 'tree/b'])
825
        tree.add(['a', 'b'], ['a-id', 'b-id'])
826
827
        dlg = commit.CommitDialog(tree)
828
        dlg._set_global_commit_message('Simple commit\n')
829
        dlg._do_commit()
830
831
        rev = tree.branch.repository.get_revision(dlg.committed_revision_id)
832
        self.failIf('file-info' in rev.properties)
833
278.1.33 by John Arbash Meinel
Only enable the per-file dialog if 'per_file_commits' is enabled in the config.
834
    def test_commit_disabled_messages(self):
835
        tree = self.make_branch_and_tree('tree')
836
        rev_id1 = tree.commit('one')
837
838
        self.build_tree(['tree/a', 'tree/b'])
839
        tree.add(['a', 'b'], ['a-id', 'b-id'])
840
841
        dlg = commit.CommitDialog(tree)
842
        self.assertFalse(dlg._file_message_expander.get_property('visible'))
843
844
        tree.branch.get_config().set_user_option('per_file_commits', 'true')
845
        dlg = commit.CommitDialog(tree)
846
        self.assertTrue(dlg._file_message_expander.get_property('visible'))
847
848
        tree.branch.get_config().set_user_option('per_file_commits', 'on')
849
        dlg = commit.CommitDialog(tree)
850
        self.assertTrue(dlg._file_message_expander.get_property('visible'))
851
852
        tree.branch.get_config().set_user_option('per_file_commits', 'y')
853
        dlg = commit.CommitDialog(tree)
854
        self.assertTrue(dlg._file_message_expander.get_property('visible'))
855
856
        tree.branch.get_config().set_user_option('per_file_commits', 'n')
857
        dlg = commit.CommitDialog(tree)
858
        self.assertFalse(dlg._file_message_expander.get_property('visible'))
859
278.1.27 by John Arbash Meinel
Add the ability to commit just specific files.
860
    def test_commit_specific_files_with_messages(self):
861
        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.
862
        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.
863
        rev_id1 = tree.commit('one')
864
        self.build_tree(['tree/a', 'tree/b'])
865
        tree.add(['a', 'b'], ['a-id', 'b-id'])
866
867
        dlg = commit.CommitDialog(tree)
868
        dlg._treeview_files.set_cursor((1,))
869
        dlg._set_file_commit_message('Message for A\n')
870
        dlg._treeview_files.set_cursor((2,))
871
        dlg._set_file_commit_message('Message for B\n')
872
        dlg._toggle_commit(None, 2, dlg._files_store) # unset 'b'
873
        dlg._set_global_commit_message('Commit just "a"')
874
875
        dlg._do_commit()
876
877
        rev_id2 = dlg.committed_revision_id
878
        self.assertEqual(rev_id2, tree.last_revision())
879
        rev = tree.branch.repository.get_revision(rev_id2)
880
        self.assertEqual('Commit just "a"', rev.message)
881
        file_info = rev.properties['file-info']
882
        self.assertEqual('ld7:file_id4:a-id'
883
                           '7:message14:Message for A\n'
884
                           '4:path1:a'
885
                         'ee', file_info)
886
        self.assertEqual([{'path':'a', 'file_id':'a-id',
887
                           'message':'Message for A\n'},
888
                         ], bencode.bdecode(file_info))
278.1.28 by John Arbash Meinel
Ensure that we can set per-file messages even during a merge.
889
890
    def test_commit_messages_after_merge(self):
891
        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.
892
        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.
893
        rev_id1 = tree.commit('one')
894
        tree2 = tree.bzrdir.sprout('tree2').open_workingtree()
895
        self.build_tree(['tree2/a', 'tree2/b'])
896
        tree2.add(['a', 'b'], ['a-id', 'b-id'])
897
        rev_id2 = tree2.commit('two')
898
899
        tree.merge_from_branch(tree2.branch)
900
901
        dlg = commit.CommitDialog(tree)
902
        dlg._treeview_files.set_cursor((1,)) # 'a'
903
        dlg._set_file_commit_message('Message for A\n')
904
        # No message for 'B'
905
        dlg._set_global_commit_message('Merging from "tree2"\n')
906
907
        dlg._do_commit()
908
909
        rev_id3 = dlg.committed_revision_id
910
        self.assertEqual(rev_id3, tree.last_revision())
911
        rev = tree.branch.repository.get_revision(rev_id3)
912
        self.assertEqual('Merging from "tree2"\n', rev.message)
913
        self.assertEqual([rev_id1, rev_id2], rev.parent_ids)
914
        file_info = rev.properties['file-info']
915
        self.assertEqual('ld7:file_id4:a-id'
916
                           '7:message14:Message for A\n'
917
                           '4:path1:a'
918
                         'ee', file_info)
919
        self.assertEqual([{'path':'a', 'file_id':'a-id',
920
                           'message':'Message for A\n'},
921
                         ], bencode.bdecode(file_info))
278.1.29 by John Arbash Meinel
Start testing with Unicode data.
922
923
    def test_commit_unicode_messages(self):
924
        from bzrlib.tests.test_diff import UnicodeFilename
925
        self.requireFeature(UnicodeFilename)
926
927
        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.
928
        tree.branch.get_config().set_user_option('per_file_commits', 'true')
278.1.29 by John Arbash Meinel
Start testing with Unicode data.
929
        self.build_tree(['tree/a', u'tree/\u03a9'])
930
        tree.add(['a', u'\u03a9'], ['a-id', 'omega-id'])
931
932
        dlg = commit.CommitDialog(tree)
933
        dlg._treeview_files.set_cursor((1,)) # 'a'
934
        dlg._set_file_commit_message(u'Test \xfan\xecc\xf6de\n')
935
        dlg._treeview_files.set_cursor((2,)) # omega
936
        dlg._set_file_commit_message(u'\u03a9 is the end of all things.\n')
937
        dlg._set_global_commit_message(u'\u03a9 and \xfan\xecc\xf6de\n')
938
939
        self.assertEqual(([u'a', u'\u03a9'],
940
                          [{'path':'a', 'file_id':'a-id',
941
                            'message':'Test \xc3\xban\xc3\xacc\xc3\xb6de\n'},
942
                           {'path':'\xce\xa9', 'file_id':'omega-id',
943
                            'message':'\xce\xa9 is the end of all things.\n'},
944
                          ]), dlg._get_specific_files())
945
946
        dlg._do_commit()
947
948
        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.
949
        file_info = rev.properties['file-info'].encode('UTF-8')
278.1.29 by John Arbash Meinel
Start testing with Unicode data.
950
        value = ('ld7:file_id4:a-id'
951
                   '7:message16:Test \xc3\xban\xc3\xacc\xc3\xb6de\n'
952
                   '4:path1:a'
953
                  'e'
954
                  'd7:file_id8:omega-id'
955
                   '7:message29:\xce\xa9 is the end of all things.\n'
956
                   '4:path2:\xce\xa9'
957
                  'e'
958
                 'e')
959
        self.assertEqual(value, file_info)
960
        file_info_decoded = bencode.bdecode(file_info)
961
        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.
962
            d['path'] = d['path'].decode('UTF-8')
963
            d['message'] = d['message'].decode('UTF-8')
278.1.29 by John Arbash Meinel
Start testing with Unicode data.
964
965
        self.assertEqual([{'path':u'a', 'file_id':'a-id',
966
                           'message':u'Test \xfan\xecc\xf6de\n'},
967
                          {'path':u'\u03a9', 'file_id':'omega-id',
968
                           'message':u'\u03a9 is the end of all things.\n'},
969
                         ], file_info_decoded)