427
448
return delta._compare_trees(self.source, self.target, want_unchanged,
428
449
specific_file_ids, include_root)
451
def _iter_changes(self, from_tree, to_tree, include_unchanged,
452
specific_file_ids, pb):
453
"""Generate an iterator of changes between trees.
456
(file_id, path, changed_content, versioned, parent, name, kind,
459
Path is relative to the to_tree. changed_content is True if the file's
460
content has changed. This includes changes to its kind, and to
463
versioned, parent, name, kind, executable are tuples of (from, to).
464
If a file is missing in a tree, its kind is None.
466
Iteration is done in parent-to-child order, relative to the to_tree.
469
from_entries_by_dir = list(from_tree.inventory.iter_entries_by_dir())
470
from_data = dict((e.file_id, (p, e)) for p, e in from_entries_by_dir)
471
to_entries_by_dir = list(to_tree.inventory.iter_entries_by_dir())
472
if specific_file_ids is not None:
473
specific_file_ids = set(specific_file_ids)
474
num_entries = len(specific_file_ids)
476
num_entries = len(from_entries_by_dir) + len(to_entries_by_dir)
478
for to_path, to_entry in to_entries_by_dir:
479
file_id = to_entry.file_id
480
to_paths[file_id] = to_path
481
if (specific_file_ids is not None and
482
file_id not in specific_file_ids):
485
changed_content = False
486
from_path, from_entry = from_data.get(file_id, (None, None))
487
from_versioned = (from_entry is not None)
488
if from_entry is not None:
489
from_versioned = True
490
from_name = from_entry.name
491
from_parent = from_entry.parent_id
492
from_kind, from_executable, from_stat = \
493
from_tree._comparison_data(from_entry, from_path)
494
if specific_file_ids is None:
497
from_versioned = False
501
from_executable = None
502
versioned = (from_versioned, True)
503
to_kind, to_executable, to_stat = \
504
to_tree._comparison_data(to_entry, to_path)
505
kind = (from_kind, to_kind)
506
if kind[0] != kind[1]:
507
changed_content = True
508
elif from_kind == 'file':
509
from_size = from_tree._file_size(from_entry, from_stat)
510
to_size = to_tree._file_size(to_entry, to_stat)
511
if from_size != to_size:
512
changed_content = True
513
elif (from_tree.get_file_sha1(file_id, from_path, from_stat) !=
514
to_tree.get_file_sha1(file_id, to_path, to_stat)):
515
changed_content = True
516
elif from_kind == 'symlink':
517
if (from_tree.get_symlink_target(file_id) !=
518
to_tree.get_symlink_target(file_id)):
519
changed_content = True
520
parent = (from_parent, to_entry.parent_id)
521
name = (from_name, to_entry.name)
522
executable = (from_executable, to_executable)
524
pb.update('comparing files', entry_count, num_entries)
525
if (changed_content is not False or versioned[0] != versioned[1]
526
or parent[0] != parent[1] or name[0] != name[1] or
527
executable[0] != executable[1] or include_unchanged):
528
yield (file_id, to_path, changed_content, versioned, parent,
529
name, kind, executable)
531
for path, from_entry in from_entries_by_dir:
532
file_id = from_entry.file_id
533
if file_id in to_paths:
535
if from_entry.parent_id is None:
538
to_path = osutils.pathjoin(to_paths[from_entry.parent_id],
540
to_paths[file_id] = to_path
541
if (specific_file_ids is not None and
542
file_id not in specific_file_ids):
546
pb.update('comparing files', entry_count, num_entries)
547
versioned = (True, False)
548
parent = (from_entry.parent_id, None)
549
name = (from_entry.name, None)
550
from_kind, from_executable, stat_value = \
551
from_tree._comparison_data(from_entry, path)
552
kind = (from_kind, None)
553
executable = (from_executable, None)
554
changed_content = True
555
# the parent's path is necessarily known at this point.
556
yield(file_id, to_path, changed_content, versioned, parent,
557
name, kind, executable)
431
560
# This was deprecated before 0.12, but did not have an official warning
432
561
@symbol_versioning.deprecated_function(symbol_versioning.zero_twelve)