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