/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 breezy/tests/test_commit.py

  • Committer: Jelmer Vernooij
  • Date: 2018-07-08 14:45:27 UTC
  • mto: This revision was merged to the branch mainline in revision 7036.
  • Revision ID: jelmer@jelmer.uk-20180708144527-codhlvdcdg9y0nji
Fix a bunch of merge tests.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2010 Canonical Ltd
 
1
# Copyright (C) 2005-2012, 2016 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
import os
19
19
 
20
 
import bzrlib
21
 
from bzrlib import (
22
 
    bzrdir,
 
20
import breezy
 
21
from .. import (
 
22
    config,
 
23
    controldir,
23
24
    errors,
24
 
    lockdir,
25
 
    osutils,
26
 
    tests,
27
 
    )
28
 
from bzrlib.branch import Branch
29
 
from bzrlib.bzrdir import BzrDir, BzrDirMetaFormat1
30
 
from bzrlib.commit import Commit, NullCommitReporter
31
 
from bzrlib.config import BranchConfig
32
 
from bzrlib.errors import (PointlessCommit, BzrError, SigningFailed,
33
 
                           LockContention)
34
 
from bzrlib.tests import SymlinkFeature, TestCaseWithTransport
35
 
from bzrlib.workingtree import WorkingTree
 
25
    )
 
26
from ..branch import Branch
 
27
from ..bzr.bzrdir import BzrDirMetaFormat1
 
28
from ..commit import (
 
29
    CannotCommitSelectedFileMerge,
 
30
    Commit,
 
31
    NullCommitReporter,
 
32
    PointlessCommit,
 
33
    filter_excluded,
 
34
    )
 
35
from ..errors import (
 
36
    BzrError,
 
37
    LockContention,
 
38
    )
 
39
from . import (
 
40
    TestCase,
 
41
    TestCaseWithTransport,
 
42
    test_foreign,
 
43
    )
 
44
from .features import (
 
45
    SymlinkFeature,
 
46
    )
 
47
from .matchers import MatchesAncestry
36
48
 
37
49
 
38
50
# TODO: Test commit with some added, and added-but-missing files
39
51
 
40
 
class MustSignConfig(BranchConfig):
41
 
 
42
 
    def signature_needed(self):
43
 
        return True
44
 
 
45
 
    def gpg_signing_command(self):
46
 
        return ['cat', '-']
47
 
 
48
 
 
49
 
class BranchWithHooks(BranchConfig):
50
 
 
51
 
    def post_commit(self):
52
 
        return "bzrlib.ahook bzrlib.ahook"
 
52
class MustSignConfig(config.MemoryStack):
 
53
 
 
54
    def __init__(self):
 
55
        super(MustSignConfig, self).__init__(b'''
 
56
create_signatures=always
 
57
''')
53
58
 
54
59
 
55
60
class CapturingReporter(NullCommitReporter):
81
86
        """Commit and check two versions of a single file."""
82
87
        wt = self.make_branch_and_tree('.')
83
88
        b = wt.branch
84
 
        file('hello', 'w').write('hello world')
 
89
        with open('hello', 'w') as f: f.write('hello world')
85
90
        wt.add('hello')
86
 
        wt.commit(message='add hello')
87
 
        file_id = wt.path2id('hello')
88
 
 
89
 
        file('hello', 'w').write('version 2')
90
 
        wt.commit(message='commit 2')
91
 
 
92
 
        eq = self.assertEquals
 
91
        rev1 = wt.commit(message='add hello')
 
92
 
 
93
        with open('hello', 'w') as f: f.write('version 2')
 
94
        rev2 = wt.commit(message='commit 2')
 
95
 
 
96
        eq = self.assertEqual
93
97
        eq(b.revno(), 2)
94
 
        rh = b.revision_history()
95
 
        rev = b.repository.get_revision(rh[0])
 
98
        rev = b.repository.get_revision(rev1)
96
99
        eq(rev.message, 'add hello')
97
100
 
98
 
        tree1 = b.repository.revision_tree(rh[0])
 
101
        tree1 = b.repository.revision_tree(rev1)
99
102
        tree1.lock_read()
100
 
        text = tree1.get_file_text(file_id)
 
103
        text = tree1.get_file_text('hello')
101
104
        tree1.unlock()
102
 
        self.assertEqual('hello world', text)
 
105
        self.assertEqual(b'hello world', text)
103
106
 
104
 
        tree2 = b.repository.revision_tree(rh[1])
 
107
        tree2 = b.repository.revision_tree(rev2)
105
108
        tree2.lock_read()
106
 
        text = tree2.get_file_text(file_id)
 
109
        text = tree2.get_file_text('hello')
107
110
        tree2.unlock()
108
 
        self.assertEqual('version 2', text)
 
111
        self.assertEqual(b'version 2', text)
 
112
 
 
113
    def test_commit_lossy_native(self):
 
114
        """Attempt a lossy commit to a native branch."""
 
115
        wt = self.make_branch_and_tree('.')
 
116
        b = wt.branch
 
117
        with open('hello', 'w') as f: f.write('hello world')
 
118
        wt.add('hello')
 
119
        revid = wt.commit(message='add hello', rev_id=b'revid', lossy=True)
 
120
        self.assertEqual('revid', revid)
 
121
 
 
122
    def test_commit_lossy_foreign(self):
 
123
        """Attempt a lossy commit to a foreign branch."""
 
124
        test_foreign.register_dummy_foreign_for_test(self)
 
125
        wt = self.make_branch_and_tree('.',
 
126
            format=test_foreign.DummyForeignVcsDirFormat())
 
