mercurial/util.py
changeset 1920 b7cc0f323a4c
parent 1903 e4abeafd6eb1
parent 1882 c0320567931f
child 1951 696230e52e4d
equal deleted inserted replaced
1919:8f565af14095 1920:b7cc0f323a4c
   177 def canonpath(root, cwd, myname):
   177 def canonpath(root, cwd, myname):
   178     """return the canonical path of myname, given cwd and root"""
   178     """return the canonical path of myname, given cwd and root"""
   179     if root == os.sep:
   179     if root == os.sep:
   180         rootsep = os.sep
   180         rootsep = os.sep
   181     else:
   181     else:
   182     	rootsep = root + os.sep
   182         rootsep = root + os.sep
   183     name = myname
   183     name = myname
   184     if not name.startswith(os.sep):
   184     if not name.startswith(os.sep):
   185         name = os.path.join(root, cwd, name)
   185         name = os.path.join(root, cwd, name)
   186     name = os.path.normpath(name)
   186     name = os.path.normpath(name)
   187     if name.startswith(rootsep):
   187     if name.startswith(rootsep):
   313                          (not pats and not files) or
   313                          (not pats and not files) or
   314                          (pats and patmatch(fn)) or
   314                          (pats and patmatch(fn)) or
   315                          (files and filematch(fn)))),
   315                          (files and filematch(fn)))),
   316             (inc or exc or (pats and pats != [('glob', '**')])) and True)
   316             (inc or exc or (pats and pats != [('glob', '**')])) and True)
   317 
   317 
   318 def system(cmd, errprefix=None):
   318 def system(cmd, environ={}, cwd=None, onerr=None, errprefix=None):
   319     """execute a shell command that must succeed"""
   319     '''enhanced shell command execution.
   320     rc = os.system(cmd)
   320     run with environment maybe modified, maybe in different dir.
   321     if rc:
   321 
   322         errmsg = "%s %s" % (os.path.basename(cmd.split(None, 1)[0]),
   322     if command fails and onerr is None, return status.  if ui object,
   323                             explain_exit(rc)[0])
   323     print error message and return status, else raise onerr object as
   324         if errprefix:
   324     exception.'''
   325             errmsg = "%s: %s" % (errprefix, errmsg)
   325     oldenv = {}
   326         raise Abort(errmsg)
   326     for k in environ:
       
   327         oldenv[k] = os.environ.get(k)
       
   328     if cwd is not None:
       
   329         oldcwd = os.getcwd()
       
   330     try:
       
   331         for k, v in environ.iteritems():
       
   332             os.environ[k] = str(v)
       
   333         if cwd is not None and oldcwd != cwd:
       
   334             os.chdir(cwd)
       
   335         rc = os.system(cmd)
       
   336         if rc and onerr:
       
   337             errmsg = '%s %s' % (os.path.basename(cmd.split(None, 1)[0]),
       
   338                                 explain_exit(rc)[0])
       
   339             if errprefix:
       
   340                 errmsg = '%s: %s' % (errprefix, errmsg)
       
   341             try:
       
   342                 onerr.warn(errmsg + '\n')
       
   343             except AttributeError:
       
   344                 raise onerr(errmsg)
       
   345         return rc
       
   346     finally:
       
   347         for k, v in oldenv.iteritems():
       
   348             if v is None:
       
   349                 del os.environ[k]
       
   350             else:
       
   351                 os.environ[k] = v
       
   352         if cwd is not None and oldcwd != cwd:
       
   353             os.chdir(oldcwd)
   327 
   354 
   328 def rename(src, dst):
   355 def rename(src, dst):
   329     """forcibly rename a file"""
   356     """forcibly rename a file"""
   330     try:
   357     try:
   331         os.rename(src, dst)
   358         os.rename(src, dst)
   361                 hardlink = False
   388                 hardlink = False
   362                 shutil.copy(src, dst)
   389                 shutil.copy(src, dst)
   363         else:
   390         else:
   364             shutil.copy(src, dst)
   391             shutil.copy(src, dst)
   365 
   392 
   366 def opener(base):
   393 def audit_path(path):
       
   394     """Abort if path contains dangerous components"""
       
   395     parts = os.path.normcase(path).split(os.sep)
       
   396     if (os.path.splitdrive(path)[0] or parts[0] in ('.hg', '')
       
   397         or os.pardir in parts):
       
   398         raise Abort(_("path contains illegal component: %s\n") % path)
       
   399 
       
   400 def opener(base, audit=True):
   367     """
   401     """
   368     return a function that opens files relative to base
   402     return a function that opens files relative to base
   369 
   403 
   370     this function is used to hide the details of COW semantics and
   404     this function is used to hide the details of COW semantics and
   371     remote file access from higher level code.
   405     remote file access from higher level code.
   372     """
   406     """
   373     p = base
   407     p = base
       
   408     audit_p = audit
   374 
   409 
   375     def mktempcopy(name):
   410     def mktempcopy(name):
   376         d, fn = os.path.split(name)
   411         d, fn = os.path.split(name)
   377         fd, temp = tempfile.mkstemp(prefix=fn, dir=d)
   412         fd, temp = tempfile.mkstemp(prefix=fn, dir=d)
   378         fp = os.fdopen(fd, "wb")
   413         fp = os.fdopen(fd, "wb")
   399                 rename(self.temp, self.__name)
   434                 rename(self.temp, self.__name)
   400         def __del__(self):
   435         def __del__(self):
   401             self.close()
   436             self.close()
   402 
   437 
   403     def o(path, mode="r", text=False, atomic=False):
   438     def o(path, mode="r", text=False, atomic=False):
       
   439         if audit_p:
       
   440             audit_path(path)
   404         f = os.path.join(p, path)
   441         f = os.path.join(p, path)
   405 
   442 
   406         if not text:
   443         if not text:
   407             mode += "b" # for that other OS
   444             mode += "b" # for that other OS
   408 
   445 
   487         if pf[0] == '`':
   524         if pf[0] == '`':
   488             pf = pf[1:-1] # Remove the quotes
   525             pf = pf[1:-1] # Remove the quotes
   489         return pf
   526         return pf
   490 
   527 
   491     try: # ActivePython can create hard links using win32file module
   528     try: # ActivePython can create hard links using win32file module
   492         import win32file
   529         import win32api, win32con, win32file
   493 
   530 
   494         def os_link(src, dst): # NB will only succeed on NTFS
   531         def os_link(src, dst): # NB will only succeed on NTFS
   495             win32file.CreateHardLink(dst, src)
   532             win32file.CreateHardLink(dst, src)
   496 
   533 
   497         def nlinks(pathname):
   534         def nlinks(pathname):
   504                 fh.Close()
   541                 fh.Close()
   505                 return res[7]
   542                 return res[7]
   506             except:
   543             except:
   507                 return os.stat(pathname).st_nlink
   544                 return os.stat(pathname).st_nlink
   508 
   545 
       
   546         def testpid(pid):
       
   547             '''return False if pid is dead, True if running or not known'''
       
   548             try:
       
   549                 win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION,
       
   550                                      False, pid)
       
   551             except:
       
   552                 return True
       
   553 
   509     except ImportError:
   554     except ImportError:
   510         pass
   555         def testpid(pid):
       
   556             '''return False if pid dead, True if running or not known'''
       
   557             return True
   511 
   558 
   512     def is_exec(f, last):
   559     def is_exec(f, last):
   513         return last
   560         return last
   514 
   561 
   515     def set_exec(f, mode):
   562     def set_exec(f, mode):
   601         except OSError, why:
   648         except OSError, why:
   602             if why.errno == errno.EINVAL:
   649             if why.errno == errno.EINVAL:
   603                 return _readlock_file(pathname)
   650                 return _readlock_file(pathname)
   604             else:
   651             else:
   605                 raise
   652                 raise
       
   653 
       
   654     def testpid(pid):
       
   655         '''return False if pid dead, True if running or not sure'''
       
   656         try:
       
   657             os.kill(pid, 0)
       
   658             return True
       
   659         except OSError, inst:
       
   660             return inst.errno != errno.ESRCH
   606 
   661 
   607     def explain_exit(code):
   662     def explain_exit(code):
   608         """return a 2-tuple (desc, code) describing a process's status"""
   663         """return a 2-tuple (desc, code) describing a process's status"""
   609         if os.WIFEXITED(code):
   664         if os.WIFEXITED(code):
   610             val = os.WEXITSTATUS(code)
   665             val = os.WEXITSTATUS(code)
   698         user = user[:f]
   753         user = user[:f]
   699     f = user.find('<')
   754     f = user.find('<')
   700     if f >= 0:
   755     if f >= 0:
   701         user = user[f+1:]
   756         user = user[f+1:]
   702     return user
   757     return user
       
   758 
       
   759 def walkrepos(path):
       
   760     '''yield every hg repository under path, recursively.'''
       
   761     def errhandler(err):
       
   762         if err.filename == path:
       
   763             raise err
       
   764 
       
   765     for root, dirs, files in os.walk(path, onerror=errhandler):
       
   766         for d in dirs:
       
   767             if d == '.hg':
       
   768                 yield root
       
   769                 dirs[:] = []
       
   770                 break