equal
deleted
inserted
replaced
17 import stat |
17 import stat |
18 import sys |
18 import sys |
19 import tempfile |
19 import tempfile |
20 import unicodedata |
20 import unicodedata |
21 |
21 |
|
22 from typing import ( |
|
23 List, |
|
24 NoReturn, |
|
25 Optional, |
|
26 ) |
|
27 |
22 from .i18n import _ |
28 from .i18n import _ |
23 from .pycompat import ( |
29 from .pycompat import ( |
24 getattr, |
30 getattr, |
25 open, |
31 open, |
26 ) |
32 ) |
42 except AttributeError: |
48 except AttributeError: |
43 # Some platforms build Python without os.link on systems that are |
49 # Some platforms build Python without os.link on systems that are |
44 # vaguely unix-like but don't have hardlink support. For those |
50 # vaguely unix-like but don't have hardlink support. For those |
45 # poor souls, just say we tried and that it failed so we fall back |
51 # poor souls, just say we tried and that it failed so we fall back |
46 # to copies. |
52 # to copies. |
47 def oslink(src, dst): |
53 def oslink(src: bytes, dst: bytes) -> NoReturn: |
48 raise OSError( |
54 raise OSError( |
49 errno.EINVAL, b'hardlinks not supported: %s to %s' % (src, dst) |
55 errno.EINVAL, b'hardlinks not supported: %s to %s' % (src, dst) |
50 ) |
56 ) |
51 |
57 |
52 |
58 |
88 def openhardlinks(): |
94 def openhardlinks(): |
89 '''return true if it is safe to hold open file handles to hardlinks''' |
95 '''return true if it is safe to hold open file handles to hardlinks''' |
90 return True |
96 return True |
91 |
97 |
92 |
98 |
93 def nlinks(name): |
99 def nlinks(name: bytes) -> int: |
94 '''return number of hardlinks for the given file''' |
100 '''return number of hardlinks for the given file''' |
95 return os.lstat(name).st_nlink |
101 return os.lstat(name).st_nlink |
96 |
102 |
97 |
103 |
98 def parsepatchoutput(output_line): |
104 def parsepatchoutput(output_line): |
346 Returns None if we are unsure. Raises OSError on ENOENT, EPERM, etc. |
352 Returns None if we are unsure. Raises OSError on ENOENT, EPERM, etc. |
347 """ |
353 """ |
348 return getattr(osutil, 'getfsmountpoint', lambda x: None)(dirpath) |
354 return getattr(osutil, 'getfsmountpoint', lambda x: None)(dirpath) |
349 |
355 |
350 |
356 |
351 def getfstype(dirpath): |
357 def getfstype(dirpath: bytes) -> Optional[bytes]: |
352 """Get the filesystem type name from a directory (best-effort) |
358 """Get the filesystem type name from a directory (best-effort) |
353 |
359 |
354 Returns None if we are unsure. Raises OSError on ENOENT, EPERM, etc. |
360 Returns None if we are unsure. Raises OSError on ENOENT, EPERM, etc. |
355 """ |
361 """ |
356 return getattr(osutil, 'getfstype', lambda x: None)(dirpath) |
362 return getattr(osutil, 'getfstype', lambda x: None)(dirpath) |
370 |
376 |
371 def localpath(path): |
377 def localpath(path): |
372 return path |
378 return path |
373 |
379 |
374 |
380 |
375 def samefile(fpath1, fpath2): |
381 def samefile(fpath1: bytes, fpath2: bytes) -> bool: |
376 """Returns whether path1 and path2 refer to the same file. This is only |
382 """Returns whether path1 and path2 refer to the same file. This is only |
377 guaranteed to work for files, not directories.""" |
383 guaranteed to work for files, not directories.""" |
378 return os.path.samefile(fpath1, fpath2) |
384 return os.path.samefile(fpath1, fpath2) |
379 |
385 |
380 |
386 |
381 def samedevice(fpath1, fpath2): |
387 def samedevice(fpath1: bytes, fpath2: bytes) -> bool: |
382 """Returns whether fpath1 and fpath2 are on the same device. This is only |
388 """Returns whether fpath1 and fpath2 are on the same device. This is only |
383 guaranteed to work for files, not directories.""" |
389 guaranteed to work for files, not directories.""" |
384 st1 = os.lstat(fpath1) |
390 st1 = os.lstat(fpath1) |
385 st2 = os.lstat(fpath2) |
391 st2 = os.lstat(fpath2) |
386 return st1.st_dev == st2.st_dev |
392 return st1.st_dev == st2.st_dev |
519 def shellsplit(s): |
525 def shellsplit(s): |
520 """Parse a command string in POSIX shell way (best-effort)""" |
526 """Parse a command string in POSIX shell way (best-effort)""" |
521 return pycompat.shlexsplit(s, posix=True) |
527 return pycompat.shlexsplit(s, posix=True) |
522 |
528 |
523 |
529 |
524 def testpid(pid): |
530 def testpid(pid: int) -> bool: |
525 '''return False if pid dead, True if running or not sure''' |
531 '''return False if pid dead, True if running or not sure''' |
526 if pycompat.sysplatform == b'OpenVMS': |
532 if pycompat.sysplatform == b'OpenVMS': |
527 return True |
533 return True |
528 try: |
534 try: |
529 os.kill(pid, 0) |
535 os.kill(pid, 0) |
562 if executable is not None: |
568 if executable is not None: |
563 return executable |
569 return executable |
564 return None |
570 return None |
565 |
571 |
566 |
572 |
567 def setsignalhandler(): |
573 def setsignalhandler() -> None: |
568 pass |
574 pass |
569 |
575 |
570 |
576 |
571 _wantedkinds = {stat.S_IFREG, stat.S_IFLNK} |
577 _wantedkinds = {stat.S_IFREG, stat.S_IFLNK} |
572 |
578 |
584 except (FileNotFoundError, NotADirectoryError): |
590 except (FileNotFoundError, NotADirectoryError): |
585 st = None |
591 st = None |
586 yield st |
592 yield st |
587 |
593 |
588 |
594 |
589 def getuser(): |
595 def getuser() -> bytes: |
590 '''return name of current user''' |
596 '''return name of current user''' |
591 return pycompat.fsencode(getpass.getuser()) |
597 return pycompat.fsencode(getpass.getuser()) |
592 |
598 |
593 |
599 |
594 def username(uid=None): |
600 def username(uid=None): |
623 """ |
629 """ |
624 name = pycompat.fsdecode(name) |
630 name = pycompat.fsdecode(name) |
625 return pycompat.rapply(pycompat.fsencode, list(grp.getgrnam(name).gr_mem)) |
631 return pycompat.rapply(pycompat.fsencode, list(grp.getgrnam(name).gr_mem)) |
626 |
632 |
627 |
633 |
628 def spawndetached(args) -> int: |
634 def spawndetached(args: List[bytes]) -> int: |
629 return os.spawnvp(os.P_NOWAIT | getattr(os, 'P_DETACH', 0), args[0], args) |
635 return os.spawnvp(os.P_NOWAIT | getattr(os, 'P_DETACH', 0), args[0], args) |
630 |
636 |
631 |
637 |
632 def gethgcmd(): |
638 def gethgcmd(): |
633 return sys.argv[:1] |
639 return sys.argv[:1] |
634 |
640 |
635 |
641 |
636 def makedir(path, notindexed): |
642 def makedir(path: bytes, notindexed: bool) -> None: |
637 os.mkdir(path) |
643 os.mkdir(path) |
638 |
644 |
639 |
645 |
640 def lookupreg(key, name=None, scope=None): |
646 def lookupreg(key, name=None, scope=None): |
641 return None |
647 return None |
642 |
648 |
643 |
649 |
644 def hidewindow(): |
650 def hidewindow() -> None: |
645 """Hide current shell window. |
651 """Hide current shell window. |
646 |
652 |
647 Used to hide the window opened when starting asynchronous |
653 Used to hide the window opened when starting asynchronous |
648 child process under Windows, unneeded on other systems. |
654 child process under Windows, unneeded on other systems. |
649 """ |
655 """ |