127
        b = wt.branch
 
128
        with open('hello', 'w') as f: f.write('hello world')
 
129
        wt.add('hello')
 
130
        revid = wt.commit(message='add hello', lossy=True,
 
131
            timestamp=1302659388, timezone=0)
 
132
        self.assertEqual('dummy-v1:1302659388.0-0-UNKNOWN', revid)
 
133
 
 
134
    def test_commit_bound_lossy_foreign(self):
 
135
        """Attempt a lossy commit to a bzr branch bound to a foreign branch."""
 
136
        test_foreign.register_dummy_foreign_for_test(self)
 
137
        foreign_branch = self.make_branch('foreign',
 
138
            format=test_foreign.DummyForeignVcsDirFormat())
 
139
        wt = foreign_branch.create_checkout("local")
 
140
        b = wt.branch
 
141
        with open('local/hello', 'w') as f: f.write('hello world')
 
142
        wt.add('hello')
 
143
        revid = wt.commit(message='add hello', lossy=True,
 
144
            timestamp=1302659388, timezone=0)
 
145
        self.assertEqual('dummy-v1:1302659388.0-0-0', revid)
 
146
        self.assertEqual('dummy-v1:1302659388.0-0-0',
 
147
            foreign_branch.last_revision())
 
148
        self.assertEqual('dummy-v1:1302659388.0-0-0',
 
149
            wt.branch.last_revision())
109
150
 
110
151
    def test_missing_commit(self):
111
152
        """Test a commit with a missing file"""
112
153
        wt = self.make_branch_and_tree('.')
113
154
        b = wt.branch
114
 
        file('hello', 'w').write('hello world')
115
 
        wt.add(['hello'], ['hello-id'])
 
155
        with open('hello', 'w') as f: f.write('hello world')
 
156
        wt.add(['hello'], [b'hello-id'])
116
157
        wt.commit(message='add hello')
117
158
 
118
159
        os.remove('hello')
119
 
        wt.commit('removed hello', rev_id='rev2')
 
160
        reporter = CapturingReporter()
 
161
        wt.commit('removed hello', rev_id=b'rev2', reporter=reporter)
 
162
        self.assertEqual(
 
163
            [('missing', u'hello'), ('deleted', u'hello')],
 
164
            reporter.calls)
120
165
 
121
 
        tree = b.repository.revision_tree('rev2')
122
 
        self.assertFalse(tree.has_id('hello-id'))
 
166
        tree = b.repository.revision_tree(b'rev2')
 
167
        self.assertFalse(tree.has_id(b'hello-id'))
123
168
 
124
169
    def test_partial_commit_move(self):
125
170
        """Test a partial commit where a file was renamed but not committed.
138
183
        wt.add(['annotate', 'olive', 'annotate/foo.py', 'olive/dialog.py'])
139
184
        wt.commit(message='add files')
140
185
        wt.rename_one("olive/dialog.py", "aaa")
141
 
        self.build_tree_contents([('annotate/foo.py', 'modified\n')])
 
186
        self.build_tree_contents([('annotate/foo.py', b'modified\n')])
142
187
        wt.commit('renamed hello', specific_files=["annotate"])
143
188
 
144
189
    def test_pointless_commit(self):
145
190
        """Commit refuses unless there are changes or it's forced."""
146
191
        wt = self.make_branch_and_tree('.')
147
192
        b = wt.branch
148
 
        file('hello', 'w').write('hello')
 
193
        with open('hello', 'w') as f: f.write('hello')
149
194
        wt.add(['hello'])
150
195
        wt.commit(message='add hello')
151
 
        self.assertEquals(b.revno(), 1)
 
196
        self.assertEqual(b.revno(), 1)
152
197
        self.assertRaises(PointlessCommit,
153
198
                          wt.commit,
154
199
                          message='fails',
155
200
                          allow_pointless=False)
156
 
        self.assertEquals(b.revno(), 1)
 
201
        self.assertEqual(b.revno(), 1)
157
202
 
158
203
    def test_commit_empty(self):
159
204
        """Commiting an empty tree works."""
165
210
                          message='empty tree',
166
211
                          allow_pointless=False)
167
212
        wt.commit(message='empty tree', allow_pointless=True)
168
 
        self.assertEquals(b.revno(), 2)
 
213
        self.assertEqual(b.revno(), 2)
169
214
 
170
215
    def test_selective_delete(self):
171
216
        """Selective commit in tree with deletions"""
172
217
        wt = self.make_branch_and_tree('.')
173
218
        b = wt.branch
174
 
        file('hello', 'w').write('hello')
175
 
        file('buongia', 'w').write('buongia')
 
219
        with open('hello', 'w') as f: f.write('hello')
 
220
        with open('buongia', 'w') as f: f.write('buongia')
176
221
        wt.add(['hello', 'buongia'],
177
 
              ['hello-id', 'buongia-id'])
 
222
              [b'hello-id', b'buongia-id'])
178
223
        wt.commit(message='add files',
179
 
                 rev_id='test@rev-1')
 
224
                 rev_id=b'test@rev-1')
180
225
 
181
226
        os.remove('hello')
182
 
        file('buongia', 'w').write('new text')
 
227
        with open('buongia', 'w') as f: f.write('new text')
183
228
        wt.commit(message='update text',
184
229
                 specific_files=['buongia'],
185
230
                 allow_pointless=False,
186
 
                 rev_id='test@rev-2')
 
231
                 rev_id=b'test@rev-2')
187
232
 
188
233
        wt.commit(message='remove hello',
189
234
                 specific_files=['hello'],
190
235
                 allow_pointless=False,
191
 
                 rev_id='test@rev-3')
 
