Rev 4679: Fix bug #322807, teach cicp_canonical_relpath how to handle in http://bazaar.launchpad.net/~jameinel/bzr/2.0.1-322807-branch-at-root

John Arbash Meinel john at arbash-meinel.com
Tue Oct 6 18:36:16 BST 2009


At http://bazaar.launchpad.net/~jameinel/bzr/2.0.1-322807-branch-at-root

------------------------------------------------------------
revno: 4679
revision-id: john at arbash-meinel.com-20091006173603-geynkwufk5orrap7
parent: john at arbash-meinel.com-20091006173334-rghfzhhwi5t0cwiy
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: 2.0.1-322807-branch-at-root
timestamp: Tue 2009-10-06 12:36:03 -0500
message:
  Fix bug #322807, teach cicp_canonical_relpath how to handle
  
  1) relpaths when the base dir is the root of the filesystem
  2) when base dir doesn't exist (makes it easier to do testing)
-------------- next part --------------
=== modified file 'NEWS'
--- a/NEWS	2009-10-06 17:33:34 +0000
+++ b/NEWS	2009-10-06 17:36:03 +0000
@@ -26,6 +26,12 @@
   with some combinations of remote and local formats.  This was causing
   "unknown object type identifier 60" errors.  (Andrew Bennetts, #427736)
 
+* Handle things like ``bzr add foo`` and ``bzr rm foo`` when the tree is
+  at the root of a drive. ``osutils._cicp_canonical_relpath`` always
+  assumed that ``abspath()`` returned a path that did not have a trailing
+  ``/``, but that is not true when working at the root of the filesystem.
+  (John Arbash Meinel, Jason Spashett, #322807)
+
 * Improve the time for ``bzr log DIR`` for 2a format repositories.
   We had been using the same code path as for <2a formats, which required
   iterating over all objects in all revisions.

=== modified file 'bzrlib/osutils.py'
--- a/bzrlib/osutils.py	2009-07-23 16:01:17 +0000
+++ b/bzrlib/osutils.py	2009-10-06 17:36:03 +0000
@@ -1083,6 +1083,12 @@
     bit_iter = iter(rel.split('/'))
     for bit in bit_iter:
         lbit = bit.lower()
+        try:
+            next_entries = _listdir(current)
+        except OSError: # enoent
+            # current doesn't match, so just append the non-existing bits
+            current = pathjoin(current, bit, *list(bit_iter))
+            break
         for look in _listdir(current):
             if lbit == look.lower():
                 current = pathjoin(current, look)
@@ -1093,7 +1099,7 @@
             # the target of a move, for example).
             current = pathjoin(current, bit, *list(bit_iter))
             break
-    return current[len(abs_base)+1:]
+    return current[len(abs_base):].lstrip('/')
 
 # XXX - TODO - we need better detection/integration of case-insensitive
 # file-systems; Linux often sees FAT32 devices (or NFS-mounted OSX

=== modified file 'bzrlib/tests/test_osutils.py'
--- a/bzrlib/tests/test_osutils.py	2009-07-23 16:01:17 +0000
+++ b/bzrlib/tests/test_osutils.py	2009-10-06 17:36:03 +0000
@@ -460,6 +460,42 @@
         self.failUnlessEqual('work/MixedCaseParent/nochild', actual)
 
 
+class Test_CICPCanonicalRelpath(tests.TestCaseWithTransport):
+
+    def assertRelpath(self, expected, base, path):
+        actual = osutils._cicp_canonical_relpath(base, path)
+        self.assertEqual(expected, actual)
+
+    def test_simple(self):
+        self.build_tree(['MixedCaseName'])
+        base = osutils.realpath(self.get_transport('.').local_abspath('.'))
+        self.assertRelpath('MixedCaseName', base, 'mixedcAsename')
+
+    def test_subdir_missing_tail(self):
+        self.build_tree(['MixedCaseParent/', 'MixedCaseParent/a_child'])
+        base = osutils.realpath(self.get_transport('.').local_abspath('.'))
+        self.assertRelpath('MixedCaseParent/a_child', base,
+                           'MixedCaseParent/a_child')
+        self.assertRelpath('MixedCaseParent/a_child', base,
+                           'MixedCaseParent/A_Child')
+        self.assertRelpath('MixedCaseParent/not_child', base,
+                           'MixedCaseParent/not_child')
+
+    def test_at_root(self):
+        # This path probably does not exist
+        # We can't test this on Windows, because it has a 'MIN_ABS_PATHLENGTH'
+        # check...
+        # self.assertRelpath('foo', '/', '/foo')
+
+        # see bug #322807
+        # The specific issue is that when at the root of a drive, 'abspath'
+        # returns "C:/" or just "/". However, the code assumes that abspath
+        # always returns something like "C:/foo" or "/foo" (no trailing slash).
+        self.assertRelpath('foo', 'C:/', 'C:/foo')
+        self.assertRelpath('foo', 'X:/', 'X:/foo')
+        self.assertRelpath('foo', 'X:/', 'X://foo')
+
+
 class TestPumpFile(tests.TestCase):
     """Test pumpfile method."""
 



More information about the bazaar-commits mailing list