142
143
return False, False
145
def diff(self, text_diff, from_label, tree, to_label, to_entry, to_tree,
146
output_to, reverse=False):
147
"""Perform a diff from this to to_entry.
149
text_diff will be used for textual difference calculation.
150
This is a template method, override _diff in child classes.
152
self._read_tree_state(tree.id2path(self.file_id), tree)
154
# cannot diff from one kind to another - you must do a removal
155
# and an addif they do not match.
156
assert self.kind == to_entry.kind
157
to_entry._read_tree_state(to_tree.id2path(to_entry.file_id),
159
self._diff(text_diff, from_label, tree, to_label, to_entry, to_tree,
144
162
def _diff(self, text_diff, from_label, tree, to_label, to_entry, to_tree,
145
163
output_to, reverse=False):
146
164
"""Perform a diff between two entries of the same kind."""
171
190
ie.executable = False
172
191
except AttributeError:
193
# must now be the same.
194
assert candidates[ie.revision] == ie
175
196
# add this revision as a candidate.
176
197
candidates[ie.revision] = ie
177
198
return candidates
200
@deprecated_method(zero_ninetyone)
201
def find_previous_heads(self, previous_inventories,
202
versioned_file_store,
205
"""Return the revisions and entries that directly precede this.
207
Returned as a map from revision to inventory entry.
209
This is a map containing the file revisions in all parents
210
for which the file exists, and its revision is not a parent of
211
any other. If the file is new, the set will be empty.
213
:param versioned_file_store: A store where ancestry data on this
214
file id can be queried.
215
:param transaction: The transaction that queries to the versioned
216
file store should be completed under.
217
:param entry_vf: The entry versioned file, if its already available.
219
candidates = self.parent_candidates(previous_inventories)
221
# revision:ie mapping with one revision for each head.
223
# common case optimisation
224
if len(candidates) == 1:
225
# if there is only one candidate revision found
226
# then we can avoid opening the versioned file to access ancestry:
227
# there cannot be any ancestors to eliminate when there is
228
# only one revision available.
231
# --- what follows is now encapsulated in repository.get_graph.heads(),
232
# but that is not accessible from here as we have no repository
233
# pointer. Note that the repository.get_graph.heads() call can return
234
# different results *at the moment* because of the kind-changing check
235
# we have in parent_candidates().
237
# eliminate ancestors amongst the available candidates:
238
# heads are those that are not an ancestor of any other candidate
239
# - this provides convergence at a per-file level.
240
def get_ancestors(weave, entry):
241
return set(weave.get_ancestry(entry.revision, topo_sorted=False))
242
# revision: ancestor list for each head
244
for ie in candidates.values():
245
# may be an ancestor of a known head:
246
already_present = 0 != len(
247
[head for head in heads
248
if ie.revision in head_ancestors[head]])
250
# an ancestor of an analyzed candidate.
252
# not an ancestor of a known head:
253
# load the versioned file for this file id if needed
255
entry_vf = versioned_file_store.get_weave_or_empty(
256
self.file_id, transaction)
257
ancestors = get_ancestors(entry_vf, ie)
258
# may knock something else out:
259
check_heads = list(heads.keys())
260
for head in check_heads:
261
if head in ancestors:
262
# this previously discovered 'head' is not
263
# really a head - its an ancestor of the newly
266
head_ancestors[ie.revision] = ancestors
267
heads[ie.revision] = ie
179
270
def get_tar_item(self, root, dp, now, tree):
180
271
"""Get a tarfile item and a file stream for its content."""
181
272
item = tarfile.TarInfo(osutils.pathjoin(root, dp).encode('utf8'))
476
570
if t in checker.checked_texts:
477
571
prev_sha = checker.checked_texts[t]
478
572
if prev_sha != self.text_sha1:
480
'mismatched sha1 on {%s} in {%s} (%s != %s) %r' %
481
(self.file_id, tree_revision_id, prev_sha, self.text_sha1,
573
raise BzrCheckError('mismatched sha1 on {%s} in {%s}' %
574
(self.file_id, tree_revision_id))
484
576
checker.repeated_text_cnt += 1
500
592
# We can't check the length, because Weave doesn't store that
501
593
# information, and the whole point of looking at the weave's
502
594
# sha1sum is that we don't have to extract the text.
503
if self.text_sha1 != w.get_sha1s([self.revision])[0]:
595
if self.text_sha1 != w.get_sha1(self.revision):
504
596
raise BzrCheckError('text {%s} version {%s} wrong sha1'
505
597
% (self.file_id, self.revision))
506
598
checker.checked_texts[t] = self.text_sha1
523
617
def _diff(self, text_diff, from_label, tree, to_label, to_entry, to_tree,
524
618
output_to, reverse=False):
525
619
"""See InventoryEntry._diff."""
526
from bzrlib.diff import DiffText
527
from_file_id = self.file_id
529
to_file_id = to_entry.file_id
533
to_file_id, from_file_id = from_file_id, to_file_id
534
tree, to_tree = to_tree, tree
535
from_label, to_label = to_label, from_label
536
differ = DiffText(tree, to_tree, output_to, 'utf-8', '', '',
538
return differ.diff_text(from_file_id, to_file_id, from_label, to_label)
621
from_text = tree.get_file(self.file_id).readlines()
623
to_text = to_tree.get_file(to_entry.file_id).readlines()
627
text_diff(from_label, from_text,
628
to_label, to_text, output_to)
630
text_diff(to_label, to_text,
631
from_label, from_text, output_to)
632
except errors.BinaryFile:
634
label_pair = (to_label, from_label)
636
label_pair = (from_label, to_label)
637
print >> output_to, \
638
("Binary files %s and %s differ" % label_pair).encode('utf8')
540
640
def has_text(self):
541
641
"""See InventoryEntry.has_text."""
633
733
def _diff(self, text_diff, from_label, tree, to_label, to_entry, to_tree,
634
734
output_to, reverse=False):
635
735
"""See InventoryEntry._diff."""
636
from bzrlib.diff import DiffSymlink
637
old_target = self.symlink_target
736
from_text = self.symlink_target
638
737
if to_entry is not None:
639
new_target = to_entry.symlink_target
648
new_target, old_target = old_target, new_target
649
differ = DiffSymlink(old_tree, new_tree, output_to)
650
return differ.diff_symlink(old_target, new_target)
738
to_text = to_entry.symlink_target
743
print >>output_to, '=== target changed %r => %r' % (from_text, to_text)
746
print >>output_to, '=== target was %r' % self.symlink_target
748
print >>output_to, '=== target is %r' % self.symlink_target
652
750
def __init__(self, file_id, name, parent_id):
653
751
super(InventoryLink, self).__init__(file_id, name, parent_id)
848
947
# TODO: jam 20051218 Should copy also copy the revision_id?
849
948
entries = self.iter_entries()
850
if self.root is None:
851
return Inventory(root_id=None)
852
949
other = Inventory(entries.next()[1].file_id)
853
950
# copy recursively so we know directories will be added before
854
951
# their children. There are more efficient ways than this...
855
for path, entry in entries:
952
for path, entry in entries():
856
953
other.add(entry.copy())