127 # a map to access file in various {location -> vfs} |
127 # a map to access file in various {location -> vfs} |
128 vfsmap = vfsmap.copy() |
128 vfsmap = vfsmap.copy() |
129 vfsmap[''] = opener # set default value |
129 vfsmap[''] = opener # set default value |
130 self._vfsmap = vfsmap |
130 self._vfsmap = vfsmap |
131 self._after = after |
131 self._after = after |
132 self.entries = [] |
132 self._entries = [] |
133 self._map = {} |
133 self._map = {} |
134 self._journal = journalname |
134 self._journal = journalname |
135 self._undoname = undoname |
135 self._undoname = undoname |
136 self._queue = [] |
136 self._queue = [] |
137 # A callback to validate transaction content before closing it. |
137 # A callback to validate transaction content before closing it. |
228 |
228 |
229 def _addentry(self, file, offset, data): |
229 def _addentry(self, file, offset, data): |
230 """add a append-only entry to memory and on-disk state""" |
230 """add a append-only entry to memory and on-disk state""" |
231 if file in self._map or file in self._backupmap: |
231 if file in self._map or file in self._backupmap: |
232 return |
232 return |
233 self.entries.append((file, offset, data)) |
233 self._entries.append((file, offset, data)) |
234 self._map[file] = len(self.entries) - 1 |
234 self._map[file] = len(self._entries) - 1 |
235 # add enough data to the journal to do the truncate |
235 # add enough data to the journal to do the truncate |
236 self._file.write("%s\0%d\n" % (file, offset)) |
236 self._file.write("%s\0%d\n" % (file, offset)) |
237 self._file.flush() |
237 self._file.flush() |
238 |
238 |
239 @active |
239 @active |
350 return any |
350 return any |
351 |
351 |
352 @active |
352 @active |
353 def find(self, file): |
353 def find(self, file): |
354 if file in self._map: |
354 if file in self._map: |
355 return self.entries[self._map[file]] |
355 return self._entries[self._map[file]] |
356 if file in self._backupmap: |
356 if file in self._backupmap: |
357 return self._backupentries[self._backupmap[file]] |
357 return self._backupentries[self._backupmap[file]] |
358 return None |
358 return None |
359 |
359 |
360 @active |
360 @active |
365 ''' |
365 ''' |
366 |
366 |
367 if file not in self._map: |
367 if file not in self._map: |
368 raise KeyError(file) |
368 raise KeyError(file) |
369 index = self._map[file] |
369 index = self._map[file] |
370 self.entries[index] = (file, offset, data) |
370 self._entries[index] = (file, offset, data) |
371 self._file.write("%s\0%d\n" % (file, offset)) |
371 self._file.write("%s\0%d\n" % (file, offset)) |
372 self._file.flush() |
372 self._file.flush() |
373 |
373 |
374 @active |
374 @active |
375 def nest(self, name=r'<unnamed>'): |
375 def nest(self, name=r'<unnamed>'): |
484 if not c: |
484 if not c: |
485 raise |
485 raise |
486 # Abort may be raise by read only opener |
486 # Abort may be raise by read only opener |
487 self._report("couldn't remove %s: %s\n" |
487 self._report("couldn't remove %s: %s\n" |
488 % (vfs.join(b), inst)) |
488 % (vfs.join(b), inst)) |
489 self.entries = [] |
489 self._entries = [] |
490 self._writeundo() |
490 self._writeundo() |
491 if self._after: |
491 if self._after: |
492 self._after() |
492 self._after() |
493 self._after = None # Help prevent cycles. |
493 self._after = None # Help prevent cycles. |
494 if self._opener.isfile(self._backupjournal): |
494 if self._opener.isfile(self._backupjournal): |
562 self._usages = 0 |
562 self._usages = 0 |
563 self._file.close() |
563 self._file.close() |
564 self._backupsfile.close() |
564 self._backupsfile.close() |
565 |
565 |
566 try: |
566 try: |
567 if not self.entries and not self._backupentries: |
567 if not self._entries and not self._backupentries: |
568 if self._backupjournal: |
568 if self._backupjournal: |
569 self._opener.unlink(self._backupjournal) |
569 self._opener.unlink(self._backupjournal) |
570 if self._journal: |
570 if self._journal: |
571 self._opener.unlink(self._journal) |
571 self._opener.unlink(self._journal) |
572 return |
572 return |
577 for cat in sorted(self._abortcallback): |
577 for cat in sorted(self._abortcallback): |
578 self._abortcallback[cat](self) |
578 self._abortcallback[cat](self) |
579 # Prevent double usage and help clear cycles. |
579 # Prevent double usage and help clear cycles. |
580 self._abortcallback = None |
580 self._abortcallback = None |
581 _playback(self._journal, self._report, self._opener, |
581 _playback(self._journal, self._report, self._opener, |
582 self._vfsmap, self.entries, self._backupentries, |
582 self._vfsmap, self._entries, self._backupentries, |
583 False, checkambigfiles=self._checkambigfiles) |
583 False, checkambigfiles=self._checkambigfiles) |
584 self._report(_("rollback completed\n")) |
584 self._report(_("rollback completed\n")) |
585 except BaseException: |
585 except BaseException: |
586 self._report(_("rollback failed - please run hg recover\n")) |
586 self._report(_("rollback failed - please run hg recover\n")) |
587 finally: |
587 finally: |