159
163
This is a map containing the file revisions in all parents
160
164
for which the file exists, and its revision is not a parent of
161
165
any other. If the file is new, the set will be empty.
167
:param versioned_file_store: A store where ancestry data on this
168
file id can be queried.
169
:param transaction: The transaction that queries to the versioned
170
file store should be completed under.
171
:param entry_vf: The entry versioned file, if its already available.
163
173
def get_ancestors(weave, entry):
164
174
return set(weave.get_ancestry(entry.revision))
175
# revision:ie mapping for each ie found in previous_inventories.
177
# revision:ie mapping with one revision for each head.
179
# revision: ancestor list for each head
166
180
head_ancestors = {}
181
# identify candidate head revision ids.
167
182
for inv in previous_inventories:
168
183
if self.file_id in inv:
169
184
ie = inv[self.file_id]
170
185
assert ie.file_id == self.file_id
171
if ie.revision in heads:
172
# fixup logic, there was a bug in revision updates.
173
# with x bit support.
186
if ie.revision in candidates:
187
# same revision value in two different inventories:
188
# correct possible inconsistencies:
189
# * there was a bug in revision updates with 'x' bit
175
if heads[ie.revision].executable != ie.executable:
176
heads[ie.revision].executable = False
192
if candidates[ie.revision].executable != ie.executable:
193
candidates[ie.revision].executable = False
177
194
ie.executable = False
178
195
except AttributeError:
180
assert heads[ie.revision] == ie
197
# must now be the same.
198
assert candidates[ie.revision] == ie
182
# may want to add it.
183
# may already be covered:
184
already_present = 0 != len(
185
[head for head in heads
186
if ie.revision in head_ancestors[head]])
188
# an ancestor of a known head.
191
ancestors = get_ancestors(entry_weave, ie)
192
# may knock something else out:
193
check_heads = list(heads.keys())
194
for head in check_heads:
195
if head in ancestors:
196
# this head is not really a head
198
head_ancestors[ie.revision] = ancestors
199
heads[ie.revision] = ie
200
# add this revision as a candidate.
201
candidates[ie.revision] = ie
203
# common case optimisation
204
if len(candidates) == 1:
205
# if there is only one candidate revision found
206
# then we can opening the versioned file to access ancestry:
207
# there cannot be any ancestors to eliminate when there is
208
# only one revision available.
209
heads[ie.revision] = ie
212
# eliminate ancestors amongst the available candidates:
213
# heads are those that are not an ancestor of any other candidate
214
# - this provides convergence at a per-file level.
215
for ie in candidates.values():
216
# may be an ancestor of a known head:
217
already_present = 0 != len(
218
[head for head in heads
219
if ie.revision in head_ancestors[head]])
221
# an ancestor of an analyzed candidate.
223
# not an ancestor of a known head:
224
# load the versioned file for this file id if needed
226
entry_vf = versioned_file_store.get_weave_or_empty(
227
self.file_id, transaction)
228
ancestors = get_ancestors(entry_vf, ie)
229
# may knock something else out:
230
check_heads = list(heads.keys())
231
for head in check_heads:
232
if head in ancestors:
233
# this previously discovered 'head' is not
234
# really a head - its an ancestor of the newly
237
head_ancestors[ie.revision] = ancestors
238
heads[ie.revision] = ie
202
241
def get_tar_item(self, root, dp, now, tree):
472
519
class InventoryFile(InventoryEntry):
473
520
"""A file in an inventory."""
475
def _check(self, checker, rev_id, tree):
522
def _check(self, checker, tree_revision_id, tree):
476
523
"""See InventoryEntry._check"""
477
revision = self.revision
478
t = (self.file_id, revision)
524
t = (self.file_id, self.revision)
479
525
if t in checker.checked_texts:
480
prev_sha = checker.checked_texts[t]
526
prev_sha = checker.checked_texts[t]
481
527
if prev_sha != self.text_sha1:
482
528
raise BzrCheckError('mismatched sha1 on {%s} in {%s}' %
483
(self.file_id, rev_id))
529
(self.file_id, tree_revision_id))
485
531
checker.repeated_text_cnt += 1
497
543
w = tree.get_weave(self.file_id)
499
mutter('check version {%s} of {%s}', rev_id, self.file_id)
500
checker.checked_text_cnt += 1
545
mutter('check version {%s} of {%s}', tree_revision_id, self.file_id)
546
checker.checked_text_cnt += 1
501
547
# We can't check the length, because Weave doesn't store that
502
548
# information, and the whole point of looking at the weave's
503
549
# sha1sum is that we don't have to extract the text.