236
                 rev_id=b'test@rev-3')
192
237
 
193
 
        eq = self.assertEquals
 
238
        eq = self.assertEqual
194
239
        eq(b.revno(), 3)
195
240
 
196
 
        tree2 = b.repository.revision_tree('test@rev-2')
 
241
        tree2 = b.repository.revision_tree(b'test@rev-2')
197
242
        tree2.lock_read()
198
243
        self.addCleanup(tree2.unlock)
199
244
        self.assertTrue(tree2.has_filename('hello'))
200
 
        self.assertEquals(tree2.get_file_text('hello-id'), 'hello')
201
 
        self.assertEquals(tree2.get_file_text('buongia-id'), 'new text')
 
245
        self.assertEqual(tree2.get_file_text('hello'), b'hello')
 
246
        self.assertEqual(tree2.get_file_text('buongia'), b'new text')
202
247
 
203
 
        tree3 = b.repository.revision_tree('test@rev-3')
 
248
        tree3 = b.repository.revision_tree(b'test@rev-3')
204
249
        tree3.lock_read()
205
250
        self.addCleanup(tree3.unlock)
206
251
        self.assertFalse(tree3.has_filename('hello'))
207
 
        self.assertEquals(tree3.get_file_text('buongia-id'), 'new text')
 
252
        self.assertEqual(tree3.get_file_text('buongia'), b'new text')
208
253
 
209
254
    def test_commit_rename(self):
210
255
        """Test commit of a revision where a file is renamed."""
211
256
        tree = self.make_branch_and_tree('.')
212
257
        b = tree.branch
213
258
        self.build_tree(['hello'], line_endings='binary')
214
 
        tree.add(['hello'], ['hello-id'])
215
 
        tree.commit(message='one', rev_id='test@rev-1', allow_pointless=False)
 
259
        tree.add(['hello'], [b'hello-id'])
 
260
        tree.commit(message='one', rev_id=b'test@rev-1', allow_pointless=False)
216
261
 
217
262
        tree.rename_one('hello', 'fruity')
218
 
        tree.commit(message='renamed', rev_id='test@rev-2', allow_pointless=False)
 
263
        tree.commit(message='renamed', rev_id=b'test@rev-2', allow_pointless=False)
219
264
 
220
 
        eq = self.assertEquals
221
 
        tree1 = b.repository.revision_tree('test@rev-1')
 
265
        eq = self.assertEqual
 
266
        tree1 = b.repository.revision_tree(b'test@rev-1')
222
267
        tree1.lock_read()
223
268
        self.addCleanup(tree1.unlock)
224
 
        eq(tree1.id2path('hello-id'), 'hello')
225
 
        eq(tree1.get_file_text('hello-id'), 'contents of hello\n')
 
269
        eq(tree1.id2path(b'hello-id'), b'hello')
 
270
        eq(tree1.get_file_text('hello'), b'contents of hello\n')
226
271
        self.assertFalse(tree1.has_filename('fruity'))
227
 
        self.check_inventory_shape(tree1.inventory, ['hello'])
228
 
        ie = tree1.inventory['hello-id']
229
 
        eq(ie.revision, 'test@rev-1')
 
272
        self.check_tree_shape(tree1, ['hello'])
 
273
        eq(tree1.get_file_revision('hello'), b'test@rev-1')
230
274
 
231
 
        tree2 = b.repository.revision_tree('test@rev-2')
 
275
        tree2 = b.repository.revision_tree(b'test@rev-2')
232
276
        tree2.lock_read()
233
277
        self.addCleanup(tree2.unlock)
234
 
        eq(tree2.id2path('hello-id'), 'fruity')
235
 
        eq(tree2.get_file_text('hello-id'), 'contents of hello\n')
236
 
        self.check_inventory_shape(tree2.inventory, ['fruity'])
237
 
        ie = tree2.inventory['hello-id']
238
 
        eq(ie.revision, 'test@rev-2')
 
278
        eq(tree2.id2path(b'hello-id'), 'fruity')
 
279
        eq(tree2.get_file_text('fruity'), b'contents of hello\n')
 
280
        self.check_tree_shape(tree2, ['fruity'])
 
281
        eq(tree2.get_file_revision('fruity'), b'test@rev-2')
239
282
 
240
283
    def test_reused_rev_id(self):
241
284
        """Test that a revision id cannot be reused in a branch"""
242
285
        wt = self.make_branch_and_tree('.')
243
286
        b = wt.branch
244
 
        wt.commit('initial', rev_id='test@rev-1', allow_pointless=True)
 
287
        wt.commit('initial', rev_id=b'test@rev-1', allow_pointless=True)
245
288
        self.assertRaises(Exception,
246
289
                          wt.commit,
247
290
                          message='reused id',
248
 
                          rev_id='test@rev-1',
 
291
                          rev_id=b'test@rev-1',
249
292
                          allow_pointless=True)
250
293
 
251
294
    def test_commit_move(self):
252
295
        """Test commit of revisions with moved files and directories"""
253
 
        eq = self.assertEquals
 
296
        eq = self.assertEqual
254
297
        wt = self.make_branch_and_tree('.')
255
298
        b = wt.branch
256
 
        r1 = 'test@rev-1'
 
299
        r1 = b'test@rev-1'
257
300
        self.build_tree(['hello', 'a/', 'b/'])
258
 
        wt.add(['hello', 'a', 'b'], ['hello-id', 'a-id', 'b-id'])
 
301
        wt.add(['hello', 'a', 'b'], [b'hello-id', b'a-id', b'b-id'])
