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) |