450 parts = os.path.normcase(path).split(os.sep) |
460 parts = os.path.normcase(path).split(os.sep) |
451 if (os.path.splitdrive(path)[0] or parts[0] in ('.hg', '') |
461 if (os.path.splitdrive(path)[0] or parts[0] in ('.hg', '') |
452 or os.pardir in parts): |
462 or os.pardir in parts): |
453 raise Abort(_("path contains illegal component: %s\n") % path) |
463 raise Abort(_("path contains illegal component: %s\n") % path) |
454 |
464 |
|
465 def _makelock_file(info, pathname): |
|
466 ld = os.open(pathname, os.O_CREAT | os.O_WRONLY | os.O_EXCL) |
|
467 os.write(ld, info) |
|
468 os.close(ld) |
|
469 |
|
470 def _readlock_file(pathname): |
|
471 return posixfile(pathname).read() |
|
472 |
|
473 def nlinks(pathname): |
|
474 """Return number of hardlinks for the given file.""" |
|
475 return os.stat(pathname).st_nlink |
|
476 |
|
477 if hasattr(os, 'link'): |
|
478 os_link = os.link |
|
479 else: |
|
480 def os_link(src, dst): |
|
481 raise OSError(0, _("Hardlinks not supported")) |
|
482 |
|
483 def fstat(fp): |
|
484 '''stat file object that may not have fileno method.''' |
|
485 try: |
|
486 return os.fstat(fp.fileno()) |
|
487 except AttributeError: |
|
488 return os.stat(fp.name) |
|
489 |
|
490 posixfile = file |
|
491 |
|
492 # Platform specific variants |
|
493 if os.name == 'nt': |
|
494 demandload(globals(), "msvcrt") |
|
495 nulldev = 'NUL:' |
|
496 |
|
497 class winstdout: |
|
498 '''stdout on windows misbehaves if sent through a pipe''' |
|
499 |
|
500 def __init__(self, fp): |
|
501 self.fp = fp |
|
502 |
|
503 def __getattr__(self, key): |
|
504 return getattr(self.fp, key) |
|
505 |
|
506 def close(self): |
|
507 try: |
|
508 self.fp.close() |
|
509 except: pass |
|
510 |
|
511 def write(self, s): |
|
512 try: |
|
513 return self.fp.write(s) |
|
514 except IOError, inst: |
|
515 if inst.errno != 0: raise |
|
516 self.close() |
|
517 raise IOError(errno.EPIPE, 'Broken pipe') |
|
518 |
|
519 sys.stdout = winstdout(sys.stdout) |
|
520 |
|
521 def system_rcpath(): |
|
522 try: |
|
523 return system_rcpath_win32() |
|
524 except: |
|
525 return [r'c:\mercurial\mercurial.ini'] |
|
526 |
|
527 def os_rcpath(): |
|
528 '''return default os-specific hgrc search path''' |
|
529 return system_rcpath() + [os.path.join(os.path.expanduser('~'), |
|
530 'mercurial.ini')] |
|
531 |
|
532 def parse_patch_output(output_line): |
|
533 """parses the output produced by patch and returns the file name""" |
|
534 pf = output_line[14:] |
|
535 if pf[0] == '`': |
|
536 pf = pf[1:-1] # Remove the quotes |
|
537 return pf |
|
538 |
|
539 def testpid(pid): |
|
540 '''return False if pid dead, True if running or not known''' |
|
541 return True |
|
542 |
|
543 def is_exec(f, last): |
|
544 return last |
|
545 |
|
546 def set_exec(f, mode): |
|
547 pass |
|
548 |
|
549 def set_binary(fd): |
|
550 msvcrt.setmode(fd.fileno(), os.O_BINARY) |
|
551 |
|
552 def pconvert(path): |
|
553 return path.replace("\\", "/") |
|
554 |
|
555 def localpath(path): |
|
556 return path.replace('/', '\\') |
|
557 |
|
558 def normpath(path): |
|
559 return pconvert(os.path.normpath(path)) |
|
560 |
|
561 makelock = _makelock_file |
|
562 readlock = _readlock_file |
|
563 |
|
564 def explain_exit(code): |
|
565 return _("exited with status %d") % code, code |
|
566 |
|
567 try: |
|
568 # override functions with win32 versions if possible |
|
569 from util_win32 import * |
|
570 except ImportError: |
|
571 pass |
|
572 |
|
573 else: |
|
574 nulldev = '/dev/null' |
|
575 |
|
576 def rcfiles(path): |
|
577 rcs = [os.path.join(path, 'hgrc')] |
|
578 rcdir = os.path.join(path, 'hgrc.d') |
|
579 try: |
|
580 rcs.extend([os.path.join(rcdir, f) for f in os.listdir(rcdir) |
|
581 if f.endswith(".rc")]) |
|
582 except OSError, inst: pass |
|
583 return rcs |
|
584 |
|
585 def os_rcpath(): |
|
586 '''return default os-specific hgrc search path''' |
|
587 path = [] |
|
588 if len(sys.argv) > 0: |
|
589 path.extend(rcfiles(os.path.dirname(sys.argv[0]) + |
|
590 '/../etc/mercurial')) |
|
591 path.extend(rcfiles('/etc/mercurial')) |
|
592 path.append(os.path.expanduser('~/.hgrc')) |
|
593 path = [os.path.normpath(f) for f in path] |
|
594 return path |
|
595 |
|
596 def parse_patch_output(output_line): |
|
597 """parses the output produced by patch and returns the file name""" |
|
598 pf = output_line[14:] |
|
599 if pf.startswith("'") and pf.endswith("'") and pf.find(" ") >= 0: |
|
600 pf = pf[1:-1] # Remove the quotes |
|
601 return pf |
|
602 |
|
603 def is_exec(f, last): |
|
604 """check whether a file is executable""" |
|
605 return (os.stat(f).st_mode & 0100 != 0) |
|
606 |
|
607 def set_exec(f, mode): |
|
608 s = os.stat(f).st_mode |
|
609 if (s & 0100 != 0) == mode: |
|
610 return |
|
611 if mode: |
|
612 # Turn on +x for every +r bit when making a file executable |
|
613 # and obey umask. |
|
614 umask = os.umask(0) |
|
615 os.umask(umask) |
|
616 os.chmod(f, s | (s & 0444) >> 2 & ~umask) |
|
617 else: |
|
618 os.chmod(f, s & 0666) |
|
619 |
|
620 def set_binary(fd): |
|
621 pass |
|
622 |
|
623 def pconvert(path): |
|
624 return path |
|
625 |
|
626 def localpath(path): |
|
627 return path |
|
628 |
|
629 normpath = os.path.normpath |
|
630 |
|
631 def makelock(info, pathname): |
|
632 try: |
|
633 os.symlink(info, pathname) |
|
634 except OSError, why: |
|
635 if why.errno == errno.EEXIST: |
|
636 raise |
|
637 else: |
|
638 _makelock_file(info, pathname) |
|
639 |
|
640 def readlock(pathname): |
|
641 try: |
|
642 return os.readlink(pathname) |
|
643 except OSError, why: |
|
644 if why.errno == errno.EINVAL: |
|
645 return _readlock_file(pathname) |
|
646 else: |
|
647 raise |
|
648 |
|
649 def testpid(pid): |
|
650 '''return False if pid dead, True if running or not sure''' |
|
651 try: |
|
652 os.kill(pid, 0) |
|
653 return True |
|
654 except OSError, inst: |
|
655 return inst.errno != errno.ESRCH |
|
656 |
|
657 def explain_exit(code): |
|
658 """return a 2-tuple (desc, code) describing a process's status""" |
|
659 if os.WIFEXITED(code): |
|
660 val = os.WEXITSTATUS(code) |
|
661 return _("exited with status %d") % val, val |
|
662 elif os.WIFSIGNALED(code): |
|
663 val = os.WTERMSIG(code) |
|
664 return _("killed by signal %d") % val, val |
|
665 elif os.WIFSTOPPED(code): |
|
666 val = os.WSTOPSIG(code) |
|
667 return _("stopped by signal %d") % val, val |
|
668 raise ValueError(_("invalid exit code")) |
|
669 |
455 def opener(base, audit=True): |
670 def opener(base, audit=True): |
456 """ |
671 """ |
457 return a function that opens files relative to base |
672 return a function that opens files relative to base |
458 |
673 |
459 this function is used to hide the details of COW semantics and |
674 this function is used to hide the details of COW semantics and |
462 p = base |
677 p = base |
463 audit_p = audit |
678 audit_p = audit |
464 |
679 |
465 def mktempcopy(name): |
680 def mktempcopy(name): |
466 d, fn = os.path.split(name) |
681 d, fn = os.path.split(name) |
467 fd, temp = tempfile.mkstemp(prefix=".%s-" % fn, dir=d) |
682 fd, temp = tempfile.mkstemp(prefix='.%s-' % fn, dir=d) |
468 fp = os.fdopen(fd, "wb") |
683 os.close(fd) |
|
684 fp = posixfile(temp, "wb") |
469 try: |
685 try: |
470 fp.write(file(name, "rb").read()) |
686 fp.write(posixfile(name, "rb").read()) |
471 except: |
687 except: |
472 try: os.unlink(temp) |
688 try: os.unlink(temp) |
473 except: pass |
689 except: pass |
474 raise |
690 raise |
475 fp.close() |
691 fp.close() |
476 st = os.lstat(name) |
692 st = os.lstat(name) |
477 os.chmod(temp, st.st_mode) |
693 os.chmod(temp, st.st_mode) |
478 return temp |
694 return temp |
479 |
695 |
480 class atomictempfile(file): |
696 class atomictempfile(posixfile): |
481 """the file will only be copied when rename is called""" |
697 """the file will only be copied when rename is called""" |
482 def __init__(self, name, mode): |
698 def __init__(self, name, mode): |
483 self.__name = name |
699 self.__name = name |
484 self.temp = mktempcopy(name) |
700 self.temp = mktempcopy(name) |
485 file.__init__(self, self.temp, mode) |
701 posixfile.__init__(self, self.temp, mode) |
486 def rename(self): |
702 def rename(self): |
487 if not self.closed: |
703 if not self.closed: |
488 file.close(self) |
704 posixfile.close(self) |
489 rename(self.temp, self.__name) |
705 rename(self.temp, self.__name) |
490 def __del__(self): |
706 def __del__(self): |
491 if not self.closed: |
707 if not self.closed: |
492 try: |
708 try: |
493 os.unlink(self.temp) |
709 os.unlink(self.temp) |
494 except: pass |
710 except: pass |
495 file.close(self) |
711 posixfile.close(self) |
496 |
712 |
497 class atomicfile(atomictempfile): |
713 class atomicfile(atomictempfile): |
498 """the file will only be copied on close""" |
714 """the file will only be copied on close""" |
499 def __init__(self, name, mode): |
715 def __init__(self, name, mode): |
500 atomictempfile.__init__(self, name, mode) |
716 atomictempfile.__init__(self, name, mode) |
523 return atomicfile(f, mode) |
739 return atomicfile(f, mode) |
524 elif atomictemp: |
740 elif atomictemp: |
525 return atomictempfile(f, mode) |
741 return atomictempfile(f, mode) |
526 if nlink > 1: |
742 if nlink > 1: |
527 rename(mktempcopy(f), f) |
743 rename(mktempcopy(f), f) |
528 return file(f, mode) |
744 return posixfile(f, mode) |
529 |
745 |
530 return o |
746 return o |
531 |
|
532 def _makelock_file(info, pathname): |
|
533 ld = os.open(pathname, os.O_CREAT | os.O_WRONLY | os.O_EXCL) |
|
534 os.write(ld, info) |
|
535 os.close(ld) |
|
536 |
|
537 def _readlock_file(pathname): |
|
538 return file(pathname).read() |
|
539 |
|
540 def nlinks(pathname): |
|
541 """Return number of hardlinks for the given file.""" |
|
542 return os.stat(pathname).st_nlink |
|
543 |
|
544 if hasattr(os, 'link'): |
|
545 os_link = os.link |
|
546 else: |
|
547 def os_link(src, dst): |
|
548 raise OSError(0, _("Hardlinks not supported")) |
|
549 |
|
550 # Platform specific variants |
|
551 if os.name == 'nt': |
|
552 demandload(globals(), "msvcrt") |
|
553 nulldev = 'NUL:' |
|
554 |
|
555 class winstdout: |
|
556 '''stdout on windows misbehaves if sent through a pipe''' |
|
557 |
|
558 def __init__(self, fp): |
|
559 self.fp = fp |
|
560 |
|
561 def __getattr__(self, key): |
|
562 return getattr(self.fp, key) |
|
563 |
|
564 def close(self): |
|
565 try: |
|
566 self.fp.close() |
|
567 except: pass |
|
568 |
|
569 def write(self, s): |
|
570 try: |
|
571 return self.fp.write(s) |
|
572 except IOError, inst: |
|
573 if inst.errno != 0: raise |
|
574 self.close() |
|
575 raise IOError(errno.EPIPE, 'Broken pipe') |
|
576 |
|
577 sys.stdout = winstdout(sys.stdout) |
|
578 |
|
579 def system_rcpath(): |
|
580 try: |
|
581 return system_rcpath_win32() |
|
582 except: |
|
583 return [r'c:\mercurial\mercurial.ini'] |
|
584 |
|
585 def os_rcpath(): |
|
586 '''return default os-specific hgrc search path''' |
|
587 return system_rcpath() + [os.path.join(os.path.expanduser('~'), |
|
588 'mercurial.ini')] |
|
589 |
|
590 def parse_patch_output(output_line): |
|
591 """parses the output produced by patch and returns the file name""" |
|
592 pf = output_line[14:] |
|
593 if pf[0] == '`': |
|
594 pf = pf[1:-1] # Remove the quotes |
|
595 return pf |
|
596 |
|
597 def testpid(pid): |
|
598 '''return False if pid dead, True if running or not known''' |
|
599 return True |
|
600 |
|
601 def is_exec(f, last): |
|
602 return last |
|
603 |
|
604 def set_exec(f, mode): |
|
605 pass |
|
606 |
|
607 def set_binary(fd): |
|
608 msvcrt.setmode(fd.fileno(), os.O_BINARY) |
|
609 |
|
610 def pconvert(path): |
|
611 return path.replace("\\", "/") |
|
612 |
|
613 def localpath(path): |
|
614 return path.replace('/', '\\') |
|
615 |
|
616 def normpath(path): |
|
617 return pconvert(os.path.normpath(path)) |
|
618 |
|
619 makelock = _makelock_file |
|
620 readlock = _readlock_file |
|
621 |
|
622 def explain_exit(code): |
|
623 return _("exited with status %d") % code, code |
|
624 |
|
625 try: |
|
626 # override functions with win32 versions if possible |
|
627 from util_win32 import * |
|
628 except ImportError: |
|
629 pass |
|
630 |
|
631 else: |
|
632 nulldev = '/dev/null' |
|
633 |
|
634 def rcfiles(path): |
|
635 rcs = [os.path.join(path, 'hgrc')] |
|
636 rcdir = os.path.join(path, 'hgrc.d') |
|
637 try: |
|
638 rcs.extend([os.path.join(rcdir, f) for f in os.listdir(rcdir) |
|
639 if f.endswith(".rc")]) |
|
640 except OSError, inst: pass |
|
641 return rcs |
|
642 |
|
643 def os_rcpath(): |
|
644 '''return default os-specific hgrc search path''' |
|
645 path = [] |
|
646 if len(sys.argv) > 0: |
|
647 path.extend(rcfiles(os.path.dirname(sys.argv[0]) + |
|
648 '/../etc/mercurial')) |
|
649 path.extend(rcfiles('/etc/mercurial')) |
|
650 path.append(os.path.expanduser('~/.hgrc')) |
|
651 path = [os.path.normpath(f) for f in path] |
|
652 return path |
|
653 |
|
654 def parse_patch_output(output_line): |
|
655 """parses the output produced by patch and returns the file name""" |
|
656 pf = output_line[14:] |
|
657 if pf.startswith("'") and pf.endswith("'") and pf.find(" ") >= 0: |
|
658 pf = pf[1:-1] # Remove the quotes |
|
659 return pf |
|
660 |
|
661 def is_exec(f, last): |
|
662 """check whether a file is executable""" |
|
663 return (os.stat(f).st_mode & 0100 != 0) |
|
664 |
|
665 def set_exec(f, mode): |
|
666 s = os.stat(f).st_mode |
|
667 if (s & 0100 != 0) == mode: |
|
668 return |
|
669 if mode: |
|
670 # Turn on +x for every +r bit when making a file executable |
|
671 # and obey umask. |
|
672 umask = os.umask(0) |
|
673 os.umask(umask) |
|
674 os.chmod(f, s | (s & 0444) >> 2 & ~umask) |
|
675 else: |
|
676 os.chmod(f, s & 0666) |
|
677 |
|
678 def set_binary(fd): |
|
679 pass |
|
680 |
|
681 def pconvert(path): |
|
682 return path |
|
683 |
|
684 def localpath(path): |
|
685 return path |
|
686 |
|
687 normpath = os.path.normpath |
|
688 |
|
689 def makelock(info, pathname): |
|
690 try: |
|
691 os.symlink(info, pathname) |
|
692 except OSError, why: |
|
693 if why.errno == errno.EEXIST: |
|
694 raise |
|
695 else: |
|
696 _makelock_file(info, pathname) |
|
697 |
|
698 def readlock(pathname): |
|
699 try: |
|
700 return os.readlink(pathname) |
|
701 except OSError, why: |
|
702 if why.errno == errno.EINVAL: |
|
703 return _readlock_file(pathname) |
|
704 else: |
|
705 raise |
|
706 |
|
707 def testpid(pid): |
|
708 '''return False if pid dead, True if running or not sure''' |
|
709 try: |
|
710 os.kill(pid, 0) |
|
711 return True |
|
712 except OSError, inst: |
|
713 return inst.errno != errno.ESRCH |
|
714 |
|
715 def explain_exit(code): |
|
716 """return a 2-tuple (desc, code) describing a process's status""" |
|
717 if os.WIFEXITED(code): |
|
718 val = os.WEXITSTATUS(code) |
|
719 return _("exited with status %d") % val, val |
|
720 elif os.WIFSIGNALED(code): |
|
721 val = os.WTERMSIG(code) |
|
722 return _("killed by signal %d") % val, val |
|
723 elif os.WIFSTOPPED(code): |
|
724 val = os.WSTOPSIG(code) |
|
725 return _("stopped by signal %d") % val, val |
|
726 raise ValueError(_("invalid exit code")) |
|
727 |
747 |
728 class chunkbuffer(object): |
748 class chunkbuffer(object): |
729 """Allow arbitrary sized chunks of data to be efficiently read from an |
749 """Allow arbitrary sized chunks of data to be efficiently read from an |
730 iterator over chunks of arbitrary size.""" |
750 iterator over chunks of arbitrary size.""" |
731 |
751 |