Merge lp:~jameinel/bzr/2.0.1-322807-branch-at-root into lp:bzr/2.0

Proposed by John A Meinel
Status: Merged
Approved by: Andrew Bennetts
Approved revision: no longer in the source branch.
Merged at revision: not available
Proposed branch: lp:~jameinel/bzr/2.0.1-322807-branch-at-root
Merge into: lp:bzr/2.0
Diff against target: 154 lines
3 files modified
NEWS (+20/-21)
bzrlib/osutils.py (+9/-2)
bzrlib/tests/test_osutils.py (+43/-0)
To merge this branch: bzr merge lp:~jameinel/bzr/2.0.1-322807-branch-at-root
Reviewer Review Type Date Requested Status
Andrew Bennetts Needs Fixing
Review via email: mp+12936@code.launchpad.net
To post a comment you must log in.
Revision history for this message
John A Meinel (jameinel) wrote :

This fixes bug #322807

Basically, cicp_canonical_relpath always assumed that 'abspath()' returned a path that did not have a trailing '/'. However, when working at the root of the filesytem, this was not true. (And, I believe, not true on Linux or Mac, either.)

So I changed:
  return current[len(abspath+1):]
to
  return current[len(abspath):].lstrip('/')

which seems to work just fine.

In the process of doing this, I also made the function handle when base doesn't actually exist, since it made testing easier. And I changed it to always run tests that I'm sure will pass. (We don't require the filesystem to have CICP to run _cicp_canonical_relpath, only if we wanted to call it by 'osutils.canonical_relpath()'. This should help increase PQM test coverage.)

Revision history for this message
Andrew Bennetts (spiv) wrote :

This seems good. I don't have a convenient Windows install to test it on, but I assume you've already taken care of that :)

I have some minor suggestions, so I'm voting Needs Fixing and marking the overall review as Approved (as that seems to be the closest approximation of bb:tweak).

81 + try:
82 + next_entries = _listdir(current)
83 + except OSError: # enoent

That's a bit odd. Why not actually check that the exc.errno == ENOENT?

87 for look in _listdir(current):

This repeats the listdir we just did. Why not reuse 'next_entries'?

129 + # This path probably does not exist
130 + # We can't test this on Windows, because it has a 'MIN_ABS_PATHLENGTH'
131 + # check...
132 + # self.assertRelpath('foo', '/', '/foo')

Ideally this would be in a separate test method that could do a requireFeature check, I think. Not a big deal.

review: Needs Fixing
Revision history for this message
John A Meinel (jameinel) wrote :

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Andrew Bennetts wrote:
> Review: Needs Fixing
> This seems good. I don't have a convenient Windows install to test it on, but I assume you've already taken care of that :)
>
> I have some minor suggestions, so I'm voting Needs Fixing and marking the overall review as Approved (as that seems to be the closest approximation of bb:tweak).
>
> 81 + try:
> 82 + next_entries = _listdir(current)
> 83 + except OSError: # enoent
>
> That's a bit odd. Why not actually check that the exc.errno == ENOENT?

Because I figured EPERM and EANYTHINGELSE would be just as reasonable.
All we are doing here is trying to translate "foo" => "Foo" based on
what is in the filesytem. If we can't access the filesystem, we have
nothing to translate.

>
> 87 for look in _listdir(current):
>
> This repeats the listdir we just did. Why not reuse 'next_entries'?

I'm sure I meant to, and just forgot to.

>
> 129 + # This path probably does not exist
> 130 + # We can't test this on Windows, because it has a 'MIN_ABS_PATHLENGTH'
> 131 + # check...
> 132 + # self.assertRelpath('foo', '/', '/foo')
>
> Ideally this would be in a separate test method that could do a requireFeature check, I think. Not a big deal.

Sure, I could do that.

John
=:->

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (Cygwin)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAkrNX2IACgkQJdeBCYSNAAMQsQCfbgmfEneaDM3KffULtewF0w8w
VUsAnROBTldhwAIp+cEEhJRBfjYg6xS0
=e7ss
-----END PGP SIGNATURE-----

Revision history for this message
Andrew Bennetts (spiv) wrote :

