# Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: shiena.jp@gmail.com-20100724123205-pce5lreh9z6jzwxo # target_branch: bzr+ssh://bazaar.launchpad.net/~bzr-pqm/bzr/bzr.dev/ # testament_sha1: ea9038d7f2f1dc7c7016e3b68ee00918cf7f79ec # timestamp: 2010-07-24 21:44:32 +0900 # base_revision_id: pqm@pqm.ubuntu.com-20100724001123-fexv81gfn5j94yif # # Begin patch === modified file 'bzrlib/mutabletree.py' --- bzrlib/mutabletree.py 2010-07-16 13:06:33 +0000 +++ bzrlib/mutabletree.py 2010-07-24 12:32:05 +0000 @@ -668,6 +668,10 @@ else: self.base_path = base_path self.raw_path = path + import sys + if sys.platform == 'darwin': + self.base_path = osutils.normalized_filename(self.base_path)[0] + self.raw_path = osutils.normalized_filename(self.raw_path)[0] def __cmp__(self, other): return cmp(self.raw_path, other.raw_path) === modified file 'bzrlib/osutils.py' --- bzrlib/osutils.py 2010-07-09 16:16:11 +0000 +++ bzrlib/osutils.py 2010-07-24 12:32:05 +0000 @@ -1749,7 +1749,17 @@ # 0 - relpath, 1- basename, 2- kind, 3- stat, 4-toppath # But we don't actually uses 1-3 in pending, so set them to None pending = [[_selected_dir_reader.top_prefix_to_starting_dir(top, prefix)]] - read_dir = _selected_dir_reader.read_dir + if sys.platform == 'darwin': + def read_dir(relroot, top): + def norm_utf8(path): + if isinstance(path, unicode): + return normalized_filename(path)[0] + else: + return normalized_filename(unicode(path, 'utf8'))[0].encode('utf8') + return [(norm_utf8(rp), norm_utf8(bn), ki, st, norm_utf8(tp)) \ + for rp, bn, ki, st, tp in _selected_dir_reader.read_dir(relroot, top)] + else: + read_dir = _selected_dir_reader.read_dir _directory = _directory_kind while pending: relroot, _, _, _, top = pending[-1].pop() === modified file 'bzrlib/tests/test_osutils.py' --- bzrlib/tests/test_osutils.py 2010-07-08 09:11:44 +0000 +++ bzrlib/tests/test_osutils.py 2010-07-24 12:32:05 +0000 @@ -1328,6 +1328,73 @@ result.append((dirdetail, new_dirblock)) self.assertEqual(expected_dirblocks, result) + def test_unicode__walkdirs_utf8_with_nfd(self): + """Walkdirs_utf8 should always return utf8 paths. + + The abspath portion might be in unicode or utf-8 + """ + self.requireFeature(tests.UnicodeFilenameFeature) + # NFC 'GA' : u'\u30ac' + # NFD 'GA' : u'\u30ab\u3099' + # - Unicode Character 'KATAKANA LETTER GA' (U+30AC) + # - Unicode Character 'KATAKANA LETTER KA' (U+30AB) + # - Unicode Character 'COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK' (U+3099) + name0 = u'0file-\u30ac' + name1 = u'1dir-\u30ab\u3099' + name2 = u'2file-\u30ab\u3099' + tree = [ + name0, + name1 + '/', + name1 + '/' + name0, + name1 + '/' + name1 + '/', + name2, + ] + self.build_tree(tree) + from unicodedata import normalize + name0 = normalize('NFC', name0).encode('utf8') + name1 = normalize('NFC', name1).encode('utf8') + name2 = normalize('NFC', name2).encode('utf8') + + expected_dirblocks = [ + (('', '.'), + [(name0, name0, 'file', './' + name0), + (name1, name1, 'directory', './' + name1), + (name2, name2, 'file', './' + name2), + ] + ), + ((name1, './' + name1), + [(name1 + '/' + name0, name0, 'file', './' + name1 + + '/' + name0), + (name1 + '/' + name1, name1, 'directory', './' + name1 + + '/' + name1), + ] + ), + ((name1 + '/' + name1, './' + name1 + '/' + name1), + [ + ] + ), + ] + result = [] + # For ease in testing, if walkdirs_utf8 returns Unicode, assert that + # all abspaths are Unicode, and encode them back into utf8. + for dirdetail, dirblock in osutils._walkdirs_utf8('.'): + self.assertIsInstance(dirdetail[0], str) + if isinstance(dirdetail[1], unicode): + dirdetail = (dirdetail[0], dirdetail[1].encode('utf8')) + dirblock = [list(info) for info in dirblock] + for info in dirblock: + self.assertIsInstance(info[4], unicode) + info[4] = info[4].encode('utf8') + new_dirblock = [] + for info in dirblock: + self.assertIsInstance(info[0], str) + self.assertIsInstance(info[1], str) + self.assertIsInstance(info[4], str) + # Remove the stat information + new_dirblock.append((info[0], info[1], info[2], info[4])) + result.append((dirdetail, new_dirblock)) + self.assertEqual(expected_dirblocks, result) + def test__walkdirs_utf8_with_unicode_fs(self): """UnicodeDirReader should be a safe fallback everywhere # Begin bundle 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 /8XckU4UJDfVeFbA