##// END OF EJS Templates
merge with stable
merge with stable

File last commit:

r41325:593f6359 default
r42612:c77ab654 merge default
Show More
windows.py
627 lines | 19.7 KiB | text/x-python | PythonLexer
Martin Geisler
put license and copyright info into comment blocks
r8226 # windows.py - Windows utility function implementations for Mercurial
#
# Copyright 2005-2009 Matt Mackall <mpm@selenic.com> and others
#
# This software may be used and distributed according to the terms of the
Matt Mackall
Update license to GPLv2+
r10263 # GNU General Public License version 2 or any later version.
Matt Mackall
util: split out posix, windows, and win32 modules
r7890
Gregory Szorc
windows: use absolute_import
r27360 from __future__ import absolute_import
Sune Foldager
posixfile: remove posixfile_nt and fix import bug in windows.py...
r8421
Gregory Szorc
windows: use absolute_import
r27360 import errno
import msvcrt
import os
import re
import stat
Matt Harbison
windows: add a method to convert Unix style command lines to Windows style...
r38502 import string
Gregory Szorc
windows: use absolute_import
r27360 import sys
from .i18n import _
from . import (
encoding,
Augie Fackler
ssh: ban any username@host or host that starts with - (SEC)...
r33724 error,
Yuya Nishihara
osutil: switch to policy importer...
r32367 policy,
Pulkit Goyal
py3: replace os.pathsep with pycompat.ospathsep...
r30612 pycompat,
Matt Harbison
windows: correct the import of win32...
r27436 win32,
Gregory Szorc
windows: use absolute_import
r27360 )
Pulkit Goyal
py3: conditionalize _winreg import...
r29760 try:
import _winreg as winreg
winreg.CloseKey
except ImportError:
import winreg
Yuya Nishihara
osutil: switch to policy importer...
r32367 osutil = policy.importmod(r'osutil')
Matt Harbison
util: add a function to show the mount point of the filesystem...
r35531 getfsmountpoint = win32.getvolumename
Matt Harbison
win32: implement util.getfstype()...
r35528 getfstype = win32.getfstype
Matt Mackall
windows: fix pyflakes warning on unused imports...
r15016 getuser = win32.getuser
hidewindow = win32.hidewindow
makedir = win32.makedir
nlinks = win32.nlinks
oslink = win32.oslink
samedevice = win32.samedevice
samefile = win32.samefile
setsignalhandler = win32.setsignalhandler
spawndetached = win32.spawndetached
Bryan O'Sullivan
util: implement a faster os.path.split for posix systems...
r17560 split = os.path.split
Matt Mackall
windows: fix pyflakes warning on unused imports...
r15016 testpid = win32.testpid
unlink = win32.unlink
Adrian Buehlmann
windows: eliminate win32 wildcard import
r14985
Gregory Szorc
global: mass rewrite to use modern octal syntax...
r25658 umask = 0o022
Matt Mackall
util: split out posix, windows, and win32 modules
r7890
Gregory Szorc
windows: insert file positioning call between reads and writes...
r26375 class mixedfilemodewrapper(object):
"""Wraps a file handle when it is opened in read/write mode.
fopen() and fdopen() on Windows have a specific-to-Windows requirement
that files opened with mode r+, w+, or a+ make a call to a file positioning
function when switching between reads and writes. Without this extra call,
Python will raise a not very intuitive "IOError: [Errno 0] Error."
This class wraps posixfile instances when the file is opened in read/write
mode and automatically adds checks or inserts appropriate file positioning
calls when necessary.
"""
OPNONE = 0
OPREAD = 1
OPWRITE = 2
def __init__(self, fp):
Yuya Nishihara
py3: abuse r'' to preserve str-ness of literals passed to __setattr__()
r31644 object.__setattr__(self, r'_fp', fp)
object.__setattr__(self, r'_lastop', 0)
Gregory Szorc
windows: insert file positioning call between reads and writes...
r26375
Matt Harbison
windows: add context manager support to mixedfilemodewrapper...
r31891 def __enter__(self):
Matt Harbison
windows: ensure mixedfilemodewrapper fd doesn't escape by entering context mgr...
r40974 self._fp.__enter__()
return self
Matt Harbison
windows: add context manager support to mixedfilemodewrapper...
r31891
def __exit__(self, exc_type, exc_val, exc_tb):
self._fp.__exit__(exc_type, exc_val, exc_tb)
Gregory Szorc
windows: insert file positioning call between reads and writes...
r26375 def __getattr__(self, name):
return getattr(self._fp, name)
def __setattr__(self, name, value):
return self._fp.__setattr__(name, value)
def _noopseek(self):
self._fp.seek(0, os.SEEK_CUR)
def seek(self, *args, **kwargs):
Yuya Nishihara
py3: abuse r'' to preserve str-ness of literals passed to __setattr__()
r31644 object.__setattr__(self, r'_lastop', self.OPNONE)
Gregory Szorc
windows: insert file positioning call between reads and writes...
r26375 return self._fp.seek(*args, **kwargs)
def write(self, d):
if self._lastop == self.OPREAD:
self._noopseek()
Yuya Nishihara
py3: abuse r'' to preserve str-ness of literals passed to __setattr__()
r31644 object.__setattr__(self, r'_lastop', self.OPWRITE)
Gregory Szorc
windows: insert file positioning call between reads and writes...
r26375 return self._fp.write(d)
def writelines(self, *args, **kwargs):
if self._lastop == self.OPREAD:
self._noopeseek()
Yuya Nishihara
py3: abuse r'' to preserve str-ness of literals passed to __setattr__()
r31644 object.__setattr__(self, r'_lastop', self.OPWRITE)
Gregory Szorc
windows: insert file positioning call between reads and writes...
r26375 return self._fp.writelines(*args, **kwargs)
def read(self, *args, **kwargs):
if self._lastop == self.OPWRITE:
self._noopseek()
Yuya Nishihara
py3: abuse r'' to preserve str-ness of literals passed to __setattr__()
r31644 object.__setattr__(self, r'_lastop', self.OPREAD)
Gregory Szorc
windows: insert file positioning call between reads and writes...
r26375 return self._fp.read(*args, **kwargs)
def readline(self, *args, **kwargs):
if self._lastop == self.OPWRITE:
self._noopseek()
Yuya Nishihara
py3: abuse r'' to preserve str-ness of literals passed to __setattr__()
r31644 object.__setattr__(self, r'_lastop', self.OPREAD)
Gregory Szorc
windows: insert file positioning call between reads and writes...
r26375 return self._fp.readline(*args, **kwargs)
def readlines(self, *args, **kwargs):
if self._lastop == self.OPWRITE:
self._noopseek()
Yuya Nishihara
py3: abuse r'' to preserve str-ness of literals passed to __setattr__()
r31644 object.__setattr__(self, r'_lastop', self.OPREAD)
Gregory Szorc
windows: insert file positioning call between reads and writes...
r26375 return self._fp.readlines(*args, **kwargs)
Matt Harbison
py3: proxy posixfile objects to re-add a useful 'name' attribute on Windows...
r39845 class fdproxy(object):
"""Wraps osutil.posixfile() to override the name attribute to reflect the
underlying file name.
"""
def __init__(self, name, fp):
self.name = name
self._fp = fp
def __enter__(self):
Matt Harbison
py3: ensure the proxied Windows fd doesn't escape by entering context manager...
r40973 self._fp.__enter__()
# Return this wrapper for the context manager so that the name is
# still available.
return self
Matt Harbison
py3: proxy posixfile objects to re-add a useful 'name' attribute on Windows...
r39845
def __exit__(self, exc_type, exc_value, traceback):
self._fp.__exit__(exc_type, exc_value, traceback)
def __iter__(self):
return iter(self._fp)
def __getattr__(self, name):
return getattr(self._fp, name)
Sune Foldager
posixfile: remove posixfile_nt and fix import bug in windows.py...
r8421 def posixfile(name, mode='r', buffering=-1):
Adrian Buehlmann
windows: adjust doc string and comments of posixfile()...
r24069 '''Open a file with even more POSIX-like semantics'''
Sune Foldager
posixfile: remove posixfile_nt and fix import bug in windows.py...
r8421 try:
Adrian Buehlmann
windows: adjust doc string and comments of posixfile()...
r24069 fp = osutil.posixfile(name, mode, buffering) # may raise WindowsError
Matt Harbison
windows: seek to the end of posixfile when opening in append mode...
r24051
Matt Harbison
py3: proxy posixfile objects to re-add a useful 'name' attribute on Windows...
r39845 # PyFile_FromFd() ignores the name, and seems to report fp.name as the
# underlying file descriptor.
if pycompat.ispy3:
fp = fdproxy(name, fp)
Matt Harbison
windows: seek to the end of posixfile when opening in append mode...
r24051 # The position when opening in append mode is implementation defined, so
# make it consistent with other platforms, which position at EOF.
if 'a' in mode:
Adrian Buehlmann
windows: use os.SEEK_END
r25462 fp.seek(0, os.SEEK_END)
Matt Harbison
windows: seek to the end of posixfile when opening in append mode...
r24051
Gregory Szorc
windows: insert file positioning call between reads and writes...
r26375 if '+' in mode:
return mixedfilemodewrapper(fp)
Matt Harbison
windows: seek to the end of posixfile when opening in append mode...
r24051 return fp
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except WindowsError as err:
Adrian Buehlmann
windows: adjust doc string and comments of posixfile()...
r24069 # convert to a friendlier exception
Matt Harbison
py3: ensure standard exceptions use `str` type strings in windows.py...
r39919 raise IOError(err.errno, r'%s: %s' % (
encoding.strfromlocal(name), err.strerror))
Matt Mackall
util: split out posix, windows, and win32 modules
r7890
Yuya Nishihara
osutil: proxy through util (and platform) modules (API)...
r32203 # may be wrapped by win32mbcs extension
listdir = osutil.listdir
Benoit Boissinot
use new style classes
r8778 class winstdout(object):
Matt Mackall
util: split out posix, windows, and win32 modules
r7890 '''stdout on windows misbehaves if sent through a pipe'''
def __init__(self, fp):
self.fp = fp
def __getattr__(self, key):
return getattr(self.fp, key)
def close(self):
try:
self.fp.close()
Idan Kamara
eliminate various naked except clauses
r14004 except IOError:
pass
Matt Mackall
util: split out posix, windows, and win32 modules
r7890
def write(self, s):
try:
# This is workaround for "Not enough space" error on
# writing large size of data to console.
limit = 16000
l = len(s)
start = 0
Benoit Boissinot
fix coding style (reported by pylint)
r10394 self.softspace = 0
Matt Mackall
util: split out posix, windows, and win32 modules
r7890 while start < l:
end = start + limit
self.fp.write(s[start:end])
start = end
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except IOError as inst:
Sune Foldager
windows: fix incorrect detection of broken pipe when writing to pager...
r38575 if inst.errno != 0 and not win32.lasterrorwaspipeerror(inst):
Matt Mackall
many, many trivial check-code fixups
r10282 raise
Matt Mackall
util: split out posix, windows, and win32 modules
r7890 self.close()
Matt Harbison
py3: ensure standard exceptions use `str` type strings in windows.py...
r39919 raise IOError(errno.EPIPE, r'Broken pipe')
Matt Mackall
util: split out posix, windows, and win32 modules
r7890
def flush(self):
try:
return self.fp.flush()
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except IOError as inst:
Sune Foldager
windows: fix incorrect detection of broken pipe when writing to pager...
r38575 if not win32.lasterrorwaspipeerror(inst):
Matt Mackall
many, many trivial check-code fixups
r10282 raise
Matt Harbison
py3: ensure standard exceptions use `str` type strings in windows.py...
r39919 raise IOError(errno.EPIPE, r'Broken pipe')
Matt Mackall
util: split out posix, windows, and win32 modules
r7890
def _is_win_9x():
'''return true if run on windows 95, 98 or me.'''
try:
return sys.getwindowsversion()[3] == 1
except AttributeError:
Pulkit Goyal
py3: replace os.environ with encoding.environ (part 3 of 5)
r30636 return 'command' in encoding.environ.get('comspec', '')
Matt Mackall
util: split out posix, windows, and win32 modules
r7890
def openhardlinks():
Adrian Buehlmann
port win32.py to using the Python ctypes library...
r13375 return not _is_win_9x()
Matt Mackall
util: split out posix, windows, and win32 modules
r7890
Adrian Buehlmann
rename util.parse_patch_output to parsepatchoutput
r14231 def parsepatchoutput(output_line):
timeless
Generally replace "file name" with "filename" in help and comments.
r8761 """parses the output produced by patch and returns the filename"""
Matt Mackall
util: split out posix, windows, and win32 modules
r7890 pf = output_line[14:]
if pf[0] == '`':
pf = pf[1:-1] # Remove the quotes
return pf
def sshargs(sshcmd, host, user, port):
'''Build argument list for ssh or Plink'''
pflag = 'plink' in sshcmd.lower() and '-P' or '-p'
args = user and ("%s@%s" % (user, host)) or host
Augie Fackler
ssh: ban any username@host or host that starts with - (SEC)...
r33724 if args.startswith('-') or args.startswith('/'):
raise error.Abort(
_('illegal ssh hostname or username starting with - or /: %s') %
args)
Jun Wu
ssh: quote parameters using shellquote (SEC)...
r33732 args = shellquote(args)
if port:
args = '%s %s %s' % (pflag, shellquote(port), args)
return args
Matt Mackall
util: split out posix, windows, and win32 modules
r7890
Adrian Buehlmann
rename util.set_flags to setflags
r14232 def setflags(f, l, x):
Matt Mackall
util: split out posix, windows, and win32 modules
r7890 pass
Boris Feld
update: fix edge-case with update.atomic-file and read-only files...
r41325 def copymode(src, dst, mode=None, enforcewritable=False):
Adrian Buehlmann
util: move copymode into posix.py and windows.py...
r15011 pass
Adrian Buehlmann
util: move checkexec() to posix.py and return False on Windows
r13879 def checkexec(path):
return False
Adrian Buehlmann
util: move checklink() to posix.py and return False on Windows...
r13890 def checklink(path):
return False
Adrian Buehlmann
rename util.set_binary to setbinary
r14233 def setbinary(fd):
Matt Mackall
util: split out posix, windows, and win32 modules
r7890 # When run without console, pipes may expose invalid
# fileno(), usually set to -1.
Augie Fackler
windows: use getattr instead of hasattr
r14969 fno = getattr(fd, 'fileno', None)
if fno is not None and fno() >= 0:
msvcrt.setmode(fno(), os.O_BINARY)
Matt Mackall
util: split out posix, windows, and win32 modules
r7890
def pconvert(path):
Pulkit Goyal
py3: replace os.sep with pycompat.ossep (part 3 of 4)
r30615 return path.replace(pycompat.ossep, '/')
Matt Mackall
util: split out posix, windows, and win32 modules
r7890
def localpath(path):
return path.replace('/', '\\')
def normpath(path):
return pconvert(os.path.normpath(path))
FUJIWARA Katsunori
windows: use upper() instead of lower() or os.path.normcase()...
r15671 def normcase(path):
Adrian Buehlmann
windows: add comment in normcase()...
r25071 return encoding.upper(path) # NTFS compares via upper()
Matt Mackall
dirstate: fix case-folding identity for traditional Unix...
r15488
Siddharth Agarwal
windows: define normcase spec and fallback...
r24598 # see posix.py for definitions
normcasespec = encoding.normcasespecs.upper
normcasefallback = encoding.upperfallback
Matt Mackall
util: split out posix, windows, and win32 modules
r7890 def samestat(s1, s2):
return False
Matt Harbison
windows: add a method to convert Unix style command lines to Windows style...
r38502 def shelltocmdexe(path, env):
r"""Convert shell variables in the form $var and ${var} inside ``path``
to %var% form. Existing Windows style variables are left unchanged.
The variables are limited to the given environment. Unknown variables are
left unchanged.
>>> e = {b'var1': b'v1', b'var2': b'v2', b'var3': b'v3'}
>>> # Only valid values are expanded
>>> shelltocmdexe(b'cmd $var1 ${var2} %var3% $missing ${missing} %missing%',
... e)
'cmd %var1% %var2% %var3% $missing ${missing} %missing%'
>>> # Single quote prevents expansion, as does \$ escaping
>>> shelltocmdexe(b"cmd '$var1 ${var2} %var3%' \$var1 \${var2} \\", e)
Matt Harbison
windows: replace single quote with double quote when translating to cmd.exe...
r38747 'cmd "$var1 ${var2} %var3%" $var1 ${var2} \\'
Matt Harbison
windows: don't consider '$$' to be an escaped '$' when translating to cmd.exe...
r38646 >>> # $$ is not special. %% is not special either, but can be the end and
>>> # start of consecutive variables
Matt Harbison
windows: add a method to convert Unix style command lines to Windows style...
r38502 >>> shelltocmdexe(b"cmd $$ %% %var1%%var2%", e)
Matt Harbison
windows: don't consider '$$' to be an escaped '$' when translating to cmd.exe...
r38646 'cmd $$ %% %var1%%var2%'
Matt Harbison
windows: add a method to convert Unix style command lines to Windows style...
r38502 >>> # No double substitution
>>> shelltocmdexe(b"$var1 %var1%", {b'var1': b'%var2%', b'var2': b'boom'})
'%var1% %var1%'
Matt Harbison
windows: expand '~/' and '~\' to %USERPROFILE% when translating to cmd.exe...
r38748 >>> # Tilde expansion
>>> shelltocmdexe(b"~/dir ~\dir2 ~tmpfile \~/", {})
'%USERPROFILE%/dir %USERPROFILE%\\dir2 ~tmpfile ~/'
Matt Harbison
windows: add a method to convert Unix style command lines to Windows style...
r38502 """
Matt Harbison
windows: expand '~/' and '~\' to %USERPROFILE% when translating to cmd.exe...
r38748 if not any(c in path for c in b"$'~"):
Matt Harbison
windows: add a method to convert Unix style command lines to Windows style...
r38502 return path
varchars = pycompat.sysbytes(string.ascii_letters + string.digits) + b'_-'
res = b''
index = 0
pathlen = len(path)
while index < pathlen:
Matt Harbison
py3: byteify windows.shelltocmdexe()...
r39946 c = path[index:index + 1]
Matt Harbison
windows: add a method to convert Unix style command lines to Windows style...
r38502 if c == b'\'': # no expansion within single quotes
path = path[index + 1:]
pathlen = len(path)
try:
index = path.index(b'\'')
Matt Harbison
windows: replace single quote with double quote when translating to cmd.exe...
r38747 res += b'"' + path[:index] + b'"'
Matt Harbison
windows: add a method to convert Unix style command lines to Windows style...
r38502 except ValueError:
res += c + path
index = pathlen - 1
elif c == b'%': # variable
path = path[index + 1:]
pathlen = len(path)
try:
index = path.index(b'%')
except ValueError:
res += b'%' + path
index = pathlen - 1
else:
var = path[:index]
res += b'%' + var + b'%'
Matt Harbison
windows: don't consider '$$' to be an escaped '$' when translating to cmd.exe...
r38646 elif c == b'$': # variable
if path[index + 1:index + 2] == b'{':
Matt Harbison
windows: add a method to convert Unix style command lines to Windows style...
r38502 path = path[index + 2:]
pathlen = len(path)
try:
index = path.index(b'}')
var = path[:index]
# See below for why empty variables are handled specially
Matt Harbison
py3: byteify windows.shelltocmdexe()...
r39946 if env.get(var, b'') != b'':
Matt Harbison
windows: add a method to convert Unix style command lines to Windows style...
r38502 res += b'%' + var + b'%'
else:
res += b'${' + var + b'}'
except ValueError:
res += b'${' + path
index = pathlen - 1
else:
var = b''
index += 1
c = path[index:index + 1]
while c != b'' and c in varchars:
var += c
index += 1
c = path[index:index + 1]
# Some variables (like HG_OLDNODE) may be defined, but have an
# empty value. Those need to be skipped because when spawning
# cmd.exe to run the hook, it doesn't replace %VAR% for an empty
# VAR, and that really confuses things like revset expressions.
# OTOH, if it's left in Unix format and the hook runs sh.exe, it
# will substitute to an empty string, and everything is happy.
Matt Harbison
py3: byteify windows.shelltocmdexe()...
r39946 if env.get(var, b'') != b'':
Matt Harbison
windows: add a method to convert Unix style command lines to Windows style...
r38502 res += b'%' + var + b'%'
else:
res += b'$' + var
Matt Harbison
py3: byteify windows.shelltocmdexe()...
r39946 if c != b'':
Matt Harbison
windows: add a method to convert Unix style command lines to Windows style...
r38502 index -= 1
Matt Harbison
windows: expand '~/' and '~\' to %USERPROFILE% when translating to cmd.exe...
r38748 elif (c == b'~' and index + 1 < pathlen
Matt Harbison
py3: byteify windows.shelltocmdexe()...
r39946 and path[index + 1:index + 2] in (b'\\', b'/')):
Matt Harbison
windows: expand '~/' and '~\' to %USERPROFILE% when translating to cmd.exe...
r38748 res += "%USERPROFILE%"
elif (c == b'\\' and index + 1 < pathlen
Matt Harbison
py3: byteify windows.shelltocmdexe()...
r39946 and path[index + 1:index + 2] in (b'$', b'~')):
Matt Harbison
windows: expand '~/' and '~\' to %USERPROFILE% when translating to cmd.exe...
r38748 # Skip '\', but only if it is escaping $ or ~
Matt Harbison
py3: byteify windows.shelltocmdexe()...
r39946 res += path[index + 1:index + 2]
Matt Harbison
windows: add a method to convert Unix style command lines to Windows style...
r38502 index += 1
else:
res += c
index += 1
return res
Matt Mackall
util: split out posix, windows, and win32 modules
r7890 # A sequence of backslashes is special iff it precedes a double quote:
# - if there's an even number of backslashes, the double quote is not
# quoted (i.e. it ends the quoted region)
# - if there's an odd number of backslashes, the double quote is quoted
# - in both cases, every pair of backslashes is unquoted into a single
# backslash
# (See http://msdn2.microsoft.com/en-us/library/a1y7w461.aspx )
# So, to quote a string, we must surround it in double quotes, double
timeless@mozdev.org
spelling: precede
r17505 # the number of backslashes that precede double quotes and add another
Matt Mackall
util: split out posix, windows, and win32 modules
r7890 # backslash before every double quote (being careful with the double
# quote we've appended to the end)
_quotere = None
FUJIWARA Katsunori
windows: quote the specified string only when it has to be quoted...
r23682 _needsshellquote = None
Matt Mackall
util: split out posix, windows, and win32 modules
r7890 def shellquote(s):
Matt Harbison
windows: add doctest for shellquote()...
r24908 r"""
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> shellquote(br'C:\Users\xyz')
Matt Harbison
windows: add doctest for shellquote()...
r24908 '"C:\\Users\\xyz"'
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> shellquote(br'C:\Users\xyz/mixed')
Matt Harbison
windows: add doctest for shellquote()...
r24908 '"C:\\Users\\xyz/mixed"'
>>> # Would be safe not to quote too, since it is all double backslashes
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> shellquote(br'C:\\Users\\xyz')
Matt Harbison
windows: add doctest for shellquote()...
r24908 '"C:\\\\Users\\\\xyz"'
>>> # But this must be quoted
Yuya Nishihara
doctest: bulk-replace string literals with b'' for Python 3...
r34133 >>> shellquote(br'C:\\Users\\xyz/abc')
Matt Harbison
windows: add doctest for shellquote()...
r24908 '"C:\\\\Users\\\\xyz/abc"'
"""
Matt Mackall
util: split out posix, windows, and win32 modules
r7890 global _quotere
if _quotere is None:
Matt Harbison
py3: fix str vs bytes in enough places to run `hg version` on Windows...
r39680 _quotere = re.compile(br'(\\*)("|\\$)')
FUJIWARA Katsunori
windows: quote the specified string only when it has to be quoted...
r23682 global _needsshellquote
if _needsshellquote is None:
Matt Harbison
windows: make shellquote() quote any path containing '\' (issue4629)...
r24885 # ":" is also treated as "safe character", because it is used as a part
# of path name on Windows. "\" is also part of a path name, but isn't
# safe because shlex.split() (kind of) treats it as an escape char and
# drops it. It will leave the next character, even if it is another
# "\".
Matt Harbison
py3: fix str vs bytes in enough places to run `hg version` on Windows...
r39680 _needsshellquote = re.compile(br'[^a-zA-Z0-9._:/-]').search
Yuya Nishihara
shellquote: fix missing quotes for empty string...
r24108 if s and not _needsshellquote(s) and not _quotere.search(s):
FUJIWARA Katsunori
windows: quote the specified string only when it has to be quoted...
r23682 # "s" shouldn't have to be quoted
return s
Matt Harbison
py3: fix str vs bytes in enough places to run `hg version` on Windows...
r39680 return b'"%s"' % _quotere.sub(br'\1\1\\\2', s)
Matt Mackall
util: split out posix, windows, and win32 modules
r7890
Yuya Nishihara
util: factor out shellsplit() function...
r36433 def _unquote(s):
if s.startswith(b'"') and s.endswith(b'"'):
return s[1:-1]
return s
def shellsplit(s):
"""Parse a command string in cmd.exe way (best-effort)"""
return pycompat.maplist(_unquote, pycompat.shlexsplit(s, posix=False))
Matt Mackall
util: split out posix, windows, and win32 modules
r7890 def quotecommand(cmd):
"""Build a command string suitable for os.popen* calls."""
Steve Borho
util: concentrate quoting knowledge to windows.py quotecommand()...
r13188 if sys.version_info < (2, 7, 1):
# Python versions since 2.7.1 do this extra quoting themselves
return '"' + cmd + '"'
return cmd
Matt Mackall
util: split out posix, windows, and win32 modules
r7890
# if you change this stub into a real check, please try to implement the
# username and groupname functions above, too.
Martin Geisler
posix: do not use fstat in isowner...
r8657 def isowner(st):
Matt Mackall
util: split out posix, windows, and win32 modules
r7890 return True
Adrian Buehlmann
rename util.find_exe to findexe
r14271 def findexe(command):
Matt Mackall
util: split out posix, windows, and win32 modules
r7890 '''Find executable for command searching like cmd.exe does.
If command is a basename then PATH is searched for command.
PATH isn't searched if command is an absolute or relative path.
An extension from PATHEXT is found and added if not present.
If command isn't found None is returned.'''
Pulkit Goyal
py3: replace os.environ with encoding.environ (part 3 of 5)
r30636 pathext = encoding.environ.get('PATHEXT', '.COM;.EXE;.BAT;.CMD')
Pulkit Goyal
py3: replace os.pathsep with pycompat.ospathsep...
r30612 pathexts = [ext for ext in pathext.lower().split(pycompat.ospathsep)]
Matt Mackall
util: split out posix, windows, and win32 modules
r7890 if os.path.splitext(command)[1].lower() in pathexts:
pathexts = ['']
def findexisting(pathcommand):
'Will append extension (if needed) and return existing file'
for ext in pathexts:
executable = pathcommand + ext
if os.path.exists(executable):
return executable
return None
Pulkit Goyal
py3: replace os.sep with pycompat.ossep (part 3 of 4)
r30615 if pycompat.ossep in command:
Matt Mackall
util: split out posix, windows, and win32 modules
r7890 return findexisting(command)
Pulkit Goyal
py3: replace os.environ with encoding.environ (part 3 of 5)
r30636 for path in encoding.environ.get('PATH', '').split(pycompat.ospathsep):
Matt Mackall
util: split out posix, windows, and win32 modules
r7890 executable = findexisting(os.path.join(path, command))
if executable is not None:
return executable
Steve Borho
windows: expand environment vars in find_exe...
r10156 return findexisting(os.path.expanduser(os.path.expandvars(command)))
Matt Mackall
util: split out posix, windows, and win32 modules
r7890
Martin von Zweigbergk
cleanup: use set literals...
r32291 _wantedkinds = {stat.S_IFREG, stat.S_IFLNK}
Bryan O'Sullivan
dirstate: move file type filtering to its source...
r18017
Matt Mackall
util: split out posix, windows, and win32 modules
r7890 def statfiles(files):
Bryan O'Sullivan
dirstate: move file type filtering to its source...
r18017 '''Stat each file in files. Yield each stat, or None if a file
does not exist or has a type we don't care about.
Matt Mackall
util: split out posix, windows, and win32 modules
r7890 Cluster and cache stat per directory to minimize number of OS stat calls.'''
dircache = {} # dirname -> filename -> status | None if file does not exist
Bryan O'Sullivan
dirstate: move file type filtering to its source...
r18017 getkind = stat.S_IFMT
Matt Mackall
util: split out posix, windows, and win32 modules
r7890 for nf in files:
FUJIWARA Katsunori
icasefs: use util.normcase() instead of str.lower() or os.path.normpath()
r15637 nf = normcase(nf)
Shun-ichi GOTO
Use os.path.split() for MBCS with win32mbcs extension.
r9099 dir, base = os.path.split(nf)
if not dir:
dir = '.'
Matt Mackall
util: split out posix, windows, and win32 modules
r7890 cache = dircache.get(dir, None)
if cache is None:
try:
FUJIWARA Katsunori
icasefs: use util.normcase() instead of str.lower() or os.path.normpath()
r15637 dmap = dict([(normcase(n), s)
Yuya Nishihara
osutil: proxy through util (and platform) modules (API)...
r32203 for n, k, s in listdir(dir, True)
Matt Mackall
windows: correctly pass a mode to S_IFMT in statfiles
r18041 if getkind(s.st_mode) in _wantedkinds])
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except OSError as err:
Matt Mackall
util: split out posix, windows, and win32 modules
r7890 # Python >= 2.5 returns ENOENT and adds winerror field
# EINVAL is raised if dir is not a directory.
Pierre-Yves David
windows: drop Python2.4 specific hack for directory not found handling...
r25204 if err.errno not in (errno.ENOENT, errno.EINVAL,
Matt Mackall
util: split out posix, windows, and win32 modules
r7890 errno.ENOTDIR):
raise
dmap = {}
cache = dircache.setdefault(dir, dmap)
yield cache.get(base, None)
def username(uid=None):
"""Return the name of the user with the given uid.
If uid is None, return the name of the current user."""
return None
def groupname(gid=None):
"""Return the name of the group with the given gid.
If gid is None, return the name of the current group."""
return None
Matt Harbison
py3: convert os.readlink() path to native strings on Windows...
r39940 def readlink(pathname):
return pycompat.fsencode(os.readlink(pycompat.fsdecode(pathname)))
FUJIWARA Katsunori
util: add removedirs as platform depending function...
r24692 def removedirs(name):
Henrik Stuart
windows: avoid deleting non-empty reparse points...
r8364 """special version of os.removedirs that does not remove symlinked
directories or junction points if they actually contain files"""
Yuya Nishihara
osutil: proxy through util (and platform) modules (API)...
r32203 if listdir(name):
Henrik Stuart
windows: avoid deleting non-empty reparse points...
r8364 return
os.rmdir(name)
head, tail = os.path.split(name)
if not tail:
head, tail = os.path.split(head)
while head and tail:
try:
Yuya Nishihara
osutil: proxy through util (and platform) modules (API)...
r32203 if listdir(head):
Henrik Stuart
windows: avoid deleting non-empty reparse points...
r8364 return
os.rmdir(head)
Idan Kamara
eliminate various naked except clauses
r14004 except (ValueError, OSError):
Henrik Stuart
windows: avoid deleting non-empty reparse points...
r8364 break
head, tail = os.path.split(head)
Adrian Buehlmann
util: move rename into posix.py and windows.py
r9549 def rename(src, dst):
'''atomically rename file src to dst, replacing dst if it exists'''
try:
os.rename(src, dst)
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except OSError as e:
Adrian Buehlmann
windows.rename: check OSError for EEXIST...
r13278 if e.errno != errno.EEXIST:
raise
Adrian Buehlmann
reintroduces util.unlink, for POSIX and Windows....
r13280 unlink(dst)
Adrian Buehlmann
util: move rename into posix.py and windows.py
r9549 os.rename(src, dst)
Patrick Mezard
Find right hg command for detached process...
r10239 def gethgcmd():
Matt Harbison
py3: resolve Unicode issues around `hg serve` on Windows...
r39755 return [encoding.strtolocal(arg) for arg in [sys.executable] + sys.argv[:1]]
Patrick Mezard
Find right hg command for detached process...
r10239
Patrick Mezard
acl: grp module is not available on windows
r11138 def groupmembers(name):
# Don't support groups on Windows for now
Brodie Rao
cleanup: "raise SomeException()" -> "raise SomeException"
r16687 raise KeyError
Patrick Mezard
acl: grp module is not available on windows
r11138
Adrian Buehlmann
util: eliminate wildcard imports
r14926 def isexec(f):
return False
Idan Kamara
posix, windows: introduce cachestat...
r14927 class cachestat(object):
def __init__(self, path):
pass
def cacheable(self):
return False
Adrian Buehlmann
win32: move lookupreg() to windows.py...
r16807 def lookupreg(key, valname=None, scope=None):
''' Look up a key/value name in the Windows registry.
valname: value name. If unspecified, the default value for the key
is used.
scope: optionally specify scope for registry lookup, this can be
a sequence of scopes to look up in order. Default (CURRENT_USER,
LOCAL_MACHINE).
'''
if scope is None:
Pulkit Goyal
py3: conditionalize _winreg import...
r29760 scope = (winreg.HKEY_CURRENT_USER, winreg.HKEY_LOCAL_MACHINE)
Adrian Buehlmann
win32: move lookupreg() to windows.py...
r16807 elif not isinstance(scope, (list, tuple)):
scope = (scope,)
for s in scope:
try:
Matt Harbison
windows: open registry keys using unicode names...
r39679 with winreg.OpenKey(s, encoding.strfromlocal(key)) as hkey:
Matt Harbison
py3: use str to query registry values on Windows...
r40302 name = valname and encoding.strfromlocal(valname) or valname
val = winreg.QueryValueEx(hkey, name)[0]
Matt Harbison
windows: open registry keys using unicode names...
r39679 # never let a Unicode string escape into the wild
return encoding.unitolocal(val)
Adrian Buehlmann
win32: move lookupreg() to windows.py...
r16807 except EnvironmentError:
pass
Matt Mackall
cmdutils: Take over glob expansion duties from util
r8614 expandglobs = True
Bryan O'Sullivan
util: add functions to check symlink/exec bits...
r18868
def statislink(st):
'''check whether a stat result is a symlink'''
return False
def statisexec(st):
'''check whether a stat result is an executable file'''
return False
Gregory Szorc
platform: implement readpipe()...
r22245
Pierre-Yves David
util: add a simple poll utility...
r25420 def poll(fds):
# see posix.py for description
raise NotImplementedError()
Gregory Szorc
platform: implement readpipe()...
r22245 def readpipe(pipe):
"""Read all available data from a pipe."""
chunks = []
while True:
Matt Harbison
windows: allow readpipe() to actually read data out of the pipe...
r24653 size = win32.peekpipe(pipe)
Gregory Szorc
platform: implement readpipe()...
r22245 if not size:
break
s = pipe.read(size)
if not s:
break
chunks.append(s)
return ''.join(chunks)
Yuya Nishihara
chgserver: extract utility to bind unix domain socket to long path...
r29530
def bindunixsocket(sock, path):
Matt Harbison
py3: ensure standard exceptions use `str` type strings in windows.py...
r39919 raise NotImplementedError(r'unsupported platform')