~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_commit.py

  • Committer: Martin Pool
  • Date: 2006-01-13 09:57:13 UTC
  • mto: This revision was merged to the branch mainline in revision 1611.
  • Revision ID: mbp@sourcefrog.net-20060113095713-1fa5912229a3898e
Review updates of pycurl transport

Split them out into 

  bzrlib.transport.http             common base
  bzrlib.transport.http._urllib     pure python
  bzrlib.transport.http._pycurl     calls pycurl

Update to work with robert's nice transport test multiplexer.

Add PyCurlTransport.has() which does just a HEAD request; should be faster.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005, 2006 by Canonical Ltd
2
 
#
 
1
# Copyright (C) 2005 by Canonical Ltd
 
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
5
5
# the Free Software Foundation; either version 2 of the License, or
6
6
# (at your option) any later version.
7
 
#
 
7
 
8
8
# This program is distributed in the hope that it will be useful,
9
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
11
# GNU General Public License for more details.
12
 
#
 
12
 
13
13
# You should have received a copy of the GNU General Public License
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
18
import os
19
19
 
20
20
import bzrlib
21
 
from bzrlib.tests import TestCaseWithTransport
 
21
from bzrlib.tests import TestCaseInTempDir
22
22
from bzrlib.branch import Branch
23
 
from bzrlib.bzrdir import BzrDir, BzrDirMetaFormat1
24
23
from bzrlib.workingtree import WorkingTree
25
 
from bzrlib.commit import Commit, NullCommitReporter
 
24
from bzrlib.commit import Commit
26
25
from bzrlib.config import BranchConfig
27
 
from bzrlib.errors import (PointlessCommit, BzrError, SigningFailed, 
28
 
                           LockContention)
 
26
from bzrlib.errors import PointlessCommit, BzrError, SigningFailed
29
27
 
30
28
 
31
29
# TODO: Test commit with some added, and added-but-missing files
45
43
        return "bzrlib.ahook bzrlib.ahook"
46
44
 
47
45
 
48
 
class CapturingReporter(NullCommitReporter):
49
 
    """This reporter captures the calls made to it for evaluation later."""
50
 
 
51
 
    def __init__(self):
52
 
        # a list of the calls this received
53
 
        self.calls = []
54
 
 
55
 
    def snapshot_change(self, change, path):
56
 
        self.calls.append(('change', change, path))
57
 
 
58
 
    def deleted(self, file_id):
59
 
        self.calls.append(('deleted', file_id))
60
 
 
61
 
    def missing(self, path):
62
 
        self.calls.append(('missing', path))
63
 
 
64
 
    def renamed(self, change, old_path, new_path):
65
 
        self.calls.append(('renamed', change, old_path, new_path))
66
 
 
67
 
 
68
 
class TestCommit(TestCaseWithTransport):
 
46
class TestCommit(TestCaseInTempDir):
69
47
 
70
48
    def test_simple_commit(self):
71
49
        """Commit and check two versions of a single file."""
72
 
        wt = self.make_branch_and_tree('.')
73
 
        b = wt.branch
 
50
        b = Branch.initialize(u'.')
74
51
        file('hello', 'w').write('hello world')
75
 
        wt.add('hello')
76
 
        wt.commit(message='add hello')
77
 
        file_id = wt.path2id('hello')
 
52
        b.working_tree().add('hello')
 
53
        b.working_tree().commit(message='add hello')
 
54
        file_id = b.working_tree().path2id('hello')
78
55
 
79
56
        file('hello', 'w').write('version 2')
80
 
        wt.commit(message='commit 2')
 
57
        b.working_tree().commit(message='commit 2')
81
58
 
82
59
        eq = self.assertEquals
83
60
        eq(b.revno(), 2)
84
61
        rh = b.revision_history()
85
 
        rev = b.repository.get_revision(rh[0])
 
62
        rev = b.get_revision(rh[0])
86
63
        eq(rev.message, 'add hello')
87
64
 
88
 
        tree1 = b.repository.revision_tree(rh[0])
 
