##// END OF EJS Templates
win32mbcs: use absolute_import
timeless -
r28417:588874c3 default
parent child Browse files
Show More
@@ -1,189 +1,196
1 1 # win32mbcs.py -- MBCS filename support for Mercurial
2 2 #
3 3 # Copyright (c) 2008 Shun-ichi Goto <shunichi.goto@gmail.com>
4 4 #
5 5 # Version: 0.3
6 6 # Author: Shun-ichi Goto <shunichi.goto@gmail.com>
7 7 #
8 8 # This software may be used and distributed according to the terms of the
9 9 # GNU General Public License version 2 or any later version.
10 10 #
11 11
12 12 '''allow the use of MBCS paths with problematic encodings
13 13
14 14 Some MBCS encodings are not good for some path operations (i.e.
15 15 splitting path, case conversion, etc.) with its encoded bytes. We call
16 16 such a encoding (i.e. shift_jis and big5) as "problematic encoding".
17 17 This extension can be used to fix the issue with those encodings by
18 18 wrapping some functions to convert to Unicode string before path
19 19 operation.
20 20
21 21 This extension is useful for:
22 22
23 23 - Japanese Windows users using shift_jis encoding.
24 24 - Chinese Windows users using big5 encoding.
25 25 - All users who use a repository with one of problematic encodings on
26 26 case-insensitive file system.
27 27
28 28 This extension is not needed for:
29 29
30 30 - Any user who use only ASCII chars in path.
31 31 - Any user who do not use any of problematic encodings.
32 32
33 33 Note that there are some limitations on using this extension:
34 34
35 35 - You should use single encoding in one repository.
36 36 - If the repository path ends with 0x5c, .hg/hgrc cannot be read.
37 37 - win32mbcs is not compatible with fixutf8 extension.
38 38
39 39 By default, win32mbcs uses encoding.encoding decided by Mercurial.
40 40 You can specify the encoding by config option::
41 41
42 42 [win32mbcs]
43 43 encoding = sjis
44 44
45 45 It is useful for the users who want to commit with UTF-8 log message.
46 46 '''
47 from __future__ import absolute_import
47 48
48 import os, sys
49 import os
50 import sys
51
52 from mercurial import (
53 encoding,
54 error,
55 )
49 56 from mercurial.i18n import _
50 from mercurial import error, encoding
57
51 58 # Note for extension authors: ONLY specify testedwith = 'internal' for
52 59 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
53 60 # be specifying the version(s) of Mercurial they are tested with, or
54 61 # leave the attribute unspecified.
55 62 testedwith = 'internal'
56 63
57 64 _encoding = None # see extsetup
58 65
59 66 def decode(arg):
60 67 if isinstance(arg, str):
61 68 uarg = arg.decode(_encoding)
62 69 if arg == uarg.encode(_encoding):
63 70 return uarg
64 71 raise UnicodeError("Not local encoding")
65 72 elif isinstance(arg, tuple):
66 73 return tuple(map(decode, arg))
67 74 elif isinstance(arg, list):
68 75 return map(decode, arg)
69 76 elif isinstance(arg, dict):
70 77 for k, v in arg.items():
71 78 arg[k] = decode(v)
72 79 return arg
73 80
74 81 def encode(arg):
75 82 if isinstance(arg, unicode):
76 83 return arg.encode(_encoding)
77 84 elif isinstance(arg, tuple):
78 85 return tuple(map(encode, arg))
79 86 elif isinstance(arg, list):
80 87 return map(encode, arg)
81 88 elif isinstance(arg, dict):
82 89 for k, v in arg.items():
83 90 arg[k] = encode(v)
84 91 return arg
85 92
86 93 def appendsep(s):
87 94 # ensure the path ends with os.sep, appending it if necessary.
88 95 try:
89 96 us = decode(s)
90 97 except UnicodeError:
91 98 us = s
92 99 if us and us[-1] not in ':/\\':
93 100 s += os.sep
94 101 return s
95 102
96 103
97 104 def basewrapper(func, argtype, enc, dec, args, kwds):
98 105 # check check already converted, then call original
99 106 for arg in args:
100 107 if isinstance(arg, argtype):
101 108 return func(*args, **kwds)
102 109
103 110 try:
104 111 # convert string arguments, call func, then convert back the
105 112 # return value.
106 113 return enc(func(*dec(args), **dec(kwds)))
107 114 except UnicodeError:
108 115 raise error.Abort(_("[win32mbcs] filename conversion failed with"
109 116 " %s encoding\n") % (_encoding))
110 117
111 118 def wrapper(func, args, kwds):
112 119 return basewrapper(func, unicode, encode, decode, args, kwds)
113 120
114 121
115 122 def reversewrapper(func, args, kwds):
116 123 return basewrapper(func, str, decode, encode, args, kwds)
117 124
118 125 def wrapperforlistdir(func, args, kwds):
119 126 # Ensure 'path' argument ends with os.sep to avoids
120 127 # misinterpreting last 0x5c of MBCS 2nd byte as path separator.
121 128 if args:
122 129 args = list(args)
123 130 args[0] = appendsep(args[0])
124 131 if 'path' in kwds:
125 132 kwds['path'] = appendsep(kwds['path'])
126 133 return func(*args, **kwds)
127 134
128 135 def wrapname(name, wrapper):
129 136 module, name = name.rsplit('.', 1)
130 137 module = sys.modules[module]
131 138 func = getattr(module, name)
132 139 def f(*args, **kwds):
133 140 return wrapper(func, args, kwds)
134 141 try:
135 142 f.__name__ = func.__name__ # fails with Python 2.3
136 143 except Exception:
137 144 pass
138 145 setattr(module, name, f)
139 146
140 147 # List of functions to be wrapped.
141 148 # NOTE: os.path.dirname() and os.path.basename() are safe because
142 149 # they use result of os.path.split()
143 150 funcs = '''os.path.join os.path.split os.path.splitext
144 151 os.path.normpath os.makedirs
145 152 mercurial.util.endswithsep mercurial.util.splitpath mercurial.util.checkcase
146 153 mercurial.util.fspath mercurial.util.pconvert mercurial.util.normpath
147 154 mercurial.util.checkwinfilename mercurial.util.checkosfilename
148 155 mercurial.util.split'''
149 156
150 157 # These functions are required to be called with local encoded string
151 158 # because they expects argument is local encoded string and cause
152 159 # problem with unicode string.
153 160 rfuncs = '''mercurial.encoding.upper mercurial.encoding.lower'''
154 161
155 162 # List of Windows specific functions to be wrapped.
156 163 winfuncs = '''os.path.splitunc'''
157 164
158 165 # codec and alias names of sjis and big5 to be faked.
159 166 problematic_encodings = '''big5 big5-tw csbig5 big5hkscs big5-hkscs
160 167 hkscs cp932 932 ms932 mskanji ms-kanji shift_jis csshiftjis shiftjis
161 168 sjis s_jis shift_jis_2004 shiftjis2004 sjis_2004 sjis2004
162 169 shift_jisx0213 shiftjisx0213 sjisx0213 s_jisx0213 950 cp950 ms950 '''
163 170
164 171 def extsetup(ui):
165 172 # TODO: decide use of config section for this extension
166 173 if ((not os.path.supports_unicode_filenames) and
167 174 (sys.platform != 'cygwin')):
168 175 ui.warn(_("[win32mbcs] cannot activate on this platform.\n"))
169 176 return
170 177 # determine encoding for filename
171 178 global _encoding
172 179 _encoding = ui.config('win32mbcs', 'encoding', encoding.encoding)
173 180 # fake is only for relevant environment.
174 181 if _encoding.lower() in problematic_encodings.split():
175 182 for f in funcs.split():
176 183 wrapname(f, wrapper)
177 184 if os.name == 'nt':
178 185 for f in winfuncs.split():
179 186 wrapname(f, wrapper)
180 187 wrapname("mercurial.osutil.listdir", wrapperforlistdir)
181 188 # wrap functions to be called with local byte string arguments
182 189 for f in rfuncs.split():
183 190 wrapname(f, reversewrapper)
184 191 # Check sys.args manually instead of using ui.debug() because
185 192 # command line options is not yet applied when
186 193 # extensions.loadall() is called.
187 194 if '--debug' in sys.argv:
188 195 ui.write("[win32mbcs] activated with encoding: %s\n"
189 196 % _encoding)
@@ -1,130 +1,129
1 1 #require test-repo
2 2
3 3 $ cd "$TESTDIR"/..
4 4
5 5 $ hg files 'set:(**.py)' | sed 's|\\|/|g' | xargs python contrib/check-py3-compat.py
6 6 contrib/check-code.py not using absolute_import
7 7 contrib/check-code.py requires print_function
8 8 contrib/debugshell.py not using absolute_import
9 9 contrib/import-checker.py not using absolute_import
10 10 contrib/import-checker.py requires print_function
11 11 contrib/memory.py not using absolute_import
12 12 contrib/perf.py not using absolute_import
13 13 contrib/python-hook-examples.py not using absolute_import
14 14 contrib/revsetbenchmarks.py not using absolute_import
15 15 contrib/revsetbenchmarks.py requires print_function
16 16 contrib/showstack.py not using absolute_import
17 17 contrib/synthrepo.py not using absolute_import
18 18 contrib/win32/hgwebdir_wsgi.py not using absolute_import
19 19 doc/check-seclevel.py not using absolute_import
20 20 doc/gendoc.py not using absolute_import
21 21 doc/hgmanpage.py not using absolute_import
22 22 hgext/__init__.py not using absolute_import
23 23 hgext/color.py not using absolute_import
24 24 hgext/eol.py not using absolute_import
25 25 hgext/extdiff.py not using absolute_import
26 26 hgext/factotum.py not using absolute_import
27 27 hgext/fetch.py not using absolute_import
28 28 hgext/gpg.py not using absolute_import
29 29 hgext/graphlog.py not using absolute_import
30 30 hgext/hgcia.py not using absolute_import
31 31 hgext/hgk.py not using absolute_import
32 32 hgext/highlight/__init__.py not using absolute_import
33 33 hgext/highlight/highlight.py not using absolute_import
34 34 hgext/histedit.py not using absolute_import
35 35 hgext/largefiles/__init__.py not using absolute_import
36 36 hgext/largefiles/basestore.py not using absolute_import
37 37 hgext/largefiles/lfcommands.py not using absolute_import
38 38 hgext/largefiles/lfutil.py not using absolute_import
39 39 hgext/largefiles/localstore.py not using absolute_import
40 40 hgext/largefiles/overrides.py not using absolute_import
41 41 hgext/largefiles/proto.py not using absolute_import
42 42 hgext/largefiles/remotestore.py not using absolute_import
43 43 hgext/largefiles/reposetup.py not using absolute_import
44 44 hgext/largefiles/uisetup.py not using absolute_import
45 45 hgext/largefiles/wirestore.py not using absolute_import
46 46 hgext/mq.py not using absolute_import
47 47 hgext/rebase.py not using absolute_import
48 48 hgext/share.py not using absolute_import
49 49 hgext/transplant.py not using absolute_import
50 hgext/win32mbcs.py not using absolute_import
51 50 hgext/win32text.py not using absolute_import
52 51 i18n/check-translation.py not using absolute_import
53 52 i18n/polib.py not using absolute_import
54 53 setup.py not using absolute_import
55 54 tests/filterpyflakes.py requires print_function
56 55 tests/generate-working-copy-states.py requires print_function
57 56 tests/get-with-headers.py requires print_function
58 57 tests/heredoctest.py requires print_function
59 58 tests/hypothesishelpers.py not using absolute_import
60 59 tests/hypothesishelpers.py requires print_function
61 60 tests/killdaemons.py not using absolute_import
62 61 tests/md5sum.py not using absolute_import
63 62 tests/mockblackbox.py not using absolute_import
64 63 tests/printenv.py not using absolute_import
65 64 tests/readlink.py not using absolute_import
66 65 tests/readlink.py requires print_function
67 66 tests/revlog-formatv0.py not using absolute_import
68 67 tests/run-tests.py not using absolute_import
69 68 tests/seq.py not using absolute_import
70 69 tests/seq.py requires print_function
71 70 tests/silenttestrunner.py not using absolute_import
72 71 tests/silenttestrunner.py requires print_function
73 72 tests/sitecustomize.py not using absolute_import
74 73 tests/svn-safe-append.py not using absolute_import
75 74 tests/svnxml.py not using absolute_import
76 75 tests/test-ancestor.py requires print_function
77 76 tests/test-atomictempfile.py not using absolute_import
78 77 tests/test-batching.py not using absolute_import
79 78 tests/test-batching.py requires print_function
80 79 tests/test-bdiff.py not using absolute_import
81 80 tests/test-bdiff.py requires print_function
82 81 tests/test-context.py not using absolute_import
83 82 tests/test-context.py requires print_function
84 83 tests/test-demandimport.py not using absolute_import
85 84 tests/test-demandimport.py requires print_function
86 85 tests/test-doctest.py not using absolute_import
87 86 tests/test-duplicateoptions.py not using absolute_import
88 87 tests/test-duplicateoptions.py requires print_function
89 88 tests/test-filecache.py not using absolute_import
90 89 tests/test-filecache.py requires print_function
91 90 tests/test-filelog.py not using absolute_import
92 91 tests/test-filelog.py requires print_function
93 92 tests/test-hg-parseurl.py not using absolute_import
94 93 tests/test-hg-parseurl.py requires print_function
95 94 tests/test-hgweb-auth.py not using absolute_import
96 95 tests/test-hgweb-auth.py requires print_function
97 96 tests/test-hgwebdir-paths.py not using absolute_import
98 97 tests/test-hybridencode.py not using absolute_import
99 98 tests/test-hybridencode.py requires print_function
100 99 tests/test-lrucachedict.py not using absolute_import
101 100 tests/test-lrucachedict.py requires print_function
102 101 tests/test-manifest.py not using absolute_import
103 102 tests/test-minirst.py not using absolute_import
104 103 tests/test-minirst.py requires print_function
105 104 tests/test-parseindex2.py not using absolute_import
106 105 tests/test-parseindex2.py requires print_function
107 106 tests/test-pathencode.py not using absolute_import
108 107 tests/test-pathencode.py requires print_function
109 108 tests/test-propertycache.py not using absolute_import
110 109 tests/test-propertycache.py requires print_function
111 110 tests/test-revlog-ancestry.py not using absolute_import
112 111 tests/test-revlog-ancestry.py requires print_function
113 112 tests/test-run-tests.py not using absolute_import
114 113 tests/test-simplemerge.py not using absolute_import
115 114 tests/test-status-inprocess.py not using absolute_import
116 115 tests/test-status-inprocess.py requires print_function
117 116 tests/test-symlink-os-yes-fs-no.py not using absolute_import
118 117 tests/test-trusted.py not using absolute_import
119 118 tests/test-trusted.py requires print_function
120 119 tests/test-ui-color.py not using absolute_import
121 120 tests/test-ui-color.py requires print_function
122 121 tests/test-ui-config.py not using absolute_import
123 122 tests/test-ui-config.py requires print_function
124 123 tests/test-ui-verbosity.py not using absolute_import
125 124 tests/test-ui-verbosity.py requires print_function
126 125 tests/test-url.py not using absolute_import
127 126 tests/test-url.py requires print_function
128 127 tests/test-walkrepo.py requires print_function
129 128 tests/test-wireproto.py requires print_function
130 129 tests/tinyproxy.py requires print_function
General Comments 0
You need to be logged in to leave comments. Login now