/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/tests/blackbox/test_commit.py

  • Committer: Robert Collins
  • Date: 2010-05-11 08:36:16 UTC
  • mto: This revision was merged to the branch mainline in revision 5223.
  • Revision ID: robertc@robertcollins.net-20100511083616-b8fjb19zomwupid0
Make all lock methods return Result objects, rather than lock_read returning self, as per John's review.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2006-2012, 2016 Canonical Ltd
 
1
# Copyright (C) 2006-2010 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
17
17
 
18
18
"""Tests for the commit CLI of bzr."""
19
19
 
20
 
import doctest
21
20
import os
22
 
import re
23
21
import sys
24
22
 
25
 
from testtools.matchers import DocTestMatches
26
 
 
27
 
from ... import (
28
 
    config,
 
23
from bzrlib import (
29
24
    osutils,
30
25
    ignores,
31
26
    msgeditor,
32
 
    )
33
 
from ...controldir import ControlDir
34
 
from ...sixish import PY3
35
 
from .. import (
36
 
    test_foreign,
37
 
    features,
38
 
    )
39
 
from .. import TestCaseWithTransport
40
 
from ..test_bedding import override_whoami
41
 
 
42
 
 
43
 
class TestCommit(TestCaseWithTransport):
 
27
    osutils,
 
28
    tests,
 
29
    )
 
30
from bzrlib.bzrdir import BzrDir
 
31
from bzrlib.tests import (
 
32
    probe_bad_non_ascii,
 
33
    TestSkipped,
 
34
    )
 
35
from bzrlib.tests.blackbox import ExternalBase
 
36
 
 
37
 
 
38
class TestCommit(ExternalBase):
44
39
 
45
40
    def test_05_empty_commit(self):
46
41
        """Commit of tree with no versioned files should fail"""
47
42
        # If forced, it should succeed, but this is not tested here.
48
43
        self.make_branch_and_tree('.')
49
44
        self.build_tree(['hello.txt'])
50
 
        out, err = self.run_bzr('commit -m empty', retcode=3)
 
45
        out,err = self.run_bzr('commit -m empty', retcode=3)
51
46
        self.assertEqual('', out)
52
 
        # Two ugly bits here.
53
 
        # 1) We really don't want 'aborting commit write group' anymore.
54
 
        # 2) brz: ERROR: is a really long line, so we wrap it with '\'
55
 
        self.assertThat(
56
 
            err,
57
 
            DocTestMatches("""\
58
 
Committing to: ...
59
 
brz: ERROR: No changes to commit.\
60
 
 Please 'brz add' the files you want to commit,\
61
 
 or use --unchanged to force an empty commit.
62
 
""", flags=doctest.ELLIPSIS | doctest.REPORT_UDIFF))
 
47
        self.assertContainsRe(err, 'bzr: ERROR: No changes to commit\.'
 
48
                                  ' Use --unchanged to commit anyhow.\n')
63
49
 
64
50
    def test_commit_success(self):
65
51
        """Successful commit should not leave behind a bzr-commit-* file"""
71
57
        self.run_bzr(["commit", "--unchanged", "-m", u'foo\xb5'])
72
58
        self.assertEqual('', self.run_bzr('unknowns')[0])
73
59
 
74
 
    def test_commit_lossy_native(self):
75
 
        """A --lossy option to commit is supported."""
76
 
        self.make_branch_and_tree('.')
77
 
        self.run_bzr('commit --lossy --unchanged -m message')
78
 
        self.assertEqual('', self.run_bzr('unknowns')[0])
79
 
 
80
 
    def test_commit_lossy_foreign(self):
81
 
        test_foreign.register_dummy_foreign_for_test(self)
82
 
        self.make_branch_and_tree('.',
83
 
                                  format=test_foreign.DummyForeignVcsDirFormat())
84
 
        self.run_bzr('commit --lossy --unchanged -m message')
85
 
        output = self.run_bzr('revision-info')[0]
86
 
        self.assertTrue(output.startswith('1 dummy-'))
87
 
 
88
60
    def test_commit_with_path(self):
89
61
        """Commit tree with path of root specified"""
90
62
        a_tree = self.make_branch_and_tree('a')
92
64
        a_tree.add('a_file')
93
65
        self.run_bzr(['commit', '-m', 'first commit', 'a'])
94
66
 
95
 
        b_tree = a_tree.controldir.sprout('b').open_workingtree()
96
 
        self.build_tree_contents([('b/a_file', b'changes in b')])
 
67
        b_tree = a_tree.bzrdir.sprout('b').open_workingtree()
 
68
        self.build_tree_contents([('b/a_file', 'changes in b')])
97
69
        self.run_bzr(['commit', '-m', 'first commit in b', 'b'])
98
70
 
99
 
        self.build_tree_contents([('a/a_file', b'new contents')])
 
71
        self.build_tree_contents([('a/a_file', 'new contents')])
100
72
        self.run_bzr(['commit', '-m', 'change in a', 'a'])
101
73
 
102
74
        b_tree.merge_from_branch(a_tree.branch)
104
76
        self.run_bzr('resolved b/a_file')
105
77
        self.run_bzr(['commit', '-m', 'merge into b', 'b'])
106
78
 
 
79
 
