/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

Merge bzr.dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
61
61
 
62
62
# TODO: If commit fails, leave the message in a file somewhere.
63
63
 
 
64
# TODO: Change the parameter 'rev_id' to 'revision_id' to be consistent with
 
65
# the rest of the code; add a deprecation of the old name.
64
66
 
65
67
import os
66
68
import re
69
71
 
70
72
from cStringIO import StringIO
71
73
 
 
74
from bzrlib import (
 
75
    errors,
 
76
    tree,
 
77
    )
72
78
import bzrlib.config
73
 
import bzrlib.errors as errors
74
79
from bzrlib.errors import (BzrError, PointlessCommit,
75
80
                           ConflictsInTree,
76
81
                           StrictCommitFailed
245
250
            self._check_bound_branch()
246
251
 
247
252
            # check for out of date working trees
248
 
            # if we are bound, then self.branch is the master branch and this
249
 
            # test is thus all we need.
 
253
            try:
 
254
                first_tree_parent = self.work_tree.get_parent_ids()[0]
 
255
            except IndexError:
 
256
                # if there are no parents, treat our parent as 'None'
 
257
                # this is so that we still consier the master branch
 
258
                # - in a checkout scenario the tree may have no
 
259
                # parents but the branch may do.
 
260
                first_tree_parent = None
250
261
            master_last = self.master_branch.last_revision()
251
 
            if (master_last is not None and 
252
 
                master_last != self.work_tree.last_revision()):
 
262
            if (master_last is not None and
 
263
                master_last != first_tree_parent):
253
264
                raise errors.OutOfDateTree(self.work_tree)
254
265
    
255
266
            if strict:
269
280
            self.work_inv = self.work_tree.inventory
270
281
            self.basis_tree = self.work_tree.basis_tree()
271
282
            self.basis_inv = self.basis_tree.inventory
 
283
            if specific_files is not None:
 
284
                # Ensure specified files are versioned
 
285
                # (We don't actually need the ids here)
 
286
                tree.find_ids_across_trees(specific_files, 
 
287
                                           [self.basis_tree, self.work_tree])
272
288
            # one to finish, one for rev and inventory, and one for each
273
289
            # inventory entry, and the same for the new inventory.
274
290
            # note that this estimate is too long when we do a partial tree
289
305
            self._populate_new_inv()
290
306
            self._report_deletes()
291
307
 
292
 
            if not (self.allow_pointless
293
 
                    or len(self.parents) > 1
294
 
                    or self.builder.new_inventory != self.basis_inv):
295
 
                raise PointlessCommit()
 
308
            self._check_pointless()
296
309
 
297
310
            self._emit_progress_update()
298
311
            # TODO: Now the new inventory is known, check for conflicts and
319
332
            # and now do the commit locally.
320
333
            self.branch.append_revision(self.rev_id)
321
334
 
322
 
            # if the builder gave us the revisiontree it created back, we
323
 
            # could use it straight away here.
324
 
            # TODO: implement this.
325
 
            self.work_tree.set_parent_trees([(self.rev_id,
326
 
                self.branch.repository.revision_tree(self.rev_id))])
 
335
            rev_tree = self.builder.revision_tree()
 
336
            self.work_tree.set_parent_trees([(self.rev_id, rev_tree)])
327
337
            # now the work tree is up to date with the branch
328
338
            
329
339
            self.reporter.completed(self.branch.revno(), self.rev_id)
340
350
            self._cleanup()
341
351
        return self.rev_id
342
352
 
 
353
    def _any_real_changes(self):
 
354
        """Are there real changes between new_inventory and basis?
 
355
 
 
356
        For trees without rich roots, inv.root.revision changes every commit.
 
357
        But if that is the only change, we want to treat it as though there
 
358
        are *no* changes.
 
359
        """
 
360
        new_entries = self.builder.new_inventory.iter_entries()
 
361
        basis_entries = self.basis_inv.iter_entries()
 
362
        new_path, new_root_ie = new_entries.next()
 
363
        basis_path, basis_root_ie = basis_entries.next()
 
364
 
 
365
        # This is a copy of InventoryEntry.__eq__ only leaving out .revision
 
366
        def ie_equal_no_revision(this, other):
 
367
            return ((this.file_id == other.file_id)
 
368
                    and (this.name == other.name)
 
369
                    and (this.symlink_target == other.symlink_target)
 
370
                    and (this.text_sha1 == other.text_sha1)
 
371
                    and (this.text_size == other.text_size)
 
372
                    and (this.text_id == other.text_id)
 
373
                    and (this.parent_id == other.parent_id)
 
374
                    and (this.kind == other.kind)
 
375
                    and (this.executable == other.executable)
 
376
                    )
 
377
        if not ie_equal_no_revision(new_root_ie, basis_root_ie):
 
378
            return True
 
379
 
 
380
        for new_ie, basis_ie in zip(new_entries, basis_entries):
 
381
            if new_ie != basis_ie:
 
382
                return True
 
383
 
 
384
        # No actual changes present
 
385
        return False
 
386
 
 
387
    def _check_pointless(self):
 
388
        if self.allow_pointless:
 
389
            return
 
390
        # A merge with no effect on files
 
391
        if len(self.parents) > 1:
 
392
            return
 
393
        # Shortcut, if the number of entries changes, then we obviously have
 
394
        # a change
 
395
        if len(self.builder.new_inventory) != len(self.basis_inv):
 
396
            return
 
397
        # If length == 1, then we only have the root entry. Which means
 
398
        # that there is no real difference (only the root could be different)
 
399
        if (len(self.builder.new_inventory) != 1 and self._any_real_changes()):
 
400
            return
 
401
        raise PointlessCommit()
 
402
 
343
403
    def _check_bound_branch(self):
344
404
        """Check to see if the local branch is bound.
345
405
 
462
522
        """
463
523
        specific = self.specific_files
464
524
        deleted_ids = []
 
525
        deleted_paths = set()
465
526
        for path, ie in self.work_inv.iter_entries():
 
527
            if is_inside_any(deleted_paths, path):
 
528
                # The tree will delete the required ids recursively.
 
529
                continue
466
530
            if specific and not is_inside_any(specific, path):
467
531
                continue
468
532
            if not self.work_tree.has_filename(path):
 
533
                deleted_paths.add(path)
469
534
                self.reporter.missing(path)
470
 
                deleted_ids.append((path, ie.file_id))
471
 
        if deleted_ids:
472
 
            deleted_ids.sort(reverse=True)
473
 
            for path, file_id in deleted_ids:
474
 
                del self.work_inv[file_id]
475
 
            self.work_tree._write_inventory(self.work_inv)
 
535
                deleted_ids.append(ie.file_id)
 
536
        self.work_tree.unversion(deleted_ids)
476
537
 
477
538
    def _populate_new_inv(self):
478
539
        """Build revision inventory.