140
149
preceeded by the parent of a directory, and all the contents of a
141
150
directory are grouped together.
143
return self.inventory.iter_entries_by_dir()
152
return self.inventory.iter_entries_by_dir(
153
specific_file_ids=specific_file_ids)
145
155
def kind(self, file_id):
146
156
raise NotImplementedError("subclasses must implement kind")
158
def _comparison_data(self, entry, path):
159
"""Return a tuple of kind, executable, stat_value for a file.
161
entry may be None if there is no inventory entry for the file, but
162
path must always be supplied.
164
kind is None if there is no file present (even if an inventory id is
165
present). executable is False for non-file entries.
167
raise NotImplementedError(self._comparison_data)
169
def _file_size(entry, stat_value):
170
raise NotImplementedError(self._file_size)
148
172
def _get_inventory(self):
149
173
return self._inventory
443
473
return delta.TreeDelta()
444
474
return delta._compare_trees(self.source, self.target, want_unchanged,
445
475
specific_file_ids, include_root)
477
def _iter_changes(self, from_tree, to_tree, include_unchanged,
478
specific_file_ids, pb):
479
"""Generate an iterator of changes between trees.
482
(file_id, path, changed_content, versioned, parent, name, kind,
485
Path is relative to the to_tree. changed_content is True if the file's
486
content has changed. This includes changes to its kind, and to
489
versioned, parent, name, kind, executable are tuples of (from, to).
490
If a file is missing in a tree, its kind is None.
492
Iteration is done in parent-to-child order, relative to the to_tree.
495
from_entries_by_dir = list(from_tree.inventory.iter_entries_by_dir(
496
specific_file_ids=specific_file_ids))
497
from_data = dict((e.file_id, (p, e)) for p, e in from_entries_by_dir)
498
to_entries_by_dir = list(to_tree.inventory.iter_entries_by_dir(
499
specific_file_ids=specific_file_ids))
500
num_entries = len(from_entries_by_dir) + len(to_entries_by_dir)
502
for to_path, to_entry in to_entries_by_dir:
503
file_id = to_entry.file_id
504
to_paths[file_id] = to_path
506
changed_content = False
507
from_path, from_entry = from_data.get(file_id, (None, None))
508
from_versioned = (from_entry is not None)
509
if from_entry is not None:
510
from_versioned = True
511
from_name = from_entry.name
512
from_parent = from_entry.parent_id
513
from_kind, from_executable, from_stat = \
514
from_tree._comparison_data(from_entry, from_path)
517
from_versioned = False
521
from_executable = None
522
versioned = (from_versioned, True)
523
to_kind, to_executable, to_stat = \
524
to_tree._comparison_data(to_entry, to_path)
525
kind = (from_kind, to_kind)
526
if kind[0] != kind[1]:
527
changed_content = True
528
elif from_kind == 'file':
529
from_size = from_tree._file_size(from_entry, from_stat)
530
to_size = to_tree._file_size(to_entry, to_stat)
531
if from_size != to_size:
532
changed_content = True
533
elif (from_tree.get_file_sha1(file_id, from_path, from_stat) !=
534
to_tree.get_file_sha1(file_id, to_path, to_stat)):
535
changed_content = True
536
elif from_kind == 'symlink':
537
if (from_tree.get_symlink_target(file_id) !=
538
to_tree.get_symlink_target(file_id)):
539
changed_content = True
540
parent = (from_parent, to_entry.parent_id)
541
name = (from_name, to_entry.name)
542
executable = (from_executable, to_executable)
544
pb.update('comparing files', entry_count, num_entries)
545
if (changed_content is not False or versioned[0] != versioned[1]
546
or parent[0] != parent[1] or name[0] != name[1] or
547
executable[0] != executable[1] or include_unchanged):
548
yield (file_id, to_path, changed_content, versioned, parent,
549
name, kind, executable)
551
def get_to_path(from_entry):
552
if from_entry.parent_id is None:
555
if from_entry.parent_id not in to_paths:
556
get_to_path(from_tree.inventory[from_entry.parent_id])
557
to_path = osutils.pathjoin(to_paths[from_entry.parent_id],
559
to_paths[from_entry.file_id] = to_path
562
for path, from_entry in from_entries_by_dir:
563
file_id = from_entry.file_id
564
if file_id in to_paths:
566
to_path = get_to_path(from_entry)
569
pb.update('comparing files', entry_count, num_entries)
570
versioned = (True, False)
571
parent = (from_entry.parent_id, None)
572
name = (from_entry.name, None)
573
from_kind, from_executable, stat_value = \
574
from_tree._comparison_data(from_entry, path)
575
kind = (from_kind, None)
576
executable = (from_executable, None)
577
changed_content = True
578
# the parent's path is necessarily known at this point.
579
yield(file_id, to_path, changed_content, versioned, parent,
580
name, kind, executable)
583
# This was deprecated before 0.12, but did not have an official warning
584
@symbol_versioning.deprecated_function(symbol_versioning.zero_twelve)
585
def RevisionTree(*args, **kwargs):
586
"""RevisionTree has moved to bzrlib.revisiontree.RevisionTree()
588
Accessing it as bzrlib.tree.RevisionTree has been deprecated as of
591
from bzrlib.revisiontree import RevisionTree as _RevisionTree
592
return _RevisionTree(*args, **kwargs)