107
80
    def test_10_verbose_commit(self):
108
81
        """Add one file and examine verbose commit output"""
109
82
        tree = self.make_branch_and_tree('.')
110
83
        self.build_tree(['hello.txt'])
111
84
        tree.add("hello.txt")
112
 
        out, err = self.run_bzr('commit -m added')
 
85
        out,err = self.run_bzr('commit -m added')
113
86
        self.assertEqual('', out)
114
87
        self.assertContainsRe(err, '^Committing to: .*\n'
115
88
                              'added hello.txt\n'
118
91
    def prepare_simple_history(self):
119
92
        """Prepare and return a working tree with one commit of one file"""
120
93
        # Commit with modified file should say so
121
 
        wt = ControlDir.create_standalone_workingtree('.')
 
94
        wt = BzrDir.create_standalone_workingtree('.')
122
95
        self.build_tree(['hello.txt', 'extra.txt'])
123
96
        wt.add(['hello.txt'])
124
97
        wt.commit(message='added')
127
100
    def test_verbose_commit_modified(self):
128
101
        # Verbose commit of modified file should say so
129
102
        wt = self.prepare_simple_history()
130
 
        self.build_tree_contents([('hello.txt', b'new contents')])
 
103
        self.build_tree_contents([('hello.txt', 'new contents')])
131
104
        out, err = self.run_bzr('commit -m modified')
132
105
        self.assertEqual('', out)
133
106
        self.assertContainsRe(err, '^Committing to: .*\n'
134
 
                              'modified hello\\.txt\n'
135
 
                              'Committed revision 2\\.\n$')
136
 
 
137
 
    def test_unicode_commit_message_is_filename(self):
138
 
        """Unicode commit message same as a filename (Bug #563646).
139
 
        """
140
 
        self.requireFeature(features.UnicodeFilenameFeature)
141
 
        file_name = u'\N{euro sign}'
142
 
        self.run_bzr(['init'])
143
 
        with open(file_name, 'w') as f:
144
 
            f.write('hello world')
145
 
        self.run_bzr(['add'])
146
 
        out, err = self.run_bzr(['commit', '-m', file_name])
147
 
        reflags = re.MULTILINE | re.DOTALL | re.UNICODE
148
 
        te = osutils.get_terminal_encoding()
149
 
        self.assertContainsRe(err if PY3 else err.decode(te),
150
 
                              u'The commit message is a file name:',
151
 
                              flags=reflags)
152
 
 
153
 
        # Run same test with a filename that causes encode
154
 
        # error for the terminal encoding. We do this
155
 
        # by forcing terminal encoding of ascii for
156
 
        # osutils.get_terminal_encoding which is used
157
 
        # by ui.text.show_warning
158
 
        default_get_terminal_enc = osutils.get_terminal_encoding
159
 
        try:
160
 
            osutils.get_terminal_encoding = lambda trace=None: 'ascii'
161
 
            file_name = u'foo\u1234'
162
 
            with open(file_name, 'w') as f:
163
 
                f.write('hello world')
164
 
            self.run_bzr(['add'])
165
 
            out, err = self.run_bzr(['commit', '-m', file_name])
166
 
            reflags = re.MULTILINE | re.DOTALL | re.UNICODE
167
 
            te = osutils.get_terminal_encoding()
168
 
            self.assertContainsRe(err if PY3 else err.decode(te, 'replace'),
169
 
                                  u'The commit message is a file name:',
170
 
                                  flags=reflags)
171
 
        finally:
172
 
            osutils.get_terminal_encoding = default_get_terminal_enc
173
 
 
174
 
    def test_non_ascii_file_unversioned_utf8(self):
175
 
        self.requireFeature(features.UnicodeFilenameFeature)
176
 
        tree = self.make_branch_and_tree(".")
177
 
        self.build_tree(["f"])
178
 
        tree.add(["f"])
179
 
        out, err = self.run_bzr_raw(["commit", "-m", "Wrong filename", u"\xa7"],
180
 
                                    encoding="utf-8", retcode=3)
181
 
        self.assertContainsRe(err, b"(?m)not versioned: \"\xc2\xa7\"$")
182
 
 
183
 
    def test_non_ascii_file_unversioned_iso_8859_5(self):
184
 
        self.requireFeature(features.UnicodeFilenameFeature)
185
 
        tree = self.make_branch_and_tree(".")
186
 
        self.build_tree(["f"])
187
 
        tree.add(["f"])
188
 
        out, err = self.run_bzr_raw(["commit", "-m", "Wrong filename", u"\xa7"],
189
 
                                    encoding="iso-8859-5", retcode=3)
190
 
        if not PY3:
191
 
            self.expectFailure("Error messages are always written as UTF-8",
192
 
                               self.assertNotContainsString, err, b"\xc2\xa7")
193
 
        else:
194
 
            self.assertNotContainsString(err, b"\xc2\xa7")
195
 
        self.assertContainsRe(err, b"(?m)not versioned: \"\xfd\"$")
 
107
                              'modified hello\.txt\n'
 
108
                              'Committed revision 2\.\n$')
196
109
 
197
110
    def test_warn_about_forgotten_commit_message(self):
198
111
        """Test that the lack of -m parameter is caught"""
