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
476
506
return delta.TreeDelta()
477
507
return delta._compare_trees(self.source, self.target, want_unchanged,
478
508
specific_file_ids, include_root)
510
def _iter_changes(self, from_tree, to_tree, include_unchanged,
511
specific_file_ids, pb):
512
"""Generate an iterator of changes between trees.
515
(file_id, path, changed_content, versioned, parent, name, kind,
518
Path is relative to the to_tree. changed_content is True if the file's
519
content has changed. This includes changes to its kind, and to
522
versioned, parent, name, kind, executable are tuples of (from, to).
523
If a file is missing in a tree, its kind is None.
525
Iteration is done in parent-to-child order, relative to the to_tree.
528
from_entries_by_dir = list(from_tree.inventory.iter_entries_by_dir(
529
specific_file_ids=specific_file_ids))
530
from_data = dict((e.file_id, (p, e)) for p, e in from_entries_by_dir)
531
to_entries_by_dir = list(to_tree.inventory.iter_entries_by_dir(
532
specific_file_ids=specific_file_ids))
533
num_entries = len(from_entries_by_dir) + len(to_entries_by_dir)
535
for to_path, to_entry in to_entries_by_dir:
536
file_id = to_entry.file_id
537
to_paths[file_id] = to_path
539
changed_content = False
540
from_path, from_entry = from_data.get(file_id, (None, None))
541
from_versioned = (from_entry is not None)
542
if from_entry is not None:
543
from_versioned = True
544
from_name = from_entry.name
545
from_parent = from_entry.parent_id
546
from_kind, from_executable, from_stat = \
547
from_tree._comparison_data(from_entry, from_path)
550
from_versioned = False
554
from_executable = None
555
versioned = (from_versioned, True)
556
to_kind, to_executable, to_stat = \
557
to_tree._comparison_data(to_entry, to_path)
558
kind = (from_kind, to_kind)
559
if kind[0] != kind[1]:
560
changed_content = True
561
elif from_kind == 'file':
562
from_size = from_tree._file_size(from_entry, from_stat)
563
to_size = to_tree._file_size(to_entry, to_stat)
564
if from_size != to_size:
565
changed_content = True
566
elif (from_tree.get_file_sha1(file_id, from_path, from_stat) !=
567
to_tree.get_file_sha1(file_id, to_path, to_stat)):
568
changed_content = True
569
elif from_kind == 'symlink':
570
if (from_tree.get_symlink_target(file_id) !=
571
to_tree.get_symlink_target(file_id)):
572
changed_content = True
573
parent = (from_parent, to_entry.parent_id)
574
name = (from_name, to_entry.name)
575
executable = (from_executable, to_executable)
577
pb.update('comparing files', entry_count, num_entries)
578
if (changed_content is not False or versioned[0] != versioned[1]
579
or parent[0] != parent[1] or name[0] != name[1] or
580
executable[0] != executable[1] or include_unchanged):
581
yield (file_id, to_path, changed_content, versioned, parent,
582
name, kind, executable)
584
def get_to_path(from_entry):
585
if from_entry.parent_id is None:
588
if from_entry.parent_id not in to_paths:
589
get_to_path(from_tree.inventory[from_entry.parent_id])
590
to_path = osutils.pathjoin(to_paths[from_entry.parent_id],
592
to_paths[from_entry.file_id] = to_path
595
for path, from_entry in from_entries_by_dir:
596
file_id = from_entry.file_id
597
if file_id in to_paths:
599
to_path = get_to_path(from_entry)
602
pb.update('comparing files', entry_count, num_entries)
603
versioned = (True, False)
604
parent = (from_entry.parent_id, None)
605
name = (from_entry.name, None)
606
from_kind, from_executable, stat_value = \
607
from_tree._comparison_data(from_entry, path)
608
kind = (from_kind, None)
609
executable = (from_executable, None)
610
changed_content = True
611
# the parent's path is necessarily known at this point.
612
yield(file_id, to_path, changed_content, versioned, parent,
613
name, kind, executable)
616
# This was deprecated before 0.12, but did not have an official warning
617
@symbol_versioning.deprecated_function(symbol_versioning.zero_twelve)
618
def RevisionTree(*args, **kwargs):
619
"""RevisionTree has moved to bzrlib.revisiontree.RevisionTree()
621
Accessing it as bzrlib.tree.RevisionTree has been deprecated as of
624
from bzrlib.revisiontree import RevisionTree as _RevisionTree
625
return _RevisionTree(*args, **kwargs)