mercurial/transaction.py
changeset 45872 ec73a6a75985
parent 45871 a985c4fb23ca
child 45942 89a2afe31e82
equal deleted inserted replaced
45871:a985c4fb23ca 45872:ec73a6a75985
   157         vfsmap = vfsmap.copy()
   157         vfsmap = vfsmap.copy()
   158         vfsmap[b''] = opener  # set default value
   158         vfsmap[b''] = opener  # set default value
   159         self._vfsmap = vfsmap
   159         self._vfsmap = vfsmap
   160         self._after = after
   160         self._after = after
   161         self._offsetmap = {}
   161         self._offsetmap = {}
       
   162         self._newfiles = set()
   162         self._journal = journalname
   163         self._journal = journalname
   163         self._undoname = undoname
   164         self._undoname = undoname
   164         self._queue = []
   165         self._queue = []
   165         # A callback to do something just after releasing transaction.
   166         # A callback to do something just after releasing transaction.
   166         if releasefn is None:
   167         if releasefn is None:
   246             self._addentry(f, o)
   247             self._addentry(f, o)
   247 
   248 
   248     @active
   249     @active
   249     def add(self, file, offset):
   250     def add(self, file, offset):
   250         """record the state of an append-only file before update"""
   251         """record the state of an append-only file before update"""
   251         if file in self._offsetmap or file in self._backupmap:
   252         if (
       
   253             file in self._newfiles
       
   254             or file in self._offsetmap
       
   255             or file in self._backupmap
       
   256         ):
   252             return
   257             return
   253         if self._queue:
   258         if self._queue:
   254             self._queue[-1].append((file, offset))
   259             self._queue[-1].append((file, offset))
   255             return
   260             return
   256 
   261 
   257         self._addentry(file, offset)
   262         self._addentry(file, offset)
   258 
   263 
   259     def _addentry(self, file, offset):
   264     def _addentry(self, file, offset):
   260         """add a append-only entry to memory and on-disk state"""
   265         """add a append-only entry to memory and on-disk state"""
   261         if file in self._offsetmap or file in self._backupmap:
   266         if (
       
   267             file in self._newfiles
       
   268             or file in self._offsetmap
       
   269             or file in self._backupmap
       
   270         ):
   262             return
   271             return
   263         self._offsetmap[file] = offset
   272         if offset:
       
   273             self._offsetmap[file] = offset
       
   274         else:
       
   275             self._newfiles.add(file)
   264         # add enough data to the journal to do the truncate
   276         # add enough data to the journal to do the truncate
   265         self._file.write(b"%s\0%d\n" % (file, offset))
   277         self._file.write(b"%s\0%d\n" % (file, offset))
   266         self._file.flush()
   278         self._file.flush()
   267 
   279 
   268     @active
   280     @active
   278         """
   290         """
   279         if self._queue:
   291         if self._queue:
   280             msg = b'cannot use transaction.addbackup inside "group"'
   292             msg = b'cannot use transaction.addbackup inside "group"'
   281             raise error.ProgrammingError(msg)
   293             raise error.ProgrammingError(msg)
   282 
   294 
   283         if file in self._offsetmap or file in self._backupmap:
   295         if (
       
   296             file in self._newfiles
       
   297             or file in self._offsetmap
       
   298             or file in self._backupmap
       
   299         ):
   284             return
   300             return
   285         vfs = self._vfsmap[location]
   301         vfs = self._vfsmap[location]
   286         dirname, filename = vfs.split(file)
   302         dirname, filename = vfs.split(file)
   287         backupfilename = b"%s.backup.%s" % (self._journal, filename)
   303         backupfilename = b"%s.backup.%s" % (self._journal, filename)
   288         backupfile = vfs.reljoin(dirname, backupfilename)
   304         backupfile = vfs.reljoin(dirname, backupfilename)
   392                     f.discard()
   408                     f.discard()
   393         return any
   409         return any
   394 
   410 
   395     @active
   411     @active
   396     def findoffset(self, file):
   412     def findoffset(self, file):
       
   413         if file in self._newfiles:
       
   414             return 0
   397         return self._offsetmap.get(file)
   415         return self._offsetmap.get(file)
   398 
   416 
   399     @active
   417     @active
   400     def readjournal(self):
   418     def readjournal(self):
   401         self._file.seek(0)
   419         self._file.seek(0)
   409     def replace(self, file, offset):
   427     def replace(self, file, offset):
   410         '''
   428         '''
   411         replace can only replace already committed entries
   429         replace can only replace already committed entries
   412         that are not pending in the queue
   430         that are not pending in the queue
   413         '''
   431         '''
   414 
   432         if file in self._newfiles:
   415         if file not in self._offsetmap:
   433             if not offset:
       
   434                 return
       
   435             self._newfiles.remove(file)
       
   436             self._offsetmap[file] = offset
       
   437         elif file in self._offsetmap:
       
   438             if not offset:
       
   439                 del self._offsetmap[file]
       
   440                 self._newfiles.add(file)
       
   441             else:
       
   442                 self._offsetmap[file] = offset
       
   443         else:
   416             raise KeyError(file)
   444             raise KeyError(file)
   417         self._offsetmap[file] = offset
       
   418         self._file.write(b"%s\0%d\n" % (file, offset))
   445         self._file.write(b"%s\0%d\n" % (file, offset))
   419         self._file.flush()
   446         self._file.flush()
   420 
   447 
   421     @active
   448     @active
   422     def nest(self, name='<unnamed>'):
   449     def nest(self, name='<unnamed>'):
   553                     # Abort may be raise by read only opener
   580                     # Abort may be raise by read only opener
   554                     self._report(
   581                     self._report(
   555                         b"couldn't remove %s: %s\n" % (vfs.join(b), inst)
   582                         b"couldn't remove %s: %s\n" % (vfs.join(b), inst)
   556                     )
   583                     )
   557         self._offsetmap = {}
   584         self._offsetmap = {}
       
   585         self._newfiles = set()
   558         self._writeundo()
   586         self._writeundo()
   559         if self._after:
   587         if self._after:
   560             self._after()
   588             self._after()
   561             self._after = None  # Help prevent cycles.
   589             self._after = None  # Help prevent cycles.
   562         if self._opener.isfile(self._backupjournal):
   590         if self._opener.isfile(self._backupjournal):
   636         self._usages = 0
   664         self._usages = 0
   637         self._file.close()
   665         self._file.close()
   638         self._backupsfile.close()
   666         self._backupsfile.close()
   639 
   667 
   640         try:
   668         try:
   641             if not self._offsetmap and not self._backupentries:
   669             if not entries and not self._backupentries:
   642                 if self._backupjournal:
   670                 if self._backupjournal:
   643                     self._opener.unlink(self._backupjournal)
   671                     self._opener.unlink(self._backupjournal)
   644                 if self._journal:
   672                 if self._journal:
   645                     self._opener.unlink(self._journal)
   673                     self._opener.unlink(self._journal)
   646                 return
   674                 return