209
122
        out, err = self.run_bzr('commit -m renamed')
210
123
        self.assertEqual('', out)
211
124
        self.assertContainsRe(err, '^Committing to: .*\n'
212
 
                              'renamed hello\\.txt => gutentag\\.txt\n'
213
 
                              'Committed revision 2\\.$\n')
 
125
                              'renamed hello\.txt => gutentag\.txt\n'
 
126
                              'Committed revision 2\.$\n')
214
127
 
215
128
    def test_verbose_commit_moved(self):
216
129
        # Verbose commit of file moved to new directory should say so
220
133
        wt.rename_one('hello.txt', 'subdir/hello.txt')
221
134
        out, err = self.run_bzr('commit -m renamed')
222
135
        self.assertEqual('', out)
223
 
        self.assertEqual({
 
136
        self.assertEqual(set([
224
137
            'Committing to: %s/' % osutils.getcwd(),
225
138
            'added subdir',
226
139
            'renamed hello.txt => subdir/hello.txt',
227
140
            'Committed revision 2.',
228
141
            '',
229
 
            }, set(err.split('\n')))
 
142
            ]), set(err.split('\n')))
230
143
 
231
144
    def test_verbose_commit_with_unknown(self):
232
145
        """Unknown files should not be listed by default in verbose output"""
233
146
        # Is that really the best policy?
234
 
        wt = ControlDir.create_standalone_workingtree('.')
 
147
        wt = BzrDir.create_standalone_workingtree('.')
235
148
        self.build_tree(['hello.txt', 'extra.txt'])
236
149
        wt.add(['hello.txt'])
237
 
        out, err = self.run_bzr('commit -m added')
 
150
        out,err = self.run_bzr('commit -m added')
238
151
        self.assertEqual('', out)
239
152
        self.assertContainsRe(err, '^Committing to: .*\n'
240
 
                              'added hello\\.txt\n'
241
 
                              'Committed revision 1\\.\n$')
 
153
                              'added hello\.txt\n'
 
154
                              'Committed revision 1\.\n$')
242
155
 
243
156
    def test_verbose_commit_with_unchanged(self):
244
157
        """Unchanged files should not be listed by default in verbose output"""
247
160
        tree.add('unchanged.txt')
248
161
        self.run_bzr('commit -m unchanged unchanged.txt')
249
162
        tree.add("hello.txt")
250
 
        out, err = self.run_bzr('commit -m added')
 
163
        out,err = self.run_bzr('commit -m added')
251
164
        self.assertEqual('', out)
252
165
        self.assertContainsRe(err, '^Committing to: .*\n'
253
 
                              'added hello\\.txt\n'
254
 
                              'Committed revision 2\\.$\n')
 
166
                              'added hello\.txt\n'
 
167
                              'Committed revision 2\.$\n')
255
168
 
256
169
    def test_verbose_commit_includes_master_location(self):
257
170
        """Location of master is displayed when committing to bound branch"""
268
181
 
269
182
    def test_commit_sanitizes_CR_in_message(self):
270
183
        # See bug #433779, basically Emacs likes to pass '\r\n' style line
271
 
        # endings to 'brz commit -m ""' which breaks because we don't allow
 
184
        # endings to 'bzr commit -m ""' which breaks because we don't allow
272
185
        # '\r' in commit messages. (Mostly because of issues where XML style
273
186
        # formats arbitrarily strip it out of the data while parsing.)
274
187
        # To make life easier for users, we just always translate '\r\n' =>
286
199
 
287
200
    def test_commit_merge_reports_all_modified_files(self):
288
201
        # the commit command should show all the files that are shown by
289
 
        # brz diff or brz status when committing, even when they were not
 
202
        # bzr diff or bzr status when committing, even when they were not
290
203
        # changed by the user but rather through doing a merge.
291
204
        this_tree = self.make_branch_and_tree('this')
292
205
        # we need a bunch of files and dirs, to perform one action on each.
313
226
            'filetoleave']
314
227
            )
315
228
        this_tree.commit('create_files')
316
 
        other_dir = this_tree.controldir.sprout('other')
 
229
        other_dir = this_tree.bzrdir.sprout('other')
317
230
        other_tree = other_dir.open_workingtree()
318
 
        with other_tree.lock_write():
319
 
            # perform the needed actions on the files and dirs.
 
231
        other_tree.lock_write()
 
232
        # perform the needed actions on the files and dirs.
 
233
        try:
320
234
            other_tree.rename_one('dirtorename', 'renameddir')
321
235
            other_tree.rename_one('dirtoreparent', 'renameddir/reparenteddir')
322
236
            other_tree.rename_one('filetorename', 'renamedfile')
325
239
            other_tree.remove(['dirtoremove', 'filetoremove'])
326
240
            self.build_tree_contents([
327
241
                ('other/newdir/',),
328
 
                ('other/filetomodify', b'new content'),
329
 
                ('other/newfile', b'new file content')])
 
242
                ('other/filetomodify', 'new content'),
 
243
                ('other/newfile', 'new file content')])
330
244
            other_tree.add('newfile')
331
245
            other_tree.add('newdir/')
332
246
            other_tree.commit('modify all sample files and dirs.')
 
247
        finally:
 
248
            other_tree.unlock()
