/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/commit.py

  • Committer: Robert Collins
  • Date: 2006-03-03 02:09:49 UTC
  • mto: (1594.2.4 integration)
  • mto: This revision was merged to the branch mainline in revision 1596.
  • Revision ID: robertc@robertcollins.net-20060303020949-0ddc6f33d0a43943
Smoke test for RevisionStore factories creating revision stores.

Show diffs side-by-side

added added

removed removed

Lines of Context:
76
76
from bzrlib.osutils import (local_time_offset,
77
77
                            rand_bytes, compact_date,
78
78
                            kind_marker, is_inside_any, quotefn,
79
 
                            sha_file, isdir, isfile,
 
79
                            sha_string, sha_strings, sha_file, isdir, isfile,
80
80
                            split_lines)
81
81
import bzrlib.config
82
82
import bzrlib.errors as errors
85
85
                           ConflictsInTree,
86
86
                           StrictCommitFailed
87
87
                           )
 
88
import bzrlib.gpg as gpg
88
89
from bzrlib.revision import Revision
89
90
from bzrlib.testament import Testament
90
91
from bzrlib.trace import mutter, note, warning
128
129
class ReportCommitToLog(NullCommitReporter):
129
130
 
130
131
    def snapshot_change(self, change, path):
131
 
        if change == 'unchanged':
132
 
            return
133
132
        note("%s %s", change, path)
134
133
 
135
134
    def completed(self, revno, rev_id):
136
 
        note('Committed revision %d.', revno)
 
135
        note('committed r%d {%s}', revno, rev_id)
137
136
    
138
137
    def deleted(self, file_id):
139
138
        note('deleted %s', file_id)
180
179
               strict=False,
181
180
               verbose=False,
182
181
               revprops=None,
183
 
               working_tree=None,
184
 
               local=False,
185
 
               reporter=None,
186
 
               config=None):
 
182
               working_tree=None):
187
183
        """Commit working copy as a new revision.
188
184
 
189
185
        branch -- the deprecated branch to commit to. New callers should pass in 
209
205
            contains unknown files.
210
206
 
211
207
        revprops -- Properties for new revision
212
 
        :param local: Perform a local only commit.
213
208
        """
214
209
        mutter('preparing to commit')
215
210
 
228
223
            raise BzrError("The message keyword parameter is required for commit().")
229
224
 
230
225
        self.weave_store = self.branch.repository.weave_store
231
 
        self.bound_branch = None
232
 
        self.local = local
233
 
        self.master_branch = None
234
 
        self.master_locked = False
235
226
        self.rev_id = rev_id
236
227
        self.specific_files = specific_files
237
228
        self.allow_pointless = allow_pointless
238
 
        self.revprops = {}
239
 
        if revprops is not None:
 
229
        self.revprops = {'branch-nick': self.branch.nick}
 
230
        if revprops:
240
231
            self.revprops.update(revprops)
241
232
 
242
 
        if reporter is None and self.reporter is None:
243
 
            self.reporter = NullCommitReporter()
244
 
        elif reporter is not None:
245
 
            self.reporter = reporter
246
 
 
247
 
        self.work_tree.lock_write()
 
233
        # check for out of date working trees
 
234
        if self.work_tree.last_revision() != self.branch.last_revision():
 
235
            raise errors.OutOfDateTree(self.work_tree)
 
236
 
 
237
        if strict:
 
238
            # raise an exception as soon as we find a single unknown.
 
239
            for unknown in self.work_tree.unknowns():
 
240
                raise StrictCommitFailed()
 
241
 
 
242
        if timestamp is None:
 
243
            self.timestamp = time.time()
 
244
        else:
 
245
            self.timestamp = long(timestamp)
 
246
            
 
247
        if self.config is None:
 
248
            self.config = bzrlib.config.BranchConfig(self.branch)
 
249
 
 
250
        if rev_id is None:
 
251
            self.rev_id = _gen_revision_id(self.config, self.timestamp)
 
252
        else:
 
253
            self.rev_id = rev_id
 
254
 
 
255
        if committer is None:
 
256
            self.committer = self.config.username()
 
257
        else:
 
258
            assert isinstance(committer, basestring), type(committer)
 
259
            self.committer = committer
 
260
 
 
261
        if timezone is None:
 
262
            self.timezone = local_time_offset()
 
263
        else:
 
264
            self.timezone = int(timezone)
 
265
 
 
266
        if isinstance(message, str):
 
267
            message = message.decode(bzrlib.user_encoding)
 
268
        assert isinstance(message, unicode), type(message)
 
269
        self.message = message
 
270
        self._escape_commit_message()
 
271
 
 
272
        self.branch.lock_write()
248
273
        try:
249
 
            # setup the bound branch variables as needed.
250
 
            self._check_bound_branch()
251
 
 
252
 
            # check for out of date working trees
253
 
            # if we are bound, then self.branch is the master branch and this
254
 
            # test is thus all we need.
