Merge lp:~jelmer/brz/remove-record-entry-contents into lp:brz

Proposed by Jelmer Vernooij on 2017-06-20
Status: Merged
Approved by: Jelmer Vernooij on 2017-06-20
Approved revision: 6711
Merge reported by: The Breezy Bot
Merged at revision: not available
Proposed branch: lp:~jelmer/brz/remove-record-entry-contents
Merge into: lp:brz
Prerequisite: lp:~jelmer/brz/iter-changes-all-the-way
Diff against target: 1633 lines (+37/-1096)
9 files modified
breezy/bzr/vf_repository.py (+10/-281)
breezy/commit.py (+8/-247)
breezy/plugins/fastimport/revision_store.py (+1/-1)
breezy/repository.py (+0/-2)
breezy/tests/per_repository/test_commit_builder.py (+6/-555)
breezy/tests/per_workingtree/test_commit.py (+1/-0)
breezy/tests/test_foreign.py (+6/-10)
breezy/tests/test_merge.py (+2/-0)
doc/en/release-notes/brz-3.0.txt (+3/-0)
To merge this branch: bzr merge lp:~jelmer/brz/remove-record-entry-contents
Reviewer Review Type Date Requested Status
Martin Packman 2017-06-20 Approve on 2017-06-20
Review via email: mp+325968@code.launchpad.net

Commit message

Remove remaining implementations of CommitBuilder.record_{entry_contents,delete}.

Description of the change

Remove remaining implementations of CommitBuilder.record_{entry_contents,delete}.

... and all their tests.

To post a comment you must log in.
Martin Packman (gz) wrote :

Changes here all look good to me.

review: Approve
6711. By Jelmer Vernooij on 2017-06-20