333
249
        this_tree.merge_from_branch(other_tree.branch)
334
 
        out, err = self.run_bzr('commit -m added', working_dir='this')
 
250
        os.chdir('this')
 
251
        out,err = self.run_bzr('commit -m added')
335
252
        self.assertEqual('', out)
336
 
        self.assertEqual({
337
 
            'Committing to: %s/' % osutils.pathjoin(osutils.getcwd(), 'this'),
 
253
        self.assertEqual(set([
 
254
            'Committing to: %s/' % osutils.getcwd(),
338
255
            'modified filetomodify',
339
256
            'added newdir',
340
257
            'added newfile',
346
263
            'deleted filetoremove',
347
264
            'Committed revision 2.',
348
265
            ''
349
 
            }, set(err.split('\n')))
 
266
            ]), set(err.split('\n')))
350
267
 
351
268
    def test_empty_commit_message(self):
352
269
        tree = self.make_branch_and_tree('.')
353
 
        self.build_tree_contents([('foo.c', b'int main() {}')])
354
 
        tree.add('foo.c')
355
 
        self.run_bzr('commit -m ""')
 
270
        self.build_tree_contents([('foo.c', 'int main() {}')])
 
271
        tree.add('foo.c')
 
272
        self.run_bzr('commit -m ""', retcode=3)
 
273
 
 
274
    def test_unsupported_encoding_commit_message(self):
 
275
        if sys.platform == 'win32':
 
276
            raise tests.TestNotApplicable('Win32 parses arguments directly'
 
277
                ' as Unicode, so we can\'t pass invalid non-ascii')
 
278
        tree = self.make_branch_and_tree('.')
 
279
        self.build_tree_contents([('foo.c', 'int main() {}')])
 
280
        tree.add('foo.c')
 
281
        # LANG env variable has no effect on Windows
 
282
        # but some characters anyway cannot be represented
 
283
        # in default user encoding
 
284
        char = probe_bad_non_ascii(osutils.get_user_encoding())
 
285
        if char is None:
 
286
            raise TestSkipped('Cannot find suitable non-ascii character'
 
287
                'for user_encoding (%s)' % osutils.get_user_encoding())
 
288
        out,err = self.run_bzr_subprocess('commit -m "%s"' % char,
 
289
                                          retcode=1,
 
290
                                          env_changes={'LANG': 'C'})
 
291
        self.assertContainsRe(err, r'bzrlib.errors.BzrError: Parameter.*is '
 
292
                                    'unsupported by the current encoding.')
356
293
 
357
294
    def test_other_branch_commit(self):
358
295
        # this branch is to ensure consistent behaviour, whether we're run
360
297
        outer_tree = self.make_branch_and_tree('.')
361
298
        inner_tree = self.make_branch_and_tree('branch')
362
299
        self.build_tree_contents([
363
 
            ('branch/foo.c', b'int main() {}'),
364
 
            ('branch/bar.c', b'int main() {}')])
 
300
            ('branch/foo.c', 'int main() {}'),
 
301
            ('branch/bar.c', 'int main() {}')])
365
302
        inner_tree.add(['foo.c', 'bar.c'])
366
303
        # can't commit files in different trees; sane error
367
304
        self.run_bzr('commit -m newstuff branch/foo.c .', retcode=3)
370
307
        # can commit to branch - records bar.c
371
308
        self.run_bzr('commit -m newstuff branch')
372
309
        # No changes left
373
 
        self.run_bzr_error(["No changes to commit"],
374
 
                           'commit -m newstuff branch')
 
310
        self.run_bzr_error(["No changes to commit"], 'commit -m newstuff branch')
375
311
 
376
312
    def test_out_of_date_tree_commit(self):
377
313
        # check we get an error code and a clear message committing with an out
382
318
        # commit to the original branch to make the checkout out of date
383
319
        tree.commit('message branch', allow_pointless=True)
384
320
        # now commit to the checkout should emit
385
 
        # ERROR: Out of date with the branch, 'brz update' is suggested
 
321
        # ERROR: Out of date with the branch, 'bzr update' is suggested
386
322
        output = self.run_bzr('commit --unchanged -m checkout_message '
387
 
                              'checkout', retcode=3)
 
323
                             'checkout', retcode=3)
388
324
        self.assertEqual(output,
389
325
                         ('',
390
 
                          "brz: ERROR: Working tree is out of date, please "
391
 
                          "run 'brz update'.\n"))
 
326
                          "bzr: ERROR: Working tree is out of date, please "
 
327
                          "run 'bzr update'.\n"))
392
328
 
393
329
    def test_local_commit_unbound(self):
394
330
        # a --local commit on an unbound branch is an error
395
331
        self.make_branch_and_tree('.')
396
332
        out, err = self.run_bzr('commit --local', retcode=3)
397
333
        self.assertEqualDiff('', out)
