Show More
@@ -197,3 +197,4 b' 8fca7e8449a847e3cf1054f2c07b51237699fad3' | |||
|
197 | 197 | 26ce8e7515036d3431a03aaeb7bc72dd96cb1112 0 iQJJBAABCgAzFiEE64UTlbQiPuL3ugso2lR0C/CHMroFAl6YlRUVHDc4OTVwdWxraXRAZ21haWwuY29tAAoJENpUdAvwhzK6Z3YP/iOqphn99v0z2OupCl0q8CepbcdZMJWW3j00OAHYSO43M0FULpMpzC2o+kZDeqeLyzN7DsjoGts2cUnAOe9WX73sPkX1n1dbiDcUSsRqNND+tCkEZMtTn4DaGNIq1zSkkm8Q7O/1uwZPnX6FaIRMBs9qGbdfmMPNEvzny2tgrKc3ra1+AA8RCdtsbpqhjy+xf+EKVB/SMsQVVSJEgPkUkW6PwpaspdrxQKgZrb7C7Jx/gRVzMTUmCQe1sVCSnZNO3I/woAqDY2UNg7/hBubeRh/EjoH1o4ONTXgBQdYCl7QdcwDHpDc2HstonrFq51qxBecHDVw+ZKQds63Ixtxuab3SK0o/SWabZ1v8bGaWnyWnRWXL/1qkyFWly+fjEGGlv1kHl3n0UmwlUY8FQJCYDZgR0FqQGXAF3vMJOEp82ysk6jWN/7NRzcnoUC7HpNo1jPMiPRjskgVf3bhErfUQnhlF1YsVu/jPTixyfftbiaZmwILMkaPF8Kg3Cyf63p2cdcnTHdbP1U6ncR+BucthlbFei4WL0J2iERb8TBeCxOyCHlEUq8kampjbmPXN7VxnK4oX3xeBTf8mMbvrD5Fv3svRD+SkCCKu/MwQvB1VT6q425TSKHbCWeNqGjVLvetpx+skVH7eaXLEQ3wlCfo/0OQTRimx2O73EnOF5r8Q2POm |
|
198 | 198 | cf3e07d7648a4371ce584d15dd692e7a6845792f 0 iQJJBAABCgAzFiEE64UTlbQiPuL3ugso2lR0C/CHMroFAl6sS5sVHDc4OTVwdWxraXRAZ21haWwuY29tAAoJENpUdAvwhzK6FQcP/1usy9WxajBppBZ54ep+qesxufLoux5qkRU7j4XZ0Id4/IcKQZeik0C/0mFMjc+dYhQDGpDiuXCADKMv5h2DCIoaWUC0GueVtVkPhhMW3zMg/BmepV7dhUuipfQ4fck8gYuaBOclunLX1MFd+CS/6BQ6XIrsKasnx9WrbO2JpieBXv+8I5mslChaZf2AxeIvUVb2BkKqsCD0rqbIjTjtfHWJpaH6spFa7XX/BZWeEYz2Nc6LVJNZY0AmvJh8ebpoGOx85dokRIEAzTmBh04SbkChi+350ki6MvG3Ax+3yrUZVc1PJtBDreL7dMs7Y3ENafSMhKnBrRaPVMyUHEm2Ygn4cmJ1YiGw4OWha1n7dtRW/uI96lXKDt8iLAQ4WBRojPhYNl4L3b6/6voCgpZUOpd7PgTRc3/00siCmYIOQzAO0HkDsALoNpk8LcCxpPFYTr8dF3bSsAT9fuaLNV6tI2ofbRLXh0gFXYdaWu10eVRrSMUMiH7n3H6EpzLa4sNdyFrK0vU4aSTlBERcjj2rj86dY0XQQL181V7Yhg8m8nyj+BzraRh7et2UXNsVosOnbTa1XX0qFVu+qAVp2BeqC4k31jm0MJk+1pDzkuAPs07z3ITwkDmTHjzxm5qoZyZ1/n37BB6miD+8xJYNH7vBX/yrDW790HbloasQOcXcerNR |
|
199 | 199 | 065704cbdbdbb05dcd6bb814eb9bbdd982211b28 0 iQJJBAABCgAzFiEE64UTlbQiPuL3ugso2lR0C/CHMroFAl7amzkVHDc4OTVwdWxraXRAZ21haWwuY29tAAoJENpUdAvwhzK6AKEP/26Hoe8VqkuGwU0ZDsK6YgErXEPs8xtgZ9A2iouDkIqw2dm1TDmWnB5X8XaWmhAWFMUdjcqd1ZZJrAyD0p13xUOm3D+hlDXYTd2INkLwS8cVu22czZ5eoxtPkjuGYlPvek9b3vrrejkZ4vpamdS3iSvIx+TzvEW+w5eZFh9s1a9gR77hcZZoir24vtM9MsNnnBuI/5/fdWkhBoe17HSU4II56ckNXDrGO0nuqrWDxPr64WAcz6EmlTGc+cUqOM45Uc0sCr3GNQGEm6VCAw5oXq2Vt9O6sjgExLxr8zdud6w5hl9b8h2MrxyisgcnVR7efbumaRuNb8QZZPzk5QqlRxbaEcStyIXzAdar4fArQUY2vrmv1WyLJR3S/G3p8QkyWYL3CZNKjCAVxSa5ytS5Dr/bM2sWaEnIHqq+W6DOagpWV4uRRnwaId9tB9b0KBoFElXZRlaq0FlNYG8RLg65ZlkF+lj6RACO23epxapadcJwibDQiNYX20mcSEFDkSEgECnLQBecA2WZvw134RRbL3vuvB49SKS0ZEJ95myXMZa9kyIJY/g+oAFBuyZeK9O8DwGii0zFDOi6VWDTZzc3/15RRS6ehqQyYrLQntYtVGwHpxnUrp2kBjk3hDIvaYOcFbTnhTGcQCzckFnIZN2oxr5YZOI+Fpfak6RQTVhnHh0/ |
|
200 | 0ea9c86fac8974cd74dc12ea681c8986eb6da6c4 0 iQJJBAABCgAzFiEE64UTlbQiPuL3ugso2lR0C/CHMroFAl78z0gVHDc4OTVwdWxraXRAZ21haWwuY29tAAoJENpUdAvwhzK6IrkP/2m/DJ93BR/SljCFe7KnExrDTzDI/i69x+ljomRZJmMRa86zRkclgd5L49woExDd1ZGebUY650V16adKNmVpz2rS6bQOgEr2NBD5fL+GiTX6UJ1VMgmQ8x1m8DYuI8pfBWbqQuZIl1vCEc0RmT3tHLZ7T8XgG9RXa4XielI2uhyimJPyZsE1K7c8Fa6UakH++DhYFBj+3QYbwS2fFDdA29L/4N5JLUzHkIbF7tPg7P1RBk+vhopKz9MMIu4S95LU+Gk7eQ3FfE8Jnv959hX2o/B2sdT2tEPIuDRSxZhSKLdlGbMy5IZvc/bZ+a5jlb2w23tlpfgzQxNarFqpX/weiJCtsxzeMXQHEVFG/+VuIOIYbfILWzySFcnSvcAtmNXExxH2F9j+XmQkLysnsgIfplNVEEIgZDBPGAkAQ+lH7UrEdw31ciSrCDsjXDaPQWcmk4zkfrXlwN7R9zJguJ+OuZ/Ga7NXWdZAC+YkPSKAfCesdUefcesyiresO8GEk9DyRNQsX/gl5BjEeuqYyUsve5541IMqscvdosg6HrU/RrmeR7sM7tZrDwCWdOWu/GdFatQ+k6zArSrMTKUBztzV93MIwUHDrnd+7OOYDfAuqGy7oM2KoW0Jp8sS2hotIJZ9a+VGwQcxCJ93I5sVT6ePBdmBoIAFW+rbncnD+E/RvVpl |
@@ -210,3 +210,4 b' 8fca7e8449a847e3cf1054f2c07b51237699fad3' | |||
|
210 | 210 | 26ce8e7515036d3431a03aaeb7bc72dd96cb1112 5.4rc0 |
|
211 | 211 | cf3e07d7648a4371ce584d15dd692e7a6845792f 5.4 |
|
212 | 212 | 065704cbdbdbb05dcd6bb814eb9bbdd982211b28 5.4.1 |
|
213 | 0ea9c86fac8974cd74dc12ea681c8986eb6da6c4 5.4.2 |
@@ -3,6 +3,8 b'' | |||
|
3 | 3 | # Copyright(C) 2007 Daniel Holth et al |
|
4 | 4 | from __future__ import absolute_import |
|
5 | 5 | |
|
6 | import codecs | |
|
7 | import locale | |
|
6 | 8 | import os |
|
7 | 9 | import re |
|
8 | 10 | import xml.dom.minidom |
@@ -63,6 +65,38 b' except ImportError:' | |||
|
63 | 65 | svn = None |
|
64 | 66 | |
|
65 | 67 | |
|
68 | # In Subversion, paths and URLs are Unicode (encoded as UTF-8), which | |
|
69 | # Subversion converts from / to native strings when interfacing with the OS. | |
|
70 | # When passing paths and URLs to Subversion, we have to recode them such that | |
|
71 | # it roundstrips with what Subversion is doing. | |
|
72 | ||
|
73 | fsencoding = None | |
|
74 | ||
|
75 | ||
|
76 | def init_fsencoding(): | |
|
77 | global fsencoding, fsencoding_is_utf8 | |
|
78 | if fsencoding is not None: | |
|
79 | return | |
|
80 | if pycompat.iswindows: | |
|
81 | # On Windows, filenames are Unicode, but we store them using the MBCS | |
|
82 | # encoding. | |
|
83 | fsencoding = 'mbcs' | |
|
84 | else: | |
|
85 | # This is the encoding used to convert UTF-8 back to natively-encoded | |
|
86 | # strings in Subversion 1.14.0 or earlier with APR 1.7.0 or earlier. | |
|
87 | with util.with_lc_ctype(): | |
|
88 | fsencoding = locale.nl_langinfo(locale.CODESET) or 'ISO-8859-1' | |
|
89 | fsencoding = codecs.lookup(fsencoding).name | |
|
90 | fsencoding_is_utf8 = fsencoding == codecs.lookup('utf-8').name | |
|
91 | ||
|
92 | ||
|
93 | def fs2svn(s): | |
|
94 | if fsencoding_is_utf8: | |
|
95 | return s | |
|
96 | else: | |
|
97 | return s.decode(fsencoding).encode('utf-8') | |
|
98 | ||
|
99 | ||
|
66 | 100 | class SvnPathNotFound(Exception): |
|
67 | 101 | pass |
|
68 | 102 | |
@@ -106,8 +140,15 b' def quote(s):' | |||
|
106 | 140 | |
|
107 | 141 | |
|
108 | 142 | def geturl(path): |
|
143 | """Convert path or URL to a SVN URL, encoded in UTF-8. | |
|
144 | ||
|
145 | This can raise UnicodeDecodeError if the path or URL can't be converted to | |
|
146 | unicode using `fsencoding`. | |
|
147 | """ | |
|
109 | 148 | try: |
|
110 |
return svn.client.url_from_path( |
|
|
149 | return svn.client.url_from_path( | |
|
150 | svn.core.svn_path_canonicalize(fs2svn(path)) | |
|
151 | ) | |
|
111 | 152 | except svn.core.SubversionException: |
|
112 | 153 | # svn.client.url_from_path() fails with local repositories |
|
113 | 154 | pass |
@@ -117,7 +158,7 b' def geturl(path):' | |||
|
117 | 158 | path = b'/' + util.normpath(path) |
|
118 | 159 | # Module URL is later compared with the repository URL returned |
|
119 | 160 | # by svn API, which is UTF-8. |
|
120 |
path = |
|
|
161 | path = fs2svn(path) | |
|
121 | 162 | path = b'file://%s' % quote(path) |
|
122 | 163 | return svn.core.svn_path_canonicalize(path) |
|
123 | 164 | |
@@ -284,7 +325,9 b' def filecheck(ui, path, proto):' | |||
|
284 | 325 | def httpcheck(ui, path, proto): |
|
285 | 326 | try: |
|
286 | 327 | opener = urlreq.buildopener() |
|
287 | rsp = opener.open(b'%s://%s/!svn/ver/0/.svn' % (proto, path), b'rb') | |
|
328 | rsp = opener.open( | |
|
329 | pycompat.strurl(b'%s://%s/!svn/ver/0/.svn' % (proto, path)), b'rb' | |
|
330 | ) | |
|
288 | 331 | data = rsp.read() |
|
289 | 332 | except urlerr.httperror as inst: |
|
290 | 333 | if inst.code != 404: |
@@ -311,6 +354,32 b' protomap = {' | |||
|
311 | 354 | } |
|
312 | 355 | |
|
313 | 356 | |
|
357 | class NonUtf8PercentEncodedBytes(Exception): | |
|
358 | pass | |
|
359 | ||
|
360 | ||
|
361 | # Subversion paths are Unicode. Since the percent-decoding is done on | |
|
362 | # UTF-8-encoded strings, percent-encoded bytes are interpreted as UTF-8. | |
|
363 | def url2pathname_like_subversion(unicodepath): | |
|
364 | if pycompat.ispy3: | |
|
365 | # On Python 3, we have to pass unicode to urlreq.url2pathname(). | |
|
366 | # Percent-decoded bytes get decoded using UTF-8 and the 'replace' error | |
|
367 | # handler. | |
|
368 | unicodepath = urlreq.url2pathname(unicodepath) | |
|
369 | if u'\N{REPLACEMENT CHARACTER}' in unicodepath: | |
|
370 | raise NonUtf8PercentEncodedBytes | |
|
371 | else: | |
|
372 | return unicodepath | |
|
373 | else: | |
|
374 | # If we passed unicode on Python 2, it would be converted using the | |
|
375 | # latin-1 encoding. Therefore, we pass UTF-8-encoded bytes. | |
|
376 | unicodepath = urlreq.url2pathname(unicodepath.encode('utf-8')) | |
|
377 | try: | |
|
378 | return unicodepath.decode('utf-8') | |
|
379 | except UnicodeDecodeError: | |
|
380 | raise NonUtf8PercentEncodedBytes | |
|
381 | ||
|
382 | ||
|
314 | 383 | def issvnurl(ui, url): |
|
315 | 384 | try: |
|
316 | 385 | proto, path = url.split(b'://', 1) |
@@ -322,31 +391,58 b' def issvnurl(ui, url):' | |||
|
322 | 391 | and path[2:6].lower() == b'%3a/' |
|
323 | 392 | ): |
|
324 | 393 | path = path[:2] + b':/' + path[6:] |
|
325 | # pycompat.fsdecode() / pycompat.fsencode() are used so that bytes | |
|
326 | # in the URL roundtrip correctly on Unix. urlreq.url2pathname() on | |
|
327 | # py3 will decode percent-encoded bytes using the utf-8 encoding | |
|
328 | # and the "replace" error handler. This means that it will not | |
|
329 | # preserve non-UTF-8 bytes (https://bugs.python.org/issue40983). | |
|
330 | # url.open() uses the reverse function (urlreq.pathname2url()) and | |
|
331 | # has a similar problem | |
|
332 | # (https://bz.mercurial-scm.org/show_bug.cgi?id=6357). It makes | |
|
333 | # sense to solve both problems together and handle all file URLs | |
|
334 | # consistently. For now, we warn. | |
|
335 | unicodepath = urlreq.url2pathname(pycompat.fsdecode(path)) | |
|
336 | if pycompat.ispy3 and u'\N{REPLACEMENT CHARACTER}' in unicodepath: | |
|
394 | try: | |
|
395 | unicodepath = path.decode(fsencoding) | |
|
396 | except UnicodeDecodeError: | |
|
337 | 397 | ui.warn( |
|
338 | 398 | _( |
|
339 | b'on Python 3, we currently do not support non-UTF-8 ' | |
|
340 | b'percent-encoded bytes in file URLs for Subversion ' | |
|
341 |
|
|
|
399 | b'Subversion requires that file URLs can be converted ' | |
|
400 | b'to Unicode using the current locale encoding (%s)\n' | |
|
401 | ) | |
|
402 | % pycompat.sysbytes(fsencoding) | |
|
403 | ) | |
|
404 | return False | |
|
405 | try: | |
|
406 | unicodepath = url2pathname_like_subversion(unicodepath) | |
|
407 | except NonUtf8PercentEncodedBytes: | |
|
408 | ui.warn( | |
|
409 | _( | |
|
410 | b'Subversion does not support non-UTF-8 ' | |
|
411 | b'percent-encoded bytes in file URLs\n' | |
|
342 | 412 | ) |
|
343 | 413 | ) |
|
344 | path = pycompat.fsencode(unicodepath) | |
|
414 | return False | |
|
415 | # Below, we approximate how Subversion checks the path. On Unix, we | |
|
416 | # should therefore convert the path to bytes using `fsencoding` | |
|
417 | # (like Subversion does). On Windows, the right thing would | |
|
418 | # actually be to leave the path as unicode. For now, we restrict | |
|
419 | # the path to MBCS. | |
|
420 | path = unicodepath.encode(fsencoding) | |
|
345 | 421 | except ValueError: |
|
346 | 422 | proto = b'file' |
|
347 | 423 | path = os.path.abspath(url) |
|
424 | try: | |
|
425 | path.decode(fsencoding) | |
|
426 | except UnicodeDecodeError: | |
|
427 | ui.warn( | |
|
428 | _( | |
|
429 | b'Subversion requires that paths can be converted to ' | |
|
430 | b'Unicode using the current locale encoding (%s)\n' | |
|
431 | ) | |
|
432 | % pycompat.sysbytes(fsencoding) | |
|
433 | ) | |
|
434 | return False | |
|
348 | 435 | if proto == b'file': |
|
349 | 436 | path = util.pconvert(path) |
|
437 | elif proto in (b'http', 'https'): | |
|
438 | if not encoding.isasciistr(path): | |
|
439 | ui.warn( | |
|
440 | _( | |
|
441 | b"Subversion sources don't support non-ASCII characters in " | |
|
442 | b"HTTP(S) URLs. Please percent-encode them.\n" | |
|
443 | ) | |
|
444 | ) | |
|
445 | return False | |
|
350 | 446 | check = protomap.get(proto, lambda *args: False) |
|
351 | 447 | while b'/' in path: |
|
352 | 448 | if check(ui, path, proto): |
@@ -373,6 +469,7 b' class svn_source(converter_source):' | |||
|
373 | 469 | def __init__(self, ui, repotype, url, revs=None): |
|
374 | 470 | super(svn_source, self).__init__(ui, repotype, url, revs=revs) |
|
375 | 471 | |
|
472 | init_fsencoding() | |
|
376 | 473 | if not ( |
|
377 | 474 | url.startswith(b'svn://') |
|
378 | 475 | or url.startswith(b'svn+ssh://') |
@@ -153,22 +153,65 b' Check tags are in UTF-8' | |||
|
153 | 153 | |
|
154 | 154 | $ cd .. |
|
155 | 155 | |
|
156 | #if py3 | |
|
157 | For now, on Python 3, we abort when encountering non-UTF-8 percent-encoded | |
|
158 | bytes in a filename. | |
|
156 | Subversion sources don't support non-ASCII characters in HTTP(S) URLs. | |
|
157 | ||
|
158 | $ XFF=$($PYTHON -c 'from mercurial.utils.procutil import stdout; stdout.write(b"\xff")') | |
|
159 | $ hg convert --source-type=svn http://localhost:$HGPORT/$XFF test | |
|
160 | initializing destination test repository | |
|
161 | Subversion sources don't support non-ASCII characters in HTTP(S) URLs. Please percent-encode them. | |
|
162 | http://localhost:$HGPORT/\xff does not look like a Subversion repository (esc) | |
|
163 | abort: http://localhost:$HGPORT/\xff: missing or unsupported repository (esc) | |
|
164 | [255] | |
|
165 | ||
|
166 | In Subversion, paths are Unicode (encoded as UTF-8). Therefore paths that can't | |
|
167 | be converted between UTF-8 and the locale encoding (which is always ASCII in | |
|
168 | tests) don't work. | |
|
159 | 169 | |
|
160 | $ hg convert file:///%ff test | |
|
170 | $ cp -R svn-repo $XFF | |
|
171 | $ hg convert $XFF test | |
|
172 | initializing destination test repository | |
|
173 | Subversion requires that paths can be converted to Unicode using the current locale encoding (ascii) | |
|
174 | \xff does not look like a CVS checkout (glob) (esc) | |
|
175 | $TESTTMP/\xff does not look like a Git repository (esc) | |
|
176 | \xff does not look like a Subversion repository (glob) (esc) | |
|
177 | \xff is not a local Mercurial repository (glob) (esc) | |
|
178 | \xff does not look like a darcs repository (glob) (esc) | |
|
179 | \xff does not look like a monotone repository (glob) (esc) | |
|
180 | \xff does not look like a GNU Arch repository (glob) (esc) | |
|
181 | \xff does not look like a Bazaar repository (glob) (esc) | |
|
182 | cannot find required "p4" tool | |
|
183 | abort: \xff: missing or unsupported repository (glob) (esc) | |
|
184 | [255] | |
|
185 | $ hg convert file://$TESTTMP/$XFF test | |
|
161 | 186 | initializing destination test repository |
|
162 | on Python 3, we currently do not support non-UTF-8 percent-encoded bytes in file URLs for Subversion repositories | |
|
163 |
file:/ |
|
|
164 |
$TESTTMP/file: |
|
|
165 |
file:/ |
|
|
166 |
file:/ |
|
|
167 |
file:/ |
|
|
168 |
file:/ |
|
|
169 |
file:/ |
|
|
170 |
file:/ |
|
|
171 |
file:/ |
|
|
172 |
abort: file:/ |
|
|
187 | Subversion requires that file URLs can be converted to Unicode using the current locale encoding (ascii) | |
|
188 | file:/*/$TESTTMP/\xff does not look like a CVS checkout (glob) (esc) | |
|
189 | $TESTTMP/file:$TESTTMP/\xff does not look like a Git repository (esc) | |
|
190 | file:/*/$TESTTMP/\xff does not look like a Subversion repository (glob) (esc) | |
|
191 | file:/*/$TESTTMP/\xff is not a local Mercurial repository (glob) (esc) | |
|
192 | file:/*/$TESTTMP/\xff does not look like a darcs repository (glob) (esc) | |
|
193 | file:/*/$TESTTMP/\xff does not look like a monotone repository (glob) (esc) | |
|
194 | file:/*/$TESTTMP/\xff does not look like a GNU Arch repository (glob) (esc) | |
|
195 | file:/*/$TESTTMP/\xff does not look like a Bazaar repository (glob) (esc) | |
|
196 | file:/*/$TESTTMP/\xff does not look like a P4 repository (glob) (esc) | |
|
197 | abort: file:/*/$TESTTMP/\xff: missing or unsupported repository (glob) (esc) | |
|
173 | 198 | [255] |
|
174 | #endif | |
|
199 | ||
|
200 | Subversion decodes percent-encoded bytes on the converted, UTF-8-encoded | |
|
201 | string. Therefore, if the percent-encoded bytes aren't valid UTF-8, Subversion | |
|
202 | would choke on them when converting them to the locale encoding. | |
|
203 | ||
|
204 | $ hg convert file://$TESTTMP/%FF test | |
|
205 | initializing destination test repository | |
|
206 | Subversion does not support non-UTF-8 percent-encoded bytes in file URLs | |
|
207 | file:/*/$TESTTMP/%FF does not look like a CVS checkout (glob) | |
|
208 | $TESTTMP/file:$TESTTMP/%FF does not look like a Git repository | |
|
209 | file:/*/$TESTTMP/%FF does not look like a Subversion repository (glob) | |
|
210 | file:/*/$TESTTMP/%FF is not a local Mercurial repository (glob) | |
|
211 | file:/*/$TESTTMP/%FF does not look like a darcs repository (glob) | |
|
212 | file:/*/$TESTTMP/%FF does not look like a monotone repository (glob) | |
|
213 | file:/*/$TESTTMP/%FF does not look like a GNU Arch repository (glob) | |
|
214 | file:/*/$TESTTMP/%FF does not look like a Bazaar repository (glob) | |
|
215 | file:/*/$TESTTMP/%FF does not look like a P4 repository (glob) | |
|
216 | abort: file:/*/$TESTTMP/%FF: missing or unsupported repository (glob) | |
|
217 | [255] |
General Comments 0
You need to be logged in to leave comments.
Login now