Mercurial > hg
comparison mercurial/util.py @ 13970:d13913355390
move opener from util to scmutil
author | Adrian Buehlmann <adrian@cadifra.com> |
---|---|
date | Wed, 20 Apr 2011 19:54:57 +0200 |
parents | d2d1ef6a5238 |
children | bfeaa88b875d |
comparison
equal
deleted
inserted
replaced
13969:336bb8b53ad0 | 13970:d13913355390 |
---|---|
893 if not name or parent == name or err.errno != errno.ENOENT: | 893 if not name or parent == name or err.errno != errno.ENOENT: |
894 raise | 894 raise |
895 makedirs(parent, mode) | 895 makedirs(parent, mode) |
896 makedirs(name, mode) | 896 makedirs(name, mode) |
897 | 897 |
898 class opener(object): | |
899 """Open files relative to a base directory | |
900 | |
901 This class is used to hide the details of COW semantics and | |
902 remote file access from higher level code. | |
903 """ | |
904 def __init__(self, base, audit=True): | |
905 self.base = base | |
906 if audit: | |
907 self.auditor = path_auditor(base) | |
908 else: | |
909 self.auditor = always | |
910 self.createmode = None | |
911 self._trustnlink = None | |
912 | |
913 @propertycache | |
914 def _can_symlink(self): | |
915 return checklink(self.base) | |
916 | |
917 def _fixfilemode(self, name): | |
918 if self.createmode is None: | |
919 return | |
920 os.chmod(name, self.createmode & 0666) | |
921 | |
922 def __call__(self, path, mode="r", text=False, atomictemp=False): | |
923 r = checkosfilename(path) | |
924 if r: | |
925 raise Abort("%s: %r" % (r, path)) | |
926 self.auditor(path) | |
927 f = os.path.join(self.base, path) | |
928 | |
929 if not text and "b" not in mode: | |
930 mode += "b" # for that other OS | |
931 | |
932 nlink = -1 | |
933 dirname, basename = os.path.split(f) | |
934 # If basename is empty, then the path is malformed because it points | |
935 # to a directory. Let the posixfile() call below raise IOError. | |
936 if basename and mode not in ('r', 'rb'): | |
937 if atomictemp: | |
938 if not os.path.isdir(dirname): | |
939 makedirs(dirname, self.createmode) | |
940 return atomictempfile(f, mode, self.createmode) | |
941 try: | |
942 if 'w' in mode: | |
943 unlink(f) | |
944 nlink = 0 | |
945 else: | |
946 # nlinks() may behave differently for files on Windows | |
947 # shares if the file is open. | |
948 fd = posixfile(f) | |
949 nlink = nlinks(f) | |
950 if nlink < 1: | |
951 nlink = 2 # force mktempcopy (issue1922) | |
952 fd.close() | |
953 except (OSError, IOError), e: | |
954 if e.errno != errno.ENOENT: | |
955 raise | |
956 nlink = 0 | |
957 if not os.path.isdir(dirname): | |
958 makedirs(dirname, self.createmode) | |
959 if nlink > 0: | |
960 if self._trustnlink is None: | |
961 self._trustnlink = nlink > 1 or checknlink(f) | |
962 if nlink > 1 or not self._trustnlink: | |
963 rename(mktempcopy(f), f) | |
964 fp = posixfile(f, mode) | |
965 if nlink == 0: | |
966 self._fixfilemode(f) | |
967 return fp | |
968 | |
969 def symlink(self, src, dst): | |
970 self.auditor(dst) | |
971 linkname = os.path.join(self.base, dst) | |
972 try: | |
973 os.unlink(linkname) | |
974 except OSError: | |
975 pass | |
976 | |
977 dirname = os.path.dirname(linkname) | |
978 if not os.path.exists(dirname): | |
979 makedirs(dirname, self.createmode) | |
980 | |
981 if self._can_symlink: | |
982 try: | |
983 os.symlink(src, linkname) | |
984 except OSError, err: | |
985 raise OSError(err.errno, _('could not symlink to %r: %s') % | |
986 (src, err.strerror), linkname) | |
987 else: | |
988 f = self(dst, "w") | |
989 f.write(src) | |
990 f.close() | |
991 self._fixfilemode(dst) | |
992 | |
993 class chunkbuffer(object): | 898 class chunkbuffer(object): |
994 """Allow arbitrary sized chunks of data to be efficiently read from an | 899 """Allow arbitrary sized chunks of data to be efficiently read from an |
995 iterator over chunks of arbitrary size.""" | 900 iterator over chunks of arbitrary size.""" |
996 | 901 |
997 def __init__(self, in_iter): | 902 def __init__(self, in_iter): |