65
        tree1 = b.revision_tree(rh[0])
89
66
        text = tree1.get_file_text(file_id)
90
67
        eq(text, 'hello world')
91
68
 
92
 
        tree2 = b.repository.revision_tree(rh[1])
 
69
        tree2 = b.revision_tree(rh[1])
93
70
        eq(tree2.get_file_text(file_id), 'version 2')
94
71
 
95
72
    def test_delete_commit(self):
96
73
        """Test a commit with a deleted file"""
97
 
        wt = self.make_branch_and_tree('.')
98
 
        b = wt.branch
 
74
        b = Branch.initialize(u'.')
99
75
        file('hello', 'w').write('hello world')
100
 
        wt.add(['hello'], ['hello-id'])
101
 
        wt.commit(message='add hello')
 
76
        b.working_tree().add(['hello'], ['hello-id'])
 
77
        b.working_tree().commit(message='add hello')
102
78
 
103
79
        os.remove('hello')
104
 
        wt.commit('removed hello', rev_id='rev2')
 
80
        b.working_tree().commit('removed hello', rev_id='rev2')
105
81
 
106
 
        tree = b.repository.revision_tree('rev2')
 
82
        tree = b.revision_tree('rev2')
107
83
        self.assertFalse(tree.has_id('hello-id'))
108
84
 
109
85
    def test_pointless_commit(self):
110
86
        """Commit refuses unless there are changes or it's forced."""
111
 
        wt = self.make_branch_and_tree('.')
112
 
        b = wt.branch
 
87
        b = Branch.initialize(u'.')
113
88
        file('hello', 'w').write('hello')
114
 
        wt.add(['hello'])
115
 
        wt.commit(message='add hello')
 
89
        b.working_tree().add(['hello'])
 
90
        b.working_tree().commit(message='add hello')
116
91
        self.assertEquals(b.revno(), 1)
117
92
        self.assertRaises(PointlessCommit,
118
 
                          wt.commit,
 
93
                          b.working_tree().commit,
119
94
                          message='fails',
120
95
                          allow_pointless=False)
121
96
        self.assertEquals(b.revno(), 1)
122
97
        
123
98
    def test_commit_empty(self):
124
99
        """Commiting an empty tree works."""
125
 
        wt = self.make_branch_and_tree('.')
126
 
        b = wt.branch
127
 
        wt.commit(message='empty tree', allow_pointless=True)
 
100
        b = Branch.initialize(u'.')
 
101
        b.working_tree().commit(message='empty tree', allow_pointless=True)
128
102
        self.assertRaises(PointlessCommit,
129
 
                          wt.commit,
 
103
                          b.working_tree().commit,
130
104
                          message='empty tree',
131
105
                          allow_pointless=False)
132
 
        wt.commit(message='empty tree', allow_pointless=True)
 
106
        b.working_tree().commit(message='empty tree', allow_pointless=True)
133
107
        self.assertEquals(b.revno(), 2)
134
108
 
 
109
 
135
110
    def test_selective_delete(self):
136
111
        """Selective commit in tree with deletions"""
137
 
        wt = self.make_branch_and_tree('.')
138
 
        b = wt.branch
 
112
        b = Branch.initialize(u'.')
139
113
        file('hello', 'w').write('hello')
140
114
        file('buongia', 'w').write('buongia')