255
 
            if self.work_tree.last_revision() != self.master_branch.last_revision():
256
 
                raise errors.OutOfDateTree(self.work_tree)
257
 
    
258
 
            if strict:
259
 
                # raise an exception as soon as we find a single unknown.
260
 
                for unknown in self.work_tree.unknowns():
261
 
                    raise StrictCommitFailed()
262
 
    
263
 
            if timestamp is None:
264
 
                self.timestamp = time.time()
265
 
            else:
266
 
                self.timestamp = long(timestamp)
267
 
                
268
 
            if self.config is None:
269
 
                self.config = bzrlib.config.BranchConfig(self.branch)
270
 
    
271
 
            if rev_id is None:
272
 
                self.rev_id = _gen_revision_id(self.config, self.timestamp)
273
 
            else:
274
 
                self.rev_id = rev_id
275
 
    
276
 
            if committer is None:
277
 
                self.committer = self.config.username()
278
 
            else:
279
 
                assert isinstance(committer, basestring), type(committer)
280
 
                self.committer = committer
281
 
    
282
 
            if timezone is None:
283
 
                self.timezone = local_time_offset()
284
 
            else:
285
 
                self.timezone = int(timezone)
286
 
    
287
 
            if isinstance(message, str):
288
 
                message = message.decode(bzrlib.user_encoding)
289
 
            assert isinstance(message, unicode), type(message)
290
 
            self.message = message
291
 
            self._escape_commit_message()
292
 
 
293
274
            self.work_inv = self.work_tree.inventory
294
275
            self.basis_tree = self.work_tree.basis_tree()
295
276
            self.basis_inv = self.basis_tree.inventory
309
290
                    or self.new_inv != self.basis_inv):
310
291
                raise PointlessCommit()
311
292
 
312
 
            if len(self.work_tree.conflicts())>0:
 
293
            if len(list(self.work_tree.iter_conflicts()))>0:
313
294
                raise ConflictsInTree
314
295
 
315
 
            self.inv_sha1 = self.branch.repository.add_inventory(
316
 
                self.rev_id,
317
 
                self.new_inv,
318
 
                self.present_parents
319
 
                )
 
296
            self._record_inventory()
320
297
            self._make_revision()
321
 
            # revision data is in the local branch now.
322
 
            
323
 
            # upload revision data to the master.
324
 
            # this will propogate merged revisions too if needed.
325
 
            if self.bound_branch:
326
 
                self.master_branch.repository.fetch(self.branch.repository,
327
 
                                                    revision_id=self.rev_id)
328
 
                # now the master has the revision data
329
 
                # 'commit' to the master first so a timeout here causes the local
330
 
                # branch to be out of date
331
 
                self.master_branch.append_revision(self.rev_id)
332
 
 
333
 
            # and now do the commit locally.
 
298
            self.work_tree.set_pending_merges([])
334
299
            self.branch.append_revision(self.rev_id)
335
 
 
336
 
            self.work_tree.set_pending_merges([])
337
 
            self.work_tree.set_last_revision(self.rev_id)
338
 
            # now the work tree is up to date with the branch
339
 
            
340
 
            self.reporter.completed(self.branch.revno(), self.rev_id)
 
300
            if len(self.parents):
 
301
                precursor = self.parents[0]
 
302
            else:
 
303
                precursor = None
 
304
            self.work_tree.set_last_revision(self.rev_id, precursor)
 
305
            self.reporter.completed(self.branch.revno()+1, self.rev_id)
341
306
            if self.config.post_commit() is not None:
342
307
                hooks = self.config.post_commit().split(' ')
343
308
                # this would be nicer with twisted.python.reflect.namedAny
347
312
                                   'bzrlib':bzrlib,
348
313
                                   'rev_id':self.rev_id})
349
314
        finally:
350
 
            self._cleanup_bound_branch()
351
 
            self.work_tree.unlock()
352
 
 
353
 
    def _check_bound_branch(self):
354
 
        """Check to see if the local branch is bound.
355
 
 
356
 
        If it is bound, then most of the commit will actually be
357
 
        done using the remote branch as the target branch.
358
 
        Only at the end will the local branch be updated.
359
 
        """
360
 
        if self.local and not self.branch.get_bound_location():
361
 
            raise errors.LocalRequiresBoundBranch()
362
 
 
363
 
        if not self.local:
364
 
            self.master_branch = self.branch.get_master_branch()
365
 
 
366
 
        if not self.master_branch:
367
 
            # make this branch the reference branch for out of date checks.
368
 
            self.master_branch = self.branch
369
 
            return
370
 
 
371
 
        # If the master branch is bound, we must fail
372
 
        master_bound_location = self.master_branch.get_bound_location()
373
 
        if master_bound_location:
374
 
            raise errors.CommitToDoubleBoundBranch(self.branch,
375
 
                    self.master_branch, master_bound_location)
376
 
 
377
 
        # TODO: jam 20051230 We could automatically push local
378
 
        #       commits to the remote branch if they would fit.