John A Meinel wrote:
[...]
> > 83 + except OSError: # enoent
> >
> > That's a bit odd. Why not actually check that the exc.errno == ENOENT?
>
> Because I figured EPERM and EANYTHINGELSE would be just as reasonable.
> All we are doing here is trying to translate "foo" => "Foo" based on
> what is in the filesytem. If we can't access the filesystem, we have
> nothing to translate.

Ah ok. Then I'd just remove the “# enoent” comment, because it seems to
imply that you only care about that one errno.

-Andrew.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'NEWS'
--- NEWS 2009-10-07 12:01:20 +0000
+++ NEWS 2009-10-08 17:16:09 +0000
@@ -2,8 +2,8 @@
2Bazaar Release Notes2Bazaar Release Notes
3####################3####################
44
52.0 series (not released)52.0.1 (not released)
6#########################6####################
77
8Compatibility Breaks8Compatibility Breaks
9********************9********************
@@ -29,6 +29,21 @@
29* Fixed ``ObjectNotLocked`` errors when doing some log and diff operations29* Fixed ``ObjectNotLocked`` errors when doing some log and diff operations
30 on branches via a smart server. (Andrew Bennetts, #389413)30 on branches via a smart server. (Andrew Bennetts, #389413)
3131
32* Handle things like ``bzr add foo`` and ``bzr rm foo`` when the tree is
33 at the root of a drive. ``osutils._cicp_canonical_relpath`` always
34 assumed that ``abspath()`` returned a path that did not have a trailing
35 ``/``, but that is not true when working at the root of the filesystem.
36 (John Arbash Meinel, Jason Spashett, #322807)
37
38* Improve the time for ``bzr log DIR`` for 2a format repositories.
39 We had been using the same code path as for <2a formats, which required
40 iterating over all objects in all revisions.
41 (John Arbash Meinel, #374730)
42
43* Make sure that we unlock the tree if we fail to create a TreeTransform
44 object when doing a merge, and there is limbo, or pending-deletions
45 directory. (Gary van der Merwe, #427773)
46
32* Occasional IndexError on renamed files have been fixed. Operations that47* Occasional IndexError on renamed files have been fixed. Operations that
33 set a full inventory in the working tree will now go via the48 set a full inventory in the working tree will now go via the
34 apply_inventory_delta code path which is simpler and easier to49 apply_inventory_delta code path which is simpler and easier to
@@ -37,6 +52,9 @@
37 but such operations are already doing full tree scans, so no radical52 but such operations are already doing full tree scans, so no radical
38 performance change should be observed. (Robert Collins, #403322)53 performance change should be observed. (Robert Collins, #403322)
3954
55* Retrieving file text or mtime from a _PreviewTree has good performance when
56 there are many changes. (Aaron Bentley)
57
40* When a file kind becomes unversionable after being added, a sensible58* When a file kind becomes unversionable after being added, a sensible
41 error will be shown instead of a traceback. (Robert Collins, #438569)59 error will be shown instead of a traceback. (Robert Collins, #438569)
4260
@@ -60,25 +78,6 @@
60Testing78Testing
61*******79*******
6280
63bzr 2.0.1
64##########
65
66Bug Fixes
67*********
68
69* Improve the time for ``bzr log DIR`` for 2a format repositories.
70 We had been using the same code path as for <2a formats, which required
71 iterating over all objects in all revisions.
72 (John Arbash Meinel, #374730)
73
74* Make sure that we unlock the tree if we fail to create a TreeTransform
75 object when doing a merge, and there is limbo, or pending-deletions
76 directory. (Gary van der Merwe, #427773)
77
78* Retrieving file text or mtime from a _PreviewTree has good performance when
79 there are many changes. (Aaron Bentley)
80
81
82bzr 2.0.081bzr 2.0.0
83#########82#########
8483
8584
=== modified file 'bzrlib/osutils.py'
--- bzrlib/osutils.py 2009-07-23 16:01:17 +0000
+++ bzrlib/osutils.py 2009-10-08 17:16:09 +0000
@@ -1083,7 +1083,14 @@
1083 bit_iter = iter(rel.split('/'))1083 bit_iter = iter(rel.split('/'))
1084 for bit in bit_iter:1084 for bit in bit_iter:
1085 lbit = bit.lower()1085 lbit = bit.lower()
1086 for look in _listdir(current):1086 try:
1087 next_entries = _listdir(current)
1088 except OSError: # enoent, eperm, etc
1089 # We can't find this in the filesystem, so just append the
1090 # remaining bits.
1091 current = pathjoin(current, bit, *list(bit_iter))
1092 break
1093 for look in next_entries:
1087 if lbit == look.lower():1094 if lbit == look.lower():
1088 current = pathjoin(current, look)1095 current = pathjoin(current, look)
1089 break1096 break
@@ -1093,7 +1100,7 @@
1093 # the target of a move, for example).1100 # the target of a move, for example).
1094 current = pathjoin(current, bit, *list(bit_iter))1101 current = pathjoin(current, bit, *list(bit_iter))
1095 break1102 break
1096 return current[len(abs_base)+1:]1103 return current[len(abs_base):].lstrip('/')
10971104
1098# XXX - TODO - we need better detection/integration of case-insensitive1105# XXX - TODO - we need better detection/integration of case-insensitive
1099# file-systems; Linux often sees FAT32 devices (or NFS-mounted OSX1106# file-systems; Linux often sees FAT32 devices (or NFS-mounted OSX
11001107
=== modified file 'bzrlib/tests/test_osutils.py'
--- bzrlib/tests/test_osutils.py 2009-07-23 16:01:17 +0000
+++ bzrlib/tests/test_osutils.py 2009-10-08 17:16:09 +0000
@@ -460,6 +460,49 @@
460 self.failUnlessEqual('work/MixedCaseParent/nochild', actual)460 self.failUnlessEqual('work/MixedCaseParent/nochild', actual)
461461
462462
463class Test_CICPCanonicalRelpath(tests.TestCaseWithTransport):
464
465 def assertRelpath(self, expected, base, path):
466 actual = osutils._cicp_canonical_relpath(base, path)
467 self.assertEqual(expected, actual)
468
469 def test_simple(self):
470 self.build_tree(['MixedCaseName'])
471 base = osutils.realpath(self.get_transport('.').local_abspath('.'))
472 self.assertRelpath('MixedCaseName', base, 'mixedcAsename')
473
474 def test_subdir_missing_tail(self):
475 self.build_tree(['MixedCaseParent/', 'MixedCaseParent/a_child'])
476 base = osutils.realpath(self.get_transport('.').local_abspath('.'))
477 self.assertRelpath('MixedCaseParent/a_child', base,
478 'MixedCaseParent/a_child')
479 self.assertRelpath('MixedCaseParent/a_child', base,
480 'MixedCaseParent/A_Child')
481 self.assertRelpath('MixedCaseParent/not_child', base,
482 'MixedCaseParent/not_child')
483
484 def test_at_root_slash(self):
485 # We can't test this on Windows, because it has a 'MIN_ABS_PATHLENGTH'
486 # check...
487 if osutils.MIN_ABS_PATHLENGTH > 1:
488 raise tests.TestSkipped('relpath requires %d chars'
489 % osutils.MIN_ABS_PATHLENGTH)
490 self.assertRelpath('foo', '/', '/foo')
491
492 def test_at_root_drive(self):
493 if sys.platform != 'win32':
494 raise tests.TestNotApplicable('we can only test drive-letter relative'
495 ' paths on Windows where we have drive'
496 ' letters.')
497 # see bug #322807
498 # The specific issue is that when at the root of a drive, 'abspath'
499 # returns "C:/" or just "/". However, the code assumes that abspath
500 # always returns something like "C:/foo" or "/foo" (no trailing slash).
501 self.assertRelpath('foo', 'C:/', 'C:/foo')
502 self.assertRelpath('foo', 'X:/', 'X:/foo')
503 self.assertRelpath('foo', 'X:/', 'X://foo')
504
505
463class TestPumpFile(tests.TestCase):506class TestPumpFile(tests.TestCase):
464 """Test pumpfile method."""507 """Test pumpfile method."""
465508

Subscribers

People subscribed via source and target branches