2227
2238
if ie.revision is not None:
2241
# XXX: Friction: parent_candidates should return a list not a dict
2242
# so that we don't have to walk the inventories again.
2230
2243
parent_candiate_entries = ie.parent_candidates(parent_invs)
2231
heads = self.repository.get_graph().heads(parent_candiate_entries.keys())
2232
# XXX: Note that this is unordered - and this is tolerable because
2233
# the previous code was also unordered.
2234
previous_entries = dict((head, parent_candiate_entries[head]) for head
2236
# we are creating a new revision for ie in the history store and
2238
ie.snapshot(self._new_revision_id, path, previous_entries, tree, self)
2240
def modified_directory(self, file_id, file_parents):
2241
"""Record the presence of a symbolic link.
2243
:param file_id: The file_id of the link to record.
2244
:param file_parents: The per-file parent revision ids.
2246
self._add_text_to_weave(file_id, [], file_parents.keys())
2248
def modified_reference(self, file_id, file_parents):
2249
"""Record the modification of a reference.
2251
:param file_id: The file_id of the link to record.
2252
:param file_parents: The per-file parent revision ids.
2254
self._add_text_to_weave(file_id, [], file_parents.keys())
2256
def modified_file_text(self, file_id, file_parents,
2257
get_content_byte_lines, text_sha1=None,
2259
"""Record the text of file file_id
2261
:param file_id: The file_id of the file to record the text of.
2262
:param file_parents: The per-file parent revision ids.
2263
:param get_content_byte_lines: A callable which will return the byte
2265
:param text_sha1: Optional SHA1 of the file contents.
2266
:param text_size: Optional size of the file contents.
2268
# mutter('storing text of file {%s} in revision {%s} into %r',
2269
# file_id, self._new_revision_id, self.repository.weave_store)
2270
# special case to avoid diffing on renames or
2272
if (len(file_parents) == 1
2273
and text_sha1 == file_parents.values()[0].text_sha1
2274
and text_size == file_parents.values()[0].text_size):
2275
previous_ie = file_parents.values()[0]
2276
versionedfile = self.repository.weave_store.get_weave(file_id,
2277
self.repository.get_transaction())
2278
versionedfile.clone_text(self._new_revision_id,
2279
previous_ie.revision, file_parents.keys())
2280
return text_sha1, text_size
2244
head_set = self.repository.get_graph().heads(parent_candiate_entries.keys())
2246
for inv in parent_invs:
2247
if ie.file_id in inv:
2248
old_rev = inv[ie.file_id].revision
2249
if old_rev in head_set:
2250
heads.append(inv[ie.file_id].revision)
2251
head_set.remove(inv[ie.file_id].revision)
2254
# now we check to see if we need to write a new record to the
2256
# We write a new entry unless there is one head to the ancestors, and
2257
# the kind-derived content is unchanged.
2259
# Cheapest check first: no ancestors, or more the one head in the
2260
# ancestors, we write a new node.
2264
# There is a single head, look it up for comparison
2265
parent_entry = parent_candiate_entries[heads[0]]
2266
# if the non-content specific data has changed, we'll be writing a
2268
if (parent_entry.parent_id != ie.parent_id or
2269
parent_entry.name != ie.name):
2271
# now we need to do content specific checks:
2273
# if the kind changed the content obviously has
2274
if kind != parent_entry.kind:
2278
if (# if the file length changed we have to store:
2279
parent_entry.text_size != content_summary[1] or
2280
# if the exec bit has changed we have to store:
2281
parent_entry.executable != content_summary[2]):
2283
elif parent_entry.text_sha1 == content_summary[3]:
2284
# all meta and content is unchanged (using a hash cache
2285
# hit to check the sha)
2286
ie.revision = parent_entry.revision
2287
ie.text_size = parent_entry.text_size
2288
ie.text_sha1 = parent_entry.text_sha1
2289
ie.executable = parent_entry.executable
2292
# Either there is only a hash change(no hash cache entry,
2293
# or same size content change), or there is no change on
2295
# There is a race condition when inserting content into the
2296
# knit though that can result in different content being
2297
# inserted so even though we may have had a hash cache hit
2298
# here we still tell the store the hash we would *not*
2299
# store a new text on, which means that it can avoid for us
2300
# without a race condition and without double-shaing the
2302
nostore_sha = parent_entry.text_sha1
2306
ie.executable = content_summary[2]
2307
lines = tree.get_file(ie.file_id, path).readlines()
2308
ie.text_sha1, ie.text_size = self._add_text_to_weave(
2309
ie.file_id, lines, heads, nostore_sha)
2310
ie.revision = self._new_revision_id
2311
except errors.ExistingContent:
2312
# we are not going to store a new file graph node as it turns
2313
# out to be unchanged.
2314
ie.revision = parent_entry.revision
2315
ie.text_size = parent_entry.text_size
2316
ie.text_sha1 = parent_entry.text_sha1
2317
ie.executable = parent_entry.executable
2319
elif kind == 'directory':
2321
# all data is meta here, so carry over:
2322
ie.revision = parent_entry.revision
2325
self._add_text_to_weave(ie.file_id, lines, heads, None)
2326
elif kind == 'symlink':
2327
current_link_target = content_summary[3]
2329
# symmlink target is not generic metadata, check if it has
2331
if current_link_target != parent_entry.symlink_target:
2334
ie.revision = parent_entry.revision
2335
ie.symlink_target = parent_entry.symlink_target
2337
ie.symlink_target = current_link_target
2339
self._add_text_to_weave(ie.file_id, lines, heads, None)
2340
elif kind == 'tree-reference':
2342
# all data is meta here, so carry over:
2343
ie.revision = parent_entry.revision
2346
self._add_text_to_weave(ie.file_id, lines, heads, None)
2282
new_lines = get_content_byte_lines()
2283
return self._add_text_to_weave(file_id, new_lines,
2284
file_parents.keys())
2286
def modified_link(self, file_id, file_parents, link_target):
2287
"""Record the presence of a symbolic link.
2289
:param file_id: The file_id of the link to record.
2290
:param file_parents: The per-file parent revision ids.
2291
:param link_target: Target location of this link.
2293
self._add_text_to_weave(file_id, [], file_parents.keys())
2295
def _add_text_to_weave(self, file_id, new_lines, parents):
2348
raise NotImplementedError('unknown kind')
2349
ie.revision = self._new_revision_id
2351
def _add_text_to_weave(self, file_id, new_lines, parents, nostore_sha):
2296
2352
versionedfile = self.repository.weave_store.get_weave_or_empty(
2297
2353
file_id, self.repository.get_transaction())
2298
result = versionedfile.add_lines(
2299
self._new_revision_id, parents, new_lines)[0:2]
2300
versionedfile.clear_cache()
2355
return versionedfile.add_lines(
2356
self._new_revision_id, parents, new_lines,
2357
nostore_sha=nostore_sha)[0:2]
2359
versionedfile.clear_cache()
2304
2362
class _CommitBuilder(CommitBuilder):