comparison mercurial/posix.py @ 43077:687b865b95ad

formatting: byteify all mercurial/ and hgext/ string literals Done with python3.7 contrib/byteify-strings.py -i $(hg files 'set:mercurial/**.py - mercurial/thirdparty/** + hgext/**.py - hgext/fsmonitor/pywatchman/** - mercurial/__init__.py') black -l 80 -t py33 -S $(hg files 'set:**.py - mercurial/thirdparty/** - "contrib/python-zstandard/**" - hgext/fsmonitor/pywatchman/**') # skip-blame mass-reformatting only Differential Revision: https://phab.mercurial-scm.org/D6972
author Augie Fackler <augie@google.com>
date Sun, 06 Oct 2019 09:48:39 -0400
parents 2372284d9457
children eef9a2d67051
comparison
equal deleted inserted replaced
43076:2372284d9457 43077:687b865b95ad
39 # vaguely unix-like but don't have hardlink support. For those 39 # vaguely unix-like but don't have hardlink support. For those
40 # poor souls, just say we tried and that it failed so we fall back 40 # poor souls, just say we tried and that it failed so we fall back
41 # to copies. 41 # to copies.
42 def oslink(src, dst): 42 def oslink(src, dst):
43 raise OSError( 43 raise OSError(
44 errno.EINVAL, 'hardlinks not supported: %s to %s' % (src, dst) 44 errno.EINVAL, b'hardlinks not supported: %s to %s' % (src, dst)
45 ) 45 )
46 46
47 47
48 readlink = os.readlink 48 readlink = os.readlink
49 unlink = os.unlink 49 unlink = os.unlink
83 ... b'/file_at_root', 83 ... b'/file_at_root',
84 ... b'///multiple_leading_separators_at_root', 84 ... b'///multiple_leading_separators_at_root',
85 ... b'']: 85 ... b'']:
86 ... assert split(f) == posixpath.split(f), f 86 ... assert split(f) == posixpath.split(f), f
87 ''' 87 '''
88 ht = p.rsplit('/', 1) 88 ht = p.rsplit(b'/', 1)
89 if len(ht) == 1: 89 if len(ht) == 1:
90 return '', p 90 return b'', p
91 nh = ht[0].rstrip('/') 91 nh = ht[0].rstrip(b'/')
92 if nh: 92 if nh:
93 return nh, ht[1] 93 return nh, ht[1]
94 return ht[0] + '/', ht[1] 94 return ht[0] + b'/', ht[1]
95 95
96 96
97 def openhardlinks(): 97 def openhardlinks():
98 '''return true if it is safe to hold open file handles to hardlinks''' 98 '''return true if it is safe to hold open file handles to hardlinks'''
99 return True 99 return True
105 105
106 106
107 def parsepatchoutput(output_line): 107 def parsepatchoutput(output_line):
108 """parses the output produced by patch and returns the filename""" 108 """parses the output produced by patch and returns the filename"""
109 pf = output_line[14:] 109 pf = output_line[14:]
110 if pycompat.sysplatform == 'OpenVMS': 110 if pycompat.sysplatform == b'OpenVMS':
111 if pf[0] == '`': 111 if pf[0] == b'`':
112 pf = pf[1:-1] # Remove the quotes 112 pf = pf[1:-1] # Remove the quotes
113 else: 113 else:
114 if pf.startswith("'") and pf.endswith("'") and " " in pf: 114 if pf.startswith(b"'") and pf.endswith(b"'") and b" " in pf:
115 pf = pf[1:-1] # Remove the quotes 115 pf = pf[1:-1] # Remove the quotes
116 return pf 116 return pf
117 117
118 118
119 def sshargs(sshcmd, host, user, port): 119 def sshargs(sshcmd, host, user, port):
120 '''Build argument list for ssh''' 120 '''Build argument list for ssh'''
121 args = user and ("%s@%s" % (user, host)) or host 121 args = user and (b"%s@%s" % (user, host)) or host
122 if '-' in args[:1]: 122 if b'-' in args[:1]:
123 raise error.Abort( 123 raise error.Abort(
124 _('illegal ssh hostname or username starting with -: %s') % args 124 _(b'illegal ssh hostname or username starting with -: %s') % args
125 ) 125 )
126 args = shellquote(args) 126 args = shellquote(args)
127 if port: 127 if port:
128 args = '-p %s %s' % (shellquote(port), args) 128 args = b'-p %s %s' % (shellquote(port), args)
129 return args 129 return args
130 130
131 131
132 def isexec(f): 132 def isexec(f):
133 """check whether a file is executable""" 133 """check whether a file is executable"""
138 st = os.lstat(f) 138 st = os.lstat(f)
139 s = st.st_mode 139 s = st.st_mode
140 if l: 140 if l:
141 if not stat.S_ISLNK(s): 141 if not stat.S_ISLNK(s):
142 # switch file to link 142 # switch file to link
143 fp = open(f, 'rb') 143 fp = open(f, b'rb')
144 data = fp.read() 144 data = fp.read()
145 fp.close() 145 fp.close()
146 unlink(f) 146 unlink(f)
147 try: 147 try:
148 os.symlink(data, f) 148 os.symlink(data, f)
149 except OSError: 149 except OSError:
150 # failed to make a link, rewrite file 150 # failed to make a link, rewrite file
151 fp = open(f, "wb") 151 fp = open(f, b"wb")
152 fp.write(data) 152 fp.write(data)
153 fp.close() 153 fp.close()
154 # no chmod needed at this point 154 # no chmod needed at this point
155 return 155 return
156 if stat.S_ISLNK(s): 156 if stat.S_ISLNK(s):
157 # switch link to file 157 # switch link to file
158 data = os.readlink(f) 158 data = os.readlink(f)
159 unlink(f) 159 unlink(f)
160 fp = open(f, "wb") 160 fp = open(f, b"wb")
161 fp.write(data) 161 fp.write(data)
162 fp.close() 162 fp.close()
163 s = 0o666 & ~umask # avoid restatting for chmod 163 s = 0o666 & ~umask # avoid restatting for chmod
164 164
165 sx = s & 0o100 165 sx = s & 0o100
166 if st.st_nlink > 1 and bool(x) != bool(sx): 166 if st.st_nlink > 1 and bool(x) != bool(sx):
167 # the file is a hardlink, break it 167 # the file is a hardlink, break it
168 with open(f, "rb") as fp: 168 with open(f, b"rb") as fp:
169 data = fp.read() 169 data = fp.read()
170 unlink(f) 170 unlink(f)
171 with open(f, "wb") as fp: 171 with open(f, b"wb") as fp:
172 fp.write(data) 172 fp.write(data)
173 173
174 if x and not sx: 174 if x and not sx:
175 # Turn on +x for every +r bit when making a file executable 175 # Turn on +x for every +r bit when making a file executable
176 # and obey umask. 176 # and obey umask.
213 # a FS remount. Frequently we can detect it if files are created 213 # a FS remount. Frequently we can detect it if files are created
214 # with exec bit on. 214 # with exec bit on.
215 215
216 try: 216 try:
217 EXECFLAGS = stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH 217 EXECFLAGS = stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
218 basedir = os.path.join(path, '.hg') 218 basedir = os.path.join(path, b'.hg')
219 cachedir = os.path.join(basedir, 'wcache') 219 cachedir = os.path.join(basedir, b'wcache')
220 storedir = os.path.join(basedir, 'store') 220 storedir = os.path.join(basedir, b'store')
221 if not os.path.exists(cachedir): 221 if not os.path.exists(cachedir):
222 try: 222 try:
223 # we want to create the 'cache' directory, not the '.hg' one. 223 # we want to create the 'cache' directory, not the '.hg' one.
224 # Automatically creating '.hg' directory could silently spawn 224 # Automatically creating '.hg' directory could silently spawn
225 # invalid Mercurial repositories. That seems like a bad idea. 225 # invalid Mercurial repositories. That seems like a bad idea.
230 copymode(basedir, cachedir) 230 copymode(basedir, cachedir)
231 except (IOError, OSError): 231 except (IOError, OSError):
232 # we other fallback logic triggers 232 # we other fallback logic triggers
233 pass 233 pass
234 if os.path.isdir(cachedir): 234 if os.path.isdir(cachedir):
235 checkisexec = os.path.join(cachedir, 'checkisexec') 235 checkisexec = os.path.join(cachedir, b'checkisexec')
236 checknoexec = os.path.join(cachedir, 'checknoexec') 236 checknoexec = os.path.join(cachedir, b'checknoexec')
237 237
238 try: 238 try:
239 m = os.stat(checkisexec).st_mode 239 m = os.stat(checkisexec).st_mode
240 except OSError as e: 240 except OSError as e:
241 if e.errno != errno.ENOENT: 241 if e.errno != errno.ENOENT:
248 try: 248 try:
249 m = os.stat(checknoexec).st_mode 249 m = os.stat(checknoexec).st_mode
250 except OSError as e: 250 except OSError as e:
251 if e.errno != errno.ENOENT: 251 if e.errno != errno.ENOENT:
252 raise 252 raise
253 open(checknoexec, 'w').close() # might fail 253 open(checknoexec, b'w').close() # might fail
254 m = os.stat(checknoexec).st_mode 254 m = os.stat(checknoexec).st_mode
255 if m & EXECFLAGS == 0: 255 if m & EXECFLAGS == 0:
256 # check-exec is exec and check-no-exec is not exec 256 # check-exec is exec and check-no-exec is not exec
257 return True 257 return True
258 # checknoexec exists but is exec - delete it 258 # checknoexec exists but is exec - delete it
264 checkdir = cachedir 264 checkdir = cachedir
265 else: 265 else:
266 # check directly in path and don't leave checkisexec behind 266 # check directly in path and don't leave checkisexec behind
267 checkdir = path 267 checkdir = path
268 checkisexec = None 268 checkisexec = None
269 fh, fn = pycompat.mkstemp(dir=checkdir, prefix='hg-checkexec-') 269 fh, fn = pycompat.mkstemp(dir=checkdir, prefix=b'hg-checkexec-')
270 try: 270 try:
271 os.close(fh) 271 os.close(fh)
272 m = os.stat(fn).st_mode 272 m = os.stat(fn).st_mode
273 if m & EXECFLAGS == 0: 273 if m & EXECFLAGS == 0:
274 os.chmod(fn, m & 0o777 | EXECFLAGS) 274 os.chmod(fn, m & 0o777 | EXECFLAGS)
288 def checklink(path): 288 def checklink(path):
289 """check whether the given path is on a symlink-capable filesystem""" 289 """check whether the given path is on a symlink-capable filesystem"""
290 # mktemp is not racy because symlink creation will fail if the 290 # mktemp is not racy because symlink creation will fail if the
291 # file already exists 291 # file already exists
292 while True: 292 while True:
293 cachedir = os.path.join(path, '.hg', 'wcache') 293 cachedir = os.path.join(path, b'.hg', b'wcache')
294 checklink = os.path.join(cachedir, 'checklink') 294 checklink = os.path.join(cachedir, b'checklink')
295 # try fast path, read only 295 # try fast path, read only
296 if os.path.islink(checklink): 296 if os.path.islink(checklink):
297 return True 297 return True
298 if os.path.isdir(cachedir): 298 if os.path.isdir(cachedir):
299 checkdir = cachedir 299 checkdir = cachedir
306 name = pycompat.fsencode(name) 306 name = pycompat.fsencode(name)
307 try: 307 try:
308 fd = None 308 fd = None
309 if cachedir is None: 309 if cachedir is None:
310 fd = pycompat.namedtempfile( 310 fd = pycompat.namedtempfile(
311 dir=checkdir, prefix='hg-checklink-' 311 dir=checkdir, prefix=b'hg-checklink-'
312 ) 312 )
313 target = os.path.basename(fd.name) 313 target = os.path.basename(fd.name)
314 else: 314 else:
315 # create a fixed file to link to; doesn't matter if it 315 # create a fixed file to link to; doesn't matter if it
316 # already exists. 316 # already exists.
317 target = 'checklink-target' 317 target = b'checklink-target'
318 try: 318 try:
319 fullpath = os.path.join(cachedir, target) 319 fullpath = os.path.join(cachedir, target)
320 open(fullpath, 'w').close() 320 open(fullpath, b'w').close()
321 except IOError as inst: 321 except IOError as inst:
322 if inst[0] == errno.EACCES: 322 if inst[0] == errno.EACCES:
323 # If we can't write to cachedir, just pretend 323 # If we can't write to cachedir, just pretend
324 # that the fs is readonly and by association 324 # that the fs is readonly and by association
325 # that the fs won't support symlinks. This 325 # that the fs won't support symlinks. This
442 def normcasefallback(path): 442 def normcasefallback(path):
443 try: 443 try:
444 u = path.decode('utf-8') 444 u = path.decode('utf-8')
445 except UnicodeDecodeError: 445 except UnicodeDecodeError:
446 # OS X percent-encodes any bytes that aren't valid utf-8 446 # OS X percent-encodes any bytes that aren't valid utf-8
447 s = '' 447 s = b''
448 pos = 0 448 pos = 0
449 l = len(path) 449 l = len(path)
450 while pos < l: 450 while pos < l:
451 try: 451 try:
452 c = encoding.getutf8char(path, pos) 452 c = encoding.getutf8char(path, pos)
453 pos += len(c) 453 pos += len(c)
454 except ValueError: 454 except ValueError:
455 c = '%%%02X' % ord(path[pos : pos + 1]) 455 c = b'%%%02X' % ord(path[pos : pos + 1])
456 pos += 1 456 pos += 1
457 s += c 457 s += c
458 458
459 u = s.decode('utf-8') 459 u = s.decode('utf-8')
460 460
462 enc = unicodedata.normalize(r'NFD', u).lower().encode('utf-8') 462 enc = unicodedata.normalize(r'NFD', u).lower().encode('utf-8')
463 # drop HFS+ ignored characters 463 # drop HFS+ ignored characters
464 return encoding.hfsignoreclean(enc) 464 return encoding.hfsignoreclean(enc)
465 465
466 466
467 if pycompat.sysplatform == 'cygwin': 467 if pycompat.sysplatform == b'cygwin':
468 # workaround for cygwin, in which mount point part of path is 468 # workaround for cygwin, in which mount point part of path is
469 # treated as case sensitive, even though underlying NTFS is case 469 # treated as case sensitive, even though underlying NTFS is case
470 # insensitive. 470 # insensitive.
471 471
472 # default mount points 472 # default mount points
473 cygwinmountpoints = sorted( 473 cygwinmountpoints = sorted(
474 ["/usr/bin", "/usr/lib", "/cygdrive",], reverse=True 474 [b"/usr/bin", b"/usr/lib", b"/cygdrive",], reverse=True
475 ) 475 )
476 476
477 # use upper-ing as normcase as same as NTFS workaround 477 # use upper-ing as normcase as same as NTFS workaround
478 def normcase(path): 478 def normcase(path):
479 pathlen = len(path) 479 pathlen = len(path)
513 513
514 _needsshellquote = None 514 _needsshellquote = None
515 515
516 516
517 def shellquote(s): 517 def shellquote(s):
518 if pycompat.sysplatform == 'OpenVMS': 518 if pycompat.sysplatform == b'OpenVMS':
519 return '"%s"' % s 519 return b'"%s"' % s
520 global _needsshellquote 520 global _needsshellquote
521 if _needsshellquote is None: 521 if _needsshellquote is None:
522 _needsshellquote = re.compile(br'[^a-zA-Z0-9._/+-]').search 522 _needsshellquote = re.compile(br'[^a-zA-Z0-9._/+-]').search
523 if s and not _needsshellquote(s): 523 if s and not _needsshellquote(s):
524 # "s" shouldn't have to be quoted 524 # "s" shouldn't have to be quoted
525 return s 525 return s
526 else: 526 else:
527 return "'%s'" % s.replace("'", "'\\''") 527 return b"'%s'" % s.replace(b"'", b"'\\''")
528 528
529 529
530 def shellsplit(s): 530 def shellsplit(s):
531 """Parse a command string in POSIX shell way (best-effort)""" 531 """Parse a command string in POSIX shell way (best-effort)"""
532 return pycompat.shlexsplit(s, posix=True) 532 return pycompat.shlexsplit(s, posix=True)
536 return cmd 536 return cmd
537 537
538 538
539 def testpid(pid): 539 def testpid(pid):
540 '''return False if pid dead, True if running or not sure''' 540 '''return False if pid dead, True if running or not sure'''
541 if pycompat.sysplatform == 'OpenVMS': 541 if pycompat.sysplatform == b'OpenVMS':
542 return True 542 return True
543 try: 543 try:
544 os.kill(pid, 0) 544 os.kill(pid, 0)
545 return True 545 return True
546 except OSError as inst: 546 except OSError as inst:
555 def findexe(command): 555 def findexe(command):
556 '''Find executable for command searching like which does. 556 '''Find executable for command searching like which does.
557 If command is a basename then PATH is searched for command. 557 If command is a basename then PATH is searched for command.
558 PATH isn't searched if command is an absolute or relative path. 558 PATH isn't searched if command is an absolute or relative path.
559 If command isn't found None is returned.''' 559 If command isn't found None is returned.'''
560 if pycompat.sysplatform == 'OpenVMS': 560 if pycompat.sysplatform == b'OpenVMS':
561 return command 561 return command
562 562
563 def findexisting(executable): 563 def findexisting(executable):
564 'Will return executable if existing file' 564 b'Will return executable if existing file'
565 if os.path.isfile(executable) and os.access(executable, os.X_OK): 565 if os.path.isfile(executable) and os.access(executable, os.X_OK):
566 return executable 566 return executable
567 return None 567 return None
568 568
569 if pycompat.ossep in command: 569 if pycompat.ossep in command:
570 return findexisting(command) 570 return findexisting(command)
571 571
572 if pycompat.sysplatform == 'plan9': 572 if pycompat.sysplatform == b'plan9':
573 return findexisting(os.path.join('/bin', command)) 573 return findexisting(os.path.join(b'/bin', command))
574 574
575 for path in encoding.environ.get('PATH', '').split(pycompat.ospathsep): 575 for path in encoding.environ.get(b'PATH', b'').split(pycompat.ospathsep):
576 executable = findexisting(os.path.join(path, command)) 576 executable = findexisting(os.path.join(path, command))
577 if executable is not None: 577 if executable is not None:
578 return executable 578 return executable
579 return None 579 return None
580 580
750 break 750 break
751 chunks.append(s) 751 chunks.append(s)
752 except IOError: 752 except IOError:
753 break 753 break
754 754
755 return ''.join(chunks) 755 return b''.join(chunks)
756 finally: 756 finally:
757 fcntl.fcntl(pipe, fcntl.F_SETFL, oldflags) 757 fcntl.fcntl(pipe, fcntl.F_SETFL, oldflags)
758 758
759 759
760 def bindunixsocket(sock, path): 760 def bindunixsocket(sock, path):
763 # AF_UNIX path has very small length limit (107 chars) on common 763 # AF_UNIX path has very small length limit (107 chars) on common
764 # platforms (see sys/un.h) 764 # platforms (see sys/un.h)
765 dirname, basename = os.path.split(path) 765 dirname, basename = os.path.split(path)
766 bakwdfd = None 766 bakwdfd = None
767 if dirname: 767 if dirname:
768 bakwdfd = os.open('.', os.O_DIRECTORY) 768 bakwdfd = os.open(b'.', os.O_DIRECTORY)
769 os.chdir(dirname) 769 os.chdir(dirname)
770 sock.bind(basename) 770 sock.bind(basename)
771 if bakwdfd: 771 if bakwdfd:
772 os.fchdir(bakwdfd) 772 os.fchdir(bakwdfd)
773 os.close(bakwdfd) 773 os.close(bakwdfd)