mercurial/util.py
changeset 13970 d13913355390
parent 13947 d2d1ef6a5238
child 13971 bfeaa88b875d
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):