142
143
return False, False
145
@deprecated_method(symbol_versioning.one_zero)
146
def diff(self, text_diff, from_label, tree, to_label, to_entry, to_tree,
147
output_to, reverse=False):
148
"""Perform a diff from this to to_entry.
150
text_diff will be used for textual difference calculation.
151
This is a template method, override _diff in child classes.
153
self._read_tree_state(tree.id2path(self.file_id), tree)
155
# cannot diff from one kind to another - you must do a removal
156
# and an addif they do not match.
157
assert self.kind == to_entry.kind
158
to_entry._read_tree_state(to_tree.id2path(to_entry.file_id),
160
self._diff(text_diff, from_label, tree, to_label, to_entry, to_tree,
144
163
def _diff(self, text_diff, from_label, tree, to_label, to_entry, to_tree,
145
164
output_to, reverse=False):
146
165
"""Perform a diff between two entries of the same kind."""
171
191
ie.executable = False
172
192
except AttributeError:
194
# must now be the same.
195
assert candidates[ie.revision] == ie
175
197
# add this revision as a candidate.
176
198
candidates[ie.revision] = ie
177
199
return candidates
179
@deprecated_method(deprecated_in((1, 6, 0)))
201
@deprecated_method(symbol_versioning.zero_ninetyone)
202
def find_previous_heads(self, previous_inventories,
203
versioned_file_store,
206
"""Return the revisions and entries that directly precede this.
208
Returned as a map from revision to inventory entry.
210
This is a map containing the file revisions in all parents
211
for which the file exists, and its revision is not a parent of
212
any other. If the file is new, the set will be empty.
214
:param versioned_file_store: A store where ancestry data on this
215
file id can be queried.
216
:param transaction: The transaction that queries to the versioned
217
file store should be completed under.
218
:param entry_vf: The entry versioned file, if its already available.
220
candidates = self.parent_candidates(previous_inventories)
222
# revision:ie mapping with one revision for each head.
224
# common case optimisation
225
if len(candidates) == 1:
226
# if there is only one candidate revision found
227
# then we can avoid opening the versioned file to access ancestry:
228
# there cannot be any ancestors to eliminate when there is
229
# only one revision available.
232
# --- what follows is now encapsulated in repository.get_graph.heads(),
233
# but that is not accessible from here as we have no repository
234
# pointer. Note that the repository.get_graph.heads() call can return
235
# different results *at the moment* because of the kind-changing check
236
# we have in parent_candidates().
238
# eliminate ancestors amongst the available candidates:
239
# heads are those that are not an ancestor of any other candidate
240
# - this provides convergence at a per-file level.
241
def get_ancestors(weave, entry):
242
return set(weave.get_ancestry(entry.revision, topo_sorted=False))
243
# revision: ancestor list for each head
245
for ie in candidates.values():
246
# may be an ancestor of a known head:
247
already_present = 0 != len(
248
[head for head in heads
249
if ie.revision in head_ancestors[head]])
251
# an ancestor of an analyzed candidate.
253
# not an ancestor of a known head:
254
# load the versioned file for this file id if needed
256
entry_vf = versioned_file_store.get_weave_or_empty(
257
self.file_id, transaction)
258
ancestors = get_ancestors(entry_vf, ie)
259
# may knock something else out:
260
check_heads = list(heads.keys())
261
for head in check_heads:
262
if head in ancestors:
263
# this previously discovered 'head' is not
264
# really a head - its an ancestor of the newly
267
head_ancestors[ie.revision] = ancestors
268
heads[ie.revision] = ie
180
271
def get_tar_item(self, root, dp, now, tree):
181
272
"""Get a tarfile item and a file stream for its content."""
182
273
item = tarfile.TarInfo(osutils.pathjoin(root, dp).encode('utf8'))
475
568
def _check(self, checker, tree_revision_id, tree):
476
569
"""See InventoryEntry._check"""
477
key = (self.file_id, self.revision)
478
if key in checker.checked_texts:
479
prev_sha = checker.checked_texts[key]
570
t = (self.file_id, self.revision)
571
if t in checker.checked_texts:
572
prev_sha = checker.checked_texts[t]
480
573
if prev_sha != self.text_sha1:
481
574
raise BzrCheckError(
482
575
'mismatched sha1 on {%s} in {%s} (%s != %s) %r' %
486
579
checker.repeated_text_cnt += 1
582
if self.file_id not in checker.checked_weaves:
583
mutter('check weave {%s}', self.file_id)
584
w = tree._get_weave(self.file_id)
585
# Not passing a progress bar, because it creates a new
586
# progress, which overwrites the current progress,
587
# and doesn't look nice
589
checker.checked_weaves[self.file_id] = True
591
w = tree._get_weave(self.file_id)
489
593
mutter('check version {%s} of {%s}', tree_revision_id, self.file_id)
490
594
checker.checked_text_cnt += 1
491
595
# We can't check the length, because Weave doesn't store that
492
596
# information, and the whole point of looking at the weave's
493
597
# sha1sum is that we don't have to extract the text.
494
if (self.text_sha1 != tree._repository.texts.get_sha1s([key])[key]):
495
raise BzrCheckError('text {%s} version {%s} wrong sha1' % key)
496
checker.checked_texts[key] = self.text_sha1
598
if self.text_sha1 != w.get_sha1(self.revision):
599
raise BzrCheckError('text {%s} version {%s} wrong sha1'
600
% (self.file_id, self.revision))
601
checker.checked_texts[t] = self.text_sha1
499
604
other = InventoryFile(self.file_id, self.name, self.parent_id)
815
923
# adds come later
817
925
# Preserve unaltered children of file_id for later reinsertion.
818
file_id_children = getattr(self[file_id], 'children', {})
819
if len(file_id_children):
820
children[file_id] = file_id_children
926
children[file_id] = getattr(self[file_id], 'children', {})
821
927
# Remove file_id and the unaltered children. If file_id is not
822
928
# being deleted it will be reinserted back later.
823
929
self.remove_recursive_id(file_id)
829
935
for new_path, new_entry in sorted((np, e) for op, np, f, e in
830
936
delta if np is not None):
831
937
if new_entry.kind == 'directory':
832
# Pop the child which to allow detection of children whose
833
# parents were deleted and which were not reattached to a new
835
new_entry.children = children.pop(new_entry.file_id, {})
938
new_entry.children = children.get(new_entry.file_id, {})
836
939
self.add(new_entry)
838
# Get the parent id that was deleted
839
parent_id, children = children.popitem()
840
raise errors.InconsistentDelta("<deleted>", parent_id,
841
"The file id was deleted but its children were not deleted.")
843
941
def _set_root(self, ie):