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