Rev 2843: Merge bzr.dev. in http://people.ubuntu.com/~robertc/baz2.0/integration
Robert Collins
robertc at robertcollins.net
Fri Sep 21 08:08:47 BST 2007
At http://people.ubuntu.com/~robertc/baz2.0/integration
------------------------------------------------------------
revno: 2843
revision-id: robertc at robertcollins.net-20070921070831-53v2gzumoto1phf8
parent: robertc at robertcollins.net-20070921063509-7ohd4716ecor5d30
parent: pqm at pqm.ubuntu.com-20070921051316-85muv96iv0duh31j
committer: Robert Collins <robertc at robertcollins.net>
branch nick: integration
timestamp: Fri 2007-09-21 17:08:31 +1000
message:
Merge bzr.dev.
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
bzrlib/commit.py commit.py-20050511101309-79ec1a0168e0e825
bzrlib/dirstate.py dirstate.py-20060728012006-d6mvoihjb3je9peu-1
bzrlib/inventory.py inventory.py-20050309040759-6648b84ca2005b37
bzrlib/osutils.py osutils.py-20050309040759-eeaff12fbf77ac86
bzrlib/repository.py rev_storage.py-20051111201905-119e9401e46257e3
bzrlib/tests/inventory_implementations/basics.py basics.py-20070903044446-kdjwbiu1p1zi9phs-1
bzrlib/tests/repository_implementations/test_commit_builder.py test_commit_builder.py-20060606110838-76e3ra5slucqus81-1
bzrlib/tests/test_osutils.py test_osutils.py-20051201224856-e48ee24c12182989
bzrlib/tests/test_workingtree_4.py test_workingtree_4.p-20070223025758-531n3tznl3zacv2o-1
bzrlib/tests/workingtree_implementations/test_commit.py test_commit.py-20060421013633-1610ec2331c8190f
bzrlib/tests/workingtree_implementations/test_rename_one.py test_rename_one.py-20070226161242-2d8ibdedl700jgio-1
bzrlib/workingtree_4.py workingtree_4.py-20070208044105-5fgpc5j3ljlh5q6c-1
------------------------------------------------------------
revno: 2841.1.3
revision-id: pqm at pqm.ubuntu.com-20070921051316-85muv96iv0duh31j
parent: pqm at pqm.ubuntu.com-20070921031326-72zmv08871klgb61
parent: ian.clatworthy at internode.on.net-20070921042253-eguu8ycfjbnb96yj
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Fri 2007-09-21 06:13:16 +0100
message:
Faster partial commits by walking less data (Robert Collins)
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
bzrlib/commit.py commit.py-20050511101309-79ec1a0168e0e825
bzrlib/dirstate.py dirstate.py-20060728012006-d6mvoihjb3je9peu-1
bzrlib/inventory.py inventory.py-20050309040759-6648b84ca2005b37
bzrlib/osutils.py osutils.py-20050309040759-eeaff12fbf77ac86
bzrlib/tests/inventory_implementations/basics.py basics.py-20070903044446-kdjwbiu1p1zi9phs-1
bzrlib/tests/test_osutils.py test_osutils.py-20051201224856-e48ee24c12182989
bzrlib/workingtree_4.py workingtree_4.py-20070208044105-5fgpc5j3ljlh5q6c-1
------------------------------------------------------------
revno: 2841.1.2.1.1
revision-id: ian.clatworthy at internode.on.net-20070921042253-eguu8ycfjbnb96yj
parent: pqm at pqm.ubuntu.com-20070921031326-72zmv08871klgb61
parent: robertc at robertcollins.net-20070920070333-eedxrxidkignx4i1
committer: Ian Clatworthy <ian.clatworthy at internode.on.net>
branch nick: ianc-integration2
timestamp: Fri 2007-09-21 14:22:53 +1000
message:
Faster partial commits by walking less data (Robert Collins)
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
bzrlib/commit.py commit.py-20050511101309-79ec1a0168e0e825
bzrlib/dirstate.py dirstate.py-20060728012006-d6mvoihjb3je9peu-1
bzrlib/inventory.py inventory.py-20050309040759-6648b84ca2005b37
bzrlib/osutils.py osutils.py-20050309040759-eeaff12fbf77ac86
bzrlib/tests/inventory_implementations/basics.py basics.py-20070903044446-kdjwbiu1p1zi9phs-1
bzrlib/tests/test_osutils.py test_osutils.py-20051201224856-e48ee24c12182989
bzrlib/workingtree_4.py workingtree_4.py-20070208044105-5fgpc5j3ljlh5q6c-1
------------------------------------------------------------
revno: 2825.7.1
revision-id: robertc at robertcollins.net-20070920070333-eedxrxidkignx4i1
parent: pqm at pqm.ubuntu.com-20070917005035-cshdkpzbj63id1uw
committer: Robert Collins <robertc at robertcollins.net>
branch nick: commit-specific-file-handling
timestamp: Thu 2007-09-20 17:03:33 +1000
message:
* Partial commits are now approximately 40% faster by walking over the
unselected current tree more efficiently. (Robert Collins)
* New method ``bzrlib.osutils.minimum_path_selection`` useful for removing
duplication from user input, when a user mentions both a path and an item
contained within that path. (Robert Collins)
* New parameter yield_parents on ``Inventory.iter_entries_by_dir`` which
causes the parents of a selected id to be returned recursively, so all the
paths from the root down to each element of selected_file_ids are
returned. (Robert Collins)
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
bzrlib/commit.py commit.py-20050511101309-79ec1a0168e0e825
bzrlib/dirstate.py dirstate.py-20060728012006-d6mvoihjb3je9peu-1
bzrlib/inventory.py inventory.py-20050309040759-6648b84ca2005b37
bzrlib/osutils.py osutils.py-20050309040759-eeaff12fbf77ac86
bzrlib/tests/blackbox/test_commit.py test_commit.py-20060212094538-ae88fc861d969db0
bzrlib/tests/inventory_implementations/basics.py basics.py-20070903044446-kdjwbiu1p1zi9phs-1
bzrlib/tests/test_commit.py test_commit.py-20050914060732-279f057f8c295434
bzrlib/tests/test_osutils.py test_osutils.py-20051201224856-e48ee24c12182989
bzrlib/workingtree_4.py workingtree_4.py-20070208044105-5fgpc5j3ljlh5q6c-1
------------------------------------------------------------
revno: 2841.1.2
revision-id: pqm at pqm.ubuntu.com-20070921031326-72zmv08871klgb61
parent: pqm at pqm.ubuntu.com-20070921022023-cgeid5vrxco9o4jo
parent: ian.clatworthy at internode.on.net-20070921010021-mr4nx4o0vrvhwu4r
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Fri 2007-09-21 04:13:26 +0100
message:
Make WorkingTree.rename_one honour our normalisation requirements (Robert Collins)
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
bzrlib/dirstate.py dirstate.py-20060728012006-d6mvoihjb3je9peu-1
bzrlib/inventory.py inventory.py-20050309040759-6648b84ca2005b37
bzrlib/tests/test_workingtree_4.py test_workingtree_4.p-20070223025758-531n3tznl3zacv2o-1
bzrlib/tests/workingtree_implementations/test_rename_one.py test_rename_one.py-20070226161242-2d8ibdedl700jgio-1
------------------------------------------------------------
revno: 2841.2.1
revision-id: ian.clatworthy at internode.on.net-20070921010021-mr4nx4o0vrvhwu4r
parent: pqm at pqm.ubuntu.com-20070921005024-anlkzk5nrdtujta4
parent: robertc at robertcollins.net-20070917053356-05fyvmd1b3xalx6h
committer: Ian Clatworthy <ian.clatworthy at internode.on.net>
branch nick: ianc-integration2
timestamp: Fri 2007-09-21 11:00:21 +1000
message:
Make WorkingTree.rename_one honour our normalisation requirements (Robert Collins)
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
bzrlib/dirstate.py dirstate.py-20060728012006-d6mvoihjb3je9peu-1
bzrlib/inventory.py inventory.py-20050309040759-6648b84ca2005b37
bzrlib/tests/test_workingtree_4.py test_workingtree_4.p-20070223025758-531n3tznl3zacv2o-1
bzrlib/tests/workingtree_implementations/test_rename_one.py test_rename_one.py-20070226161242-2d8ibdedl700jgio-1
------------------------------------------------------------
revno: 2825.6.1
revision-id: robertc at robertcollins.net-20070917053356-05fyvmd1b3xalx6h
parent: pqm at pqm.ubuntu.com-20070917005035-cshdkpzbj63id1uw
committer: Robert Collins <robertc at robertcollins.net>
branch nick: rename_one
timestamp: Mon 2007-09-17 15:33:56 +1000
message:
* ``WorkingTree.rename_one`` will now raise an error if normalisation of the
new path causes bzr to be unable to access the file. (Robert Collins)
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
bzrlib/dirstate.py dirstate.py-20060728012006-d6mvoihjb3je9peu-1
bzrlib/inventory.py inventory.py-20050309040759-6648b84ca2005b37
bzrlib/tests/test_workingtree_4.py test_workingtree_4.p-20070223025758-531n3tznl3zacv2o-1
bzrlib/tests/workingtree_implementations/test_rename_one.py test_rename_one.py-20070226161242-2d8ibdedl700jgio-1
------------------------------------------------------------
revno: 2841.1.1
revision-id: pqm at pqm.ubuntu.com-20070921022023-cgeid5vrxco9o4jo
parent: pqm at pqm.ubuntu.com-20070921005024-anlkzk5nrdtujta4
parent: ian.clatworthy at internode.on.net-20070921002235-u5lbs3wog6na1qxg
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Fri 2007-09-21 03:20:23 +0100
message:
faster pointless commit detection (Robert Collins)
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
bzrlib/commit.py commit.py-20050511101309-79ec1a0168e0e825
bzrlib/inventory.py inventory.py-20050309040759-6648b84ca2005b37
bzrlib/repository.py rev_storage.py-20051111201905-119e9401e46257e3
bzrlib/tests/repository_implementations/test_commit_builder.py test_commit_builder.py-20060606110838-76e3ra5slucqus81-1
bzrlib/tests/workingtree_implementations/test_commit.py test_commit.py-20060421013633-1610ec2331c8190f
------------------------------------------------------------
revno: 2840.1.1
revision-id: ian.clatworthy at internode.on.net-20070921002235-u5lbs3wog6na1qxg
parent: pqm at pqm.ubuntu.com-20070920235505-6w61gqyajy9i0ioj
parent: robertc at robertcollins.net-20070920075948-6f32d46hr3oyw4zb
committer: Ian Clatworthy <ian.clatworthy at internode.on.net>
branch nick: ianc-integration
timestamp: Fri 2007-09-21 10:22:35 +1000
message:
faster pointless commit detection (Robert Collins)
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
bzrlib/commit.py commit.py-20050511101309-79ec1a0168e0e825
bzrlib/inventory.py inventory.py-20050309040759-6648b84ca2005b37
bzrlib/repository.py rev_storage.py-20051111201905-119e9401e46257e3
bzrlib/tests/repository_implementations/test_commit_builder.py test_commit_builder.py-20060606110838-76e3ra5slucqus81-1
bzrlib/tests/workingtree_implementations/test_commit.py test_commit.py-20060421013633-1610ec2331c8190f
------------------------------------------------------------
revno: 2825.5.2
revision-id: robertc at robertcollins.net-20070920075948-6f32d46hr3oyw4zb
parent: robertc at robertcollins.net-20070920034311-lgjoomiumagdhksn
committer: Robert Collins <robertc at robertcollins.net>
branch nick: record-entry-returns-status
timestamp: Thu 2007-09-20 17:59:48 +1000
message:
Review feedback, and fix pointless commits with nested trees to raise PointlessCommit appropriately.
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
bzrlib/commit.py commit.py-20050511101309-79ec1a0168e0e825
bzrlib/inventory.py inventory.py-20050309040759-6648b84ca2005b37
bzrlib/repository.py rev_storage.py-20051111201905-119e9401e46257e3
bzrlib/tests/workingtree_implementations/test_commit.py test_commit.py-20060421013633-1610ec2331c8190f
------------------------------------------------------------
revno: 2825.5.1
revision-id: robertc at robertcollins.net-20070920034311-lgjoomiumagdhksn
parent: pqm at pqm.ubuntu.com-20070917005035-cshdkpzbj63id1uw
committer: Robert Collins <robertc at robertcollins.net>
branch nick: record-entry-returns-status
timestamp: Thu 2007-09-20 13:43:11 +1000
message:
* Committing a change which is not a merge and does not change the number of
files in the tree is faster by utilising the data about whether files are
changed to determine if a the tree is unchanged rather than recalculating
it at the end of the commit process. (Robert Collins)
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
bzrlib/commit.py commit.py-20050511101309-79ec1a0168e0e825
bzrlib/repository.py rev_storage.py-20051111201905-119e9401e46257e3
bzrlib/tests/repository_implementations/test_commit_builder.py test_commit_builder.py-20060606110838-76e3ra5slucqus81-1
=== modified file 'NEWS'
--- a/NEWS 2007-09-21 06:35:09 +0000
+++ b/NEWS 2007-09-21 07:08:31 +0000
@@ -35,9 +35,17 @@
* Commit no longer checks for new text keys during insertion when the
revision id was deterministically unique. (Robert Collins)
+ * Committing a change which is not a merge and does not change the number of
+ files in the tree is faster by utilising the data about whether files are
+ changed to determine if the tree is unchanged rather than recalculating
+ it at the end of the commit process. (Robert Collins)
+
* Inventory serialisation no longer double-sha's the content.
(Robert Collins)
+ * Partial commits are now approximately 40% faster by walking over the
+ unselected current tree more efficiently. (Robert Collins)
+
* XML inventory serialisation takes 20% less time while being stricter about
the contents. (Robert Collins)
@@ -72,6 +80,9 @@
* Fix selftest semi-random noise during http related tests.
(Vincent Ladeuil, #140614)
+ * ``WorkingTree.rename_one`` will now raise an error if normalisation of the
+ new path causes bzr to be unable to access the file. (Robert Collins)
+
API BREAKS:
* The ``VersionedFile`` interface now allows content checks to be bypassed
@@ -91,6 +102,10 @@
INTERNALS:
+ * New method ``bzrlib.osutils.minimum_path_selection`` useful for removing
+ duplication from user input, when a user mentions both a path and an item
+ contained within that path. (Robert Collins)
+
* New method on xml serialisers, write_inventory_to_lines, which matches the
API used by knits for adding content. (Robert Collins)
@@ -98,6 +113,11 @@
and returns a gzipped version of the same. This is used to avoid a bunch
of api friction during adding of knit hunks. (Robert Collins)
+ * New parameter yield_parents on ``Inventory.iter_entries_by_dir`` which
+ causes the parents of a selected id to be returned recursively, so all the
+ paths from the root down to each element of selected_file_ids are
+ returned. (Robert Collins)
+
TESTING:
=== modified file 'bzrlib/commit.py'
--- a/bzrlib/commit.py 2007-09-18 01:29:59 +0000
+++ b/bzrlib/commit.py 2007-09-21 04:22:53 +0000
@@ -68,8 +68,9 @@
ConflictsInTree,
StrictCommitFailed
)
-from bzrlib.osutils import (kind_marker, isdir,isfile, is_inside_any,
+from bzrlib.osutils import (kind_marker, isdir,isfile, is_inside_any,
is_inside_or_parent_of_any,
+ minimum_path_selection,
quotefn, sha_file, split_lines)
from bzrlib.testament import Testament
from bzrlib.trace import mutter, note, warning, is_quiet
@@ -241,11 +242,18 @@
" parameter is required for commit().")
self.bound_branch = None
+ self.any_entries_changed = False
+ self.any_entries_deleted = False
self.local = local
self.master_branch = None
self.master_locked = False
self.rev_id = None
- self.specific_files = specific_files
+ if specific_files is not None:
+ self.specific_files = sorted(
+ minimum_path_selection(specific_files))
+ else:
+ self.specific_files = None
+ self.specific_file_ids = None
self.allow_pointless = allow_pointless
self.recursive = recursive
self.revprops = revprops
@@ -280,14 +288,17 @@
self.config = self.branch.get_config()
# If provided, ensure the specified files are versioned
- if specific_files is not None:
- # Note: We don't actually need the IDs here. This routine
+ if self.specific_files is not None:
+ # Note: This routine
# is being called because it raises PathNotVerisonedError
- # as a side effect of finding the IDs.
+ # as a side effect of finding the IDs. We later use the ids we
+ # found as input to the working tree inventory iterator, so we
+ # only consider those ids rather than examining the whole tree
+ # again.
# XXX: Dont we have filter_unversioned to do this more
# cheaply?
- tree.find_ids_across_trees(specific_files,
- [self.basis_tree, self.work_tree])
+ self.specific_file_ids = tree.find_ids_across_trees(
+ specific_files, [self.basis_tree, self.work_tree])
# Setup the progress bar. As the number of files that need to be
# committed in unknown, progress is reported as stages.
@@ -383,41 +394,6 @@
return NullCommitReporter()
return ReportCommitToLog()
- def _any_real_changes(self):
- """Are there real changes between new_inventory and basis?
-
- For trees without rich roots, inv.root.revision changes every commit.
- But if that is the only change, we want to treat it as though there
- are *no* changes.
- """
- new_entries = self.builder.new_inventory.iter_entries()
- basis_entries = self.basis_inv.iter_entries()
- new_path, new_root_ie = new_entries.next()
- basis_path, basis_root_ie = basis_entries.next()
-
- # This is a copy of InventoryEntry.__eq__ only leaving out .revision
- def ie_equal_no_revision(this, other):
- return ((this.file_id == other.file_id)
- and (this.name == other.name)
- and (this.symlink_target == other.symlink_target)
- and (this.text_sha1 == other.text_sha1)
- and (this.text_size == other.text_size)
- and (this.text_id == other.text_id)
- and (this.parent_id == other.parent_id)
- and (this.kind == other.kind)
- and (this.executable == other.executable)
- and (this.reference_revision == other.reference_revision)
- )
- if not ie_equal_no_revision(new_root_ie, basis_root_ie):
- return True
-
- for new_ie, basis_ie in zip(new_entries, basis_entries):
- if new_ie != basis_ie:
- return True
-
- # No actual changes present
- return False
-
def _check_pointless(self):
if self.allow_pointless:
return
@@ -434,7 +410,8 @@
return
# If length == 1, then we only have the root entry. Which means
# that there is no real difference (only the root could be different)
- if (len(self.builder.new_inventory) != 1 and self._any_real_changes()):
+ if len(self.builder.new_inventory) != 1 and (self.any_entries_changed
+ or self.any_entries_deleted):
return
raise PointlessCommit()
@@ -671,18 +648,28 @@
# recorded in their previous state. For more details, see
# https://lists.ubuntu.com/archives/bazaar/2007q3/028476.html.
if specific_files:
- for path, new_ie in self.basis_inv.iter_entries():
- if new_ie.file_id in self.builder.new_inventory:
+ for path, old_ie in self.basis_inv.iter_entries():
+ if old_ie.file_id in self.builder.new_inventory:
continue
if is_inside_any(specific_files, path):
continue
- ie = new_ie.copy()
- ie.revision = None
- self.builder.record_entry_contents(ie, self.parent_invs, path,
- self.basis_tree)
+ if old_ie.kind == 'directory':
+ self._next_progress_entry()
+ ie = old_ie.copy()
+ # Note: specific file commits after a merge are currently
+ # prohibited. This test is for sanity/safety in case it's
+ # required after that changes.
+ if len(self.parents) > 1:
+ ie.revision = None
+ if self.builder.record_entry_contents(ie, self.parent_invs, path,
+ self.basis_tree):
+ self.any_entries_changed = True
+ # note that deletes have occurred
+ if set(self.basis_inv._byid.keys()) - set(self.builder.new_inventory._byid.keys()):
+ self.any_entries_deleted = True
# Report what was deleted.
- if self.reporter.is_verbose():
+ if self.any_entries_deleted and self.reporter.is_verbose():
for path, ie in self.basis_inv.iter_entries():
if ie.file_id not in self.builder.new_inventory:
self.reporter.deleted(path)
@@ -699,7 +686,8 @@
deleted_paths = set()
work_inv = self.work_tree.inventory
assert work_inv.root is not None
- entries = work_inv.iter_entries_by_dir()
+ entries = work_inv.iter_entries_by_dir(
+ specific_file_ids=self.specific_file_ids, yield_parents=True)
if not self.builder.record_root_entry:
entries.next()
for path, existing_ie in entries:
@@ -709,7 +697,6 @@
kind = existing_ie.kind
if kind == 'directory':
self._next_progress_entry()
-
# Skip files that have been deleted from the working tree.
# The deleted files/directories are also recorded so they
# can be explicitly unversioned later. Note that when a
@@ -717,12 +704,11 @@
# deleted files matching that filter.
if is_inside_any(deleted_paths, path):
continue
- if not specific_files or is_inside_any(specific_files, path):
- if not self.work_tree.has_filename(path):
- deleted_paths.add(path)
- self.reporter.missing(path)
- deleted_ids.append(file_id)
- continue
+ if not self.work_tree.has_filename(path):
+ deleted_paths.add(path)
+ self.reporter.missing(path)
+ deleted_ids.append(file_id)
+ continue
try:
kind = self.work_tree.kind(file_id)
# TODO: specific_files filtering before nested tree processing
@@ -735,7 +721,7 @@
# Note: I don't particularly want to have the existing_ie
# parameter but the test suite currently (28-Jun-07) breaks
# without it thanks to a unicode normalisation issue. :-(
- definitely_changed = kind != existing_ie.kind
+ definitely_changed = kind != existing_ie.kind
self._record_entry(path, file_id, specific_files, kind, name,
parent_id, definitely_changed, existing_ie, report_changes)
@@ -772,26 +758,17 @@
report_changes=True):
"Record the new inventory entry for a path if any."
# mutter('check %s {%s}', path, file_id)
- if (not specific_files or
- is_inside_or_parent_of_any(specific_files, path)):
- # mutter('%s selected for commit', path)
- if definitely_changed or existing_ie is None:
- ie = inventory.make_entry(kind, name, parent_id, file_id)
- else:
- ie = existing_ie.copy()
- ie.revision = None
+ # mutter('%s selected for commit', path)
+ if definitely_changed or existing_ie is None:
+ ie = inventory.make_entry(kind, name, parent_id, file_id)
else:
- # mutter('%s not selected for commit', path)
- if self.basis_inv.has_id(file_id):
- ie = self.basis_inv[file_id].copy()
- else:
- # this entry is new and not being committed
- ie = None
- if ie is not None:
- self.builder.record_entry_contents(ie, self.parent_invs,
- path, self.work_tree)
- if report_changes:
- self._report_change(ie, path)
+ ie = existing_ie.copy()
+ ie.revision = None
+ if self.builder.record_entry_contents(ie, self.parent_invs,
+ path, self.work_tree):
+ self.any_entries_changed = True
+ if report_changes:
+ self._report_change(ie, path)
return ie
def _report_change(self, ie, path):
=== modified file 'bzrlib/dirstate.py'
--- a/bzrlib/dirstate.py 2007-09-14 02:25:32 +0000
+++ b/bzrlib/dirstate.py 2007-09-21 04:22:53 +0000
@@ -365,7 +365,7 @@
# find the location in the block.
# check its not there
# add it.
- #------- copied from inventory.make_entry
+ #------- copied from inventory.ensure_normalized_name - keep synced.
# --- normalized_filename wants a unicode basename only, so get one.
dirname, basename = osutils.split(path)
# we dont import normalized_filename directly because we want to be
@@ -1470,7 +1470,8 @@
kind = inv_entry.kind
minikind = DirState._kind_to_minikind[kind]
tree_data = inv_entry.revision
- assert len(tree_data) > 0, 'empty revision for the inv_entry.'
+ assert tree_data, 'empty revision for the inv_entry %s.' % \
+ inv_entry.file_id
if kind == 'directory':
fingerprint = ''
size = 0
=== modified file 'bzrlib/inventory.py'
--- a/bzrlib/inventory.py 2007-09-04 03:53:07 +0000
+++ b/bzrlib/inventory.py 2007-09-21 04:22:53 +0000
@@ -879,6 +879,13 @@
def _forget_tree_state(self):
self.reference_revision = None
+ def _unchanged(self, previous_ie):
+ """See InventoryEntry._unchanged."""
+ compatible = super(TreeReference, self)._unchanged(previous_ie)
+ if self.reference_revision != previous_ie.reference_revision:
+ compatible = False
+ return compatible
+
class Inventory(object):
"""Inventory of versioned files in a tree.
@@ -1004,7 +1011,8 @@
# if we finished all children, pop it off the stack
stack.pop()
- def iter_entries_by_dir(self, from_dir=None, specific_file_ids=None):
+ def iter_entries_by_dir(self, from_dir=None, specific_file_ids=None,
+ yield_parents=False):
"""Iterate over the entries in a directory first order.
This returns all entries for a directory before returning
@@ -1012,6 +1020,9 @@
lexicographically sorted order, and is a hybrid between
depth-first and breadth-first.
+ :param yield_parents: If True, yield the parents from the root leading
+ down to specific_file_ids that have been requested. This has no
+ impact if specific_file_ids is None.
:return: This yields (path, entry) pairs
"""
if specific_file_ids:
@@ -1023,13 +1034,14 @@
if self.root is None:
return
# Optimize a common case
- if specific_file_ids is not None and len(specific_file_ids) == 1:
+ if (not yield_parents and specific_file_ids is not None and
+ len(specific_file_ids) == 1):
file_id = list(specific_file_ids)[0]
if file_id in self:
yield self.id2path(file_id), self[file_id]
return
from_dir = self.root
- if (specific_file_ids is None or
+ if (specific_file_ids is None or yield_parents or
self.root.file_id in specific_file_ids):
yield u'', self.root
elif isinstance(from_dir, basestring):
@@ -1064,7 +1076,8 @@
child_relpath = cur_relpath + child_name
if (specific_file_ids is None or
- child_ie.file_id in specific_file_ids):
+ child_ie.file_id in specific_file_ids or
+ (yield_parents and child_ie.file_id in parents)):
yield child_relpath, child_ie
if child_ie.kind == 'directory':
@@ -1371,6 +1384,7 @@
This does not move the working file.
"""
file_id = osutils.safe_file_id(file_id)
+ new_name = ensure_normalized_name(new_name)
if not is_valid_name(new_name):
raise BzrError("not an acceptable filename: %r" % new_name)
@@ -1418,7 +1432,21 @@
file_id = generate_ids.gen_file_id(name)
else:
file_id = osutils.safe_file_id(file_id)
-
+ name = ensure_normalized_name(name)
+ try:
+ factory = entry_factory[kind]
+ except KeyError:
+ raise BzrError("unknown kind %r" % kind)
+ return factory(file_id, name, parent_id)
+
+
+def ensure_normalized_name(name):
+ """Normalize name.
+
+ :raises InvalidNormalization: When name is not normalized, and cannot be
+ accessed on this platform by the normalized path.
+ :return: The NFC/NFKC normalised version of name.
+ """
#------- This has been copied to bzrlib.dirstate.DirState.add, please
# keep them synchronised.
# we dont import normalized_filename directly because we want to be
@@ -1426,17 +1454,12 @@
norm_name, can_access = osutils.normalized_filename(name)
if norm_name != name:
if can_access:
- name = norm_name
+ return norm_name
else:
# TODO: jam 20060701 This would probably be more useful
# if the error was raised with the full path
raise errors.InvalidNormalization(name)
-
- try:
- factory = entry_factory[kind]
- except KeyError:
- raise BzrError("unknown kind %r" % kind)
- return factory(file_id, name, parent_id)
+ return name
_NAME_RE = None
=== modified file 'bzrlib/osutils.py'
--- a/bzrlib/osutils.py 2007-09-20 09:30:39 +0000
+++ b/bzrlib/osutils.py 2007-09-21 04:22:53 +0000
@@ -87,6 +87,23 @@
os.chmod(filename, mod)
+def minimum_path_selection(paths):
+ """Return the smallset subset of paths which are outside paths.
+
+ :param paths: A container (and hence not None) of paths.
+ :return: A set of paths sufficient to include everything in paths via
+ is_inside_any, drawn from the paths parameter.
+ """
+ search_paths = set()
+ paths = set(paths)
+ for path in paths:
+ other_paths = paths.difference([path])
+ if not is_inside_any(other_paths, path):
+ # this is a top level path, we must check it.
+ search_paths.add(path)
+ return search_paths
+
+
_QUOTE_RE = None
=== modified file 'bzrlib/repository.py'
--- a/bzrlib/repository.py 2007-09-16 23:48:15 +0000
+++ b/bzrlib/repository.py 2007-09-21 00:22:35 +0000
@@ -70,6 +70,8 @@
# all clients should supply tree roots.
record_root_entry = True
+ # the default CommitBuilder does not manage trees whose root is versioned.
+ _versioned_root = False
def __init__(self, repository, parents, config, timestamp=None,
timezone=None, committer=None, revprops=None,
@@ -216,6 +218,9 @@
:param path: The path the entry is at in the tree.
:param tree: The tree which contains this entry and should be used to
obtain content.
+ :return: True if a new version of the entry has been recorded.
+ (Committing a merge where a file was only changed on the other side
+ will not return True.)
"""
if self.new_inventory.root is None:
self._check_root(ie, parent_invs, tree)
@@ -225,7 +230,8 @@
# for committing. ie.snapshot will record the correct revision
# which may be the sole parent if it is untouched.
if ie.revision is not None:
- return
+ return ie.revision == self._new_revision_id and (path != '' or
+ self._versioned_root)
parent_candiate_entries = ie.parent_candidates(parent_invs)
heads = self.repository.get_graph().heads(parent_candiate_entries.keys())
@@ -236,6 +242,8 @@
# we are creating a new revision for ie in the history store and
# inventory.
ie.snapshot(self._new_revision_id, path, previous_entries, tree, self)
+ return ie.revision == self._new_revision_id and (path != '' or
+ self._versioned_root)
def modified_directory(self, file_id, file_parents):
"""Record the presence of a symbolic link.
@@ -313,6 +321,9 @@
class RootCommitBuilder(CommitBuilder):
"""This commitbuilder actually records the root id"""
+ # the root entry gets versioned properly by this builder.
+ _versioned_root = True
+
def _check_root(self, ie, parent_invs, tree):
"""Helper for record_entry_contents.
=== modified file 'bzrlib/tests/inventory_implementations/basics.py'
--- a/bzrlib/tests/inventory_implementations/basics.py 2007-09-03 04:45:38 +0000
+++ b/bzrlib/tests/inventory_implementations/basics.py 2007-09-20 07:03:33 +0000
@@ -202,6 +202,13 @@
], [(path, ie.file_id) for path, ie in inv.iter_entries_by_dir(
specific_file_ids=('bye-id',))])
+ self.assertEqual([
+ ('', 'tree-root'),
+ ('src', 'src-id'),
+ ('src/bye.c', 'bye-id'),
+ ], [(path, ie.file_id) for path, ie in inv.iter_entries_by_dir(
+ specific_file_ids=('bye-id',), yield_parents=True)])
+
def test_add_recursive(self):
parent = InventoryDirectory('src-id', 'src', 'tree-root')
child = InventoryFile('hello-id', 'hello.c', 'src-id')
=== modified file 'bzrlib/tests/repository_implementations/test_commit_builder.py'
--- a/bzrlib/tests/repository_implementations/test_commit_builder.py 2007-09-20 09:30:39 +0000
+++ b/bzrlib/tests/repository_implementations/test_commit_builder.py 2007-09-21 00:22:35 +0000
@@ -138,6 +138,27 @@
rev_id = builder.commit('foo bar')
finally:
tree.unlock()
+
+ def test_commit_unchanged_root(self):
+ tree = self.make_branch_and_tree(".")
+ tree.commit('')
+ tree.lock_write()
+ parent_tree = tree.basis_tree()
+ parent_tree.lock_read()
+ self.addCleanup(parent_tree.unlock)
+ builder = tree.branch.get_commit_builder([parent_tree.inventory])
+ try:
+ ie = inventory.make_entry('directory', '', None,
+ tree.inventory.root.file_id)
+ self.assertFalse(builder.record_entry_contents(
+ ie, [parent_tree.inventory], '', tree))
+ builder.abort()
+ except:
+ builder.abort()
+ tree.unlock()
+ raise
+ else:
+ tree.unlock()
def test_commit(self):
tree = self.make_branch_and_tree(".")
@@ -299,7 +320,42 @@
tree.add([name], [name + 'id'])
rev1 = tree.commit('')
changer()
- rev2 = tree.commit('')
+ tree.lock_write()
+ try:
+ # mini manual commit here so we can check the return of
+ # record_entry_contents.
+ builder = tree.branch.get_commit_builder([tree.last_revision()])
+ parent_tree = tree.basis_tree()
+ parent_tree.lock_read()
+ self.addCleanup(parent_tree.unlock)
+ parent_invs = [parent_tree.inventory]
+ # root
+ builder.record_entry_contents(
+ inventory.make_entry('directory', '', None,
+ tree.inventory.root.file_id), parent_invs, '', tree)
+ def commit_id(file_id):
+ old_ie = tree.inventory[file_id]
+ path = tree.id2path(file_id)
+ ie = inventory.make_entry(tree.kind(file_id), old_ie.name,
+ old_ie.parent_id, file_id)
+ return builder.record_entry_contents(ie, parent_invs, path, tree)
+
+ file_id = name + 'id'
+ parent_id = tree.inventory[file_id].parent_id
+ if parent_id != tree.inventory.root.file_id:
+ commit_id(parent_id)
+ # because a change of some sort is meant to have occurred,
+ # recording the entry must return True.
+ self.assertTrue(commit_id(file_id))
+ builder.finish_inventory()
+ rev2 = builder.commit('')
+ tree.set_parent_ids([rev2])
+ except:
+ builder.abort()
+ tree.unlock()
+ raise
+ else:
+ tree.unlock()
tree1, tree2 = self._get_revtrees(tree, [rev1, rev2])
self.assertEqual(rev1, tree1.inventory[name + 'id'].revision)
self.assertEqual(rev2, tree2.inventory[name + 'id'].revision)
=== modified file 'bzrlib/tests/test_osutils.py'
--- a/bzrlib/tests/test_osutils.py 2007-09-04 11:00:30 +0000
+++ b/bzrlib/tests/test_osutils.py 2007-09-20 07:03:33 +0000
@@ -477,6 +477,16 @@
# osutils.getcwd() renormalize the path.
self.assertEndsWith(osutils._win32_getcwd(), u'mu-\xb5')
+ def test_minimum_path_selection(self):
+ self.assertEqual(set(),
+ osutils.minimum_path_selection([]))
+ self.assertEqual(set(['a', 'b']),
+ osutils.minimum_path_selection(['a', 'b']))
+ self.assertEqual(set(['a/', 'b']),
+ osutils.minimum_path_selection(['a/', 'b']))
+ self.assertEqual(set(['a/', 'b']),
+ osutils.minimum_path_selection(['a/c', 'a/', 'b']))
+
def test_mkdtemp(self):
tmpdir = osutils._win32_mkdtemp(dir='.')
self.assertFalse('\\' in tmpdir)
=== modified file 'bzrlib/tests/test_workingtree_4.py'
--- a/bzrlib/tests/test_workingtree_4.py 2007-04-26 22:56:01 +0000
+++ b/bzrlib/tests/test_workingtree_4.py 2007-09-17 05:33:56 +0000
@@ -419,12 +419,12 @@
tree.add(['b'], ['b-id'])
try:
- tree.rename_one('a', u'b\xb5rry')
- new_path = u'b\xb5rry'
+ new_path = u'b\u03bcrry'
+ tree.rename_one('a', new_path)
except UnicodeEncodeError:
# support running the test on non-unicode platforms
- tree.rename_one('a', 'c')
new_path = 'c'
+ tree.rename_one('a', new_path)
self.assertEqual(new_path, tree.id2path('a-id'))
tree.commit(u'b\xb5rry')
tree.unversion(['a-id'])
=== modified file 'bzrlib/tests/workingtree_implementations/test_commit.py'
--- a/bzrlib/tests/workingtree_implementations/test_commit.py 2007-08-27 08:38:37 +0000
+++ b/bzrlib/tests/workingtree_implementations/test_commit.py 2007-09-20 07:59:48 +0000
@@ -90,14 +90,14 @@
def test_commit_sets_last_revision(self):
tree = self.make_branch_and_tree('tree')
- committed_id = tree.commit('foo', rev_id='foo', allow_pointless=True)
+ committed_id = tree.commit('foo', rev_id='foo')
self.assertEqual(['foo'], tree.get_parent_ids())
# the commit should have returned the same id we asked for.
self.assertEqual('foo', committed_id)
def test_commit_returns_revision_id(self):
tree = self.make_branch_and_tree('.')
- committed_id = tree.commit('message', allow_pointless=True)
+ committed_id = tree.commit('message')
self.assertTrue(tree.branch.repository.has_revision(committed_id))
self.assertNotEqual(None, committed_id)
@@ -323,6 +323,22 @@
basis.get_reference_revision(basis.path2id('subtree')))
self.assertNotEqual(rev_id, rev_id2)
+ def test_nested_pointless_commits_are_pointless(self):
+ tree = self.make_branch_and_tree('.')
+ if not tree.supports_tree_reference():
+ # inapplicable test.
+ return
+ subtree = self.make_branch_and_tree('subtree')
+ tree.add(['subtree'])
+ # record the reference.
+ rev_id = tree.commit('added reference')
+ child_revid = subtree.last_revision()
+ # now do a no-op commit with allow_pointless=False
+ self.assertRaises(errors.PointlessCommit, tree.commit, '',
+ allow_pointless=False)
+ self.assertEqual(child_revid, subtree.last_revision())
+ self.assertEqual(rev_id, tree.last_revision())
+
class TestCommitProgress(TestCaseWithWorkingTree):
=== modified file 'bzrlib/tests/workingtree_implementations/test_rename_one.py'
--- a/bzrlib/tests/workingtree_implementations/test_rename_one.py 2007-02-26 16:19:02 +0000
+++ b/bzrlib/tests/workingtree_implementations/test_rename_one.py 2007-09-17 05:33:56 +0000
@@ -308,3 +308,10 @@
('c', 'c-id')], tree)
self.assertTreeLayout([('', root_id), ('a', 'a-id'), ('c', 'c-id'),
('a/b', 'b-id')], tree.basis_tree())
+
+ def test_rename_to_denormalised_fails(self):
+ tree = self.make_branch_and_tree('.')
+ self.build_tree(['a'])
+ tree.add(['a'])
+ self.assertRaises((errors.InvalidNormalization, UnicodeEncodeError),
+ tree.rename_one, 'a', u'b\xb5rry')
=== modified file 'bzrlib/workingtree_4.py'
--- a/bzrlib/workingtree_4.py 2007-09-14 02:25:32 +0000
+++ b/bzrlib/workingtree_4.py 2007-09-20 07:03:33 +0000
@@ -946,12 +946,7 @@
if not all_versioned:
raise errors.PathsNotVersionedError(paths)
# -- remove redundancy in supplied paths to prevent over-scanning --
- search_paths = set()
- for path in paths:
- other_paths = paths.difference(set([path]))
- if not osutils.is_inside_any(other_paths, path):
- # this is a top level path, we must check it.
- search_paths.add(path)
+ search_paths = osutils.minimum_path_selection(paths)
# sketch:
# for all search_indexs in each path at or under each element of
# search_paths, if the detail is relocated: add the id, and add the
More information about the bazaar-commits
mailing list