141
 
        wt.add(['hello', 'buongia'],
 
115
        b.working_tree().add(['hello', 'buongia'],
142
116
              ['hello-id', 'buongia-id'])
143
 
        wt.commit(message='add files',
 
117
        b.working_tree().commit(message='add files',
144
118
                 rev_id='test@rev-1')
145
119
        
146
120
        os.remove('hello')
147
121
        file('buongia', 'w').write('new text')
148
 
        wt.commit(message='update text',
 
122
        b.working_tree().commit(message='update text',
149
123
                 specific_files=['buongia'],
150
124
                 allow_pointless=False,
151
125
                 rev_id='test@rev-2')
152
126
 
153
 
        wt.commit(message='remove hello',
 
127
        b.working_tree().commit(message='remove hello',
154
128
                 specific_files=['hello'],
155
129
                 allow_pointless=False,
156
130
                 rev_id='test@rev-3')
158
132
        eq = self.assertEquals
159
133
        eq(b.revno(), 3)
160
134
 
161
 
        tree2 = b.repository.revision_tree('test@rev-2')
 
135
        tree2 = b.revision_tree('test@rev-2')
162
136
        self.assertTrue(tree2.has_filename('hello'))
163
137
        self.assertEquals(tree2.get_file_text('hello-id'), 'hello')
164
138
        self.assertEquals(tree2.get_file_text('buongia-id'), 'new text')
165
139
        
166
 
        tree3 = b.repository.revision_tree('test@rev-3')
 
140
        tree3 = b.revision_tree('test@rev-3')
167
141
        self.assertFalse(tree3.has_filename('hello'))
168
142
        self.assertEquals(tree3.get_file_text('buongia-id'), 'new text')
169
143
 
 
144
 
170
145
    def test_commit_rename(self):
171
146
        """Test commit of a revision where a file is renamed."""
172
 
        tree = self.make_branch_and_tree('.')
173
 
        b = tree.branch
 
147
        b = Branch.initialize(u'.')
 
148
        tree = WorkingTree(u'.', b)
174
149
        self.build_tree(['hello'], line_endings='binary')
175
150
        tree.add(['hello'], ['hello-id'])
176
151
        tree.commit(message='one', rev_id='test@rev-1', allow_pointless=False)
179
154
        tree.commit(message='renamed', rev_id='test@rev-2', allow_pointless=False)
180
155
 
181
156
        eq = self.assertEquals
182
 
        tree1 = b.repository.revision_tree('test@rev-1')
 
157
        tree1 = b.revision_tree('test@rev-1')
183
158
        eq(tree1.id2path('hello-id'), 'hello')
184
159
        eq(tree1.get_file_text('hello-id'), 'contents of hello\n')
185
160
        self.assertFalse(tree1.has_filename('fruity'))
187
162
        ie = tree1.inventory['hello-id']
188
163
        eq(ie.revision, 'test@rev-1')
189
164
 
190
 
        tree2 = b.repository.revision_tree('test@rev-2')
 
165
        tree2 = b.revision_tree('test@rev-2')
191
166
        eq(tree2.id2path('hello-id'), 'fruity')
192
167
        eq(tree2.get_file_text('hello-id'), 'contents of hello\n')
193
168
        self.check_inventory_shape(tree2.inventory, ['fruity'])
196
171
 
197
172
    def test_reused_rev_id(self):
198
173
        """Test that a revision id cannot be reused in a branch"""
199
 
        wt = self.make_branch_and_tree('.')
200
 
        b = wt.branch
201
 
        wt.commit('initial', rev_id='test@rev-1', allow_pointless=True)
 
174
        b = Branch.initialize(u'.')
 
175
        b.working_tree().commit('initial', rev_id='test@rev-1', allow_pointless=True)
202
176
        self.assertRaises(Exception,
203
 
                          wt.commit,
 
177
                          b.working_tree().commit,
204
178
                          message='reused id',
205
179
                          rev_id='test@rev-1',
206
180
                          allow_pointless=True)
208
182
    def test_commit_move(self):
209
183
        """Test commit of revisions with moved files and directories"""
210
184
        eq = self.assertEquals
211
 
        wt = self.make_branch_and_tree('.')
212
 
        b = wt.branch
 
185
        b = Branch.initialize(u'.')
213
186
        r1 = 'test@rev-1'
214
187
        self.build_tree(['hello', 'a/', 'b/'])
215
 
        wt.add(['hello', 'a', 'b'], ['hello-id', 'a-id', 'b-id'])
216
 
        wt.commit('initial', rev_id=r1, allow_pointless=False)
217
 
        wt.move(['hello'], 'a')
 
188
        b.working_tree().add(['hello', 'a', 'b'], ['hello-id', 'a-id', 'b-id'])
 
189
        b.working_tree().commit('initial', rev_id=r1, allow_pointless=False)
 
190
        b.working_tree().move(['hello'], 'a')
218
191
        r2 = 'test@rev-2'
219
 
        wt.commit('two', rev_id=r2, allow_pointless=False)
220
 
        self.check_inventory_shape(wt.read_working_inventory(),
 
192
        b.working_tree().commit('two', rev_id=r2, allow_pointless=False)
 
193
        self.check_inventory_shape(b.working_tree().read_working_inventory(),
221
194
                                   ['a', 'a/hello', 'b'])
222
195
 
223
 
        wt.move(['b'], 'a')
 
196
        b.working_tree().move(['b'], 'a')
224
197
        r3 = 'test@rev-3'
225
 
        wt.commit('three', rev_id=r3, allow_pointless=False)
226
 
        self.check_inventory_shape(wt.read_working_inventory(),
 
198
        b.working_tree().commit('three', rev_id=r3, allow_pointless=False)
 
199
        self.check_inventory_shape(b.working_tree().read_working_inventory(),
227
200
                                   ['a', 'a/hello', 'a/b'])
228
 
        self.check_inventory_shape(b.repository.get_revision_inventory(r3),
 
201
        self.check_inventory_shape(b.get_revision_inventory(r3),
229
202
                                   ['a', 'a/hello', 'a/b'])
230
203
 
231
 
        wt.move(['a/hello'], 'a/b')
 
204
        b.working_tree().move(['a/hello'], 'a/b')
232
205
        r4 = 'test@rev-4'
233
 
        wt.commit('four', rev_id=r4, allow_pointless=False)
234
 
        self.check_inventory_shape(wt.read_working_inventory(),
 
206
        b.working_tree().commit('four', rev_id=r4, allow_pointless=False)
 
207
        self.check_inventory_shape(b.working_tree().read_working_inventory(),
235
208
                                   ['a', 'a/b/hello', 'a/b'])
236
209
 
237
 
        inv = b.repository.get_revision_inventory(r4)
 
210
        inv = b.get_revision_inventory(r4)
238
211
        eq(inv['hello-id'].revision, r4)
239
212
        eq(inv['a-id'].revision, r1)
240
213
        eq(inv['b-id'].revision, r3)
241
214
        
242
215
    def test_removed_commit(self):
243
216
        """Commit with a removed file"""
244
 
        wt = self.make_branch_and_tree('.')
245
 
        b = wt.branch
 
217
        b = Branch.initialize(u'.')
 
218
        wt = b.working_tree()
246
219
        file('hello', 'w').write('hello world')
247
 
        wt.add(['hello'], ['hello-id'])
248
 
        wt.commit(message='add hello')
 
220
        b.working_tree().add(['hello'], ['hello-id'])
 
221
        b.working_tree().commit(message='add hello')
 
222
 
 
223
        wt = b.working_tree()  # FIXME: kludge for aliasing of working inventory
249
224
        wt.remove('hello')
250
 
        wt.commit('removed hello', rev_id='rev2')
 
225
        b.working_tree().commit('removed hello', rev_id='rev2')
251
226
 
252
 
        tree = b.repository.revision_tree('rev2')
 
227
        tree = b.revision_tree('rev2')
253
228
        self.assertFalse(tree.has_id('hello-id'))
254
229
 
 
230
 
255
231
    def test_committed_ancestry(self):
256
232
        """Test commit appends revisions to ancestry."""
257
 
        wt = self.make_branch_and_tree('.')
258
 
        b = wt.branch
 
233
        b = Branch.initialize(u'.')
259
234
        rev_ids = []
260
235
        for i in range(4):
261
236
            file('hello', 'w').write((str(i) * 4) + '\n')
262
237
            if i == 0:
263
 
                wt.add(['hello'], ['hello-id'])
 
238
                b.working_tree().add(['hello'], ['hello-id'])
264
239
            rev_id = 'test@rev-%d' % (i+1)
265
240
            rev_ids.append(rev_id)
266
 
            wt.commit(message='rev %d' % (i+1),
 
241
            b.working_tree().commit(message='rev %d' % (i+1),
267
242
                     rev_id=rev_id)
268
243
        eq = self.assertEquals
269
244
        eq(b.revision_history(), rev_ids)
270
245
        for i in range(4):
271
 
            anc = b.repository.get_ancestry(rev_ids[i])
 
246
            anc = b.get_ancestry(rev_ids[i])
272
247
            eq(anc, [None] + rev_ids[:i+1])
273
248
 
274
249
    def test_commit_new_subdir_child_selective(self):
275
 
        wt = self.make_branch_and_tree('.')
276
 
        b = wt.branch
 
250
        b = Branch.initialize(u'.')
277
251
        self.build_tree(['dir/', 'dir/file1', 'dir/file2'])
278
 
        wt.add(['dir', 'dir/file1', 'dir/file2'],
 
252
        b.working_tree().add(['dir', 'dir/file1', 'dir/file2'],
279
253
              ['dirid', 'file1id', 'file2id'])
280
 
        wt.commit('dir/file1', specific_files=['dir/file1'], rev_id='1')
281
 
        inv = b.repository.get_inventory('1')
 
254
        b.working_tree().commit('dir/file1', specific_files=['dir/file1'], rev_id='1')
 
255
        inv = b.get_inventory('1')
282
256
        self.assertEqual('1', inv['dirid'].revision)
283
257
        self.assertEqual('1', inv['file1id'].revision)
284
258
        # FIXME: This should raise a KeyError I think, rbc20051006
287
261
    def test_strict_commit(self):
288
262
        """Try and commit with unknown files and strict = True, should fail."""
289
263
        from bzrlib.errors import StrictCommitFailed
290
 
        wt = self.make_branch_and_tree('.')
291
 
        b = wt.branch
 
264
        b = Branch.initialize(u'.')
292
265
        file('hello', 'w').write('hello world')
293
 
        wt.add('hello')
 
266
        b.working_tree().add('hello')
294
267
        file('goodbye', 'w').write('goodbye cruel world!')
295
 
        self.assertRaises(StrictCommitFailed, wt.commit,
 
268
        self.assertRaises(StrictCommitFailed, b.working_tree().commit,
296
269
            message='add hello but not goodbye', strict=True)
297
270
 
298
271
    def test_strict_commit_without_unknowns(self):
299
272
        """Try and commit with no unknown files and strict = True,
300
273
        should work."""
301
274
        from bzrlib.errors import StrictCommitFailed
302
 
        wt = self.make_branch_and_tree('.')
303
 
        b = wt.branch
 
275
        b = Branch.initialize(u'.')
304
276
        file('hello', 'w').write('hello world')
305
 
        wt.add('hello')
306
 
        wt.commit(message='add hello', strict=True)
 
277
        b.working_tree().add('hello')
 
278
        b.working_tree().commit(message='add hello', strict=True)
307
279
 
308
280
    def test_nonstrict_commit(self):
309
281
        """Try and commit with unknown files and strict = False, should work."""
310
 
        wt = self.make_branch_and_tree('.')
311
 
        b = wt.branch
 
282
        b = Branch.initialize(u'.')
312
283
        file('hello', 'w').write('hello world')
313
 
        wt.add('hello')
 
284
        b.working_tree().add('hello')
314
285
        file('goodbye', 'w').write('goodbye cruel world!')
315
 
        wt.commit(message='add hello but not goodbye', strict=False)
 
286
        b.working_tree().commit(message='add hello but not goodbye', strict=False)
316
287
 
317
288
    def test_nonstrict_commit_without_unknowns(self):
318
289
        """Try and commit with no unknown files and strict = False,
319
290
        should work."""
320
 
        wt = self.make_branch_and_tree('.')
321
 
        b = wt.branch
 
291
        b = Branch.initialize(u'.')
322
292
        file('hello', 'w').write('hello world')
323
 
        wt.add('hello')
324
 
        wt.commit(message='add hello', strict=False)
 
293
        b.working_tree().add('hello')
 
294
        b.working_tree().commit(message='add hello', strict=False)
325
295
 
326
296
    def test_signed_commit(self):
327
297
        import bzrlib.gpg
328
298
        import bzrlib.commit as commit
329
299
        oldstrategy = bzrlib.gpg.GPGStrategy
330
 
        wt = self.make_branch_and_tree('.')
331
 
        branch = wt.branch
332
 
        wt.commit("base", allow_pointless=True, rev_id='A')
333
 
        self.failIf(branch.repository.has_signature_for_revision_id('A'))
 
300
        branch = Branch.initialize(u'.')
 
301
        branch.working_tree().commit("base", allow_pointless=True, rev_id='A')
 
302
        self.failIf(branch.revision_store.has_id('A', 'sig'))
334
303
        try:
335
304
            from bzrlib.testament import Testament
336
305
            # monkey patch gpg signing mechanism
337
306
            bzrlib.gpg.GPGStrategy = bzrlib.gpg.LoopbackGPGStrategy
338
 
            commit.Commit(config=MustSignConfig(branch)).commit(message="base",
 
307
            commit.Commit(config=MustSignConfig(branch)).commit(branch, "base",
339
308
                                                      allow_pointless=True,
340
 
                                                      rev_id='B',
341
 
                                                      working_tree=wt)
342
 
            self.assertEqual(Testament.from_revision(branch.repository,
343
 
                             'B').as_short_text(),
344
 
                             branch.repository.get_signature_text('B'))
 
309
                                                      rev_id='B')
 
310
            self.assertEqual(Testament.from_revision(branch,'B').as_short_text(),
 
311
                             branch.revision_store.get('B', 'sig').read())
345
312
        finally:
346
313
            bzrlib.gpg.GPGStrategy = oldstrategy
347
314
 
349
316
        import bzrlib.gpg
350
317
        import bzrlib.commit as commit
351
318
        oldstrategy = bzrlib.gpg.GPGStrategy
352
 
        wt = self.make_branch_and_tree('.')
353
 
        branch = wt.branch
354
 
        wt.commit("base", allow_pointless=True, rev_id='A')
355
 
        self.failIf(branch.repository.has_signature_for_revision_id('A'))
 
319
        branch = Branch.initialize(u'.')
 
320
        branch.working_tree().commit("base", allow_pointless=True, rev_id='A')
 
321
        self.failIf(branch.revision_store.has_id('A', 'sig'))
356
322
        try:
357
323
            from bzrlib.testament import Testament
358
324
            # monkey patch gpg signing mechanism
360
326
            config = MustSignConfig(branch)
361
327
            self.assertRaises(SigningFailed,
362
328
                              commit.Commit(config=config).commit,
363
 
                              message="base",
 
329
                              branch, "base",
364
330
                              allow_pointless=True,
365
 
                              rev_id='B',
366
 
                              working_tree=wt)
367
 
            branch = Branch.open(self.get_url('.'))
 
331
                              rev_id='B')
 
332
            branch = Branch.open(u'.')
368
333
            self.assertEqual(branch.revision_history(), ['A'])
369
 
            self.failIf(branch.repository.has_revision('B'))
 
334
            self.failIf(branch.revision_store.has_id('B'))
370
335
        finally:
371
336
            bzrlib.gpg.GPGStrategy = oldstrategy
372
337
 
373
338
    def test_commit_invokes_hooks(self):
374
339
        import bzrlib.commit as commit
375
 
        wt = self.make_branch_and_tree('.')
376
 
        branch = wt.branch
 
340
        branch = Branch.initialize(u'.')
377
341
        calls = []
378
342
        def called(branch, rev_id):
379
343
            calls.append('called')
381
345
        try:
382
346
            config = BranchWithHooks(branch)
383
347
            commit.Commit(config=config).commit(
384
 
                            message = "base",
 
348
                            branch, "base",
385
349
                            allow_pointless=True,
386
 
                            rev_id='A', working_tree = wt)
 
350
                            rev_id='A')
387
351
            self.assertEqual(['called', 'called'], calls)
388
352
        finally:
389
353
            del bzrlib.ahook
390
 
 
391
 
    def test_commit_object_doesnt_set_nick(self):
392
 
        # using the Commit object directly does not set the branch nick.
393
 
        wt = self.make_branch_and_tree('.')
394
 
        c = Commit()
395
 
        c.commit(working_tree=wt, message='empty tree', allow_pointless=True)
396
 
        self.assertEquals(wt.branch.revno(), 1)
397
 
        self.assertEqual({},
398
 
                         wt.branch.repository.get_revision(
399
 
                            wt.branch.last_revision()).properties)
400
 
 
401
 
    def test_safe_master_lock(self):
402
 
        os.mkdir('master')
403
 
        master = BzrDirMetaFormat1().initialize('master')
404
 
        master.create_repository()
405
 
        master_branch = master.create_branch()
406
 
        master.create_workingtree()
407
 
        bound = master.sprout('bound')
408
 
        wt = bound.open_workingtree()
409
 
        wt.branch.set_bound_location(os.path.realpath('master'))
410
 
        master_branch.lock_write()
411
 
        try:
412
 
            self.assertRaises(LockContention, wt.commit, 'silly')
413
 
        finally:
414
 
            master_branch.unlock()
415
 
 
416
 
    def test_commit_bound_merge(self):
417
 
        # see bug #43959; commit of a merge in a bound branch fails to push
418
 
        # the new commit into the master
419
 
        master_branch = self.make_branch('master')
420
 
        bound_tree = self.make_branch_and_tree('bound')
421
 
        bound_tree.branch.bind(master_branch)
422
 
 
423
 
        self.build_tree_contents([('bound/content_file', 'initial contents\n')])
424
 
        bound_tree.add(['content_file'])
425
 
        bound_tree.commit(message='woo!')
426
 
 
427
 
        other_bzrdir = master_branch.bzrdir.sprout('other')
428
 
        other_tree = other_bzrdir.open_workingtree()
429
 
 
430
 
        # do a commit to the the other branch changing the content file so
431
 
        # that our commit after merging will have a merged revision in the
432
 
        # content file history.
433
 
        self.build_tree_contents([('other/content_file', 'change in other\n')])
434
 
        other_tree.commit('change in other')
435
 
 
436
 
        # do a merge into the bound branch from other, and then change the
437
 
        # content file locally to force a new revision (rather than using the
438
 
        # revision from other). This forces extra processing in commit.
439
 
        self.merge(other_tree.branch, bound_tree)
440
 
        self.build_tree_contents([('bound/content_file', 'change in bound\n')])
441
 
 
442
 
        # before #34959 was fixed, this failed with 'revision not present in
443
 
        # weave' when trying to implicitly push from the bound branch to the master
444
 
        bound_tree.commit(message='commit of merge in bound tree')
445
 
 
446
 
    def test_commit_reporting_after_merge(self):
447
 
        # when doing a commit of a merge, the reporter needs to still 
448
 
        # be called for each item that is added/removed/deleted.
449
 
        this_tree = self.make_branch_and_tree('this')
450
 
        # we need a bunch of files and dirs, to perform one action on each.
451
 
        self.build_tree([
452
 
            'this/dirtorename/',
453
 
            'this/dirtoreparent/',
454
 
            'this/dirtoleave/',
455
 
            'this/dirtoremove/',
456
 
            'this/filetoreparent',
457
 
            'this/filetorename',
458
 
            'this/filetomodify',
459
 
            'this/filetoremove',
460
 
            'this/filetoleave']
461
 
            )
462
 
        this_tree.add([
463
 
            'dirtorename',
464
 
            'dirtoreparent',
465
 
            'dirtoleave',
466
 
            'dirtoremove',
467
 
            'filetoreparent',
468
 
            'filetorename',
469
 
            'filetomodify',
470
 
            'filetoremove',
471
 
            'filetoleave']
472
 
            )
473
 
        this_tree.commit('create_files')
474
 
        other_dir = this_tree.bzrdir.sprout('other')
475
 
        other_tree = other_dir.open_workingtree()
476
 
        other_tree.lock_write()
477
 
        # perform the needed actions on the files and dirs.
478
 
        try:
479
 
            other_tree.rename_one('dirtorename', 'renameddir')
480
 
            other_tree.rename_one('dirtoreparent', 'renameddir/reparenteddir')
481
 
            other_tree.rename_one('filetorename', 'renamedfile')
482
 
            other_tree.rename_one('filetoreparent', 'renameddir/reparentedfile')
483
 
            other_tree.remove(['dirtoremove', 'filetoremove'])
484
 
            self.build_tree_contents([
485
 
                ('other/newdir/', ),
486
 
                ('other/filetomodify', 'new content'),
487
 
                ('other/newfile', 'new file content')])
488
 
            other_tree.add('newfile')
489
 
            other_tree.add('newdir/')
490
 
            other_tree.commit('modify all sample files and dirs.')
491
 
        finally:
492
 
            other_tree.unlock()
493
 
        self.merge(other_tree.branch, this_tree)
494
 
        reporter = CapturingReporter()
495
 
        this_tree.commit('do the commit', reporter=reporter)
496
 
        self.assertEqual([
497
 
            ('change', 'unchanged', ''),
498
 
            ('change', 'unchanged', 'dirtoleave'),
499
 
            ('change', 'unchanged', 'filetoleave'),
500
 
            ('change', 'modified', 'filetomodify'),
501
 
            ('change', 'added', 'newdir'),
502
 
            ('change', 'added', 'newfile'),
503
 
            ('renamed', 'renamed', 'dirtorename', 'renameddir'),
504
 
            ('renamed', 'renamed', 'dirtoreparent', 'renameddir/reparenteddir'),
505
 
            ('renamed', 'renamed', 'filetoreparent', 'renameddir/reparentedfile'),
506
 
            ('renamed', 'renamed', 'filetorename', 'renamedfile'),
507
 
            ('deleted', 'dirtoremove'),
508
 
            ('deleted', 'filetoremove'),
509
 
            ],
510
 
            reporter.calls)
511
 
 
512
 
    def test_commit_removals_respects_filespec(self):
513
 
        """Commit respects the specified_files for removals."""
514
 
        tree = self.make_branch_and_tree('.')
515
 
        self.build_tree(['a', 'b'])
516
 
        tree.add(['a', 'b'])
517
 
        tree.commit('added a, b')
518
 
        tree.remove(['a', 'b'])
519
 
        tree.commit('removed a', specific_files='a')
520
 
        basis = tree.basis_tree().inventory
521
 
        self.assertIs(None, basis.path2id('a'))
522
 
        self.assertFalse(basis.path2id('b') is None)
523
 
 
524
 
    def test_commit_saves_1ms_timestamp(self):
525
 
        """Passing in a timestamp is saved with 1ms resolution"""
526
 
        tree = self.make_branch_and_tree('.')
527
 
        self.build_tree(['a'])
528
 
        tree.add('a')
529
 
        tree.commit('added a', timestamp=1153248633.4186721, timezone=0,
530
 
                    rev_id='a1')
531
 
 
532
 
        rev = tree.branch.repository.get_revision('a1')
533
 
        self.assertEqual(1153248633.419, rev.timestamp)
534
 
 
535
 
    def test_commit_has_1ms_resolution(self):
536
 
        """Allowing commit to generate the timestamp also has 1ms resolution"""
537
 
        tree = self.make_branch_and_tree('.')
538
 
        self.build_tree(['a'])
539
 
        tree.add('a')
540
 
        tree.commit('added a', rev_id='a1')
541
 
 
542
 
        rev = tree.branch.repository.get_revision('a1')
543
 
        timestamp = rev.timestamp
544
 
        timestamp_1ms = round(timestamp, 3)
545
 
        self.assertEqual(timestamp_1ms, timestamp)