100
107
if self.is_control_filename(f):
101
108
raise errors.ForbiddenControlFileError(filename=f)
102
109
fp = splitpath(f)
104
raise BzrError("cannot add top-level %r" % f)
105
110
# fill out file kinds for all files [not needed when we stop
106
111
# caring about the instantaneous file kind within a uncommmitted tree
108
113
self._gather_kinds(files, kinds)
109
114
self._add(files, ids, kinds)
116
def add_reference(self, sub_tree):
117
"""Add a TreeReference to the tree, pointing at sub_tree"""
118
raise errors.UnsupportedOperation(self.add_reference, self)
120
def _add_reference(self, sub_tree):
121
"""Standard add_reference implementation, for use by subclasses"""
123
sub_tree_path = self.relpath(sub_tree.basedir)
124
except errors.PathNotChild:
125
raise errors.BadReferenceTarget(self, sub_tree,
126
'Target not inside tree.')
127
sub_tree_id = sub_tree.get_root_id()
128
if sub_tree_id == self.get_root_id():
129
raise errors.BadReferenceTarget(self, sub_tree,
130
'Trees have the same root id.')
131
if sub_tree_id in self.inventory:
132
raise errors.BadReferenceTarget(self, sub_tree,
133
'Root id already present in tree')
134
self._add([sub_tree_path], [sub_tree_id], ['tree-reference'])
111
136
def _add(self, files, ids, kinds):
112
"""Helper function for add - updates the inventory."""
137
"""Helper function for add - updates the inventory.
139
:param files: sequence of pathnames, relative to the tree root
140
:param ids: sequence of suggested ids for the files (may be None)
141
:param kinds: sequence of inventory kinds of the files (i.e. may
142
contain "tree-reference")
113
144
raise NotImplementedError(self._add)
146
@needs_tree_write_lock
147
def apply_inventory_delta(self, changes):
148
"""Apply changes to the inventory as an atomic operation.
150
The argument is a set of changes to apply. It must describe a
151
valid result, but the order is not important. Specifically,
152
intermediate stages *may* be invalid, such as when two files
155
The changes should be structured as a list of tuples, of the form
156
(old_path, new_path, file_id, new_entry). For creation, old_path
157
must be None. For deletion, new_path and new_entry must be None.
158
file_id is always non-None. For renames and other mutations, all
159
values must be non-None.
161
If the new_entry is a directory, its children should be an empty
162
dict. Children are handled by apply_inventory_delta itself.
164
:param changes: A list of tuples for the change to apply:
165
[(old_path, new_path, file_id, new_inventory_entry), ...]
170
for old_path, file_id in sorted(((op, f) for op, np, f, e in changes
171
if op is not None), reverse=True):
172
if file_id not in inv:
174
children[file_id] = getattr(inv[file_id], 'children', {})
175
inv.remove_recursive_id(file_id)
176
for new_path, new_entry in sorted((np, e) for op, np, f, e in
177
changes if np is not None):
178
if getattr(new_entry, 'children', None) is not None:
179
new_entry.children = children.get(new_entry.file_id, {})
181
self._write_inventory(inv)
115
183
@needs_write_lock
116
def commit(self, message=None, revprops=None, *args, **kwargs):
184
def commit(self, message=None, revprops=None, *args,
117
186
# avoid circular imports
118
187
from bzrlib import commit
119
188
if revprops is None: