mercurial/appendfile.py
changeset 4260 bdbfc2193524
parent 4259 eb081ba21eff
equal deleted inserted replaced
4259:eb081ba21eff 4260:bdbfc2193524
   103 class appendopener(object):
   103 class appendopener(object):
   104     '''special opener for files that only read or append.'''
   104     '''special opener for files that only read or append.'''
   105 
   105 
   106     def __init__(self, opener):
   106     def __init__(self, opener):
   107         self.realopener = opener
   107         self.realopener = opener
   108         # key: file name, value: appendfile name
   108         self.tmpname = None
   109         self.tmpnames = {}
       
   110 
   109 
   111     def __call__(self, name, mode='r'):
   110     def __call__(self, name, mode='r'):
   112         '''open file.'''
   111         '''open file.'''
   113 
   112         # only handle .i file
       
   113         if not name.endswith("."):
       
   114             return self.realopener(name, mode)
   114         assert mode in 'ra+'
   115         assert mode in 'ra+'
   115         try:
   116         try:
   116             realfp = self.realopener(name, 'r')
   117             realfp = self.realopener(name, 'r')
   117         except IOError, err:
   118         except IOError, err:
   118             if err.errno != errno.ENOENT: raise
   119             if err.errno != errno.ENOENT: raise
   119             realfp = self.realopener(name, 'w+')
   120             self.realfp = self.realopener(name, 'w+')
   120         tmpname = self.tmpnames.get(name)
   121         fp = appendfile(realfp, self.tmpname)
   121         fp = appendfile(realfp, tmpname)
       
   122         if tmpname is None:
   122         if tmpname is None:
   123             self.tmpnames[name] = fp.tmpname
   123             self.tmpname = fp.tmpname
       
   124             self.name = name
   124         return fp
   125         return fp
   125 
   126 
   126     def writedata(self):
   127     def writedata(self):
   127         '''copy data from temp files to real files.'''
   128         '''copy data from temp files to real files.'''
   128         # write .d file before .i file.
   129         if not self.tmpname:
   129         tmpnames = self.tmpnames.items()
   130             return
   130         tmpnames.sort()
   131         ifp = open(self.tmpname, 'rb')
   131         for name, tmpname in tmpnames:
   132         ofp = self.realopener(self.name, 'a')
   132             ifp = open(tmpname, 'rb')
   133         for chunk in util.filechunkiter(ifp):
   133             ofp = self.realopener(name, 'a')
   134             ofp.write(chunk)
   134             for chunk in util.filechunkiter(ifp):
   135         ifp.close()
   135                 ofp.write(chunk)
   136         os.unlink(self.tmpname)
   136             ifp.close()
   137         ofp.close()
   137             os.unlink(tmpname)
       
   138             del self.tmpnames[name]
       
   139             ofp.close()
       
   140 
   138 
   141     def cleanup(self):
   139     def cleanup(self):
   142         '''delete temp files (this discards unwritten data!)'''
   140         '''delete temp files (this discards unwritten data!)'''
   143         for tmpname in self.tmpnames.values():
   141         if self.tmpname:
   144             os.unlink(tmpname)
   142             os.unlink(self.tmpname)
   145 
   143 
   146 # files for changelog and manifest are in different appendopeners, so
   144 # files for changelog and manifest are in different appendopeners, so
   147 # not mixed up together.
   145 # not mixed up together.
   148 
   146 
   149 class appendchangelog(changelog.changelog, appendopener):
   147 class appendchangelog(changelog.changelog, appendopener):