comparison mercurial/hg.py @ 44571:6a8738dc4a01

hg: make _local() behave consistently on Python 3.8 (issue6287) Python 3.8 makes os.path.isfile quietly eat "path invalid" errors and return False instead of allowing the exception to propagate. Given that this is a change from 2018 (sigh) and it's mentioned in the release notes (double sigh) we're definitely too late to complain to Python about the behavior change, so open-code part of os.path.isfile() in this method so we can catch invalid-path errors and handle them appropriately. I confirmed that posixpath and ntpath both delegate to genericpath, which uses os.stat() under the covers. Differential Revision: https://phab.mercurial-scm.org/D8302
author Augie Fackler <augie@google.com>
date Wed, 18 Mar 2020 15:08:14 -0400
parents 2f290136b7d6
children 843418dc0b1b
comparison
equal deleted inserted replaced
44570:9e63108123a4 44571:6a8738dc4a01
58 58
59 def _local(path): 59 def _local(path):
60 path = util.expandpath(util.urllocalpath(path)) 60 path = util.expandpath(util.urllocalpath(path))
61 61
62 try: 62 try:
63 isfile = os.path.isfile(path) 63 # we use os.stat() directly here instead of os.path.isfile()
64 # because the latter started returning `False` on invalid path
65 # exceptions starting in 3.8 and we care about handling
66 # invalid paths specially here.
67 st = os.stat(path)
68 isfile = stat.S_ISREG(st.st_mode)
64 # Python 2 raises TypeError, Python 3 ValueError. 69 # Python 2 raises TypeError, Python 3 ValueError.
65 except (TypeError, ValueError) as e: 70 except (TypeError, ValueError) as e:
66 raise error.Abort( 71 raise error.Abort(
67 _(b'invalid path %s: %s') % (path, pycompat.bytestr(e)) 72 _(b'invalid path %s: %s') % (path, pycompat.bytestr(e))
68 ) 73 )
74 except OSError:
75 isfile = False
69 76
70 return isfile and bundlerepo or localrepo 77 return isfile and bundlerepo or localrepo
71 78
72 79
73 def addbranchrevs(lrepo, other, branches, revs): 80 def addbranchrevs(lrepo, other, branches, revs):