mercurial/util.py
changeset 51284 f15cb5111a1e
parent 51282 9d3721552b6c
child 51291 7d3b92e8df13
equal deleted inserted replaced
51283:81224afd938d 51284:f15cb5111a1e
   145 umask = platform.umask
   145 umask = platform.umask
   146 unlink = platform.unlink
   146 unlink = platform.unlink
   147 username = platform.username
   147 username = platform.username
   148 
   148 
   149 
   149 
   150 def setumask(val):
   150 def setumask(val: int) -> None:
   151     # type: (int) -> None
       
   152     '''updates the umask. used by chg server'''
   151     '''updates the umask. used by chg server'''
   153     if pycompat.iswindows:
   152     if pycompat.iswindows:
   154         return
   153         return
   155     os.umask(val)
   154     os.umask(val)
   156     global umask
   155     global umask
  1848 if pycompat.ispypy:
  1847 if pycompat.ispypy:
  1849     # PyPy runs slower with gc disabled
  1848     # PyPy runs slower with gc disabled
  1850     nogc = lambda x: x
  1849     nogc = lambda x: x
  1851 
  1850 
  1852 
  1851 
  1853 def pathto(root, n1, n2):
  1852 def pathto(root: bytes, n1: bytes, n2: bytes) -> bytes:
  1854     # type: (bytes, bytes, bytes) -> bytes
       
  1855     """return the relative path from one place to another.
  1853     """return the relative path from one place to another.
  1856     root should use os.sep to separate directories
  1854     root should use os.sep to separate directories
  1857     n1 should use os.sep to separate directories
  1855     n1 should use os.sep to separate directories
  1858     n2 should use "/" to separate directories
  1856     n2 should use "/" to separate directories
  1859     returns an os.sep-separated path.
  1857     returns an os.sep-separated path.
  2060     b'lpt9',
  2058     b'lpt9',
  2061 }
  2059 }
  2062 _winreservedchars = b':*?"<>|'
  2060 _winreservedchars = b':*?"<>|'
  2063 
  2061 
  2064 
  2062 
  2065 def checkwinfilename(path):
  2063 def checkwinfilename(path: bytes) -> Optional[bytes]:
  2066     # type: (bytes) -> Optional[bytes]
       
  2067     r"""Check that the base-relative path is a valid filename on Windows.
  2064     r"""Check that the base-relative path is a valid filename on Windows.
  2068     Returns None if the path is ok, or a UI string describing the problem.
  2065     Returns None if the path is ok, or a UI string describing the problem.
  2069 
  2066 
  2070     >>> checkwinfilename(b"just/a/normal/path")
  2067     >>> checkwinfilename(b"just/a/normal/path")
  2071     >>> checkwinfilename(b"foo/bar/con.xml")
  2068     >>> checkwinfilename(b"foo/bar/con.xml")
  2155     ld = os.open(pathname, flags)
  2152     ld = os.open(pathname, flags)
  2156     os.write(ld, info)
  2153     os.write(ld, info)
  2157     os.close(ld)
  2154     os.close(ld)
  2158 
  2155 
  2159 
  2156 
  2160 def readlock(pathname):
  2157 def readlock(pathname: bytes) -> bytes:
  2161     # type: (bytes) -> bytes
       
  2162     try:
  2158     try:
  2163         return readlink(pathname)
  2159         return readlink(pathname)
  2164     except OSError as why:
  2160     except OSError as why:
  2165         if why.errno not in (errno.EINVAL, errno.ENOSYS):
  2161         if why.errno not in (errno.EINVAL, errno.ENOSYS):
  2166             raise
  2162             raise
  2179 
  2175 
  2180 
  2176 
  2181 # File system features
  2177 # File system features
  2182 
  2178 
  2183 
  2179 
  2184 def fscasesensitive(path):
  2180 def fscasesensitive(path: bytes) -> bool:
  2185     # type: (bytes) -> bool
       
  2186     """
  2181     """
  2187     Return true if the given path is on a case-sensitive filesystem
  2182     Return true if the given path is on a case-sensitive filesystem
  2188 
  2183 
  2189     Requires a path (like /foo/.hg) ending with a foldable final
  2184     Requires a path (like /foo/.hg) ending with a foldable final
  2190     directory component.
  2185     directory component.
  2284 re = _re()
  2279 re = _re()
  2285 
  2280 
  2286 _fspathcache = {}
  2281 _fspathcache = {}
  2287 
  2282 
  2288 
  2283 
  2289 def fspath(name, root):
  2284 def fspath(name: bytes, root: bytes) -> bytes:
  2290     # type: (bytes, bytes) -> bytes
       
  2291     """Get name in the case stored in the filesystem
  2285     """Get name in the case stored in the filesystem
  2292 
  2286 
  2293     The name should be relative to root, and be normcase-ed for efficiency.
  2287     The name should be relative to root, and be normcase-ed for efficiency.
  2294 
  2288 
  2295     Note that this function is unnecessary, and should not be
  2289     Note that this function is unnecessary, and should not be
  2329         dir = os.path.join(dir, part)
  2323         dir = os.path.join(dir, part)
  2330 
  2324 
  2331     return b''.join(result)
  2325     return b''.join(result)
  2332 
  2326 
  2333 
  2327 
  2334 def checknlink(testfile):
  2328 def checknlink(testfile: bytes) -> bool:
  2335     # type: (bytes) -> bool
       
  2336     '''check whether hardlink count reporting works properly'''
  2329     '''check whether hardlink count reporting works properly'''
  2337 
  2330 
  2338     # testfile may be open, so we need a separate file for checking to
  2331     # testfile may be open, so we need a separate file for checking to
  2339     # work around issue2543 (or testfile may get lost on Samba shares)
  2332     # work around issue2543 (or testfile may get lost on Samba shares)
  2340     f1, f2, fp = None, None, None
  2333     f1, f2, fp = None, None, None
  2363                     os.unlink(f)
  2356                     os.unlink(f)
  2364             except OSError:
  2357             except OSError:
  2365                 pass
  2358                 pass
  2366 
  2359 
  2367 
  2360 
  2368 def endswithsep(path):
  2361 def endswithsep(path: bytes) -> bool:
  2369     # type: (bytes) -> bool
       
  2370     '''Check path ends with os.sep or os.altsep.'''
  2362     '''Check path ends with os.sep or os.altsep.'''
  2371     return bool(  # help pytype
  2363     return bool(  # help pytype
  2372         path.endswith(pycompat.ossep)
  2364         path.endswith(pycompat.ossep)
  2373         or pycompat.osaltsep
  2365         or pycompat.osaltsep
  2374         and path.endswith(pycompat.osaltsep)
  2366         and path.endswith(pycompat.osaltsep)
  2375     )
  2367     )
  2376 
  2368 
  2377 
  2369 
  2378 def splitpath(path):
  2370 def splitpath(path: bytes) -> List[bytes]:
  2379     # type: (bytes) -> List[bytes]
       
  2380     """Split path by os.sep.
  2371     """Split path by os.sep.
  2381     Note that this function does not use os.altsep because this is
  2372     Note that this function does not use os.altsep because this is
  2382     an alternative of simple "xxx.split(os.sep)".
  2373     an alternative of simple "xxx.split(os.sep)".
  2383     It is recommended to use os.path.normpath() before using this
  2374     It is recommended to use os.path.normpath() before using this
  2384     function if need."""
  2375     function if need."""
  2607     except OSError as e:
  2598     except OSError as e:
  2608         if e.errno != errno.ENOENT and e.errno != errno.ENOTEMPTY:
  2599         if e.errno != errno.ENOENT and e.errno != errno.ENOTEMPTY:
  2609             raise
  2600             raise
  2610 
  2601 
  2611 
  2602 
  2612 def unlinkpath(f, ignoremissing=False, rmdir=True):
  2603 def unlinkpath(
  2613     # type: (bytes, bool, bool) -> None
  2604     f: bytes, ignoremissing: bool = False, rmdir: bool = True
       
  2605 ) -> None:
  2614     """unlink and remove the directory if it is empty"""
  2606     """unlink and remove the directory if it is empty"""
  2615     if ignoremissing:
  2607     if ignoremissing:
  2616         tryunlink(f)
  2608         tryunlink(f)
  2617     else:
  2609     else:
  2618         unlink(f)
  2610         unlink(f)
  2622             removedirs(os.path.dirname(f))
  2614             removedirs(os.path.dirname(f))
  2623         except OSError:
  2615         except OSError:
  2624             pass
  2616             pass
  2625 
  2617 
  2626 
  2618 
  2627 def tryunlink(f):
  2619 def tryunlink(f: bytes) -> None:
  2628     # type: (bytes) -> None
       
  2629     """Attempt to remove a file, ignoring FileNotFoundError."""
  2620     """Attempt to remove a file, ignoring FileNotFoundError."""
  2630     try:
  2621     try:
  2631         unlink(f)
  2622         unlink(f)
  2632     except FileNotFoundError:
  2623     except FileNotFoundError:
  2633         pass
  2624         pass
  2634 
  2625 
  2635 
  2626 
  2636 def makedirs(name, mode=None, notindexed=False):
  2627 def makedirs(
  2637     # type: (bytes, Optional[int], bool) -> None
  2628     name: bytes, mode: Optional[int] = None, notindexed: bool = False
       
  2629 ) -> None:
  2638     """recursive directory creation with parent mode inheritance
  2630     """recursive directory creation with parent mode inheritance
  2639 
  2631 
  2640     Newly created directories are marked as "not to be indexed by
  2632     Newly created directories are marked as "not to be indexed by
  2641     the content indexing service", if ``notindexed`` is specified
  2633     the content indexing service", if ``notindexed`` is specified
  2642     for "write" mode access.
  2634     for "write" mode access.
  2661             raise
  2653             raise
  2662     if mode is not None:
  2654     if mode is not None:
  2663         os.chmod(name, mode)
  2655         os.chmod(name, mode)
  2664 
  2656 
  2665 
  2657 
  2666 def readfile(path):
  2658 def readfile(path: bytes) -> bytes:
  2667     # type: (bytes) -> bytes
       
  2668     with open(path, b'rb') as fp:
  2659     with open(path, b'rb') as fp:
  2669         return fp.read()
  2660         return fp.read()
  2670 
  2661 
  2671 
  2662 
  2672 def writefile(path, text):
  2663 def writefile(path: bytes, text: bytes) -> None:
  2673     # type: (bytes, bytes) -> None
       
  2674     with open(path, b'wb') as fp:
  2664     with open(path, b'wb') as fp:
  2675         fp.write(text)
  2665         fp.write(text)
  2676 
  2666 
  2677 
  2667 
  2678 def appendfile(path, text):
  2668 def appendfile(path: bytes, text: bytes) -> None:
  2679     # type: (bytes, bytes) -> None
       
  2680     with open(path, b'ab') as fp:
  2669     with open(path, b'ab') as fp:
  2681         fp.write(text)
  2670         fp.write(text)
  2682 
  2671 
  2683 
  2672 
  2684 class chunkbuffer:
  2673 class chunkbuffer:
  2835         return unittable[-1][2] % count
  2824         return unittable[-1][2] % count
  2836 
  2825 
  2837     return go
  2826     return go
  2838 
  2827 
  2839 
  2828 
  2840 def processlinerange(fromline, toline):
  2829 def processlinerange(fromline: int, toline: int) -> Tuple[int, int]:
  2841     # type: (int, int) -> Tuple[int, int]
       
  2842     """Check that linerange <fromline>:<toline> makes sense and return a
  2830     """Check that linerange <fromline>:<toline> makes sense and return a
  2843     0-based range.
  2831     0-based range.
  2844 
  2832 
  2845     >>> processlinerange(10, 20)
  2833     >>> processlinerange(10, 20)
  2846     (9, 20)
  2834     (9, 20)
  2895 # are removed or a LF. We do not care about old Macintosh files, so a
  2883 # are removed or a LF. We do not care about old Macintosh files, so a
  2896 # stray CR is an error.
  2884 # stray CR is an error.
  2897 _eolre = remod.compile(br'\r*\n')
  2885 _eolre = remod.compile(br'\r*\n')
  2898 
  2886 
  2899 
  2887 
  2900 def tolf(s):
  2888 def tolf(s: bytes) -> bytes:
  2901     # type: (bytes) -> bytes
       
  2902     return _eolre.sub(b'\n', s)
  2889     return _eolre.sub(b'\n', s)
  2903 
  2890 
  2904 
  2891 
  2905 def tocrlf(s):
  2892 def tocrlf(s: bytes) -> bytes:
  2906     # type: (bytes) -> bytes
       
  2907     return _eolre.sub(b'\r\n', s)
  2893     return _eolre.sub(b'\r\n', s)
  2908 
  2894 
  2909 
  2895 
  2910 def _crlfwriter(fp):
  2896 def _crlfwriter(fp):
  2911     return transformingwriter(fp, tocrlf)
  2897     return transformingwriter(fp, tocrlf)
  2924 # TODO delete since workaround variant for Python 2 no longer needed.
  2910 # TODO delete since workaround variant for Python 2 no longer needed.
  2925 def iterfile(fp):
  2911 def iterfile(fp):
  2926     return fp
  2912     return fp
  2927 
  2913 
  2928 
  2914 
  2929 def iterlines(iterator):
  2915 def iterlines(iterator: Iterable[bytes]) -> Iterator[bytes]:
  2930     # type: (Iterable[bytes]) -> Iterator[bytes]
       
  2931     for chunk in iterator:
  2916     for chunk in iterator:
  2932         for line in chunk.splitlines():
  2917         for line in chunk.splitlines():
  2933             yield line
  2918             yield line
  2934 
  2919 
  2935 
  2920 
  2936 def expandpath(path):
  2921 def expandpath(path: bytes) -> bytes:
  2937     # type: (bytes) -> bytes
       
  2938     return os.path.expanduser(os.path.expandvars(path))
  2922     return os.path.expanduser(os.path.expandvars(path))
  2939 
  2923 
  2940 
  2924 
  2941 def interpolate(prefix, mapping, s, fn=None, escape_prefix=False):
  2925 def interpolate(prefix, mapping, s, fn=None, escape_prefix=False):
  2942     """Return the result of interpolating items in the mapping into string s.
  2926     """Return the result of interpolating items in the mapping into string s.
  3060     (b'gb', 2 ** 30),
  3044     (b'gb', 2 ** 30),
  3061     (b'b', 1),
  3045     (b'b', 1),
  3062 )
  3046 )
  3063 
  3047 
  3064 
  3048 
  3065 def sizetoint(s):
  3049 def sizetoint(s: bytes) -> int:
  3066     # type: (bytes) -> int
       
  3067     """Convert a space specifier to a byte count.
  3050     """Convert a space specifier to a byte count.
  3068 
  3051 
  3069     >>> sizetoint(b'30')
  3052     >>> sizetoint(b'30')
  3070     30
  3053     30
  3071     >>> sizetoint(b'2.2kb')
  3054     >>> sizetoint(b'2.2kb')
  3283             locale.setlocale(locale.LC_CTYPE, oldloc)
  3266             locale.setlocale(locale.LC_CTYPE, oldloc)
  3284     else:
  3267     else:
  3285         yield
  3268         yield
  3286 
  3269 
  3287 
  3270 
  3288 def _estimatememory():
  3271 def _estimatememory() -> Optional[int]:
  3289     # type: () -> Optional[int]
       
  3290     """Provide an estimate for the available system memory in Bytes.
  3272     """Provide an estimate for the available system memory in Bytes.
  3291 
  3273 
  3292     If no estimate can be provided on the platform, returns None.
  3274     If no estimate can be provided on the platform, returns None.
  3293     """
  3275     """
  3294     if pycompat.sysplatform.startswith(b'win'):
  3276     if pycompat.sysplatform.startswith(b'win'):