comparison mercurial/util.py @ 1920:b7cc0f323a4c

merge with crew.
author Vadim Gelfer <vadim.gelfer@gmail.com>
date Sun, 12 Mar 2006 16:21:59 -0800
parents e4abeafd6eb1 c0320567931f
children 696230e52e4d
comparison
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