379
 
        #       But for now, just require remote to be identical
380
 
        #       to local.
381
 
        
382
 
        # Make sure the local branch is identical to the master
383
 
        master_rh = self.master_branch.revision_history()
384
 
        local_rh = self.branch.revision_history()
385
 
        if local_rh != master_rh:
386
 
            raise errors.BoundBranchOutOfDate(self.branch,
387
 
                    self.master_branch)
388
 
 
389
 
        # Now things are ready to change the master branch
390
 
        # so grab the lock
391
 
        self.bound_branch = self.branch
392
 
        self.master_branch.lock_write()
393
 
        self.master_locked = True
394
 
####        
395
 
####        # Check to see if we have any pending merges. If we do
396
 
####        # those need to be pushed into the master branch
397
 
####        pending_merges = self.work_tree.pending_merges()
398
 
####        if pending_merges:
399
 
####            for revision_id in pending_merges:
400
 
####                self.master_branch.repository.fetch(self.bound_branch.repository,
401
 
####                                                    revision_id=revision_id)
402
 
 
403
 
    def _cleanup_bound_branch(self):
404
 
        """Executed at the end of a try/finally to cleanup a bound branch.
405
 
 
406
 
        If the branch wasn't bound, this is a no-op.
407
 
        If it was, it resents self.branch to the local branch, instead
408
 
        of being the master.
409
 
        """
410
 
        if not self.bound_branch:
411
 
            return
412
 
        if self.master_locked:
413
 
            self.master_branch.unlock()
 
315
            self.branch.unlock()
 
316
 
 
317
    def _record_inventory(self):
 
318
        """Store the inventory for the new revision."""
 
319
        inv_text = serializer_v5.write_inventory_to_string(self.new_inv)
 
320
        self.inv_sha1 = sha_string(inv_text)
 
321
        s = self.branch.repository.control_weaves
 
322
        inv_versioned_file = s.get_weave('inventory',
 
323
                                         self.branch.repository.get_transaction())
 
324
        inv_versioned_file.add_lines(self.rev_id,
 
325
                                     self.present_parents,
 
326
                                     split_lines(inv_text))
414
327
 
415
328
    def _escape_commit_message(self):
416
329
        """Replace xml-incompatible control characters."""
453
366
            
454
367
    def _make_revision(self):
455
368
        """Record a new revision object for this commit."""
456
 
        rev = Revision(timestamp=self.timestamp,
457
 
                       timezone=self.timezone,
458
 
                       committer=self.committer,
459
 
                       message=self.message,
460
 
                       inventory_sha1=self.inv_sha1,
461
 
                       revision_id=self.rev_id,
462
 
                       properties=self.revprops)
463
 
        rev.parent_ids = self.parents
464
 
        self.branch.repository.add_revision(self.rev_id, rev, self.new_inv, self.config)
 
369
        self.rev = Revision(timestamp=self.timestamp,
 
370
                            timezone=self.timezone,
 
371
                            committer=self.committer,
 
372
                            message=self.message,
 
373
                            inventory_sha1=self.inv_sha1,
 
374
                            revision_id=self.rev_id,
 
375
                            properties=self.revprops)
 
376
        self.rev.parent_ids = self.parents
 
377
        rev_tmp = StringIO()
 
378
        serializer_v5.write_revision(self.rev, rev_tmp)
 
379
        rev_tmp.seek(0)
 
380
        if self.config.signature_needed():
 
381
            plaintext = Testament(self.rev, self.new_inv).as_short_text()
 
382
            self.branch.repository.store_revision_signature(
 
383
                gpg.GPGStrategy(self.config), plaintext, self.rev_id)
 
384
        self.branch.repository.revision_store.add(rev_tmp, self.rev_id)
 
385
        mutter('new revision_id is {%s}', self.rev_id)
465
386
 
466
387
    def _remove_deleted(self):
467
388
        """Remove deleted files from the working inventories.
500
421
        # mark-merge.  
501
422
        for path, ie in self.new_inv.iter_entries():
502
423
            previous_entries = ie.find_previous_heads(
503
 
                self.parent_invs,
504
 
                self.weave_store,
505
 
                self.branch.repository.get_transaction())
 
424
                self.parent_invs, 
 
425
                self.weave_store.get_weave_or_empty(ie.file_id,
 
426
                    self.branch.get_transaction()))
506
427
            if ie.revision is None:
507
428
                change = ie.snapshot(self.rev_id, path, previous_entries,
508
429
                                     self.work_tree, self.weave_store,
522
443
        revision set to their prior value.
523
444
        """
524
445
        mutter("Selecting files for commit with filter %s", self.specific_files)
525
 
        self.new_inv = Inventory(revision_id=self.rev_id)
 
446
        self.new_inv = Inventory()
526
447
        for path, new_ie in self.work_inv.iter_entries():
527
448
            file_id = new_ie.file_id
528
449
            mutter('check %s {%s}', path, new_ie.file_id)