161
160
if sub_tree_id == self.get_root_id():
162
161
raise errors.BadReferenceTarget(self, sub_tree,
163
162
'Trees have the same root id.')
164
if sub_tree_id in self.inventory:
163
if sub_tree_id in self:
165
164
raise errors.BadReferenceTarget(self, sub_tree,
166
165
'Root id already present in tree')
167
166
self._add([sub_tree_path], [sub_tree_id], ['tree-reference'])
382
371
raise NotImplementedError(self.set_parent_trees)
373
def smart_add(self, file_list, recurse=True, action=None, save=True):
374
"""Version file_list, optionally recursing into directories.
376
This is designed more towards DWIM for humans than API clarity.
377
For the specific behaviour see the help for cmd_add().
379
:param file_list: List of zero or more paths. *NB: these are
380
interpreted relative to the process cwd, not relative to the
381
tree.* (Add and most other tree methods use tree-relative
383
:param action: A reporter to be called with the inventory, parent_ie,
384
path and kind of the path being added. It may return a file_id if
385
a specific one should be used.
386
:param save: Save the inventory after completing the adds. If False
387
this provides dry-run functionality by doing the add and not saving
389
:return: A tuple - files_added, ignored_files. files_added is the count
390
of added files, and ignored_files is a dict mapping files that were
391
ignored to the rule that caused them to be ignored.
393
raise NotImplementedError(self.smart_add)
395
def update_basis_by_delta(self, new_revid, delta):
396
"""Update the parents of this tree after a commit.
398
This gives the tree one parent, with revision id new_revid. The
399
inventory delta is applied to the current basis tree to generate the
400
inventory for the parent new_revid, and all other parent trees are
403
All the changes in the delta should be changes synchronising the basis
404
tree with some or all of the working tree, with a change to a directory
405
requiring that its contents have been recursively included. That is,
406
this is not a general purpose tree modification routine, but a helper
407
for commit which is not required to handle situations that do not arise
410
See the inventory developers documentation for the theory behind
413
:param new_revid: The new revision id for the trees parent.
414
:param delta: An inventory delta (see apply_inventory_delta) describing
415
the changes from the current left most parent revision to new_revid.
417
raise NotImplementedError(self.update_basis_by_delta)
420
class MutableInventoryTree(MutableTree,tree.InventoryTree):
422
@needs_tree_write_lock
423
def apply_inventory_delta(self, changes):
424
"""Apply changes to the inventory as an atomic operation.
426
:param changes: An inventory delta to apply to the working tree's
429
:seealso Inventory.apply_delta: For details on the changes parameter.
433
inv.apply_delta(changes)
434
self._write_inventory(inv)
436
def _fix_case_of_inventory_path(self, path):
437
"""If our tree isn't case sensitive, return the canonical path"""
438
if not self.case_sensitive:
439
path = self.get_canonical_inventory_path(path)
384
442
@needs_tree_write_lock
385
443
def smart_add(self, file_list, recurse=True, action=None, save=True):
386
444
"""Version file_list, optionally recursing into directories.
562
620
# Same as in _add_one below, if the inventory doesn't
563
621
# think this is a directory, update the inventory
564
622
if this_ie.kind != 'directory':
565
this_ie = inventory.make_entry('directory',
623
this_ie = _mod_inventory.make_entry('directory',
566
624
this_ie.name, this_ie.parent_id, this_id)
635
693
# TODO: Consider re-evaluating the need for this with CHKInventory
636
694
# we don't strictly need to mutate an inventory for this
637
695
# it only makes sense when apply_delta is cheaper than get_inventory()
638
inventory = basis.inventory._get_mutable_inventory()
696
inventory = _mod_inventory.mutable_inventory_from_tree(basis)
640
698
inventory.apply_delta(delta)
641
rev_tree = revisiontree.RevisionTree(self.branch.repository,
699
rev_tree = revisiontree.InventoryRevisionTree(self.branch.repository,
642
700
inventory, new_revid)
643
701
self.set_parent_trees([(new_revid, rev_tree)])
652
710
"""Create the default hooks.
655
hooks.Hooks.__init__(self)
656
self.create_hook(hooks.HookPoint('start_commit',
713
hooks.Hooks.__init__(self, "bzrlib.mutabletree", "MutableTree.hooks")
714
self.add_hook('start_commit',
657
715
"Called before a commit is performed on a tree. The start commit "
658
716
"hook is able to change the tree before the commit takes place. "
659
717
"start_commit is called with the bzrlib.mutabletree.MutableTree "
660
"that the commit is being performed on.", (1, 4), None))
661
self.create_hook(hooks.HookPoint('post_commit',
718
"that the commit is being performed on.", (1, 4))
719
self.add_hook('post_commit',
662
720
"Called after a commit is performed on a tree. The hook is "
663
721
"called with a bzrlib.mutabletree.PostCommitHookParams object. "
664
722
"The mutable tree the commit was performed on is available via "
665
"the mutable_tree attribute of that object.", (2, 0), None))
723
"the mutable_tree attribute of that object.", (2, 0))
668
726
# install the default hooks into the MutableTree class.
751
809
if parent_ie.kind != 'directory':
752
810
# nb: this relies on someone else checking that the path we're using
753
811
# doesn't contain symlinks.
754
new_parent_ie = inventory.make_entry('directory', parent_ie.name,
812
new_parent_ie = _mod_inventory.make_entry('directory', parent_ie.name,
755
813
parent_ie.parent_id, parent_ie.file_id)
756
814
del inv[parent_ie.file_id]
757
815
inv.add(new_parent_ie)