398
 
        self.assertEqualDiff('brz: ERROR: Cannot perform local-only commits '
 
334
        self.assertEqualDiff('bzr: ERROR: Cannot perform local-only commits '
399
335
                             'on unbound branches.\n', err)
400
336
 
401
337
    def test_commit_a_text_merge_in_a_checkout(self):
407
343
        trunk = self.make_branch_and_tree('trunk')
408
344
 
409
345
        u1 = trunk.branch.create_checkout('u1')
410
 
        self.build_tree_contents([('u1/hosts', b'initial contents\n')])
 
346
        self.build_tree_contents([('u1/hosts', 'initial contents\n')])
411
347
        u1.add('hosts')
412
348
        self.run_bzr('commit -m add-hosts u1')
413
349
 
414
350
        u2 = trunk.branch.create_checkout('u2')
415
 
        self.build_tree_contents([('u2/hosts', b'altered in u2\n')])
 
351
        self.build_tree_contents([('u2/hosts', 'altered in u2\n')])
416
352
        self.run_bzr('commit -m checkin-from-u2 u2')
417
353
 
418
354
        # make an offline commits
419
 
        self.build_tree_contents(
420
 
            [('u1/hosts', b'first offline change in u1\n')])
 
355
        self.build_tree_contents([('u1/hosts', 'first offline change in u1\n')])
421
356
        self.run_bzr('commit -m checkin-offline --local u1')
422
357
 
423
358
        # now try to pull in online work from u2, and then commit our offline
424
359
        # work as a merge
425
360
        # retcode 1 as we expect a text conflict
426
361
        self.run_bzr('update u1', retcode=1)
427
 
        self.assertFileEqual(b'''\
 
362
        self.assertFileEqual('''\
428
363
<<<<<<< TREE
429
364
first offline change in u1
430
365
=======
437
372
        # add a text change here to represent resolving the merge conflicts in
438
373
        # favour of a new version of the file not identical to either the u1
439
374
        # version or the u2 version.
440
 
        self.build_tree_contents([('u1/hosts', b'merge resolution\n')])
 
375
        self.build_tree_contents([('u1/hosts', 'merge resolution\n')])
441
376
        self.run_bzr('commit -m checkin-merge-of-the-offline-work-from-u1 u1')
442
377
 
443
378
    def test_commit_exclude_excludes_modified_files(self):
476
411
        t.add(['file-a', 'dir-a', 'dir-a/file-b'])
477
412
        t.commit('Create')
478
413
        t.remove(['file-a', 'dir-a/file-b'])
479
 
        result = self.run_bzr('commit . -m removed-file-b',
480
 
                              working_dir='dir-a')[1]
 
414
        os.chdir('dir-a')
 
415
        result = self.run_bzr('commit . -m removed-file-b')[1]
481
416
        self.assertNotContainsRe(result, 'file-a')
482
 
        result = self.run_bzr('status', working_dir='dir-a')[0]
 
417
        result = self.run_bzr('status')[0]
483
418
        self.assertContainsRe(result, 'removed:\n  file-a')
484
419
 
485
420
    def test_strict_commit(self):
489
424
        self.build_tree(['tree/a'])
490
425
        tree.add('a')
491
426
        # A simple change should just work
492
 
        self.run_bzr('commit --strict -m adding-a', working_dir='tree')
 
427
        self.run_bzr('commit --strict -m adding-a',
 
428
                     working_dir='tree')
493
429
 
494
430
    def test_strict_commit_no_changes(self):
495
431
        """commit --strict gives "no changes" if there is nothing to commit"""
535
471
            'commit -m hello --fixes=lp:23452 tree/hello.txt')
536
472
        self.assertEqual('', output)
537
473
        self.assertContainsRe(err, 'Committing to: .*\n'
538
 
                              'added hello\\.txt\n'
539
 
                              'Committed revision 1\\.\n')
540
 
 
541
 
    def test_fixes_bug_unicode(self):
542
 
        """commit --fixes=lp:unicode succeeds without output."""
543
 
        tree = self.make_branch_and_tree('tree')
544
 
        self.build_tree(['tree/hello.txt'])
545
 
        tree.add('hello.txt')
546
 
        output, err = self.run_bzr_raw(
547
 
            ['commit', '-m', 'hello',
548
 
             u'--fixes=generic:\u20ac', 'tree/hello.txt'],
549
 
            encoding='utf-8', retcode=3)
550
 
        self.assertEqual(b'', output)
551
 
        self.assertContainsRe(err,
552
 
                              b'brz: ERROR: Unrecognized bug generic:\xe2\x82\xac\\. Commit refused.\n')
 
474
                              'added hello\.txt\n'
 
475
                              'Committed revision 1\.\n')
553
476
 
554
477
    def test_no_bugs_no_properties(self):
