Mercurial > hg
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) |