Merge lp:~ericmoritz/bzr/488519-walkdirs-encoding-bug into lp:bzr

Proposed by Eric Moritz
Status: Superseded
Proposed branch: lp:~ericmoritz/bzr/488519-walkdirs-encoding-bug
Merge into: lp:bzr
Diff against target: 187 lines (+72/-11)
4 files modified
bzrlib/errors.py (+1/-1)
bzrlib/osutils.py (+25/-9)
bzrlib/tests/__init__.py (+11/-0)
bzrlib/tests/test_osutils.py (+35/-1)
To merge this branch: bzr merge lp:~ericmoritz/bzr/488519-walkdirs-encoding-bug
Reviewer Review Type Date Requested Status
Martin Packman Pending
Eric Moritz Pending
Martin Pool Pending
Review via email: mp+27004@code.launchpad.net

This proposal has been superseded by a proposal from 2010-06-08.

Description of the change

A fix for bug #488519

To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'bzrlib/errors.py'
--- bzrlib/errors.py 2010-05-28 06:04:57 +0000
+++ bzrlib/errors.py 2010-06-08 01:47:22 +0000
@@ -1914,7 +1914,7 @@
19141914
1915 _fmt = "Parameter %(param)s is neither unicode nor utf8."1915 _fmt = "Parameter %(param)s is neither unicode nor utf8."
19161916
19171917
1918class ReusingTransform(BzrError):1918class ReusingTransform(BzrError):
19191919
1920 _fmt = "Attempt to reuse a transform that has already been applied."1920 _fmt = "Attempt to reuse a transform that has already been applied."
19211921
=== modified file 'bzrlib/osutils.py'
--- bzrlib/osutils.py 2010-05-27 17:59:18 +0000
+++ bzrlib/osutils.py 2010-06-08 01:47:22 +0000
@@ -931,7 +931,7 @@
931931
932def parent_directories(filename):932def parent_directories(filename):
933 """Return the list of parent directories, deepest first.933 """Return the list of parent directories, deepest first.
934 934
935 For example, parent_directories("a/b/c") -> ["a/b", "a"].935 For example, parent_directories("a/b/c") -> ["a/b", "a"].
936 """936 """
937 parents = []937 parents = []
@@ -961,7 +961,7 @@
961 # NB: This docstring is just an example, not a doctest, because doctest961 # NB: This docstring is just an example, not a doctest, because doctest
962 # currently can't cope with the use of lazy imports in this namespace --962 # currently can't cope with the use of lazy imports in this namespace --
963 # mbp 20090729963 # mbp 20090729
964 964
965 # This currently doesn't report the failure at the time it occurs, because965 # This currently doesn't report the failure at the time it occurs, because
966 # they tend to happen very early in startup when we can't check config966 # they tend to happen very early in startup when we can't check config
967 # files etc, and also we want to report all failures but not spam the user967 # files etc, and also we want to report all failures but not spam the user
@@ -1037,8 +1037,8 @@
10371037
10381038
1039def delete_any(path):1039def delete_any(path):
1040 """Delete a file, symlink or directory. 1040 """Delete a file, symlink or directory.
1041 1041
1042 Will delete even if readonly.1042 Will delete even if readonly.
1043 """1043 """
1044 try:1044 try:
@@ -1233,6 +1233,22 @@
1233 # but for now, we haven't optimized...1233 # but for now, we haven't optimized...
1234 return [canonical_relpath(base, p) for p in paths]1234 return [canonical_relpath(base, p) for p in paths]
12351235
1236
1237def decode_filename(filename):
1238 """Decode the filename using the filesystem encoding
1239
1240 If it is unicode, it is returned.
1241 Otherwise it is decoded from the the filesystem's encoding. If decoding
1242 fails, a errors.BadFilenameEncoding exception is raised.
1243 """
1244 if isinstance(filename, unicode):
1245 return filename
1246 try:
1247 return filename.decode(_fs_enc)
1248 except UnicodeDecodeError:
1249 raise errors.BadFilenameEncoding(filename, _fs_enc)
1250
1251
1236def safe_unicode(unicode_or_utf8_string):1252def safe_unicode(unicode_or_utf8_string):
1237 """Coerce unicode_or_utf8_string into unicode.1253 """Coerce unicode_or_utf8_string into unicode.
12381254
@@ -1644,7 +1660,7 @@
1644 dirblock = []1660 dirblock = []
1645 append = dirblock.append1661 append = dirblock.append
1646 try:1662 try:
1647 names = sorted(_listdir(top))1663 names = sorted(map(decode_filename, _listdir(top)))
1648 except OSError, e:1664 except OSError, e:
1649 if not _is_error_enotdir(e):1665 if not _is_error_enotdir(e):
1650 raise1666 raise
@@ -2020,14 +2036,14 @@
20202036
2021def send_all(sock, bytes, report_activity=None):2037def send_all(sock, bytes, report_activity=None):
2022 """Send all bytes on a socket.2038 """Send all bytes on a socket.
2023 2039
2024 Breaks large blocks in smaller chunks to avoid buffering limitations on2040 Breaks large blocks in smaller chunks to avoid buffering limitations on
2025 some platforms, and catches EINTR which may be thrown if the send is2041 some platforms, and catches EINTR which may be thrown if the send is
2026 interrupted by a signal.2042 interrupted by a signal.
20272043
2028 This is preferred to socket.sendall(), because it avoids portability bugs2044 This is preferred to socket.sendall(), because it avoids portability bugs
2029 and provides activity reporting.2045 and provides activity reporting.
2030 2046
2031 :param report_activity: Call this as bytes are read, see2047 :param report_activity: Call this as bytes are read, see
2032 Transport._report_activity2048 Transport._report_activity
2033 """2049 """
@@ -2121,7 +2137,7 @@
21212137
2122def until_no_eintr(f, *a, **kw):2138def until_no_eintr(f, *a, **kw):
2123 """Run f(*a, **kw), retrying if an EINTR error occurs.2139 """Run f(*a, **kw), retrying if an EINTR error occurs.
2124 2140
2125 WARNING: you must be certain that it is safe to retry the call repeatedly2141 WARNING: you must be certain that it is safe to retry the call repeatedly
2126 if EINTR does occur. This is typically only true for low-level operations2142 if EINTR does occur. This is typically only true for low-level operations
2127 like os.read. If in any doubt, don't use this.2143 like os.read. If in any doubt, don't use this.
@@ -2258,7 +2274,7 @@
2258if sys.platform == 'win32':2274if sys.platform == 'win32':
2259 def open_file(filename, mode='r', bufsize=-1):2275 def open_file(filename, mode='r', bufsize=-1):
2260 """This function is used to override the ``open`` builtin.2276 """This function is used to override the ``open`` builtin.
2261 2277
2262 But it uses O_NOINHERIT flag so the file handle is not inherited by2278 But it uses O_NOINHERIT flag so the file handle is not inherited by
2263 child processes. Deleting or renaming a closed file opened with this2279 child processes. Deleting or renaming a closed file opened with this
2264 function is not blocking child processes.2280 function is not blocking child processes.
22652281
=== modified file 'bzrlib/tests/__init__.py'
--- bzrlib/tests/__init__.py 2010-05-25 17:27:52 +0000
+++ bzrlib/tests/__init__.py 2010-06-08 01:47:22 +0000
@@ -4345,6 +4345,17 @@
4345UnicodeFilename = _UnicodeFilename()4345UnicodeFilename = _UnicodeFilename()
43464346
43474347
4348class _ByteStringNamedFilesystem(Feature):
4349 """Is the filesystem based on bytes?"""
4350
4351 def _probe(self):
4352 if os.name == "posix":
4353 return True
4354 return False
4355
4356ByteStringNamedFilesystem = _ByteStringNamedFilesystem()
4357
4358
4348class _UTF8Filesystem(Feature):4359class _UTF8Filesystem(Feature):
4349 """Is the filesystem UTF-8?"""4360 """Is the filesystem UTF-8?"""
43504361
43514362
=== modified file 'bzrlib/tests/test_osutils.py'
--- bzrlib/tests/test_osutils.py 2010-05-27 17:59:18 +0000
+++ bzrlib/tests/test_osutils.py 2010-06-08 01:47:22 +0000
@@ -1083,6 +1083,40 @@
1083 # Ensure the message contains the file name1083 # Ensure the message contains the file name
1084 self.assertContainsRe(str(e), "\./test-unreadable")1084 self.assertContainsRe(str(e), "\./test-unreadable")
10851085
1086
1087 def test_walkdirs_encoding_error(self):
1088 # <https://bugs.launchpad.net/bzr/+bug/488519>
1089 # walkdirs didn't raise a useful message when the filenames
1090 # are not using the filesystem's encoding
1091
1092 # require a bytestring based filesystem
1093 self.requireFeature(tests.ByteStringNamedFilesystem)
1094
1095 tree = [
1096 '.bzr',
1097 '0file',
1098 '1dir/',
1099 '1dir/0file',
1100 '1dir/1dir/',
1101 '1file'
1102 ]
1103
1104 self.build_tree(tree)
1105
1106 # rename the 1file to a latin-1 filename
1107 os.rename("./1file", "\xe8file")
1108
1109 self._save_platform_info()
1110 win32utils.winver = None # Avoid the win32 detection code
1111 osutils._fs_enc = 'UTF-8'
1112
1113 # this should raise on error
1114 def attempt():
1115 for dirdetail, dirblock in osutils.walkdirs('.'):
1116 pass
1117
1118 self.assertRaises(errors.BadFilenameEncoding, attempt)
1119
1086 def test__walkdirs_utf8(self):1120 def test__walkdirs_utf8(self):
1087 tree = [1121 tree = [
1088 '.bzr',1122 '.bzr',
@@ -1921,7 +1955,7 @@
1921 def restore_osutils_globals(self):1955 def restore_osutils_globals(self):
1922 osutils._terminal_size_state = self._orig_terminal_size_state1956 osutils._terminal_size_state = self._orig_terminal_size_state
1923 osutils._first_terminal_size = self._orig_first_terminal_size1957 osutils._first_terminal_size = self._orig_first_terminal_size
1924 1958
1925 def replace_stdout(self, new):1959 def replace_stdout(self, new):
1926 self.overrideAttr(sys, 'stdout', new)1960 self.overrideAttr(sys, 'stdout', new)
19271961