Rev 4731: (mbp) fix renaming when entries differ only by case in file:///home/pqm/archives/thelove/bzr/2.0/
Canonical.com Patch Queue Manager
pqm at pqm.ubuntu.com
Fri Feb 12 04:49:52 GMT 2010
At file:///home/pqm/archives/thelove/bzr/2.0/
------------------------------------------------------------
revno: 4731 [merge]
revision-id: pqm at pqm.ubuntu.com-20100212044951-a34u2j4bd0etf3hu
parent: pqm at pqm.ubuntu.com-20100205074746-v2eq314fui8vk5m1
parent: mbp at sourcefrog.net-20100212033433-zc6lpwxj7dv9c0s2
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: 2.0
timestamp: Fri 2010-02-12 04:49:51 +0000
message:
(mbp) fix renaming when entries differ only by case
modified:
NEWS NEWS-20050323055033-4e00b5db738777ff
bzrlib/tests/__init__.py selftest.py-20050531073622-8d0e3c8845c97a64
bzrlib/tests/per_tree/test_inv.py test_inv.py-20070312023226-0cdvk5uwhutis9vg-1
bzrlib/tree.py tree.py-20050309040759-9d5f2496be663e77
=== modified file 'NEWS'
--- a/NEWS 2010-02-05 06:30:42 +0000
+++ b/NEWS 2010-02-11 08:47:14 +0000
@@ -14,6 +14,9 @@
Bug Fixes
*********
+* Handle renames correctly when there are files or directories that
+ differ only in case. (Chris Jones, Martin Pool, #368931)
+
* If ``bzr push --create-prefix`` triggers an unexpected ``NoSuchFile``
error, report that error rather than failing with an unhelpful
``UnboundLocalError``.
=== modified file 'bzrlib/tests/__init__.py'
--- a/bzrlib/tests/__init__.py 2009-10-29 04:19:13 +0000
+++ b/bzrlib/tests/__init__.py 2010-02-12 03:34:33 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2005, 2006, 2007, 2008, 2009 Canonical Ltd
+# Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Canonical Ltd
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -4060,6 +4060,23 @@
CaseInsensitiveFilesystemFeature = _CaseInsensitiveFilesystemFeature()
+class _CaseSensitiveFilesystemFeature(Feature):
+
+ def _probe(self):
+ if CaseInsCasePresFilenameFeature.available():
+ return False
+ elif CaseInsensitiveFilesystemFeature.available():
+ return False
+ else:
+ return True
+
+ def feature_name(self):
+ return 'case-sensitive filesystem'
+
+# new coding style is for feature instances to be lowercase
+case_sensitive_filesystem_feature = _CaseSensitiveFilesystemFeature()
+
+
class _SubUnitFeature(Feature):
"""Check if subunit is available."""
=== modified file 'bzrlib/tests/per_tree/test_inv.py'
--- a/bzrlib/tests/per_tree/test_inv.py 2009-07-10 07:14:02 +0000
+++ b/bzrlib/tests/per_tree/test_inv.py 2010-02-12 03:33:36 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2007, 2008 Canonical Ltd
+# Copyright (C) 2007, 2008, 2010 Canonical Ltd
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -23,7 +23,10 @@
from bzrlib import (
tests,
)
-from bzrlib.tests import per_tree
+from bzrlib.tests import (
+ features,
+ per_tree,
+ )
from bzrlib.mutabletree import MutableTree
from bzrlib.tests import SymlinkFeature, TestSkipped
from bzrlib.transform import _PreviewTree
@@ -131,6 +134,8 @@
work_tree.add(['dir', 'dir/file'])
if commit:
work_tree.commit('commit 1')
+ # XXX: this isn't actually guaranteed to return the class we want to
+ # test -- mbp 2010-02-12
return work_tree
def test_canonical_path(self):
@@ -163,3 +168,21 @@
work_tree = self._make_canonical_test_tree()
self.assertEqual('dir/None',
work_tree.get_canonical_inventory_path('Dir/None'))
+
+ def test_canonical_tree_name_mismatch(self):
+ # see <https://bugs.edge.launchpad.net/bzr/+bug/368931>
+ # some of the trees we want to use can only exist on a disk, not in
+ # memory - therefore we can only test this if the filesystem is
+ # case-sensitive.
+ self.requireFeature(tests.case_sensitive_filesystem_feature)
+ work_tree = self.make_branch_and_tree('.')
+ self.build_tree(['test/', 'test/file', 'Test'])
+ work_tree.add(['test/', 'test/file', 'Test'])
+
+ test_tree = self._convert_tree(work_tree)
+ test_tree.lock_read()
+ self.addCleanup(test_tree.unlock)
+
+ self.assertEqual(['test', 'test/file', 'Test', 'test/foo', 'Test/foo'],
+ test_tree.get_canonical_inventory_paths(
+ ['test', 'test/file', 'Test', 'test/foo', 'Test/foo']))
=== modified file 'bzrlib/tree.py'
--- a/bzrlib/tree.py 2009-08-26 05:38:16 +0000
+++ b/bzrlib/tree.py 2010-02-11 08:47:14 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2005, 2009 Canonical Ltd
+# Copyright (C) 2005, 2009, 2010 Canonical Ltd
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -404,16 +404,34 @@
bit_iter = iter(path.split("/"))
for elt in bit_iter:
lelt = elt.lower()
+ new_path = None
for child in self.iter_children(cur_id):
try:
+ # XXX: it seem like if the child is known to be in the
+ # tree, we shouldn't need to go from its id back to
+ # its path -- mbp 2010-02-11
+ #
+ # XXX: it seems like we could be more efficient
+ # by just directly looking up the original name and
+ # only then searching all children; also by not
+ # chopping paths so much. -- mbp 2010-02-11
child_base = os.path.basename(self.id2path(child))
- if child_base.lower() == lelt:
+ if (child_base == elt):
+ # if we found an exact match, we can stop now; if
+ # we found an approximate match we need to keep
+ # searching because there might be an exact match
+ # later.
cur_id = child
- cur_path = osutils.pathjoin(cur_path, child_base)
+ new_path = osutils.pathjoin(cur_path, child_base)
break
+ elif child_base.lower() == lelt:
+ cur_id = child
+ new_path = osutils.pathjoin(cur_path, child_base)
except NoSuchId:
# before a change is committed we can see this error...
continue
+ if new_path:
+ cur_path = new_path
else:
# got to the end of this directory and no entries matched.
# Return what matched so far, plus the rest as specified.
More information about the bazaar-commits
mailing list