555
478
        """If no bugs are fixed, the bugs property is not set.
559
482
        tree = self.make_branch_and_tree('tree')
560
483
        self.build_tree(['tree/hello.txt'])
561
484
        tree.add('hello.txt')
562
 
        self.run_bzr('commit -m hello tree/hello.txt')
 
485
        self.run_bzr( 'commit -m hello tree/hello.txt')
563
486
        # Get the revision properties, ignoring the branch-nick property, which
564
487
        # we don't care about for this test.
565
488
        last_rev = tree.branch.repository.get_revision(tree.last_revision())
567
490
        del properties['branch-nick']
568
491
        self.assertFalse('bugs' in properties)
569
492
 
570
 
    def test_bugs_sets_property(self):
571
 
        """commit --bugs=lp:234 sets the lp:234 revprop to 'related'."""
572
 
        tree = self.make_branch_and_tree('tree')
573
 
        self.build_tree(['tree/hello.txt'])
574
 
        tree.add('hello.txt')
575
 
        self.run_bzr('commit -m hello --bugs=lp:234 tree/hello.txt')
576
 
 
577
 
        # Get the revision properties, ignoring the branch-nick property, which
578
 
        # we don't care about for this test.
579
 
        last_rev = tree.branch.repository.get_revision(tree.last_revision())
580
 
        properties = dict(last_rev.properties)
581
 
        del properties[u'branch-nick']
582
 
 
583
 
        self.assertEqual({u'bugs': 'https://launchpad.net/bugs/234 related'},
584
 
                         properties)
585
 
 
586
493
    def test_fixes_bug_sets_property(self):
587
494
        """commit --fixes=lp:234 sets the lp:234 revprop to 'fixed'."""
588
495
        tree = self.make_branch_and_tree('tree')
594
501
        # we don't care about for this test.
595
502
        last_rev = tree.branch.repository.get_revision(tree.last_revision())
596
503
        properties = dict(last_rev.properties)
597
 
        del properties[u'branch-nick']
 
504
        del properties['branch-nick']
598
505
 
599
 
        self.assertEqual({u'bugs': 'https://launchpad.net/bugs/234 fixed'},
 
506
        self.assertEqual({'bugs': 'https://launchpad.net/bugs/234 fixed'},
600
507
                         properties)
601
508
 
602
509
    def test_fixes_multiple_bugs_sets_properties(self):
614
521
        del properties['branch-nick']
615
522
 
616
523
        self.assertEqual(
617
 
            {u'bugs': 'https://launchpad.net/bugs/123 fixed\n'
618
 
             'https://launchpad.net/bugs/235 fixed'},
 
524
            {'bugs': 'https://launchpad.net/bugs/123 fixed\n'
 
525
                     'https://launchpad.net/bugs/235 fixed'},
619
526
            properties)
620
527
 
621
528
    def test_fixes_bug_with_alternate_trackers(self):
627
534
            'trac_twisted_url', 'http://twistedmatrix.com/trac')
628
535
        self.build_tree(['tree/hello.txt'])
629
536
        tree.add('hello.txt')
630
 
        self.run_bzr(
631
 
            'commit -m hello --fixes=lp:123 --fixes=twisted:235 tree/')
 
537
        self.run_bzr('commit -m hello --fixes=lp:123 --fixes=twisted:235 tree/')
632
538
 
633
539
        # Get the revision properties, ignoring the branch-nick property, which
634
540
        # we don't care about for this test.
650
556
            'commit -m add-b --fixes=xxx:123',
651
557
            working_dir='tree')
652
558
 
653
 
    def test_fixes_bug_with_default_tracker(self):
654
 
        """commit --fixes=234 uses the default bug tracker."""
655
 
        tree = self.make_branch_and_tree('tree')
656
 
        self.build_tree(['tree/hello.txt'])
657
 
        tree.add('hello.txt')
658
 
        self.run_bzr_error(
659
 
            ["brz: ERROR: No tracker specified for bug 123. Use the form "
660
 
             "'tracker:id' or specify a default bug tracker using the "
661
 
             "`bugtracker` option.\n"
662
 
             "See \"brz help bugs\" for more information on this feature. "
663
 
             "Commit refused."],
664
 
            'commit -m add-b --fixes=123',
665
 
            working_dir='tree')
666
 
        tree.branch.get_config_stack().set("bugtracker", "lp")
667
 
        self.run_bzr('commit -m hello --fixes=234 tree/hello.txt')
668
 
        last_rev = tree.branch.repository.get_revision(tree.last_revision())
669
 
        self.assertEqual('https://launchpad.net/bugs/234 fixed',
670
 
                         last_rev.properties['bugs'])
671
 
 
672
559
    def test_fixes_invalid_bug_number(self):
673
560
        tree = self.make_branch_and_tree('tree')
674
561
        self.build_tree(['tree/hello.txt'])
675
562
        tree.add('hello.txt')
676
563
        self.run_bzr_error(
677
564
            ["Did not understand bug identifier orange: Must be an integer. "
678
 
             "See \"brz help bugs\" for more information on this feature.\n"
 
565
             "See \"bzr help bugs\" for more information on this feature.\n"
679
566
             "Commit refused."],
680
567
            'commit -m add-b --fixes=lp:orange',
681
568
            working_dir='tree')
686
573
        self.build_tree(['tree/hello.txt'])
687
574
        tree.add('hello.txt')
688
575
        self.run_bzr_error(
689
 
            [r"Invalid bug orange:apples:bananas. Must be in the form of "
690
 
             r"'tracker:id'\. See \"brz help bugs\" for more information on "
691
 
             r"this feature.\nCommit refused\."],
692
 
            'commit -m add-b --fixes=orange:apples:bananas',
 
576
            [r"Invalid bug orange. Must be in the form of 'tracker:id'\. "
 
577
             r"See \"bzr help bugs\" for more information on this feature.\n"
 
578
             r"Commit refused\."],
 
579
            'commit -m add-b --fixes=orange',
693
580
            working_dir='tree')
694
581
 
695
582
    def test_no_author(self):
697
584
        tree = self.make_branch_and_tree('tree')
698
585
        self.build_tree(['tree/hello.txt'])
699
586
        tree.add('hello.txt')
700
 
        self.run_bzr('commit -m hello tree/hello.txt')
 
587
        self.run_bzr( 'commit -m hello tree/hello.txt')
701
588
        last_rev = tree.branch.repository.get_revision(tree.last_revision())
702
589
        properties = last_rev.properties
703
590
        self.assertFalse('author' in properties)
711
598
        tree.add('hello.txt')
712
599
        self.run_bzr(["commit", '-m', 'hello',
713
600
                      '--author', u'John D\xf6 <jdoe@example.com>',
714
 
                      "tree/hello.txt"])
 
601
                     "tree/hello.txt"])
715
602
        last_rev = tree.branch.repository.get_revision(tree.last_revision())
716
603
        properties = last_rev.properties
717
 
        self.assertEqual(u'John D\xf6 <jdoe@example.com>',
718
 
                         properties['authors'])
 
604
        self.assertEqual(u'John D\xf6 <jdoe@example.com>', properties['authors'])
719
605
 
720
606
    def test_author_no_email(self):
721
607
        """Author's name without an email address is allowed, too."""