Merge trunk.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'breezy/bzr/vf_repository.py'
2--- breezy/bzr/vf_repository.py 2017-06-20 00:39:00 +0000
3+++ breezy/bzr/vf_repository.py 2017-06-20 22:39:47 +0000
4@@ -112,9 +112,6 @@
5 """Commit builder implementation for versioned files based repositories.
6 """
7
8- # this commit builder supports the record_entry_contents interface
9- supports_record_entry_contents = True
10-
11 # the default CommitBuilder does not manage trees whose root is versioned.
12 _versioned_root = False
13
14@@ -129,7 +126,7 @@
15 except IndexError:
16 basis_id = _mod_revision.NULL_REVISION
17 self.basis_delta_revision = basis_id
18- self.new_inventory = Inventory(None)
19+ self._new_inventory = None
20 self._basis_delta = []
21 self.__heads = graph.HeadsCache(repository.get_graph()).heads
22 # memo'd check for no-op commits.
23@@ -220,11 +217,11 @@
24 require deserializing the inventory, while we already have a copy in
25 memory.
26 """
27- if self.new_inventory is None:
28- self.new_inventory = self.repository.get_inventory(
29+ if self._new_inventory is None:
30+ self._new_inventory = self.repository.get_inventory(
31 self._new_revision_id)
32 return inventorytree.InventoryRevisionTree(self.repository,
33- self.new_inventory, self._new_revision_id)
34+ self._new_inventory, self._new_revision_id)
35
36 def finish_inventory(self):
37 """Tell the builder that the inventory is finished.
38@@ -232,42 +229,14 @@
39 :return: The inventory id in the repository, which can be used with
40 repository.get_inventory.
41 """
42- if self.new_inventory is None:
43- # an inventory delta was accumulated without creating a new
44- # inventory.
45- basis_id = self.basis_delta_revision
46- # We ignore the 'inventory' returned by add_inventory_by_delta
47- # because self.new_inventory is used to hint to the rest of the
48- # system what code path was taken
49- self.inv_sha1, _ = self.repository.add_inventory_by_delta(
50- basis_id, self._basis_delta, self._new_revision_id,
51- self.parents)
52- else:
53- if self.new_inventory.root is None:
54- raise AssertionError('Root entry should be supplied to'
55- ' record_entry_contents, as of bzr 0.10.')
56- self.new_inventory.add(InventoryDirectory(ROOT_ID, '', None))
57- self.new_inventory.revision_id = self._new_revision_id
58- self.inv_sha1 = self.repository.add_inventory(
59- self._new_revision_id,
60- self.new_inventory,
61- self.parents
62- )
63+ # an inventory delta was accumulated without creating a new
64+ # inventory.
65+ basis_id = self.basis_delta_revision
66+ self.inv_sha1, self._new_inventory = self.repository.add_inventory_by_delta(
67+ basis_id, self._basis_delta, self._new_revision_id,
68+ self.parents)
69 return self._new_revision_id
70
71- def _check_root(self, ie, parent_invs, tree):
72- """Helper for record_entry_contents.
73-
74- :param ie: An entry being added.
75- :param parent_invs: The inventories of the parent revisions of the
76- commit.
77- :param tree: The tree that is being committed.
78- """
79- # In this revision format, root entries have no knit or weave When
80- # serializing out to disk and back in root.revision is always
81- # _new_revision_id
82- ie.revision = self._new_revision_id
83-
84 def _require_root_change(self, tree):
85 """Enforce an appropriate root object change.
86
87@@ -311,241 +280,11 @@
88 def get_basis_delta(self):
89 """Return the complete inventory delta versus the basis inventory.
90
91- This has been built up with the calls to record_delete and
92- record_entry_contents.
93-
94 :return: An inventory delta, suitable for use with apply_delta, or
95 Repository.add_inventory_by_delta, etc.
96 """
97 return self._basis_delta
98
99- def record_delete(self, path, file_id):
100- """Record that a delete occured against a basis tree.
101-
102- This is an optional API - when used it adds items to the basis_delta
103- being accumulated by the commit builder.
104-
105- :param path: The path of the thing deleted.
106- :param file_id: The file id that was deleted.
107- """
108- delta = (path, None, file_id, None)
109- self._basis_delta.append(delta)
110- self._any_changes = True
111- return delta
112-
113- def record_entry_contents(self, ie, parent_invs, path, tree,
114- content_summary):
115- """Record the content of ie from tree into the commit if needed.
116-
117- Side effect: sets ie.revision when unchanged
118-
119- :param ie: An inventory entry present in the commit.
120- :param parent_invs: The inventories of the parent revisions of the
121- commit.
122- :param path: The path the entry is at in the tree.
123- :param tree: The tree which contains this entry and should be used to
124- obtain content.
125- :param content_summary: Summary data from the tree about the paths
126- content - stat, length, exec, sha/link target. This is only
127- accessed when the entry has a revision of None - that is when it is
128- a candidate to commit.
129- :return: A tuple (change_delta, version_recorded, fs_hash).
130- change_delta is an inventory_delta change for this entry against
131- the basis tree of the commit, or None if no change occured against
132- the basis tree.
133- version_recorded is True if a new version of the entry has been
134- recorded. For instance, committing a merge where a file was only
135- changed on the other side will return (delta, False).
136- fs_hash is either None, or the hash details for the path (currently
137- a tuple of the contents sha1 and the statvalue returned by
138- tree.get_file_with_stat()).
139- """
140- if self.new_inventory.root is None:
141- if ie.parent_id is not None:
142- raise errors.RootMissing()
143- self._check_root(ie, parent_invs, tree)
144- if ie.revision is None:
145- kind = content_summary[0]
146- else:
147- # ie is carried over from a prior commit
148- kind = ie.kind
149- # XXX: repository specific check for nested tree support goes here - if
150- # the repo doesn't want nested trees we skip it ?
151- if (kind == 'tree-reference' and
152- not self.repository._format.supports_tree_reference):
153- # mismatch between commit builder logic and repository:
154- # this needs the entry creation pushed down into the builder.
155- raise NotImplementedError('Missing repository subtree support.')
156- self.new_inventory.add(ie)
157-
158- # TODO: slow, take it out of the inner loop.
159- try:
160- basis_inv = parent_invs[0]
161- except IndexError:
162- basis_inv = Inventory(root_id=None)
163-
164- # ie.revision is always None if the InventoryEntry is considered
165- # for committing. We may record the previous parents revision if the
166- # content is actually unchanged against a sole head.
167- if ie.revision is not None:
168- if not self._versioned_root and path == '':
169- # repositories that do not version the root set the root's
170- # revision to the new commit even when no change occurs (more
171- # specifically, they do not record a revision on the root; and
172- # the rev id is assigned to the root during deserialisation -
173- # this masks when a change may have occurred against the basis.
174- # To match this we always issue a delta, because the revision
175- # of the root will always be changing.
176- if basis_inv.has_id(ie.file_id):
177- delta = (basis_inv.id2path(ie.file_id), path,
178- ie.file_id, ie)
179- else:
180- # add
181- delta = (None, path, ie.file_id, ie)
182- self._basis_delta.append(delta)
183- return delta, False, None
184- else:
185- # we don't need to commit this, because the caller already
186- # determined that an existing revision of this file is
187- # appropriate. If it's not being considered for committing then
188- # it and all its parents to the root must be unaltered so
189- # no-change against the basis.
190- if ie.revision == self._new_revision_id:
191- raise AssertionError("Impossible situation, a skipped "
192- "inventory entry (%r) claims to be modified in this "
193- "commit (%r).", (ie, self._new_revision_id))
194- return None, False, None
195- # XXX: Friction: parent_candidates should return a list not a dict
196- # so that we don't have to walk the inventories again.
197- parent_candidate_entries = ie.parent_candidates(parent_invs)
198- head_set = self._heads(ie.file_id, parent_candidate_entries)
199- heads = []
200- for inv in parent_invs:
201- if inv.has_id(ie.file_id):
202- old_rev = inv[ie.file_id].revision
203- if old_rev in head_set:
204- heads.append(inv[ie.file_id].revision)
205- head_set.remove(inv[ie.file_id].revision)
206-
207- store = False
208- # now we check to see if we need to write a new record to the
209- # file-graph.
210- # We write a new entry unless there is one head to the ancestors, and
211- # the kind-derived content is unchanged.
212-
213- # Cheapest check first: no ancestors, or more the one head in the
214- # ancestors, we write a new node.
215- if len(heads) != 1:
216- store = True
217- if not store:
218- # There is a single head, look it up for comparison
219- parent_entry = parent_candidate_entries[heads[0]]
220- # if the non-content specific data has changed, we'll be writing a
221- # node:
222- if (parent_entry.parent_id != ie.parent_id or
223- parent_entry.name != ie.name):
224- store = True
225- # now we need to do content specific checks:
226- if not store:
227- # if the kind changed the content obviously has
228- if kind != parent_entry.kind:
229- store = True
230- # Stat cache fingerprint feedback for the caller - None as we usually
231- # don't generate one.
232- fingerprint = None
233- if kind == 'file':
234- if content_summary[2] is None:
235- raise ValueError("Files must not have executable = None")
236- if not store:
237- # We can't trust a check of the file length because of content
238- # filtering...
239- if (# if the exec bit has changed we have to store:
240- parent_entry.executable != content_summary[2]):
241- store = True
242- elif parent_entry.text_sha1 == content_summary[3]:
243- # all meta and content is unchanged (using a hash cache
244- # hit to check the sha)
245- ie.revision = parent_entry.revision
246- ie.text_size = parent_entry.text_size
247- ie.text_sha1 = parent_entry.text_sha1
248- ie.executable = parent_entry.executable
249- return self._get_delta(ie, basis_inv, path), False, None
250- else:
251- # Either there is only a hash change(no hash cache entry,
252- # or same size content change), or there is no change on
253- # this file at all.
254- # Provide the parent's hash to the store layer, so that the
255- # content is unchanged we will not store a new node.
256- nostore_sha = parent_entry.text_sha1
257- if store:
258- # We want to record a new node regardless of the presence or
259- # absence of a content change in the file.
260- nostore_sha = None
261- ie.executable = content_summary[2]
262- file_obj, stat_value = tree.get_file_with_stat(ie.file_id, path)
263- try:
264- text = file_obj.read()
265- finally:
266- file_obj.close()
267- try:
268- ie.text_sha1, ie.text_size = self._add_text_to_weave(
269- ie.file_id, text, heads, nostore_sha)
270- # Let the caller know we generated a stat fingerprint.
271- fingerprint = (ie.text_sha1, stat_value)
272- except errors.ExistingContent:
273- # Turns out that the file content was unchanged, and we were
274- # only going to store a new node if it was changed. Carry over
275- # the entry.
276- ie.revision = parent_entry.revision
277- ie.text_size = parent_entry.text_size
278- ie.text_sha1 = parent_entry.text_sha1
279- ie.executable = parent_entry.executable
280- return self._get_delta(ie, basis_inv, path), False, None
281- elif kind == 'directory':
282- if not store:
283- # all data is meta here, nothing specific to directory, so
284- # carry over:
285- ie.revision = parent_entry.revision
286- return self._get_delta(ie, basis_inv, path), False, None
287- self._add_text_to_weave(ie.file_id, '', heads, None)
288- elif kind == 'symlink':
289- current_link_target = content_summary[3]
290- if not store:
291- # symlink target is not generic metadata, check if it has
292- # changed.
293- if current_link_target != parent_entry.symlink_target:
294- store = True
295- if not store:
296- # unchanged, carry over.
297- ie.revision = parent_entry.revision
298- ie.symlink_target = parent_entry.symlink_target
299- return self._get_delta(ie, basis_inv, path), False, None
300- ie.symlink_target = current_link_target
301- self._add_text_to_weave(ie.file_id, '', heads, None)
302- elif kind == 'tree-reference':
303- if not store:
304- if content_summary[3] != parent_entry.reference_revision:
305- store = True
306- if not store:
307- # unchanged, carry over.
308- ie.reference_revision = parent_entry.reference_revision
309- ie.revision = parent_entry.revision
310- return self._get_delta(ie, basis_inv, path), False, None
311- ie.reference_revision = content_summary[3]
312- if ie.reference_revision is None:
313- raise AssertionError("invalid content_summary for nested tree: %r"
314- % (content_summary,))
315- self._add_text_to_weave(ie.file_id, '', heads, None)
316- else:
317- raise NotImplementedError('unknown kind')
318- ie.revision = self._new_revision_id
319- # The initial commit adds a root directory, but this in itself is not
320- # a worthwhile commit.
321- if (self.basis_delta_revision != _mod_revision.NULL_REVISION or
322- path != ""):
323- self._any_changes = True
324- return self._get_delta(ie, basis_inv, path), True, fingerprint
325-
326 def record_iter_changes(self, tree, basis_revision_id, iter_changes,
327 _entry_factory=entry_factory):
328 """Record a new tree via iter_changes.
329@@ -805,7 +544,6 @@
330 inv_delta.append((change[1][0], new_path, change[0], entry))
331 if new_path == '':
332 seen_root = True
333- self.new_inventory = None
334 # The initial commit adds a root directory, but this in itself is not
335 # a worthwhile commit.
336 if ((len(inv_delta) > 0 and basis_revision_id != _mod_revision.NULL_REVISION) or
337@@ -832,15 +570,6 @@
338 # the root entry gets versioned properly by this builder.
339 _versioned_root = True
340
341- def _check_root(self, ie, parent_invs, tree):
342- """Helper for record_entry_contents.
343-
344- :param ie: An entry being added.
345- :param parent_invs: The inventories of the parent revisions of the
346- commit.
347- :param tree: The tree that is being committed.
348- """
349-
350 def _require_root_change(self, tree):
351 """Enforce an appropriate root object change.
352
353
354=== modified file 'breezy/commit.py'
355--- breezy/commit.py 2017-06-20 22:29:58 +0000
356+++ breezy/commit.py 2017-06-20 22:39:47 +0000
357@@ -344,9 +344,6 @@
358 self.work_tree.lock_write()
359 operation.add_cleanup(self.work_tree.unlock)
360 self.parents = self.work_tree.get_parent_ids()
361- # We can use record_iter_changes IFF no tree references are involved.
362- self.use_record_iter_changes = (
363- not self.branch.repository._format.supports_tree_reference)
364 self.pb = ui.ui_factory.nested_progress_bar()
365 operation.add_cleanup(self.pb.finished)
366 self.basis_revid = self.work_tree.last_revision()
367@@ -371,8 +368,6 @@
368 if self.config_stack is None:
369 self.config_stack = self.work_tree.get_config_stack()
370
371- self._set_specific_file_ids()
372-
373 # Setup the progress bar. As the number of files that need to be
374 # committed in unknown, progress is reported as stages.
375 # We keep track of entries separately though and include that
376@@ -390,7 +385,6 @@
377 self.pb.show_count = True
378 self.pb.show_bar = True
379
380- self._gather_parents()
381 # After a merge, a selected file commit is not supported.
382 # See 'bzr help merge' for an explanation as to why.
383 if len(self.parents) > 1 and self.specific_files is not None:
384@@ -654,44 +648,21 @@
385 old_revno, old_revid, new_revno, self.rev_id,
386 tree_delta, future_tree)
387
388- def _gather_parents(self):
389- """Record the parents of a merge for merge detection."""
390- # TODO: Make sure that this list doesn't contain duplicate
391- # entries and the order is preserved when doing this.
392- if self.use_record_iter_changes:
393- return
394- self.basis_inv = self.basis_tree.root_inventory
395- self.parent_invs = [self.basis_inv]
396- for revision in self.parents[1:]:
397- if self.branch.repository.has_revision(revision):
398- mutter('commit parent revision {%s}', revision)
399- inventory = self.branch.repository.get_inventory(revision)
400- self.parent_invs.append(inventory)
401- else:
402- mutter('commit parent ghost revision {%s}', revision)
403-
404 def _update_builder_with_changes(self):
405 """Update the commit builder with the data about what has changed.
406 """
407- exclude = self.exclude
408 specific_files = self.specific_files
409 mutter("Selecting files for commit with filter %r", specific_files)
410
411 self._check_strict()
412- if self.use_record_iter_changes:
413- iter_changes = self.work_tree.iter_changes(self.basis_tree,
414- specific_files=specific_files)
415- if self.exclude:
416- iter_changes = filter_excluded(iter_changes, self.exclude)
417- iter_changes = self._filter_iter_changes(iter_changes)
418- for file_id, path, fs_hash in self.builder.record_iter_changes(
419- self.work_tree, self.basis_revid, iter_changes):
420- self.work_tree._observed_sha1(file_id, path, fs_hash)
421- else:
422- # Build the new inventory
423- self._populate_from_inventory()
424- self._record_unselected()
425- self._report_and_accumulate_deletes()
426+ iter_changes = self.work_tree.iter_changes(self.basis_tree,
427+ specific_files=specific_files)
428+ if self.exclude:
429+ iter_changes = filter_excluded(iter_changes, self.exclude)
430+ iter_changes = self._filter_iter_changes(iter_changes)
431+ for file_id, path, fs_hash in self.builder.record_iter_changes(
432+ self.work_tree, self.basis_revid, iter_changes):
433+ self.work_tree._observed_sha1(file_id, path, fs_hash)
434
435 def _filter_iter_changes(self, iter_changes):
436 """Process iter_changes.
437@@ -745,55 +716,6 @@
438 # Unversion IDs that were found to be deleted
439 self.deleted_ids = deleted_ids
440
441- def _record_unselected(self):
442- # If specific files are selected, then all un-selected files must be
443- # recorded in their previous state. For more details, see
444- # https://lists.ubuntu.com/archives/bazaar/2007q3/028476.html.
445- if self.specific_files or self.exclude:
446- specific_files = self.specific_files or []
447- for path, old_ie in self.basis_inv.iter_entries():
448- if self.builder.new_inventory.has_id(old_ie.file_id):
449- # already added - skip.
450- continue
451- if (is_inside_any(specific_files, path)
452- and not is_inside_any(self.exclude, path)):
453- # was inside the selected path, and not excluded - if not
454- # present it has been deleted so skip.
455- continue
456- # From here down it was either not selected, or was excluded:
457- # We preserve the entry unaltered.
458- ie = old_ie.copy()
459- # Note: specific file commits after a merge are currently
460- # prohibited. This test is for sanity/safety in case it's
461- # required after that changes.
462- if len(self.parents) > 1:
463- ie.revision = None
464- self.builder.record_entry_contents(ie, self.parent_invs, path,
465- self.basis_tree, None)
466-
467- def _report_and_accumulate_deletes(self):
468- if (isinstance(self.basis_inv, Inventory)
469- and isinstance(self.builder.new_inventory, Inventory)):
470- # the older Inventory classes provide a _byid dict, and building a
471- # set from the keys of this dict is substantially faster than even
472- # getting a set of ids from the inventory
473- #
474- # <lifeless> set(dict) is roughly the same speed as
475- # set(iter(dict)) and both are significantly slower than
476- # set(dict.keys())
477- deleted_ids = set(self.basis_inv._byid.keys()) - \
478- set(self.builder.new_inventory._byid.keys())
479- else:
480- deleted_ids = set(self.basis_inv) - set(self.builder.new_inventory)
481- if deleted_ids:
482- self.any_entries_deleted = True
483- deleted = sorted([(self.basis_tree.id2path(file_id), file_id)
484- for file_id in deleted_ids])
485- # XXX: this is not quite directory-order sorting
486- for path, file_id in deleted:
487- self.builder.record_delete(path, file_id)
488- self.reporter.deleted(path)
489-
490 def _check_strict(self):
491 # XXX: when we use iter_changes this would likely be faster if
492 # iter_changes would check for us (even in the presence of
493@@ -803,107 +725,6 @@
494 for unknown in self.work_tree.unknowns():
495 raise StrictCommitFailed()
496
497- def _populate_from_inventory(self):
498- """Populate the CommitBuilder by walking the working tree inventory."""
499- # Build the revision inventory.
500- #
501- # This starts by creating a new empty inventory. Depending on
502- # which files are selected for commit, and what is present in the
503- # current tree, the new inventory is populated. inventory entries
504- # which are candidates for modification have their revision set to
505- # None; inventory entries that are carried over untouched have their
506- # revision set to their prior value.
507- #
508- # ESEPARATIONOFCONCERNS: this function is diffing and using the diff
509- # results to create a new inventory at the same time, which results
510- # in bugs like #46635. Any reason not to use/enhance Tree.changes_from?
511- # ADHB 11-07-2006
512-
513- specific_files = self.specific_files
514- exclude = self.exclude
515- report_changes = self.reporter.is_verbose()
516- deleted_ids = []
517- # A tree of paths that have been deleted. E.g. if foo/bar has been
518- # deleted, then we have {'foo':{'bar':{}}}
519- deleted_paths = {}
520- # XXX: Note that entries may have the wrong kind because the entry does
521- # not reflect the status on disk.
522- # NB: entries will include entries within the excluded ids/paths
523- # because iter_entries_by_dir has no 'exclude' facility today.
524- entries = self.work_tree.iter_entries_by_dir(
525- specific_file_ids=self.specific_file_ids, yield_parents=True)
526- for path, existing_ie in entries:
527- file_id = existing_ie.file_id
528- name = existing_ie.name
529- parent_id = existing_ie.parent_id
530- kind = existing_ie.kind
531- # Skip files that have been deleted from the working tree.
532- # The deleted path ids are also recorded so they can be explicitly
533- # unversioned later.
534- if deleted_paths:
535- path_segments = splitpath(path)
536- deleted_dict = deleted_paths
537- for segment in path_segments:
538- deleted_dict = deleted_dict.get(segment, None)
539- if not deleted_dict:
540- # We either took a path not present in the dict
541- # (deleted_dict was None), or we've reached an empty
542- # child dir in the dict, so are now a sub-path.
543- break
544- else:
545- deleted_dict = None
546- if deleted_dict is not None:
547- # the path has a deleted parent, do not add it.
548- continue
549- if exclude and is_inside_any(exclude, path):
550- # Skip excluded paths. Excluded paths are processed by
551- # _update_builder_with_changes.
552- continue
553- content_summary = self.work_tree.path_content_summary(path)
554- kind = content_summary[0]
555- # Note that when a filter of specific files is given, we must only
556- # skip/record deleted files matching that filter.
557- if not specific_files or is_inside_any(specific_files, path):
558- if kind == 'missing':
559- if not deleted_paths:
560- # path won't have been split yet.
561- path_segments = splitpath(path)
562- deleted_dict = deleted_paths
563- for segment in path_segments:
564- deleted_dict = deleted_dict.setdefault(segment, {})
565- self.reporter.missing(path)
566- self._next_progress_entry()
567- deleted_ids.append(file_id)
568- continue
569- # TODO: have the builder do the nested commit just-in-time IF and
570- # only if needed.
571- if kind == 'tree-reference':
572- # enforce repository nested tree policy.
573- if (not self.work_tree.supports_tree_reference() or
574- # repository does not support it either.
575- not self.branch.repository._format.supports_tree_reference):
576- kind = 'directory'
577- content_summary = (kind, None, None, None)
578- elif self.recursive == 'down':
579- nested_revision_id = self._commit_nested_tree(
580- file_id, path)
581- content_summary = (kind, None, None, nested_revision_id)
582- else:
583- nested_revision_id = self.work_tree.get_reference_revision(file_id)
584- content_summary = (kind, None, None, nested_revision_id)
585-
586- # Record an entry for this item
587- # Note: I don't particularly want to have the existing_ie
588- # parameter but the test suite currently (28-Jun-07) breaks
589- # without it thanks to a unicode normalisation issue. :-(
590- definitely_changed = kind != existing_ie.kind
591- self._record_entry(path, file_id, specific_files, kind, name,
592- parent_id, definitely_changed, existing_ie, report_changes,
593- content_summary)
594-
595- # Unversion IDs that were found to be deleted
596- self.deleted_ids = deleted_ids
597-
598 def _commit_nested_tree(self, file_id, path):
599 "Commit a nested tree."
600 sub_tree = self.work_tree.get_nested_tree(file_id, path)
601@@ -929,49 +750,6 @@
602 except errors.PointlessCommit:
603 return self.work_tree.get_reference_revision(file_id)
604
605- def _record_entry(self, path, file_id, specific_files, kind, name,
606- parent_id, definitely_changed, existing_ie, report_changes,
607- content_summary):
608- "Record the new inventory entry for a path if any."
609- # mutter('check %s {%s}', path, file_id)
610- # mutter('%s selected for commit', path)
611- if definitely_changed or existing_ie is None:
612- ie = make_entry(kind, name, parent_id, file_id)
613- else:
614- ie = existing_ie.copy()
615- ie.revision = None
616- # For carried over entries we don't care about the fs hash - the repo
617- # isn't generating a sha, so we're not saving computation time.
618- _, _, fs_hash = self.builder.record_entry_contents(
619- ie, self.parent_invs, path, self.work_tree, content_summary)
620- if report_changes:
621- self._report_change(ie, path)
622- if fs_hash:
623- self.work_tree._observed_sha1(ie.file_id, path, fs_hash)
624- return ie
625-
626- def _report_change(self, ie, path):
627- """Report a change to the user.
628-
629- The change that has occurred is described relative to the basis
630- inventory.
631- """
632- if (self.basis_inv.has_id(ie.file_id)):
633- basis_ie = self.basis_inv[ie.file_id]
634- else:
635- basis_ie = None
636- change = ie.describe_change(basis_ie, ie)
637- if change in (InventoryEntry.RENAMED,
638- InventoryEntry.MODIFIED_AND_RENAMED):
639- old_path = self.basis_inv.id2path(ie.file_id)
640- self.reporter.renamed(change, old_path, path)
641- self._next_progress_entry()
642- else:
643- if change == gettext('unchanged'):
644- return
645- self.reporter.snapshot_change(change, path)
646- self._next_progress_entry()
647-
648 def _set_progress_stage(self, name, counter=False):
649 """Set the progress stage and emit an update to the progress bar."""
650 self.pb_stage_name = name
651@@ -994,20 +772,3 @@
652 else:
653 text = gettext("%s - Stage") % (self.pb_stage_name, )
654 self.pb.update(text, self.pb_stage_count, self.pb_stage_total)
655-
656- def _set_specific_file_ids(self):
657- """populate self.specific_file_ids if we will use it."""
658- if not self.use_record_iter_changes:
659- # If provided, ensure the specified files are versioned
660- if self.specific_files is not None:
661- # Note: This routine is being called because it raises
662- # PathNotVersionedError as a side effect of finding the IDs. We
663- # later use the ids we found as input to the working tree
664- # inventory iterator, so we only consider those ids rather than
665- # examining the whole tree again.
666- # XXX: Dont we have filter_unversioned to do this more
667- # cheaply?
668- self.specific_file_ids = tree.find_ids_across_trees(
669- self.specific_files, [self.basis_tree, self.work_tree])
670- else:
671- self.specific_file_ids = None
672
673=== modified file 'breezy/plugins/fastimport/revision_store.py'
674--- breezy/plugins/fastimport/revision_store.py 2017-06-13 00:24:51 +0000
675+++ breezy/plugins/fastimport/revision_store.py 2017-06-20 22:39:47 +0000
676@@ -417,7 +417,7 @@
677 rev.inv_sha1 = builder.inv_sha1
678 config = builder._config_stack
679 builder.repository.add_revision(builder._new_revision_id, rev,
680- builder.new_inventory)
681+ builder.revision_tree().root_inventory)
682 if self._graph is not None:
683 # TODO: Use StaticTuple and .intern() for these things
684 self._graph.add_node(builder._new_revision_id, rev.parent_ids)
685
686=== modified file 'breezy/repository.py'
687--- breezy/repository.py 2017-06-20 00:39:00 +0000
688+++ breezy/repository.py 2017-06-20 22:39:47 +0000
689@@ -74,8 +74,6 @@
690
691 # all clients should supply tree roots.
692 record_root_entry = True
693- # whether this commit builder supports the record_entry_contents interface
694- supports_record_entry_contents = False
695 # whether this commit builder will automatically update the branch that is
696 # being committed to
697 updates_branch = False
698
699=== modified file 'breezy/tests/per_repository/test_commit_builder.py'
700--- breezy/tests/per_repository/test_commit_builder.py 2017-06-20 00:51:07 +0000
701+++ breezy/tests/per_repository/test_commit_builder.py 2017-06-20 22:39:47 +0000
702@@ -47,34 +47,6 @@
703 branch.repository.commit_write_group()
704 branch.repository.unlock()
705
706- def record_root(self, builder, tree):
707- if builder.record_root_entry is True:
708- tree.lock_read()
709- try:
710- ie = tree.root_inventory.root
711- finally:
712- tree.unlock()
713- parent_tree = tree.branch.repository.revision_tree(
714- _mod_revision.NULL_REVISION)
715- parent_invs = []
716- builder.record_entry_contents(ie, parent_invs, '', tree,
717- tree.path_content_summary(''))
718-
719- def test_finish_inventory_with_record_root(self):
720- tree = self.make_branch_and_tree(".")
721- tree.lock_write()
722- try:
723- builder = tree.branch.get_commit_builder([])
724- if not builder.supports_record_entry_contents:
725- raise tests.TestNotApplicable("CommitBuilder doesn't support "
726- "record_entry_contents")
727- repo = tree.branch.repository
728- self.record_root(builder, tree)
729- builder.finish_inventory()
730- repo.commit_write_group()
731- finally:
732- tree.unlock()
733-
734 def test_finish_inventory_record_iter_changes(self):
735 tree = self.make_branch_and_tree(".")
736 tree.lock_write()
737@@ -92,20 +64,6 @@
738 finally:
739 tree.unlock()
740
741- def test_abort_record_entry_contents(self):
742- tree = self.make_branch_and_tree(".")
743- tree.lock_write()
744- try:
745- builder = tree.branch.get_commit_builder([])
746- if not builder.supports_record_entry_contents:
747- raise tests.TestNotApplicable("CommitBuilder doesn't support "
748- "record_entry_contents")
749- self.record_root(builder, tree)
750- builder.finish_inventory()
751- builder.abort()
752- finally:
753- tree.unlock()
754-
755 def test_abort_record_iter_changes(self):
756 tree = self.make_branch_and_tree(".")
757 tree.lock_write()
758@@ -165,41 +123,6 @@
759 actually_updated_branch = (tree.branch.last_revision() == rev_id)
760 self.assertEqual(actually_updated_branch, will_update_branch)
761
762- def test_commit_with_revision_id_record_entry_contents(self):
763- tree = self.make_branch_and_tree(".")
764- tree.lock_write()
765- try:
766- # use a unicode revision id to test more corner cases.
767- # The repository layer is meant to handle this.
768- revision_id = u'\xc8abc'.encode('utf8')
769- try:
770- try:
771- builder = tree.branch.get_commit_builder([],
772- revision_id=revision_id)
773- except errors.NonAsciiRevisionId:
774- revision_id = 'abc'
775- builder = tree.branch.get_commit_builder([],
776- revision_id=revision_id)
777- except errors.CannotSetRevisionId:
778- # This format doesn't support supplied revision ids
779- return
780- if not builder.supports_record_entry_contents:
781- raise tests.TestNotApplicable("CommitBuilder doesn't support "
782- "record_entry_contents")
783- self.assertFalse(builder.random_revid)
784- self.record_root(builder, tree)
785- builder.finish_inventory()
786- self.assertEqual(revision_id, builder.commit('foo bar'))
787- finally:
788- tree.unlock()
789- self.assertTrue(tree.branch.repository.has_revision(revision_id))
790- # the revision id must be set on the inventory when saving it. This
791- # does not precisely test that - a repository that wants to can add it
792- # on deserialisation, but thats all the current contract guarantees
793- # anyway.
794- self.assertEqual(revision_id,
795- tree.branch.repository.get_inventory(revision_id).revision_id)
796-
797 def test_commit_with_revision_id_record_iter_changes(self):
798 tree = self.make_branch_and_tree(".")
799 tree.lock_write()
800@@ -256,64 +179,6 @@
801 finally:
802 tree.unlock()
803
804- def test_commit_without_root_or_record_iter_changes_errors(self):
805- tree = self.make_branch_and_tree(".")
806- tree.lock_write()
807- try:
808- self.build_tree(['foo'])
809- tree.add('foo', 'foo-id')
810- builder = tree.branch.get_commit_builder([])
811- if not builder.supports_record_entry_contents:
812- raise tests.TestNotApplicable("CommitBuilder doesn't support "
813- "record_entry_contents")
814- entry = tree.root_inventory['foo-id']
815- self.assertRaises(errors.RootMissing,
816- builder.record_entry_contents, entry, [], 'foo', tree,
817- tree.path_content_summary('foo'))
818- builder.abort()
819- finally:
820- tree.unlock()
821-
822- def test_commit_unchanged_root_record_entry_contents(self):
823- tree = self.make_branch_and_tree(".")
824- old_revision_id = tree.commit('')
825- tree.lock_write()
826- parent_tree = tree.basis_tree()
827- parent_tree.lock_read()
828- self.addCleanup(parent_tree.unlock)
829- builder = tree.branch.get_commit_builder([old_revision_id])
830- try:
831- if not builder.supports_record_entry_contents:
832- raise tests.TestNotApplicable("CommitBuilder doesn't support "
833- "record_entry_contents")
834- ie = inventory.make_entry('directory', '', None,
835- tree.get_root_id())
836- delta, version_recorded, fs_hash = builder.record_entry_contents(
837- ie, [parent_tree.root_inventory], '', tree,
838- tree.path_content_summary(''))
839- # Regardless of repository root behaviour we should consider this a
840- # pointless commit.
841- self.assertFalse(builder.any_changes())
842- self.assertFalse(version_recorded)
843- # if the repository format recorded a new root revision, that
844- # should be in the delta
845- got_new_revision = ie.revision != old_revision_id
846- if got_new_revision:
847- self.assertEqual(('', '', ie.file_id, ie), delta)
848- # The delta should be tracked
849- self.assertEqual(delta, builder.get_basis_delta()[-1])
850- else:
851- self.assertEqual(None, delta)
852- # Directories do not get hashed.
853- self.assertEqual(None, fs_hash)
854- builder.abort()
855- except:
856- builder.abort()
857- tree.unlock()
858- raise
859- else:
860- tree.unlock()
861-
862 def test_commit_unchanged_root_record_iter_changes(self):
863 tree = self.make_branch_and_tree(".")
864 old_revision_id = tree.commit('')
865@@ -338,105 +203,6 @@
866 finally:
867 tree.unlock()
868
869- def test_commit_record_entry_contents(self):
870- tree = self.make_branch_and_tree(".")
871- tree.lock_write()
872- try:
873- builder = tree.branch.get_commit_builder([])
874- if not builder.supports_record_entry_contents:
875- raise tests.TestNotApplicable("CommitBuilder doesn't "
876- "support record_entry_contents")
877- self.record_root(builder, tree)
878- builder.finish_inventory()
879- rev_id = builder.commit('foo bar')
880- finally:
881- tree.unlock()
882- self.assertNotEqual(None, rev_id)
883- self.assertTrue(tree.branch.repository.has_revision(rev_id))
884- # the revision id must be set on the inventory when saving it. This does not
885- # precisely test that - a repository that wants to can add it on deserialisation,
886- # but thats all the current contract guarantees anyway.
887- self.assertEqual(rev_id, tree.branch.repository.get_inventory(rev_id).revision_id)
888-
889- def test_get_basis_delta(self):
890- tree = self.make_branch_and_tree(".")
891- self.build_tree(["foo"])
892- tree.add(["foo"], ["foo-id"])
893- old_revision_id = tree.commit("added foo")
894- tree.lock_write()
895- try:
896- self.build_tree(['bar'])
897- tree.add(['bar'], ['bar-id'])
898- basis = tree.branch.repository.revision_tree(old_revision_id)
899- basis.lock_read()
900- self.addCleanup(basis.unlock)
901- builder = tree.branch.get_commit_builder([old_revision_id])
902- total_delta = []
903- try:
904- if not builder.supports_record_entry_contents:
905- raise tests.TestNotApplicable("CommitBuilder doesn't "
906- "support record_entry_contents")
907- parent_invs = [basis.root_inventory]
908- if builder.record_root_entry:
909- ie = basis.root_inventory.root.copy()
910- delta, _, _ = builder.record_entry_contents(ie, parent_invs,
911- '', tree, tree.path_content_summary(''))
912- if delta is not None:
913- total_delta.append(delta)
914- delta = builder.record_delete("foo", "foo-id")
915- total_delta.append(delta)
916- new_bar = inventory.make_entry('file', 'bar',
917- parent_id=tree.get_root_id(), file_id='bar-id')
918- delta, _, _ = builder.record_entry_contents(new_bar, parent_invs,
919- 'bar', tree, tree.path_content_summary('bar'))
920- total_delta.append(delta)
921- # All actions should have been recorded in the basis_delta
922- self.assertEqual(total_delta, builder.get_basis_delta())
923- builder.finish_inventory()
924- builder.commit('delete foo, add bar')
925- except:
926- tree.branch.repository.abort_write_group()
927- raise
928- finally:
929- tree.unlock()
930-
931- def test_record_delete(self):
932- tree = self.make_branch_and_tree(".")
933- self.build_tree(["foo"])
934- tree.add(["foo"], ["foo-id"])
935- rev_id = tree.commit("added foo")
936- # Remove the inventory details for foo-id, because
937- # record_entry_contents ends up copying root verbatim.
938- tree.unversion(["foo-id"])
939- tree.lock_write()
940- try:
941- basis = tree.branch.repository.revision_tree(rev_id)
942- builder = tree.branch.get_commit_builder([rev_id])
943- try:
944- if not builder.supports_record_entry_contents:
945- raise tests.TestNotApplicable("CommitBuilder doesn't "
946- "support record_entry_contents")
947- if builder.record_root_entry is True:
948- parent_invs = [basis.root_inventory]
949- del basis.root_inventory.root.children['foo']
950- builder.record_entry_contents(basis.root_inventory.root,
951- parent_invs, '', tree, tree.path_content_summary(''))
952- # the delta should be returned, and recorded in _basis_delta
953- delta = builder.record_delete("foo", "foo-id")
954- self.assertEqual(("foo", None, "foo-id", None), delta)
955- self.assertEqual(delta, builder.get_basis_delta()[-1])
956- builder.finish_inventory()
957- rev_id2 = builder.commit('delete foo')
958- except:
959- tree.branch.repository.abort_write_group()
960- raise
961- finally:
962- tree.unlock()
963- rev_tree = builder.revision_tree()
964- rev_tree.lock_read()
965- self.addCleanup(rev_tree.unlock)
966- self.assertFalse(rev_tree.path2id('foo'))
967-
968 def test_record_delete_record_iter_changes(self):
969 tree = self.make_branch_and_tree(".")
970 self.build_tree(["foo"])
971@@ -466,44 +232,6 @@
972 self.addCleanup(rev_tree.unlock)
973 self.assertFalse(rev_tree.path2id('foo'))
974
975- def test_record_delete_without_notification(self):
976- tree = self.make_branch_and_tree(".")
977- self.build_tree(["foo"])
978- tree.add(["foo"], ["foo-id"])
979- rev_id = tree.commit("added foo")
980- tree.lock_write()
981- try:
982- builder = tree.branch.get_commit_builder([rev_id])
983- try:
984- if not builder.supports_record_entry_contents:
985- raise tests.TestNotApplicable("CommitBuilder doesn't "
986- "support record_entry_contents")
987- self.record_root(builder, tree)
988- builder.record_delete("foo", "foo-id")
989- finally:
990- tree.branch.repository.abort_write_group()
991- finally:
992- tree.unlock()
993-
994- def test_revision_tree_record_entry_contents(self):
995- tree = self.make_branch_and_tree(".")
996- tree.lock_write()
997- try:
998- builder = tree.branch.get_commit_builder([])
999- if not builder.supports_record_entry_contents:
1000- raise tests.TestNotApplicable("CommitBuilder doesn't "
1001- "support record_entry_contents")
1002- self.record_root(builder, tree)
1003- builder.finish_inventory()
1004- rev_id = builder.commit('foo bar')
1005- finally:
1006- tree.unlock()
1007- rev_tree = builder.revision_tree()
1008- # Just a couple simple tests to ensure that it actually follows
1009- # the RevisionTree api.
1010- self.assertEqual(rev_id, rev_tree.get_revision_id())
1011- self.assertEqual([], rev_tree.get_parent_ids())
1012-
1013 def test_revision_tree_record_iter_changes(self):
1014 tree = self.make_branch_and_tree(".")
1015 tree.lock_write()
1016@@ -573,8 +301,6 @@
1017
1018 def _commit_check_unchanged(self, tree, name, file_id, mini_commit=None):
1019 rev1 = tree.commit('')
1020- if mini_commit is None:
1021- mini_commit = self.mini_commit
1022 rev2 = mini_commit(tree, name, name, False, False)
1023 tree1, tree2 = self._get_revtrees(tree, [rev1, rev2])
1024 self.assertEqual(rev1, tree1.get_file_revision(file_id))
1025@@ -587,12 +313,6 @@
1026 # committing without changing a dir does not change the last modified.
1027 tree = self.make_branch_and_tree('.')
1028 self.build_tree(['dir/'])
1029- self._add_commit_check_unchanged(tree, 'dir')
1030-
1031- def test_last_modified_revision_after_commit_dir_unchanged_ric(self):
1032- # committing without changing a dir does not change the last modified.
1033- tree = self.make_branch_and_tree('.')
1034- self.build_tree(['dir/'])
1035 self._add_commit_check_unchanged(tree, 'dir',
1036 mini_commit=self.mini_commit_record_iter_changes)
1037
1038@@ -618,12 +338,6 @@
1039 # committing without changing a file does not change the last modified.
1040 tree = self.make_branch_and_tree('.')
1041 self.build_tree(['file'])
1042- self._add_commit_check_unchanged(tree, 'file')
1043-
1044- def test_last_modified_revision_after_commit_file_unchanged_ric(self):
1045- # committing without changing a file does not change the last modified.
1046- tree = self.make_branch_and_tree('.')
1047- self.build_tree(['file'])
1048 self._add_commit_check_unchanged(tree, 'file',
1049 mini_commit=self.mini_commit_record_iter_changes)
1050
1051@@ -632,13 +346,6 @@
1052 self.requireFeature(features.SymlinkFeature)
1053 tree = self.make_branch_and_tree('.')
1054 os.symlink('target', 'link')
1055- self._add_commit_check_unchanged(tree, 'link')
1056-
1057- def test_last_modified_revision_after_commit_link_unchanged_ric(self):
1058- # committing without changing a link does not change the last modified.
1059- self.requireFeature(features.SymlinkFeature)
1060- tree = self.make_branch_and_tree('.')
1061- os.symlink('target', 'link')
1062 self._add_commit_check_unchanged(tree, 'link',
1063 mini_commit=self.mini_commit_record_iter_changes)
1064
1065@@ -650,18 +357,6 @@
1066 try:
1067 tree.add_reference(subtree)
1068 self._commit_check_unchanged(tree, 'reference',
1069- subtree.get_root_id())
1070- except errors.UnsupportedOperation:
1071- return
1072-
1073- def test_last_modified_revision_after_commit_reference_unchanged_ric(self):
1074- # committing without changing a subtree does not change the last
1075- # modified.
1076- tree = self.make_branch_and_tree('.')
1077- subtree = self.make_reference('reference')
1078- try:
1079- tree.add_reference(subtree)
1080- self._commit_check_unchanged(tree, 'reference',
1081 subtree.get_root_id(),
1082 mini_commit=self.mini_commit_record_iter_changes)
1083 except errors.UnsupportedOperation:
1084@@ -685,12 +380,6 @@
1085 # renaming a dir changes the last modified.
1086 tree = self.make_branch_and_tree('.')
1087 self.build_tree(['dir/'])
1088- self._add_commit_renamed_check_changed(tree, 'dir')
1089-
1090- def test_last_modified_revision_after_rename_dir_changes_ric(self):
1091- # renaming a dir changes the last modified.
1092- tree = self.make_branch_and_tree('.')
1093- self.build_tree(['dir/'])
1094 self._add_commit_renamed_check_changed(tree, 'dir',
1095 mini_commit=self.mini_commit_record_iter_changes)
1096
1097@@ -699,13 +388,6 @@
1098 tree = self.make_branch_and_tree('.')
1099 self.build_tree(['file'])
1100 self._add_commit_renamed_check_changed(tree, 'file',
1101- expect_fs_hash=True)
1102-
1103- def test_last_modified_revision_after_rename_file_changes_ric(self):
1104- # renaming a file changes the last modified.
1105- tree = self.make_branch_and_tree('.')
1106- self.build_tree(['file'])
1107- self._add_commit_renamed_check_changed(tree, 'file',
1108 expect_fs_hash=True,
1109 mini_commit=self.mini_commit_record_iter_changes)
1110
1111@@ -714,13 +396,6 @@
1112 self.requireFeature(features.SymlinkFeature)
1113 tree = self.make_branch_and_tree('.')
1114 os.symlink('target', 'link')
1115- self._add_commit_renamed_check_changed(tree, 'link')
1116-
1117- def test_last_modified_revision_after_rename_link_changes_ric(self):
1118- # renaming a link changes the last modified.
1119- self.requireFeature(features.SymlinkFeature)
1120- tree = self.make_branch_and_tree('.')
1121- os.symlink('target', 'link')
1122 self._add_commit_renamed_check_changed(tree, 'link',
1123 mini_commit=self.mini_commit_record_iter_changes)
1124
1125@@ -731,17 +406,6 @@
1126 try:
1127 tree.add_reference(subtree)
1128 self._commit_renamed_check_changed(tree, 'reference',
1129- subtree.get_root_id())
1130- except errors.UnsupportedOperation:
1131- return
1132-
1133- def test_last_modified_revision_after_rename_ref_changes_ric(self):
1134- # renaming a reference changes the last modified.
1135- tree = self.make_branch_and_tree('.')
1136- subtree = self.make_reference('reference')
1137- try:
1138- tree.add_reference(subtree)
1139- self._commit_renamed_check_changed(tree, 'reference',
1140 subtree.get_root_id(),
1141 mini_commit=self.mini_commit_record_iter_changes)
1142 except errors.UnsupportedOperation:
1143@@ -760,12 +424,6 @@
1144 # reparenting a dir changes the last modified.
1145 tree = self.make_branch_and_tree('.')
1146 self.build_tree(['dir/'])
1147- self._add_commit_reparent_check_changed(tree, 'dir')
1148-
1149- def test_last_modified_revision_after_reparent_dir_changes_ric(self):
1150- # reparenting a dir changes the last modified.
1151- tree = self.make_branch_and_tree('.')
1152- self.build_tree(['dir/'])
1153 self._add_commit_reparent_check_changed(tree, 'dir',
1154 mini_commit=self.mini_commit_record_iter_changes)
1155
1156@@ -774,13 +432,6 @@
1157 tree = self.make_branch_and_tree('.')
1158 self.build_tree(['file'])
1159 self._add_commit_reparent_check_changed(tree, 'file',
1160- expect_fs_hash=True)
1161-
1162- def test_last_modified_revision_after_reparent_file_changes_ric(self):
1163- # reparenting a file changes the last modified.
1164- tree = self.make_branch_and_tree('.')
1165- self.build_tree(['file'])
1166- self._add_commit_reparent_check_changed(tree, 'file',
1167 expect_fs_hash=True,
1168 mini_commit=self.mini_commit_record_iter_changes)
1169
1170@@ -789,13 +440,6 @@
1171 self.requireFeature(features.SymlinkFeature)
1172 tree = self.make_branch_and_tree('.')
1173 os.symlink('target', 'link')
1174- self._add_commit_reparent_check_changed(tree, 'link')
1175-
1176- def test_last_modified_revision_after_reparent_link_changes_ric(self):
1177- # reparenting a link changes the last modified.
1178- self.requireFeature(features.SymlinkFeature)
1179- tree = self.make_branch_and_tree('.')
1180- os.symlink('target', 'link')
1181 self._add_commit_reparent_check_changed(tree, 'link',
1182 mini_commit=self.mini_commit_record_iter_changes)
1183
1184@@ -812,8 +456,6 @@
1185 expect_fs_hash=False, mini_commit=None):
1186 rev1 = tree.commit('')
1187 changer()
1188- if mini_commit is None:
1189- mini_commit = self.mini_commit
1190 rev2 = mini_commit(tree, name, tree.id2path(file_id),
1191 expect_fs_hash=expect_fs_hash)
1192 tree1, tree2 = self._get_revtrees(tree, [rev1, rev2])
1193@@ -824,97 +466,6 @@
1194 expected_graph[(file_id, rev2)] = ((file_id, rev1),)
1195 self.assertFileGraph(expected_graph, tree, (file_id, rev2))
1196
1197- def mini_commit(self, tree, name, new_name, records_version=True,
1198- delta_against_basis=True, expect_fs_hash=False):
1199- """Perform a miniature commit looking for record entry results.
1200-
1201- :param tree: The tree to commit.
1202- :param name: The path in the basis tree of the tree being committed.
1203- :param new_name: The path in the tree being committed.
1204- :param records_version: True if the commit of new_name is expected to
1205- record a new version.
1206- :param delta_against_basis: True of the commit of new_name is expected
1207- to have a delta against the basis.
1208- :param expect_fs_hash: True or false to indicate whether we expect a
1209- file hash to be returned from the record_entry_contents call.
1210- """
1211- tree.lock_write()
1212- try:
1213- # mini manual commit here so we can check the return of
1214- # record_entry_contents.
1215- parent_ids = tree.get_parent_ids()
1216- builder = tree.branch.get_commit_builder(parent_ids)
1217- try:
1218- if not builder.supports_record_entry_contents:
1219- raise tests.TestNotApplicable("CommitBuilder doesn't "
1220- "support record_entry_contents")
1221- parent_tree = tree.basis_tree()
1222- parent_tree.lock_read()
1223- self.addCleanup(parent_tree.unlock)
1224- parent_invs = [parent_tree.root_inventory]
1225- for parent_id in parent_ids[1:]:
1226- parent_invs.append(tree.branch.repository.revision_tree(
1227- parent_id).root_inventory)
1228- # root
1229- builder.record_entry_contents(
1230- inventory.make_entry('directory', '', None,
1231- tree.get_root_id()), parent_invs, '', tree,
1232- tree.path_content_summary(''))
1233- def commit_id(file_id):
1234- old_ie = tree.root_inventory[file_id]
1235- path = tree.id2path(file_id)
1236- ie = inventory.make_entry(tree.kind(file_id), old_ie.name,
1237- old_ie.parent_id, file_id)
1238- content_summary = tree.path_content_summary(path)
1239- if content_summary[0] == 'tree-reference':
1240- content_summary = content_summary[:3] + (
1241- tree.get_reference_revision(file_id),)
1242- return builder.record_entry_contents(ie, parent_invs, path,
1243- tree, content_summary)
1244-
1245- file_id = tree.path2id(new_name)
1246- parent_id = tree.root_inventory[file_id].parent_id
1247- if parent_id != tree.get_root_id():
1248- commit_id(parent_id)
1249- # because a change of some sort is meant to have occurred,
1250- # recording the entry must return True.
1251- delta, version_recorded, fs_hash = commit_id(file_id)
1252- if records_version:
1253- self.assertTrue(version_recorded)
1254- else:
1255- self.assertFalse(version_recorded)
1256- if expect_fs_hash:
1257- tree_file_stat = tree.get_file_with_stat(file_id)
1258- tree_file_stat[0].close()
1259- self.assertEqual(2, len(fs_hash))
1260- self.assertEqual(tree.get_file_sha1(file_id), fs_hash[0])
1261- self.assertEqualStat(tree_file_stat[1], fs_hash[1])
1262- else:
1263- self.assertEqual(None, fs_hash)
1264- new_entry = builder.new_inventory[file_id]
1265- if delta_against_basis:
1266- expected_delta = (name, new_name, file_id, new_entry)
1267- # The delta should be recorded
1268- self.assertEqual(expected_delta,
1269- builder.get_basis_delta()[-1])
1270- else:
1271- expected_delta = None
1272- self.assertEqual(expected_delta, delta)
1273- builder.finish_inventory()
1274- except:
1275- builder.abort()
1276- raise
1277- else:
1278- rev2 = builder.commit('')
1279- except:
1280- tree.unlock()
1281- raise
1282- try:
1283- tree.set_parent_ids([rev2])
1284- finally:
1285- tree.unlock()
1286- return rev2
1287-
1288 def mini_commit_record_iter_changes(self, tree, name, new_name,
1289 records_version=True, delta_against_basis=True, expect_fs_hash=False):
1290 """Perform a miniature commit looking for record entry results.
1291@@ -934,7 +485,7 @@
1292 tree.lock_write()
1293 try:
1294 # mini manual commit here so we can check the return of
1295- # record_entry_contents.
1296+ # record_iter_changes
1297 parent_ids = tree.get_parent_ids()
1298 builder = tree.branch.get_commit_builder(parent_ids)
1299 parent_tree = tree.basis_tree()
1300@@ -958,14 +509,12 @@
1301 self.assertEqualStat(result[2][1], tree_file_stat[1])
1302 else:
1303 self.assertEqual([], result)
1304- self.assertIs(None, builder.new_inventory)
1305 builder.finish_inventory()
1306 if tree.branch.repository._format.supports_full_versioned_files:
1307 inv_key = (builder._new_revision_id,)
1308 inv_sha1 = tree.branch.repository.inventories.get_sha1s(
1309 [inv_key])[inv_key]
1310 self.assertEqual(inv_sha1, builder.inv_sha1)
1311- self.assertIs(None, builder.new_inventory)
1312 rev2 = builder.commit('')
1313 delta = builder.get_basis_delta()
1314 delta_dict = dict((change[2], change) for change in delta)
1315@@ -1009,29 +558,10 @@
1316 def change_file():
1317 tree.put_file_bytes_non_atomic('fileid', 'new content')
1318 self._add_commit_change_check_changed(tree, 'file', change_file,
1319- expect_fs_hash=True)
1320-
1321- def test_last_modified_revision_after_content_file_changes_ric(self):
1322- # altering a file changes the last modified.
1323- tree = self.make_branch_and_tree('.')
1324- self.build_tree(['file'])
1325- def change_file():
1326- tree.put_file_bytes_non_atomic('fileid', 'new content')
1327- self._add_commit_change_check_changed(tree, 'file', change_file,
1328 expect_fs_hash=True,
1329 mini_commit=self.mini_commit_record_iter_changes)
1330
1331- def test_last_modified_revision_after_content_link_changes(self):
1332- # changing a link changes the last modified.
1333- self.requireFeature(features.SymlinkFeature)
1334- tree = self.make_branch_and_tree('.')
1335- os.symlink('target', 'link')
1336- def change_link():
1337- os.unlink('link')
1338- os.symlink('newtarget', 'link')
1339- self._add_commit_change_check_changed(tree, 'link', change_link)
1340-
1341- def _test_last_mod_rev_after_content_link_changes_ric(
1342+ def _test_last_mod_rev_after_content_link_changes(
1343 self, link, target, newtarget, file_id=None):
1344 if file_id is None:
1345 file_id = link
1346@@ -1047,13 +577,13 @@
1347 mini_commit=self.mini_commit_record_iter_changes,
1348 file_id=file_id)
1349
1350- def test_last_modified_rev_after_content_link_changes_ric(self):
1351- self._test_last_mod_rev_after_content_link_changes_ric(
1352+ def test_last_modified_rev_after_content_link_changes(self):
1353+ self._test_last_mod_rev_after_content_link_changes(
1354 'link', 'target', 'newtarget')
1355
1356- def test_last_modified_rev_after_content_unicode_link_changes_ric(self):
1357+ def test_last_modified_rev_after_content_unicode_link_changes(self):
1358 self.requireFeature(features.UnicodeFilenameFeature)
1359- self._test_last_mod_rev_after_content_link_changes_ric(
1360+ self._test_last_mod_rev_after_content_link_changes(
1361 u'li\u1234nk', u'targ\N{Euro Sign}t', u'n\N{Euro Sign}wtarget',
1362
1363 file_id=u'li\u1234nk'.encode('UTF-8'))
1364@@ -1075,8 +605,6 @@
1365 rev2 = self._rename_in_tree(tree1, name)
1366 rev3 = self._rename_in_tree(tree2, name)
1367 tree1.merge_from_branch(tree2.branch)
1368- if mini_commit is None:
1369- mini_commit = self.mini_commit
1370 rev4 = mini_commit(tree1, 'new_' + name, 'new_' + name,
1371 expect_fs_hash=expect_fs_hash)
1372 tree3, = self._get_revtrees(tree1, [rev4])
1373@@ -1093,12 +621,6 @@
1374 # merge a dir changes the last modified.
1375 tree1 = self.make_branch_and_tree('t1')
1376 self.build_tree(['t1/dir/'])
1377- self._commit_sprout_rename_merge(tree1, 'dir')
1378-
1379- def test_last_modified_revision_after_merge_dir_changes_ric(self):
1380- # merge a dir changes the last modified.
1381- tree1 = self.make_branch_and_tree('t1')
1382- self.build_tree(['t1/dir/'])
1383 self._commit_sprout_rename_merge(tree1, 'dir',
1384 mini_commit=self.mini_commit_record_iter_changes)
1385
1386@@ -1106,12 +628,6 @@
1387 # merge a file changes the last modified.
1388 tree1 = self.make_branch_and_tree('t1')
1389 self.build_tree(['t1/file'])
1390- self._commit_sprout_rename_merge(tree1, 'file', expect_fs_hash=True)
1391-
1392- def test_last_modified_revision_after_merge_file_changes_ric(self):
1393- # merge a file changes the last modified.
1394- tree1 = self.make_branch_and_tree('t1')
1395- self.build_tree(['t1/file'])
1396 self._commit_sprout_rename_merge(tree1, 'file', expect_fs_hash=True,
1397 mini_commit=self.mini_commit_record_iter_changes)
1398
1399@@ -1120,13 +636,6 @@
1400 self.requireFeature(features.SymlinkFeature)
1401 tree1 = self.make_branch_and_tree('t1')
1402 os.symlink('target', 't1/link')
1403- self._commit_sprout_rename_merge(tree1, 'link')
1404-
1405- def test_last_modified_revision_after_merge_link_changes_ric(self):
1406- # merge a link changes the last modified.
1407- self.requireFeature(features.SymlinkFeature)
1408- tree1 = self.make_branch_and_tree('t1')
1409- os.symlink('target', 't1/link')
1410 self._commit_sprout_rename_merge(tree1, 'link',
1411 mini_commit=self.mini_commit_record_iter_changes)
1412
1413@@ -1140,8 +649,6 @@
1414 # change on the other side to merge back
1415 rev2 = self._rename_in_tree(tree2, name)
1416 tree1.merge_from_branch(tree2.branch)
1417- if mini_commit is None:
1418- mini_commit = self.mini_commit
1419 def _check_graph(in_tree, changed_in_tree):
1420 rev3 = mini_commit(in_tree, name, 'new_' + name, False,
1421 delta_against_basis=changed_in_tree)
1422@@ -1173,8 +680,6 @@
1423 tree2.add(['name'], [file_id])
1424 rev2 = tree2.commit('')
1425 tree1.merge_from_branch(tree2.branch)
1426- if mini_commit is None:
1427- mini_commit = self.mini_commit
1428 rev3 = mini_commit(tree1, None, 'name', False)
1429 tree3, = self._get_revtrees(tree1, [rev2])
1430 # in rev2, name should be only changed in rev2
1431@@ -1187,12 +692,6 @@
1432 # merge a dir that changed preserves the last modified.
1433 tree1 = self.make_branch_and_tree('t1')
1434 self.build_tree(['t1/dir/'])
1435- self._commit_sprout_rename_merge_converged(tree1, 'dir')
1436-
1437- def test_last_modified_revision_after_converged_merge_dir_unchanged_ric(self):
1438- # merge a dir that changed preserves the last modified.
1439- tree1 = self.make_branch_and_tree('t1')
1440- self.build_tree(['t1/dir/'])
1441 self._commit_sprout_rename_merge_converged(tree1, 'dir',
1442 mini_commit=self.mini_commit_record_iter_changes)
1443
1444@@ -1200,12 +699,6 @@
1445 # merge a file that changed preserves the last modified.
1446 tree1 = self.make_branch_and_tree('t1')
1447 self.build_tree(['t1/file'])
1448- self._commit_sprout_rename_merge_converged(tree1, 'file')
1449-
1450- def test_last_modified_revision_after_converged_merge_file_unchanged_ric(self):
1451- # merge a file that changed preserves the last modified.
1452- tree1 = self.make_branch_and_tree('t1')
1453- self.build_tree(['t1/file'])
1454 self._commit_sprout_rename_merge_converged(tree1, 'file',
1455 mini_commit=self.mini_commit_record_iter_changes)
1456
1457@@ -1214,46 +707,24 @@
1458 self.requireFeature(features.SymlinkFeature)
1459 tree1 = self.make_branch_and_tree('t1')
1460 os.symlink('target', 't1/link')
1461- self._commit_sprout_rename_merge_converged(tree1, 'link')
1462-
1463- def test_last_modified_revision_after_converged_merge_link_unchanged_ric(self):
1464- # merge a link that changed preserves the last modified.
1465- self.requireFeature(features.SymlinkFeature)
1466- tree1 = self.make_branch_and_tree('t1')
1467- os.symlink('target', 't1/link')
1468 self._commit_sprout_rename_merge_converged(tree1, 'link',
1469 mini_commit=self.mini_commit_record_iter_changes)
1470
1471 def test_last_modified_revision_after_merge_new_dir_unchanged(self):
1472 # merge a new dir does not change the last modified.
1473 tree1 = self.make_branch_and_tree('t1')
1474- self._commit_sprout_make_merge(tree1, self.make_dir)
1475-
1476- def test_last_modified_revision_after_merge_new_dir_unchanged_ric(self):
1477- # merge a new dir does not change the last modified.
1478- tree1 = self.make_branch_and_tree('t1')
1479 self._commit_sprout_make_merge(tree1, self.make_dir,
1480 mini_commit=self.mini_commit_record_iter_changes)
1481
1482 def test_last_modified_revision_after_merge_new_file_unchanged(self):
1483 # merge a new file does not change the last modified.
1484 tree1 = self.make_branch_and_tree('t1')
1485- self._commit_sprout_make_merge(tree1, self.make_file)
1486-
1487- def test_last_modified_revision_after_merge_new_file_unchanged_ric(self):
1488- # merge a new file does not change the last modified.
1489- tree1 = self.make_branch_and_tree('t1')
1490 self._commit_sprout_make_merge(tree1, self.make_file,
1491 mini_commit=self.mini_commit_record_iter_changes)
1492
1493 def test_last_modified_revision_after_merge_new_link_unchanged(self):
1494 # merge a new link does not change the last modified.
1495 tree1 = self.make_branch_and_tree('t1')
1496- self._commit_sprout_make_merge(tree1, self.make_link)
1497-
1498- def test_last_modified_revision_after_merge_new_link_unchanged_ric(self):
1499- # merge a new link does not change the last modified.
1500- tree1 = self.make_branch_and_tree('t1')
1501 self._commit_sprout_make_merge(tree1, self.make_link,
1502 mini_commit=self.mini_commit_record_iter_changes)
1503
1504@@ -1289,10 +760,6 @@
1505 expect_fs_hash=expect_fs_hash, mini_commit=mini_commit)
1506
1507 def test_last_modified_dir_file(self):
1508- self._check_kind_change(self.make_dir, self.make_file,
1509- expect_fs_hash=True)
1510-
1511- def test_last_modified_dir_file_ric(self):
1512 try:
1513 self._check_kind_change(self.make_dir, self.make_file,
1514 expect_fs_hash=True,
1515@@ -1303,9 +770,6 @@
1516 "directory to file")
1517
1518 def test_last_modified_dir_link(self):
1519- self._check_kind_change(self.make_dir, self.make_link)
1520-
1521- def test_last_modified_dir_link_ric(self):
1522 try:
1523 self._check_kind_change(self.make_dir, self.make_link,
1524 mini_commit=self.mini_commit_record_iter_changes)
1525@@ -1316,31 +780,18 @@
1526
1527 def test_last_modified_link_file(self):
1528 self._check_kind_change(self.make_link, self.make_file,
1529- expect_fs_hash=True)
1530-
1531- def test_last_modified_link_file_ric(self):
1532- self._check_kind_change(self.make_link, self.make_file,
1533 expect_fs_hash=True,
1534 mini_commit=self.mini_commit_record_iter_changes)
1535
1536 def test_last_modified_link_dir(self):
1537- self._check_kind_change(self.make_link, self.make_dir)
1538-
1539- def test_last_modified_link_dir_ric(self):
1540 self._check_kind_change(self.make_link, self.make_dir,
1541 mini_commit=self.mini_commit_record_iter_changes)
1542
1543 def test_last_modified_file_dir(self):
1544- self._check_kind_change(self.make_file, self.make_dir)
1545-
1546- def test_last_modified_file_dir_ric(self):
1547 self._check_kind_change(self.make_file, self.make_dir,
1548 mini_commit=self.mini_commit_record_iter_changes)
1549
1550 def test_last_modified_file_link(self):
1551- self._check_kind_change(self.make_file, self.make_link)
1552-
1553- def test_last_modified_file_link_ric(self):
1554 self._check_kind_change(self.make_file, self.make_link,
1555 mini_commit=self.mini_commit_record_iter_changes)
1556
1557
1558=== modified file 'breezy/tests/per_workingtree/test_commit.py'
1559--- breezy/tests/per_workingtree/test_commit.py 2017-06-10 00:17:06 +0000
1560+++ breezy/tests/per_workingtree/test_commit.py 2017-06-20 22:39:47 +0000
1561@@ -420,6 +420,7 @@
1562 if not tree.supports_tree_reference():
1563 # inapplicable test.
1564 return
1565+ self.knownFailure('nested trees don\'t work well with iter_changes')
1566 subtree = self.make_branch_and_tree('subtree')
1567 tree.add(['subtree'])
1568 self.build_tree(['subtree/file'])
1569
1570=== modified file 'breezy/tests/test_foreign.py'
1571--- breezy/tests/test_foreign.py 2017-06-10 16:40:42 +0000
1572+++ breezy/tests/test_foreign.py 2017-06-20 22:39:47 +0000
1573@@ -203,28 +203,24 @@
1574 parent_revids = []
1575 else:
1576 parent_revids = [parent_revid]
1577- builder = self.target.get_commit_builder(parent_revids,
1578+ builder = self.target.get_commit_builder(parent_revids,
1579 self.target.get_config_stack(), rev.timestamp,
1580 rev.timezone, rev.committer, rev.properties,
1581 new_revid)
1582 try:
1583 parent_tree = self.target.repository.revision_tree(
1584 parent_revid)
1585- for path, ie in tree.iter_entries_by_dir():
1586- new_ie = ie.copy()
1587- new_ie.revision = None
1588- builder.record_entry_contents(new_ie,
1589- [parent_tree.root_inventory],
1590- path, tree,
1591- (ie.kind, ie.text_size, ie.executable, ie.text_sha1))
1592+ iter_changes = tree.iter_changes(parent_tree)
1593+ list(builder.record_iter_changes(
1594+ tree, parent_revid, iter_changes))
1595 builder.finish_inventory()
1596 except:
1597 builder.abort()
1598 raise
1599 revidmap[revid] = builder.commit(rev.message)
1600- self.target.set_last_revision_info(parent_revno+1,
1601+ self.target.set_last_revision_info(parent_revno+1,
1602 revidmap[revid])
1603- trace.mutter('lossily pushed revision %s -> %s',
1604+ trace.mutter('lossily pushed revision %s -> %s',
1605 revid, revidmap[revid])
1606 finally:
1607 self.source.unlock()
1608
1609=== modified file 'breezy/tests/test_merge.py'
1610--- breezy/tests/test_merge.py 2017-06-10 16:40:42 +0000
1611+++ breezy/tests/test_merge.py 2017-06-20 22:39:47 +0000
1612@@ -226,6 +226,8 @@
1613 tree_a.conflicts())
1614
1615 def test_nested_merge(self):
1616+ self.knownFailure(
1617+ 'iter_changes doesn\'t work with changes in nested trees')
1618 tree = self.make_branch_and_tree('tree',
1619 format='development-subtree')
1620 sub_tree = self.make_branch_and_tree('tree/sub-tree',
1621
1622=== modified file 'doc/en/release-notes/brz-3.0.txt'
1623--- doc/en/release-notes/brz-3.0.txt 2017-06-19 14:35:58 +0000
1624+++ doc/en/release-notes/brz-3.0.txt 2017-06-20 22:39:47 +0000
1625@@ -121,6 +121,9 @@
1626 * All previously deprecated functionality has been removed.
1627 (Jelmer Vernooń≥)
1628
1629+ * ``CommitBuilder.record_entry_contents`` has been removed.
1630+ (Jelmer Vernooń≥, #731433, #604953)
1631+
1632 * Renamed ``breezy.delta.report_delta`` parameter ``filter=`` to
1633 ``predicate=``. (Martin Packman)
1634

Subscribers

People subscribed via source and target branches