--- a/mercurial/util.py Sun Mar 12 15:58:56 2006 -0800
+++ b/mercurial/util.py Sun Mar 12 16:21:59 2006 -0800
@@ -179,7 +179,7 @@
if root == os.sep:
rootsep = os.sep
else:
- rootsep = root + os.sep
+ rootsep = root + os.sep
name = myname
if not name.startswith(os.sep):
name = os.path.join(root, cwd, name)
@@ -315,15 +315,42 @@
(files and filematch(fn)))),
(inc or exc or (pats and pats != [('glob', '**')])) and True)
-def system(cmd, errprefix=None):
- """execute a shell command that must succeed"""
- rc = os.system(cmd)
- if rc:
- errmsg = "%s %s" % (os.path.basename(cmd.split(None, 1)[0]),
- explain_exit(rc)[0])
- if errprefix:
- errmsg = "%s: %s" % (errprefix, errmsg)
- raise Abort(errmsg)
+def system(cmd, environ={}, cwd=None, onerr=None, errprefix=None):
+ '''enhanced shell command execution.
+ run with environment maybe modified, maybe in different dir.
+
+ if command fails and onerr is None, return status. if ui object,
+ print error message and return status, else raise onerr object as
+ exception.'''
+ oldenv = {}
+ for k in environ:
+ oldenv[k] = os.environ.get(k)
+ if cwd is not None:
+ oldcwd = os.getcwd()
+ try:
+ for k, v in environ.iteritems():
+ os.environ[k] = str(v)
+ if cwd is not None and oldcwd != cwd:
+ os.chdir(cwd)
+ rc = os.system(cmd)
+ if rc and onerr:
+ errmsg = '%s %s' % (os.path.basename(cmd.split(None, 1)[0]),
+ explain_exit(rc)[0])
+ if errprefix:
+ errmsg = '%s: %s' % (errprefix, errmsg)
+ try:
+ onerr.warn(errmsg + '\n')
+ except AttributeError:
+ raise onerr(errmsg)
+ return rc
+ finally:
+ for k, v in oldenv.iteritems():
+ if v is None:
+ del os.environ[k]
+ else:
+ os.environ[k] = v
+ if cwd is not None and oldcwd != cwd:
+ os.chdir(oldcwd)
def rename(src, dst):
"""forcibly rename a file"""
@@ -363,7 +390,14 @@
else:
shutil.copy(src, dst)
-def opener(base):
+def audit_path(path):
+ """Abort if path contains dangerous components"""
+ parts = os.path.normcase(path).split(os.sep)
+ if (os.path.splitdrive(path)[0] or parts[0] in ('.hg', '')
+ or os.pardir in parts):
+ raise Abort(_("path contains illegal component: %s\n") % path)
+
+def opener(base, audit=True):
"""
return a function that opens files relative to base
@@ -371,6 +405,7 @@
remote file access from higher level code.
"""
p = base
+ audit_p = audit
def mktempcopy(name):
d, fn = os.path.split(name)
@@ -401,6 +436,8 @@
self.close()
def o(path, mode="r", text=False, atomic=False):
+ if audit_p:
+ audit_path(path)
f = os.path.join(p, path)
if not text:
@@ -489,7 +526,7 @@
return pf
try: # ActivePython can create hard links using win32file module
- import win32file
+ import win32api, win32con, win32file
def os_link(src, dst): # NB will only succeed on NTFS
win32file.CreateHardLink(dst, src)
@@ -506,8 +543,18 @@
except:
return os.stat(pathname).st_nlink
+ def testpid(pid):
+ '''return False if pid is dead, True if running or not known'''
+ try:
+ win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION,
+ False, pid)
+ except:
+ return True
+
except ImportError:
- pass
+ def testpid(pid):
+ '''return False if pid dead, True if running or not known'''
+ return True
def is_exec(f, last):
return last
@@ -604,6 +651,14 @@
else:
raise
+ def testpid(pid):
+ '''return False if pid dead, True if running or not sure'''
+ try:
+ os.kill(pid, 0)
+ return True
+ except OSError, inst:
+ return inst.errno != errno.ESRCH
+
def explain_exit(code):
"""return a 2-tuple (desc, code) describing a process's status"""
if os.WIFEXITED(code):
@@ -700,3 +755,16 @@
if f >= 0:
user = user[f+1:]
return user
+
+def walkrepos(path):
+ '''yield every hg repository under path, recursively.'''
+ def errhandler(err):
+ if err.filename == path:
+ raise err
+
+ for root, dirs, files in os.walk(path, onerror=errhandler):
+ for d in dirs:
+ if d == '.hg':
+ yield root
+ dirs[:] = []
+ break