mercurial/posix.py
changeset 52364 7ac7d5f20cb0
parent 51859 f4733654f144
child 52526 dd052842fc8e
equal deleted inserted replaced
52363:6a8edf9f0a6d 52364:7ac7d5f20cb0
    35     Tuple,
    35     Tuple,
    36     Union,
    36     Union,
    37 )
    37 )
    38 
    38 
    39 from .i18n import _
    39 from .i18n import _
    40 from .pycompat import (
       
    41     open,
       
    42 )
       
    43 from . import (
    40 from . import (
    44     encoding,
    41     encoding,
    45     error,
    42     error,
    46     policy,
    43     policy,
    47     pycompat,
    44     pycompat,
    98 expandglobs: bool = False
    95 expandglobs: bool = False
    99 
    96 
   100 umask: int = os.umask(0)
    97 umask: int = os.umask(0)
   101 os.umask(umask)
    98 os.umask(umask)
   102 
    99 
   103 posixfile = open
   100 posixfile = pycompat.open
   104 
   101 
   105 
   102 
   106 def split(p: bytes) -> Tuple[bytes, bytes]:
   103 def split(p: bytes) -> Tuple[bytes, bytes]:
   107     """Same as posixpath.split, but faster
   104     """Same as posixpath.split, but faster
   108 
   105 
   172     st = os.lstat(f)
   169     st = os.lstat(f)
   173     s = st.st_mode
   170     s = st.st_mode
   174     if l:
   171     if l:
   175         if not stat.S_ISLNK(s):
   172         if not stat.S_ISLNK(s):
   176             # switch file to link
   173             # switch file to link
   177             with open(f, b'rb') as fp:
   174             with open(f, 'rb') as fp:
   178                 data = fp.read()
   175                 data = fp.read()
   179             unlink(f)
   176             unlink(f)
   180             try:
   177             try:
   181                 os.symlink(data, f)
   178                 os.symlink(data, f)
   182             except OSError:
   179             except OSError:
   183                 # failed to make a link, rewrite file
   180                 # failed to make a link, rewrite file
   184                 with open(f, b"wb") as fp:
   181                 with open(f, "wb") as fp:
   185                     fp.write(data)
   182                     fp.write(data)
   186 
   183 
   187         # no chmod needed at this point
   184         # no chmod needed at this point
   188         return
   185         return
   189     if stat.S_ISLNK(s):
   186     if stat.S_ISLNK(s):
   190         # switch link to file
   187         # switch link to file
   191         data = os.readlink(f)
   188         data = os.readlink(f)
   192         unlink(f)
   189         unlink(f)
   193         with open(f, b"wb") as fp:
   190         with open(f, "wb") as fp:
   194             fp.write(data)
   191             fp.write(data)
   195         s = 0o666 & ~umask  # avoid restatting for chmod
   192         s = 0o666 & ~umask  # avoid restatting for chmod
   196 
   193 
   197     sx = s & 0o100
   194     sx = s & 0o100
   198     if st.st_nlink > 1 and bool(x) != bool(sx):
   195     if st.st_nlink > 1 and bool(x) != bool(sx):
   199         # the file is a hardlink, break it
   196         # the file is a hardlink, break it
   200         with open(f, b"rb") as fp:
   197         with open(f, "rb") as fp:
   201             data = fp.read()
   198             data = fp.read()
   202         unlink(f)
   199         unlink(f)
   203         with open(f, b"wb") as fp:
   200         with open(f, "wb") as fp:
   204             fp.write(data)
   201             fp.write(data)
   205 
   202 
   206     if x and not sx:
   203     if x and not sx:
   207         # Turn on +x for every +r bit when making a file executable
   204         # Turn on +x for every +r bit when making a file executable
   208         # and obey umask.
   205         # and obey umask.
   280                 if m & EXECFLAGS != 0:
   277                 if m & EXECFLAGS != 0:
   281                     # ensure checknoexec exists, check it isn't exec
   278                     # ensure checknoexec exists, check it isn't exec
   282                     try:
   279                     try:
   283                         m = os.stat(checknoexec).st_mode
   280                         m = os.stat(checknoexec).st_mode
   284                     except FileNotFoundError:
   281                     except FileNotFoundError:
   285                         open(checknoexec, b'w').close()  # might fail
   282                         open(checknoexec, 'w').close()  # might fail
   286                         m = os.stat(checknoexec).st_mode
   283                         m = os.stat(checknoexec).st_mode
   287                     if m & EXECFLAGS == 0:
   284                     if m & EXECFLAGS == 0:
   288                         # check-exec is exec and check-no-exec is not exec
   285                         # check-exec is exec and check-no-exec is not exec
   289                         return True
   286                         return True
   290                     # checknoexec exists but is exec - delete it
   287                     # checknoexec exists but is exec - delete it
   347                 # create a fixed file to link to; doesn't matter if it
   344                 # create a fixed file to link to; doesn't matter if it
   348                 # already exists.
   345                 # already exists.
   349                 target = b'checklink-target'
   346                 target = b'checklink-target'
   350                 try:
   347                 try:
   351                     fullpath = os.path.join(cachedir, target)
   348                     fullpath = os.path.join(cachedir, target)
   352                     open(fullpath, b'w').close()
   349                     open(fullpath, 'w').close()
   353                 except PermissionError:
   350                 except PermissionError:
   354                     # If we can't write to cachedir, just pretend
   351                     # If we can't write to cachedir, just pretend
   355                     # that the fs is readonly and by association
   352                     # that the fs is readonly and by association
   356                     # that the fs won't support symlinks. This
   353                     # that the fs won't support symlinks. This
   357                     # seems like the least dangerous way to avoid
   354                     # seems like the least dangerous way to avoid