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