# HG changeset patch # User Pierre-Yves David # Date 2014-11-05 01:52:46 # Node ID 7eb520f5efe4d07ba21b1a82b61a4d542722d3d4 # Parent dadcd40b62d8e9d0d6616af1c15b7eaa540fe4c3 transaction: change the on disk format for backupentries We need to store new data to improve the current transaction logic: - location: We want to generate and backup file outside of the 'store' (eg: bookmarks, or various cache files). This requires knowing and preserving where each file is located. The value of this new field is a string. It will be used as a key for a vfs mapping. - cache: We would like to handle cache file in the transaction code. This Will help to have cache consistent with the repository state and avoid performance issue on big repository like Mozilla. However, failure to handle cache file should not result in a transaction failure. We add a new field that carry this information. The value is boolean, A True value mean any error while handling this file can be ignored. Those two mechanisms are not implemented yet, but they are now persisted in the on disk file. Support for new mechanisms is coming in later changeset. We update the file format now and will introduce the new features in later changeset. The format version is set to 0 until we actually support the new feature. This will prevent misunderstanding between incomplete and final client. Support for reading both version 1 and (future) version 2 could be achieved (using default value when reading version 1) but has not been seen as necessary for now. diff --git a/mercurial/transaction.py b/mercurial/transaction.py --- a/mercurial/transaction.py +++ b/mercurial/transaction.py @@ -15,7 +15,7 @@ from i18n import _ import errno import error, util -version = 1 +version = 0 def active(func): def _active(self, *args, **kwds): @@ -43,7 +43,7 @@ def _playback(journal, report, opener, e raise backupfiles = [] - for f, b in backupentries: + for l, f, b, c in backupentries: if f and b: filepath = opener.join(f) backuppath = opener.join(b) @@ -99,9 +99,10 @@ class transaction(object): self.hookargs = {} self.file = opener.open(self.journal, "w") - # a list of ('path', 'backuppath') entries. + # a list of ('location', 'path', 'backuppath', cache) entries. # if 'backuppath' is empty, no file existed at backup time # if 'path' is empty, this is a temporary transaction file + # (location, and cache are current unused) self._backupentries = [] self._backupmap = {} self._backupjournal = "%s.backupfiles" % journal @@ -193,13 +194,13 @@ class transaction(object): else: backupfile = '' - self._addbackupentry((file, backupfile)) + self._addbackupentry(('', file, backupfile, False)) def _addbackupentry(self, entry): """register a new backup entry and write it to disk""" self._backupentries.append(entry) self._backupmap[file] = len(self._backupentries) - 1 - self._backupsfile.write("%s\0%s\n" % entry) + self._backupsfile.write("%s\0%s\0%s\0%d\n" % entry) self._backupsfile.flush() @active @@ -209,7 +210,7 @@ class transaction(object): Such file will be delete when the transaction exit (on both failure and success). """ - self._addbackupentry(('', tmpfile)) + self._addbackupentry(('', '', tmpfile, False)) @active def addfilegenerator(self, genid, filenames, genfunc, order=0, vfs=None): @@ -355,7 +356,7 @@ class transaction(object): self.file.close() self._backupsfile.close() # cleanup temporary files - for f, b in self._backupentries: + for _l, f, b, _c in self._backupentries: if not f and b and self.opener.exists(b): self.opener.unlink(b) self.entries = [] @@ -365,7 +366,7 @@ class transaction(object): self.opener.unlink(self.journal) if self.opener.isfile(self._backupjournal): self.opener.unlink(self._backupjournal) - for _f, b in self._backupentries: + for _l, _f, b, _c in self._backupentries: if b and self.opener.exists(b): self.opener.unlink(b) self._backupentries = [] @@ -447,10 +448,10 @@ def rollback(opener, file, report): if line: # Shave off the trailing newline line = line[:-1] - f, b = line.split('\0') - backupentries.append((f, b)) + l, f, b, c = line.split('\0') + backupentries.append((l, f, b, bool(c))) else: - report(_("journal was created by a newer version of " + report(_("journal was created by a different version of " "Mercurial")) _playback(file, report, opener, entries, backupentries)