259
302
        wt.commit('initial', rev_id=r1, allow_pointless=False)
260
303
        wt.move(['hello'], 'a')
261
 
        r2 = 'test@rev-2'
 
304
        r2 = b'test@rev-2'
262
305
        wt.commit('two', rev_id=r2, allow_pointless=False)
263
306
        wt.lock_read()
264
307
        try:
265
 
            self.check_inventory_shape(wt.read_working_inventory(),
266
 
                                       ['a/', 'a/hello', 'b/'])
 
308
            self.check_tree_shape(wt, ['a/', 'a/hello', 'b/'])
267
309
        finally:
268
310
            wt.unlock()
269
311
 
270
312
        wt.move(['b'], 'a')
271
 
        r3 = 'test@rev-3'
 
313
        r3 = b'test@rev-3'
272
314
        wt.commit('three', rev_id=r3, allow_pointless=False)
273
315
        wt.lock_read()
274
316
        try:
275
 
            self.check_inventory_shape(wt.read_working_inventory(),
 
317
            self.check_tree_shape(wt,
276
318
                                       ['a/', 'a/hello', 'a/b/'])
277
 
            self.check_inventory_shape(b.repository.get_inventory(r3),
 
319
            self.check_tree_shape(b.repository.revision_tree(r3),
278
320
                                       ['a/', 'a/hello', 'a/b/'])
279
321
        finally:
280
322
            wt.unlock()
281
323
 
282
324
        wt.move(['a/hello'], 'a/b')
283
 
        r4 = 'test@rev-4'
 
325
        r4 = b'test@rev-4'
284
326
        wt.commit('four', rev_id=r4, allow_pointless=False)
285
327
        wt.lock_read()
286
328
        try:
287
 
            self.check_inventory_shape(wt.read_working_inventory(),
288
 
                                       ['a/', 'a/b/hello', 'a/b/'])
 
329
            self.check_tree_shape(wt, ['a/', 'a/b/hello', 'a/b/'])
289
330
        finally:
290
331
            wt.unlock()
291
332
 
292
333
        inv = b.repository.get_inventory(r4)
293
 
        eq(inv['hello-id'].revision, r4)
294
 
        eq(inv['a-id'].revision, r1)
295
 
        eq(inv['b-id'].revision, r3)
 
334
        eq(inv.get_entry(b'hello-id').revision, r4)
 
335
        eq(inv.get_entry(b'a-id').revision, r1)
 
336
        eq(inv.get_entry(b'b-id').revision, r3)
296
337
 
297
338
    def test_removed_commit(self):
298
339
        """Commit with a removed file"""
299
340
        wt = self.make_branch_and_tree('.')
300
341
        b = wt.branch
301
 
        file('hello', 'w').write('hello world')
302
 
        wt.add(['hello'], ['hello-id'])
 
342
        with open('hello', 'w') as f: f.write('hello world')
 
343
        wt.add(['hello'], [b'hello-id'])
303
344
        wt.commit(message='add hello')
304
345
        wt.remove('hello')
305
 
        wt.commit('removed hello', rev_id='rev2')
 
346
        wt.commit('removed hello', rev_id=b'rev2')
306
347
 
307
 
        tree = b.repository.revision_tree('rev2')
308
 
        self.assertFalse(tree.has_id('hello-id'))
 
348
        tree = b.repository.revision_tree(b'rev2')
 
349
        self.assertFalse(tree.has_id(b'hello-id'))
309
350
 
310
351
    def test_committed_ancestry(self):
311
352
        """Test commit appends revisions to ancestry."""
313
354
        b = wt.branch
314
355
        rev_ids = []
315
356
        for i in range(4):
316
 
            file('hello', 'w').write((str(i) * 4) + '\n')
 
357
            with open('hello', 'w') as f: f.write((str(i) * 4) + '\n')
317
358
            if i == 0:
318
 
                wt.add(['hello'], ['hello-id'])
 
359
                wt.add(['hello'], [b'hello-id'])
319
360
            rev_id = 'test@rev-%d' % (i+1)
320
361
            rev_ids.append(rev_id)
321
362
            wt.commit(message='rev %d' % (i+1),
322
363
                     rev_id=rev_id)
323
 
        eq = self.assertEquals
324
 
        eq(b.revision_history(), rev_ids)
325
364
        for i in range(4):
326
 
            anc = b.repository.get_ancestry(rev_ids[i])
327
 
            eq(anc, [None] + rev_ids[:i+1])
 
365
            self.assertThat(rev_ids[:i+1],
 
366
                MatchesAncestry(b.repository, rev_ids[i]))
328
367
 
329
368
    def test_commit_new_subdir_child_selective(self):
330
369
        wt = self.make_branch_and_tree('.')
331
370
        b = wt.branch
332
371
        self.build_tree(['dir/', 'dir/file1', 'dir/file2'])
333
372
        wt.add(['dir', 'dir/file1', 'dir/file2'],
334
 
              ['dirid', 'file1id', 'file2id'])
335
 
        wt.commit('dir/file1', specific_files=['dir/file1'], rev_id='1')
336
 
        inv = b.repository.get_inventory('1')
337
 
        self.assertEqual('1', inv['dirid'].revision)
338
 
        self.assertEqual('1', inv['file1id'].revision)
 
373
              [b'dirid', b'file1id', b'file2id'])
 
374
        wt.commit('dir/file1', specific_files=['dir/file1'], rev_id=b'1')
 
375
        inv = b.repository.get_inventory(b'1')
 
376
        self.assertEqual(b'1', inv.get_entry(b'dirid').revision)
 
377
        self.assertEqual(b'1', inv.get_entry(b'file1id').revision)
339
378
        # FIXME: This should raise a KeyError I think, rbc20051006
340
 
        self.assertRaises(BzrError, inv.__getitem__, 'file2id')
 
379
        self.assertRaises(BzrError, inv.get_entry, b'file2id')
341
380
 
342
381
    def test_strict_commit(self):
343
382
        """Try and commit with unknown files and strict = True, should fail."""
344
 
        from bzrlib.errors import StrictCommitFailed
 
383
        from ..errors import StrictCommitFailed
345
384
        wt = self.make_branch_and_tree('.')
346
385
        b = wt.branch
347
 
        file('hello', 'w').write('hello world')
 
386
        with open('hello', 'w') as f: f.write('hello world')
348
387
        wt.add('hello')
349
 
        file('goodbye', 'w').write('goodbye cruel world!')
 
388
        with open('goodbye', 'w') as f: f.write('goodbye cruel world!')
350
389
        self.assertRaises(StrictCommitFailed, wt.commit,
351
390
            message='add hello but not goodbye', strict=True)
352
391
 
353
392
    def test_strict_commit_without_unknowns(self):
354
393
        """Try and commit with no unknown files and strict = True,
355
394
        should work."""
356
 
        from bzrlib.errors import StrictCommitFailed
357
395
        wt = self.make_branch_and_tree('.')
358
396
        b = wt.branch
359
 
        file('hello', 'w').write('hello world')
 
397
        with open('hello', 'w') as f: f.write('hello world')
360
398
        wt.add('hello')
361
399
        wt.commit(message='add hello', strict=True)
362
400
 
364
402
        """Try and commit with unknown files and strict = False, should work."""
365
403
        wt = self.make_branch_and_tree('.')
366
404
        b = wt.branch
367
 
        file('hello', 'w').write('hello world')
 
405
        with open('hello', 'w') as f: f.write('hello world')
368
406
        wt.add('hello')
369
 
        file('goodbye', 'w').write('goodbye cruel world!')
 
407
        with open('goodbye', 'w') as f: f.write('goodbye cruel world!')
370
408
        wt.commit(message='add hello but not goodbye', strict=False)
371
409
 
372
410
    def test_nonstrict_commit_without_unknowns(self):
374
412
        should work."""
375
413
        wt = self.make_branch_and_tree('.')
376
414
        b = wt.branch
377
 
        file('hello', 'w').write('hello world')
 
415
        with open('hello', 'w') as f: f.write('hello world')
378
416
        wt.add('hello')
379
417
        wt.commit(message='add hello', strict=False)
380
418
 
381
419
    def test_signed_commit(self):
382
 
        import bzrlib.gpg
383
 
        import bzrlib.commit as commit
384
 
        oldstrategy = bzrlib.gpg.GPGStrategy
 
420
        import breezy.gpg
 
421
        import breezy.commit as commit
 
422
        oldstrategy = breezy.gpg.GPGStrategy
385
423
        wt = self.make_branch_and_tree('.')
386
424
        branch = wt.branch
387
 
        wt.commit("base", allow_pointless=True, rev_id='A')
388
 
        self.failIf(branch.repository.has_signature_for_revision_id('A'))
 
425
        wt.commit("base", allow_pointless=True, rev_id=b'A')
 
426
        self.assertFalse(branch.repository.has_signature_for_revision_id('A'))
389
427
        try:
390
 
            from bzrlib.testament import Testament
 
428
            from ..testament import Testament
391
429
            # monkey patch gpg signing mechanism
392
 
            bzrlib.gpg.GPGStrategy = bzrlib.gpg.LoopbackGPGStrategy
393
 
            commit.Commit(config=MustSignConfig(branch)).commit(message="base",
394
 
                                                      allow_pointless=True,
395
 
                                                      rev_id='B',
396
 
                                                      working_tree=wt)
 
430
            breezy.gpg.GPGStrategy = breezy.gpg.LoopbackGPGStrategy
 
431
            conf = config.MemoryStack(b'''
 
432
create_signatures=always
 
433
''')
 
434
            commit.Commit(config_stack=conf).commit(
 
435
                message="base", allow_pointless=True, rev_id=b'B',
 
436
                working_tree=wt)
397
437
            def sign(text):
398
 
                return bzrlib.gpg.LoopbackGPGStrategy(None).sign(text)
 
438
                return breezy.gpg.LoopbackGPGStrategy(None).sign(
 
439
                        text, breezy.gpg.MODE_CLEAR)
399
440
            self.assertEqual(sign(Testament.from_revision(branch.repository,
400
 
                             'B').as_short_text()),
 
441
                                                          'B').as_short_text()),
401
442
                             branch.repository.get_signature_text('B'))
402
443
        finally:
403
 
            bzrlib.gpg.GPGStrategy = oldstrategy
 
444
            breezy.gpg.GPGStrategy = oldstrategy
404
445
 
405
446
    def test_commit_failed_signature(self):
406
 
        import bzrlib.gpg
407
 
        import bzrlib.commit as commit
408
 
        oldstrategy = bzrlib.gpg.GPGStrategy
 
447
        import breezy.gpg
 
448
        import breezy.commit as commit
 
449
        oldstrategy = breezy.gpg.GPGStrategy
409
450
        wt = self.make_branch_and_tree('.')
410
451
        branch = wt.branch
411
 
        wt.commit("base", allow_pointless=True, rev_id='A')
412
 
        self.failIf(branch.repository.has_signature_for_revision_id('A'))
 
452
        wt.commit("base", allow_pointless=True, rev_id=b'A')
 
453
        self.assertFalse(branch.repository.has_signature_for_revision_id(b'A'))
413
454
        try:
414
 
            from bzrlib.testament import Testament
415
455
            # monkey patch gpg signing mechanism
416
 
            bzrlib.gpg.GPGStrategy = bzrlib.gpg.DisabledGPGStrategy
417
 
            config = MustSignConfig(branch)
418
 
            self.assertRaises(SigningFailed,
419
 
                              commit.Commit(config=config).commit,
 
456
            breezy.gpg.GPGStrategy = breezy.gpg.DisabledGPGStrategy
 
457
            conf = config.MemoryStack(b'''
 
458
create_signatures=always
 
459
''')
 
460
            self.assertRaises(breezy.gpg.SigningFailed,
 
461
                              commit.Commit(config_stack=conf).commit,
420
462
                              message="base",
421
463
                              allow_pointless=True,
422
 
                              rev_id='B',
 
464
                              rev_id=b'B',
423
465
                              working_tree=wt)
424
466
            branch = Branch.open(self.get_url('.'))
425
 
            self.assertEqual(branch.revision_history(), ['A'])
426
 
            self.failIf(branch.repository.has_revision('B'))
 
467
            self.assertEqual(branch.last_revision(), b'A')
 
468
            self.assertFalse(branch.repository.has_revision(b'B'))
427
469
        finally:
428
 
            bzrlib.gpg.GPGStrategy = oldstrategy
 
470
            breezy.gpg.GPGStrategy = oldstrategy
429
471
 
430
472
    def test_commit_invokes_hooks(self):
431
 
        import bzrlib.commit as commit
 
473
        import breezy.commit as commit
432
474
        wt = self.make_branch_and_tree('.')
433
475
        branch = wt.branch
434
476
        calls = []
435
477
        def called(branch, rev_id):
436
478
            calls.append('called')
437
 
        bzrlib.ahook = called
 
479
        breezy.ahook = called
438
480
        try:
439
 
            config = BranchWithHooks(branch)
440
 
            commit.Commit(config=config).commit(
441
 
                            message = "base",
442
 
                            allow_pointless=True,
443
 
                            rev_id='A', working_tree = wt)
 
481
            conf = config.MemoryStack(b'post_commit=breezy.ahook breezy.ahook')
 
482
            commit.Commit(config_stack=conf).commit(
 
483
                message = "base", allow_pointless=True, rev_id=b'A',
 
484
                working_tree = wt)
444
485
            self.assertEqual(['called', 'called'], calls)
445
486
        finally:
446
 
            del bzrlib.ahook
 
487
            del breezy.ahook
447
488
 
448
489
    def test_commit_object_doesnt_set_nick(self):
449
490
        # using the Commit object directly does not set the branch nick.
450
491
        wt = self.make_branch_and_tree('.')
451
492
        c = Commit()
452
493
        c.commit(working_tree=wt, message='empty tree', allow_pointless=True)
453
 
        self.assertEquals(wt.branch.revno(), 1)
 
494
        self.assertEqual(wt.branch.revno(), 1)
454
495
        self.assertEqual({},
455
496
                         wt.branch.repository.get_revision(
456
497
                            wt.branch.last_revision()).properties)
477
518
        bound_tree = self.make_branch_and_tree('bound')
478
519
        bound_tree.branch.bind(master_branch)
479
520
 
480
 
        self.build_tree_contents([('bound/content_file', 'initial contents\n')])
 
521
        self.build_tree_contents([('bound/content_file', b'initial contents\n')])
481
522
        bound_tree.add(['content_file'])
482
523
        bound_tree.commit(message='woo!')
483
524
 
484
 
        other_bzrdir = master_branch.bzrdir.sprout('other')
 
525
        other_bzrdir = master_branch.controldir.sprout('other')
485
526
        other_tree = other_bzrdir.open_workingtree()
486
527
 
487
528
        # do a commit to the other branch changing the content file so
488
529
        # that our commit after merging will have a merged revision in the
489
530
        # content file history.
490
 
        self.build_tree_contents([('other/content_file', 'change in other\n')])
 
531
        self.build_tree_contents([('other/content_file', b'change in other\n')])
491
532
        other_tree.commit('change in other')
492
533
 
493
534
        # do a merge into the bound branch from other, and then change the
494
535
        # content file locally to force a new revision (rather than using the
495
536
        # revision from other). This forces extra processing in commit.
496
537
        bound_tree.merge_from_branch(other_tree.branch)
497
 
        self.build_tree_contents([('bound/content_file', 'change in bound\n')])
 
538
        self.build_tree_contents([('bound/content_file', b'change in bound\n')])
498
539
 
499
540
        # before #34959 was fixed, this failed with 'revision not present in
500
541
        # weave' when trying to implicitly push from the bound branch to the master
528
569
            'filetoleave']
529
570
            )
530
571
        this_tree.commit('create_files')
531
 
        other_dir = this_tree.bzrdir.sprout('other')
 
572
        other_dir = this_tree.controldir.sprout('other')
532
573
        other_tree = other_dir.open_workingtree()
533
574
        other_tree.lock_write()
534
575
        # perform the needed actions on the files and dirs.
540
581
            other_tree.remove(['dirtoremove', 'filetoremove'])
541
582
            self.build_tree_contents([
542
583
                ('other/newdir/', ),
543
 
                ('other/filetomodify', 'new content'),
544
 
                ('other/newfile', 'new file content')])
 
584
                ('other/filetomodify', b'new content'),
 
585
                ('other/newfile', b'new file content')])
545
586
            other_tree.add('newfile')
546
587
            other_tree.add('newdir/')
547
588
            other_tree.commit('modify all sample files and dirs.')
550
591
        this_tree.merge_from_branch(other_tree.branch)
551
592
        reporter = CapturingReporter()
552
593
        this_tree.commit('do the commit', reporter=reporter)
553
 
        expected = set([
 
594
        expected = {
554
595
            ('change', 'modified', 'filetomodify'),
555
596
            ('change', 'added', 'newdir'),
556
597
            ('change', 'added', 'newfile'),
560
601
            ('renamed', 'renamed', 'filetoreparent', 'renameddir/reparentedfile'),
561
602
            ('deleted', 'dirtoremove'),
562
603
            ('deleted', 'filetoremove'),
563
 
            ])
 
604
            }
564
605
        result = set(reporter.calls)
565
606
        missing = expected - result
566
607
        new = result - expected
575
616
        tree.remove(['a', 'b'])
576
617
        tree.commit('removed a', specific_files='a')
577
618
        basis = tree.basis_tree()
578
 
        tree.lock_read()
579
 
        try:
580
 
            self.assertIs(None, basis.path2id('a'))
581
 
            self.assertFalse(basis.path2id('b') is None)
582
 
        finally:
583
 
            tree.unlock()
 
619
        with tree.lock_read():
 
620
            self.assertFalse(basis.is_versioned('a'))
 
621
            self.assertTrue(basis.is_versioned('b'))
584
622
 
585
623
    def test_commit_saves_1ms_timestamp(self):
586
624
        """Passing in a timestamp is saved with 1ms resolution"""
588
626
        self.build_tree(['a'])
589
627
        tree.add('a')
590
628
        tree.commit('added a', timestamp=1153248633.4186721, timezone=0,
591
 
                    rev_id='a1')
 
629
                    rev_id=b'a1')
592
630
 
593
 
        rev = tree.branch.repository.get_revision('a1')
 
631
        rev = tree.branch.repository.get_revision(b'a1')
594
632
        self.assertEqual(1153248633.419, rev.timestamp)
595
633
 
596
634
    def test_commit_has_1ms_resolution(self):
598
636
        tree = self.make_branch_and_tree('.')
599
637
        self.build_tree(['a'])
600
638
        tree.add('a')
601
 
        tree.commit('added a', rev_id='a1')
 
639
        tree.commit('added a', rev_id=b'a1')
602
640
 
603
 
        rev = tree.branch.repository.get_revision('a1')
 
641
        rev = tree.branch.repository.get_revision(b'a1')
604
642
        timestamp = rev.timestamp
605
643
        timestamp_1ms = round(timestamp, 3)
606
644
        self.assertEqual(timestamp_1ms, timestamp)
607
645
 
608
 
    def assertBasisTreeKind(self, kind, tree, file_id):
 
646
    def assertBasisTreeKind(self, kind, tree, path):
609
647
        basis = tree.basis_tree()
610
648
        basis.lock_read()
611
649
        try:
612
 
            self.assertEqual(kind, basis.kind(file_id))
 
650
            self.assertEqual(kind, basis.kind(path))
613
651
        finally:
614
652
            basis.unlock()
615
653
 
617
655
        self.requireFeature(SymlinkFeature)
618
656
        tree = self.make_branch_and_tree('.')
619
657
        os.symlink('target', 'name')
620
 
        tree.add('name', 'a-file-id')
 
658
        tree.add('name', b'a-file-id')
621
659
        tree.commit('Added a symlink')
622
 
        self.assertBasisTreeKind('symlink', tree, 'a-file-id')
 
660
        self.assertBasisTreeKind('symlink', tree, 'name')
623
661
 
624
662
        os.unlink('name')
625
663
        self.build_tree(['name'])
626
664
        tree.commit('Changed symlink to file')
627
 
        self.assertBasisTreeKind('file', tree, 'a-file-id')
 
665
        self.assertBasisTreeKind('file', tree, 'name')
628
666
 
629
667
        os.unlink('name')
630
668
        os.symlink('target', 'name')
631
669
        tree.commit('file to symlink')
632
 
        self.assertBasisTreeKind('symlink', tree, 'a-file-id')
 
670
        self.assertBasisTreeKind('symlink', tree, 'name')
633
671
 
634
672
        os.unlink('name')
635
673
        os.mkdir('name')
636
674
        tree.commit('symlink to directory')
637
 
        self.assertBasisTreeKind('directory', tree, 'a-file-id')
 
675
        self.assertBasisTreeKind('directory', tree, 'name')
638
676
 
639
677
        os.rmdir('name')
640
678
        os.symlink('target', 'name')
641
679
        tree.commit('directory to symlink')
642
 
        self.assertBasisTreeKind('symlink', tree, 'a-file-id')
 
680
        self.assertBasisTreeKind('symlink', tree, 'name')
643
681
 
644
682
        # prepare for directory <-> file tests
645
683
        os.unlink('name')
646
684
        os.mkdir('name')
647
685
        tree.commit('symlink to directory')
648
 
        self.assertBasisTreeKind('directory', tree, 'a-file-id')
 
686
        self.assertBasisTreeKind('directory', tree, 'name')
649
687
 
650
688
        os.rmdir('name')
651
689
        self.build_tree(['name'])
652
690
        tree.commit('Changed directory to file')
653
 
        self.assertBasisTreeKind('file', tree, 'a-file-id')
 
691
        self.assertBasisTreeKind('file', tree, 'name')
654
692
 
655
693
        os.unlink('name')
656
694
        os.mkdir('name')
657
695
        tree.commit('file to directory')
658
 
        self.assertBasisTreeKind('directory', tree, 'a-file-id')
 
696
        self.assertBasisTreeKind('directory', tree, 'name')
659
697
 
660
698
    def test_commit_unversioned_specified(self):
661
699
        """Commit should raise if specified files isn't in basis or worktree"""
681
719
        tree = self.make_branch_and_tree('.')
682
720
        try:
683
721
            tree.commit()
684
 
        except Exception, e:
 
722
        except Exception as e:
685
723
            self.assertTrue(isinstance(e, BzrError))
686
724
            self.assertEqual('The message or message_callback keyword'
687
725
                             ' parameter is required for commit().', str(e))
720
758
        tree = self.make_branch_and_tree('foo')
721
759
        # pending merge would turn into a left parent
722
760
        tree.commit('commit 1')
723
 
        tree.add_parent_tree_id('example')
 
761
        tree.add_parent_tree_id(b'example')
724
762
        self.build_tree(['foo/bar', 'foo/baz'])
725
763
        tree.add(['bar', 'baz'])
726
 
        err = self.assertRaises(errors.CannotCommitSelectedFileMerge,
 
764
        err = self.assertRaises(CannotCommitSelectedFileMerge,
727
765
            tree.commit, 'commit 2', specific_files=['bar', 'baz'])
728
766
        self.assertEqual(['bar', 'baz'], err.files)
729
767
        self.assertEqual('Selected-file commit of merges is not supported'
751
789
        self.assertFalse('authors' in rev.properties)
752
790
 
753
791
    def test_commit_author(self):
754
 
        """Passing a non-empty author kwarg to MutableTree.commit should add
 
792
        """Passing a non-empty authors kwarg to MutableTree.commit should add
755
793
        the 'author' revision property.
756
794
        """
757
795
        tree = self.make_branch_and_tree('foo')
758
 
        rev_id = self.callDeprecated(['The parameter author was '
759
 
                'deprecated in version 1.13. Use authors instead'],
760
 
                tree.commit, 'commit 1', author='John Doe <jdoe@example.com>')
 
796
        rev_id = tree.commit(
 
797
            'commit 1',
 
798
            authors=['John Doe <jdoe@example.com>'])
761
799
        rev = tree.branch.repository.get_revision(rev_id)
762
800
        self.assertEqual('John Doe <jdoe@example.com>',
763
801
                         rev.properties['authors'])
781
819
                'Jane Rey <jrey@example.com>', rev.properties['authors'])
782
820
        self.assertFalse('author' in rev.properties)
783
821
 
784
 
    def test_author_and_authors_incompatible(self):
785
 
        tree = self.make_branch_and_tree('foo')
786
 
        self.assertRaises(AssertionError, tree.commit, 'commit 1',
787
 
                authors=['John Doe <jdoe@example.com>',
788
 
                         'Jane Rey <jrey@example.com>'],
789
 
                author="Jack Me <jme@example.com>")
790
 
 
791
822
    def test_author_with_newline_rejected(self):
792
823
        tree = self.make_branch_and_tree('foo')
793
824
        self.assertRaises(AssertionError, tree.commit, 'commit 1',
796
827
    def test_commit_with_checkout_and_branch_sharing_repo(self):
797
828
        repo = self.make_repository('repo', shared=True)
798
829
        # make_branch_and_tree ignores shared repos
799
 
        branch = bzrdir.BzrDir.create_branch_convenience('repo/branch')
 
830
        branch = controldir.ControlDir.create_branch_convenience('repo/branch')
800
831
        tree2 = branch.create_checkout('repo/tree2')
801
 
        tree2.commit('message', rev_id='rev1')
802
 
        self.assertTrue(tree2.branch.repository.has_revision('rev1'))
 
832
        tree2.commit('message', rev_id=b'rev1')
 
833
        self.assertTrue(tree2.branch.repository.has_revision(b'rev1'))
 
834
 
 
835
 
 
836
class FilterExcludedTests(TestCase):
 
837
 
 
838
    def test_add_file_not_excluded(self):
 
839
        changes = [
 
840
            ('fid', (None, 'newpath'),
 
841
             0, (False, False), ('pid', 'pid'), ('newpath', 'newpath'),
 
842
             ('file', 'file'), (True, True))]
 
843
        self.assertEqual(changes, list(filter_excluded(changes, ['otherpath'])))
 
844
 
 
845
    def test_add_file_excluded(self):
 
846
        changes = [
 
847
            ('fid', (None, 'newpath'),
 
848
             0, (False, False), ('pid', 'pid'), ('newpath', 'newpath'),
 
849
             ('file', 'file'), (True, True))]
 
850
        self.assertEqual([], list(filter_excluded(changes, ['newpath'])))
 
851
 
 
852
    def test_delete_file_excluded(self):
 
853
        changes = [
 
854
            ('fid', ('somepath', None),
 
855
             0, (False, None), ('pid', None), ('newpath', None),
 
856
             ('file', None), (True, None))]
 
857
        self.assertEqual([], list(filter_excluded(changes, ['somepath'])))
 
858
 
 
859
    def test_move_from_or_to_excluded(self):
 
860
        changes = [
 
861
            ('fid', ('oldpath', 'newpath'),
 
862
             0, (False, False), ('pid', 'pid'), ('oldpath', 'newpath'),
 
863
             ('file', 'file'), (True, True))]
 
864
        self.assertEqual([], list(filter_excluded(changes, ['oldpath'])))
 
865
        self.assertEqual([], list(filter_excluded(changes, ['newpath'])))