15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
17
from bzrlib.inventory import InventoryEntry
18
from bzrlib.osutils import pathjoin
18
19
from bzrlib.trace import mutter
20
22
class TreeDelta(object):
21
23
"""Describes changes from one tree to another.
177
179
def _compare_trees(old_tree, new_tree, want_unchanged, specific_files):
179
from osutils import is_inside_any
181
from bzrlib.osutils import is_inside_any
181
183
old_inv = old_tree.inventory
182
184
new_inv = new_tree.inventory
188
190
# Perhaps should take a list of file-ids instead? Need to indicate any
189
191
# ids or names which were not found in the trees.
191
for file_id in old_tree:
192
if file_id in new_tree:
193
old_ie = old_inv[file_id]
194
new_ie = new_inv[file_id]
197
assert kind == new_ie.kind
193
# Map file_id to path and inventory entry
194
# We probably need to
195
new_id_to_path_map = {None:''}
197
def get_new_path(new_ie):
198
if new_ie.file_id in new_id_to_path_map:
199
return new_id_to_path_map[new_ie.file_id]
200
if new_ie.parent_id is None:
202
return pathjoin(get_new_path(new_inv[new_ie.parent_id]), new_ie.name)
204
for old_path, old_ie in old_inv.iter_entries():
205
if not old_tree.has_file_or_id(old_path, old_ie.file_id):
206
# In case old_tree is a WorkingTree, and the file
209
if new_inv.has_id(old_ie.file_id):
210
new_ie = new_inv[old_ie.file_id]
211
new_path = get_new_path(new_ie)
215
if new_path and new_tree.has_file_or_id(new_path, old_ie.file_id):
216
assert old_ie.kind == new_ie.kind
199
assert kind in InventoryEntry.known_kinds, \
200
'invalid file kind %r' % kind
218
assert old_ie.kind in InventoryEntry.known_kinds, \
219
'invalid file kind %r' % old_ie.kind
202
if kind == 'root_directory':
221
if old_ie.kind == 'root_directory':
205
224
if specific_files:
206
if (not is_inside_any(specific_files, old_inv.id2path(file_id))
207
and not is_inside_any(specific_files, new_inv.id2path(file_id))):
225
if (not is_inside_any(specific_files, old_path)
226
and not is_inside_any(specific_files, new_path)):
210
# temporary hack until all entries are populated before clients
212
old_path = old_inv.id2path(file_id)
213
new_path = new_inv.id2path(file_id)
214
229
old_ie._read_tree_state(old_path, old_tree)
215
230
new_ie._read_tree_state(new_path, new_tree)
216
231
text_modified, meta_modified = new_ie.detect_changes(old_ie)
224
239
or old_ie.parent_id != new_ie.parent_id):
225
240
delta.renamed.append((old_path,
242
old_ie.file_id, old_ie.kind,
228
243
text_modified, meta_modified))
229
244
elif text_modified or meta_modified:
230
delta.modified.append((new_path, file_id, kind,
245
delta.modified.append((new_path, old_ie.file_id, old_ie.kind,
231
246
text_modified, meta_modified))
232
247
elif want_unchanged:
233
delta.unchanged.append((new_path, file_id, kind))
248
delta.unchanged.append((new_path, old_ie.file_id, old_ie.kind))
235
kind = old_inv.get_file_kind(file_id)
236
if kind == 'root_directory':
250
if old_ie.kind == 'root_directory':
238
old_path = old_inv.id2path(file_id)
239
252
if specific_files:
240
253
if not is_inside_any(specific_files, old_path):
242
delta.removed.append((old_path, file_id, kind))
255
delta.removed.append((old_path, old_ie.file_id, old_ie.kind))
244
257
mutter('start looking for new files')
245
for file_id in new_inv:
246
if file_id in old_inv or file_id not in new_tree:
248
kind = new_inv.get_file_kind(file_id)
249
if kind == 'root_directory':
251
new_path = new_inv.id2path(file_id)
258
for new_path, new_ie in new_inv.iter_entries():
259
if (new_ie.file_id in old_inv
260
or not new_tree.has_file_or_id(new_path, new_ie.file_id)):
262
if new_ie.kind == 'root_directory':
252
264
if specific_files:
253
265
if not is_inside_any(specific_files, new_path):
255
delta.added.append((new_path, file_id, kind))
267
delta.added.append((new_path, new_ie.file_id, new_ie.kind))
257
269
delta.removed.sort()
258
270
delta.added.sort()