744
630
        self.build_tree(['tree/hello.txt'])
745
631
        tree.add('hello.txt')
746
632
        out, err = self.run_bzr("commit -m hello "
747
 
                                "--commit-time='2009-10-10 08:00:00 +0100' tree/hello.txt")
 
633
            "--commit-time='2009-10-10 08:00:00 +0100' tree/hello.txt")
748
634
        last_rev = tree.branch.repository.get_revision(tree.last_revision())
749
635
        self.assertEqual(
750
636
            'Sat 2009-10-10 08:00:00 +0100',
751
637
            osutils.format_date(last_rev.timestamp, last_rev.timezone))
752
 
 
 
638
        
753
639
    def test_commit_time_bad_time(self):
754
640
        tree = self.make_branch_and_tree('tree')
755
641
        self.build_tree(['tree/hello.txt'])
756
642
        tree.add('hello.txt')
757
643
        out, err = self.run_bzr("commit -m hello "
758
 
                                "--commit-time='NOT A TIME' tree/hello.txt", retcode=3)
759
 
        self.assertStartsWith(
760
 
            err, "brz: ERROR: Could not parse --commit-time:")
761
 
 
762
 
    def test_commit_time_missing_tz(self):
763
 
        tree = self.make_branch_and_tree('tree')
764
 
        self.build_tree(['tree/hello.txt'])
765
 
        tree.add('hello.txt')
766
 
        out, err = self.run_bzr("commit -m hello "
767
 
                                "--commit-time='2009-10-10 08:00:00' tree/hello.txt", retcode=3)
768
 
        self.assertStartsWith(
769
 
            err, "brz: ERROR: Could not parse --commit-time:")
770
 
        # Test that it is actually checking and does not simply crash with
771
 
        # some other exception
772
 
        self.assertContainsString(err, "missing a timezone offset")
 
644
            "--commit-time='NOT A TIME' tree/hello.txt", retcode=3)
 
645
        self.assertStartsWith(
 
646
            err, "bzr: ERROR: Could not parse --commit-time:")
773
647
 
774
648
    def test_partial_commit_with_renames_in_tree(self):
775
649
        # this test illustrates bug #140419
782
656
        # then during partial commit we have error
783
657
        # parent_id {dir-XXX} not in inventory
784
658
        t.rename_one('dir/a', 'a')
785
 
        self.build_tree_contents([('test', b'changes in test')])
 
659
        self.build_tree_contents([('test', 'changes in test')])
786
660
        # partial commit
787
661
        out, err = self.run_bzr('commit test -m "partial commit"')
788
 
        self.assertEqual('', out)
 
662
        self.assertEquals('', out)
789
663
        self.assertContainsRe(err, r'modified test\nCommitted revision 2.')
790
664
 
791
665
    def test_commit_readonly_checkout(self):
792
 
        # https://bugs.launchpad.net/bzr/+bug/129701
 
666
        # https://bugs.edge.launchpad.net/bzr/+bug/129701
793
667
        # "UnlockableTransport error trying to commit in checkout of readonly
794
668
        # branch"
795
669
        self.make_branch('master')
796
 
        master = ControlDir.open_from_transport(
 
670
        master = BzrDir.open_from_transport(
797
671
            self.get_readonly_transport('master')).open_branch()
798
672
        master.create_checkout('checkout')
799
673
        out, err = self.run_bzr(['commit', '--unchanged', '-mfoo', 'checkout'],
800
 
                                retcode=3)
 
674
            retcode=3)
801
675
        self.assertContainsRe(err,
802
 
                              r'^brz: ERROR: Cannot lock.*readonly transport')
 
676
            r'^bzr: ERROR: Cannot lock.*readonly transport')
803
677
 
804
678
    def setup_editor(self):
805
679
        # Test that commit template hooks work
806
680
        if sys.platform == "win32":
807
 
            with open('fed.bat', 'w') as f:
808
 
                f.write('@rem dummy fed')
809
 
            self.overrideEnv('BRZ_EDITOR', "fed.bat")
 
681
            f = file('fed.bat', 'w')
 
682
            f.write('@rem dummy fed')
 
683
            f.close()
 
684
            osutils.set_or_unset_env('BZR_EDITOR', "fed.bat")
810
685
        else:
811
 
            with open('fed.sh', 'wb') as f:
812
 
                f.write(b'#!/bin/sh\n')
813
 
            os.chmod('fed.sh', 0o755)
814
 
            self.overrideEnv('BRZ_EDITOR', "./fed.sh")
 
686
            f = file('fed.sh', 'wb')
 
687
            f.write('#!/bin/sh\n')
 
688
            f.close()
 
689
            os.chmod('fed.sh', 0755)
 
690
            osutils.set_or_unset_env('BZR_EDITOR', "./fed.sh")
815
691
 
816
692
    def setup_commit_with_template(self):
817
693
        self.setup_editor()
818
694
        msgeditor.hooks.install_named_hook("commit_message_template",
819
 
                                           lambda commit_obj, msg: "save me some typing\n", None)
 
695
                lambda commit_obj, msg: "save me some typing\n", None)
820
696
        tree = self.make_branch_and_tree('tree')
821
697
        self.build_tree(['tree/hello.txt'])
822
698
        tree.add('hello.txt')
823
699
        return tree
824
700
 
825
 
    def test_edit_empty_message(self):
826
 
        tree = self.make_branch_and_tree('tree')
827
 
        self.setup_editor()
828
 
        self.build_tree(['tree/hello.txt'])
829
 
        tree.add('hello.txt')
830
 
        out, err = self.run_bzr("commit tree/hello.txt", retcode=3,
831
 
                                stdin="y\n")
832
 
        self.assertContainsRe(err,
833
 
                              "brz: ERROR: Empty commit message specified")
834
 
 
835
701
    def test_commit_hook_template_accepted(self):
836
702
        tree = self.setup_commit_with_template()
837
703
        out, err = self.run_bzr("commit tree/hello.txt", stdin="y\n")
841
707
    def test_commit_hook_template_rejected(self):
842
708
        tree = self.setup_commit_with_template()
843
709
        expected = tree.last_revision()
844
 
        out, err = self.run_bzr_error(["Empty commit message specified."
845
 
                                       " Please specify a commit message with either"
846
 
                                       " --message or --file or leave a blank message"
847
 
                                       " with --message \"\"."],
848
 
                                      "commit tree/hello.txt", stdin="n\n")
 
710
        out, err = self.run_bzr_error(["empty commit message"],
 
711
            "commit tree/hello.txt", stdin="n\n")
849
712
        self.assertEqual(expected, tree.last_revision())
850
 
 
851
 
    def test_set_commit_message(self):
852
 
        msgeditor.hooks.install_named_hook("set_commit_message",
853
 
                                           lambda commit_obj, msg: "save me some typing\n", None)
854
 
        tree = self.make_branch_and_tree('tree')
855
 
        self.build_tree(['tree/hello.txt'])
856
 
        tree.add('hello.txt')
857
 
        out, err = self.run_bzr("commit tree/hello.txt")
858
 
        last_rev = tree.branch.repository.get_revision(tree.last_revision())
859
 
        self.assertEqual('save me some typing\n', last_rev.message)
860
 
 
861
 
    def test_commit_without_username(self):
862
 
        """Ensure commit error if username is not set.
863
 
        """
864
 
        self.run_bzr(['init', 'foo'])
865
 
        with open('foo/foo.txt', 'w') as f:
866
 
            f.write('hello')
867
 
        self.run_bzr(['add'], working_dir='foo')
868
 
        override_whoami(self)
869
 
        self.run_bzr_error(
870
 
            ['Unable to determine your name'],
871
 
            ['commit', '-m', 'initial'], working_dir='foo')
872
 
 
873
 
    def test_commit_recursive_checkout(self):
874
 
        """Ensure that a commit to a recursive checkout fails cleanly.
875
 
        """
876
 
        self.run_bzr(['init', 'test_branch'])
877
 
        self.run_bzr(['checkout', 'test_branch', 'test_checkout'])
878
 
        # bind to self
879
 
        self.run_bzr(['bind', '.'], working_dir='test_checkout')
880
 
        with open('test_checkout/foo.txt', 'w') as f:
881
 
            f.write('hello')
882
 
        self.run_bzr(['add'], working_dir='test_checkout')
883
 
        out, err = self.run_bzr_error(
884
 
            ['Branch.*test_checkout.*appears to be bound to itself'],
885
 
            ['commit', '-m', 'addedfoo'], working_dir='test_checkout')
886
 
 
887
 
    def test_mv_dirs_non_ascii(self):
888
 
        """Move directory with non-ascii name and containing files.
889
 
 
890
 
        Regression test for bug 185211.
891
 
        """
892
 
        tree = self.make_branch_and_tree('.')
893
 
        self.build_tree([u'abc\xa7/', u'abc\xa7/foo'])
894
 
 
895
 
        tree.add([u'abc\xa7/', u'abc\xa7/foo'])
896
 
        tree.commit('checkin')
897
 
 
898
 
        tree.rename_one(u'abc\xa7', 'abc')
899
 
 
900
 
        self.run_bzr('ci -m "non-ascii mv"')
901