[PATCH 3 of 5] transaction: use "location" when doing backup
Olle
olle.lundberg at gmail.com
Sat Oct 18 11:55:58 UTC 2014
On Sat, Oct 18, 2014 at 1:44 PM, Pierre-Yves David <
pierre-yves.david at ens-lyon.org> wrote:
> # HG changeset patch
> # User Pierre-Yves David <pierre-yves.david at fb.com>
> # Date 1413605075 25200
> # Fri Oct 17 21:04:35 2014 -0700
> # Node ID f533386d7f84a8e5ad1885d654d5983d81302b79
> # Parent 580364627689487b0c13185a28d925f676fa0526
> transaction: use "location" when doing backup
>
> Same logic here, we stop passing vfs object as arguments and use the
> location
> identifier to backup the right file. We persist this in the transaction
> state
> file. As this is a format change (3 values per entry instead of 2) we
> change
> the file name to "backupfiles2".
>
> Note that backup of empty file is handled by the "entries" list, not
> "backupentries" and will improve that in the next changeset.
>
> Some more compatibility layer between "backupfiles" and "backupfiles2" may
> come
> in the futur.
>
> diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
> --- a/mercurial/localrepo.py
> +++ b/mercurial/localrepo.py
> @@ -915,11 +915,12 @@ class localrepository(object):
> def recover(self):
> lock = self.lock()
> try:
> if self.svfs.exists("journal"):
> self.ui.status(_("rolling back interrupted
> transaction\n"))
> - transaction.rollback(self.sopener, "journal",
> + vfsmap = {'store': self.sopener, 'plain': self.opener}
> + transaction.rollback(self.sopener, vfsmap, "journal",
> self.ui.warn)
> self.invalidate()
> return True
> else:
> self.ui.warn(_("no interrupted transaction available\n"))
> @@ -971,11 +972,12 @@ class localrepository(object):
> if dryrun:
> return 0
>
> parents = self.dirstate.parents()
> self.destroying()
> - transaction.rollback(self.sopener, 'undo', ui.warn)
> + vfsmap = {'store': self.sopener, 'plain': self.opener}
> + transaction.rollback(self.sopener, vfsmap, 'undo', ui.warn)
> if self.vfs.exists('undo.bookmarks'):
> self.vfs.rename('undo.bookmarks', 'bookmarks')
> if self.svfs.exists('undo.phaseroots'):
> self.svfs.rename('undo.phaseroots', 'phaseroots')
> self.invalidate()
> diff --git a/mercurial/transaction.py b/mercurial/transaction.py
> --- a/mercurial/transaction.py
> +++ b/mercurial/transaction.py
> @@ -21,11 +21,12 @@ def active(func):
> raise error.Abort(_(
> 'cannot use transaction when it is already
> committed/aborted'))
> return func(self, *args, **kwds)
> return _active
>
> -def _playback(journal, report, opener, entries, backupentries,
> unlink=True):
> +def _playback(journal, report, opener, vfsmap, entries, backupentries,\
> + unlink=True):
>
Inside parens there is no need to use a backslash to denote a line
continuation.
> for f, o, _ignore in entries:
> if o or not unlink:
> try:
> fp = opener(f, 'a')
> fp.truncate(o)
> @@ -39,22 +40,23 @@ def _playback(journal, report, opener, e
> except (IOError, OSError), inst:
> if inst.errno != errno.ENOENT:
> raise
>
> backupfiles = []
> - for f, b, _ignore in backupentries:
> - filepath = opener.join(f)
> - backuppath = opener.join(b)
> + for l, f, b, _ignore in backupentries:
> + vfs = vfsmap[l]
> + filepath = vfs.join(f)
> + backuppath = vfs.join(b)
> try:
> util.copyfile(backuppath, filepath)
> backupfiles.append(b)
> except IOError:
> report(_("failed to recover %s\n") % f)
> raise
>
> opener.unlink(journal)
> - backuppath = "%s.backupfiles" % journal
> + backuppath = "%s.backupfiles2" % journal
> if opener.exists(backuppath):
> opener.unlink(backuppath)
> for f in backupfiles:
> opener.unlink(f)
>
> @@ -90,11 +92,11 @@ class transaction(object):
> self.journal = journal
> self._queue = []
> # a dict of arguments to be passed to hooks
> self.hookargs = {}
>
> - self.backupjournal = "%s.backupfiles" % journal
> + self.backupjournal = "%s.backupfiles2" % journal
> self.file = opener.open(self.journal, "w")
> self.backupsfile = opener.open(self.backupjournal, 'w')
> if createmode is not None:
> opener.chmod(self.journal, createmode & 0666)
> opener.chmod(self.backupjournal, createmode & 0666)
> @@ -119,18 +121,18 @@ class transaction(object):
> offsets = []
> backups = []
> for f, o, _data in q[0]:
> offsets.append((f, o))
>
> - for f, b, _data in q[1]:
> - backups.append((f, b))
> + for l, f, b, _data in q[1]:
> + backups.append((l, f, b))
>
> d = ''.join(['%s\0%d\n' % (f, o) for f, o in offsets])
> self.file.write(d)
> self.file.flush()
>
> - d = ''.join(['%s\0%s\0' % (f, b) for f, b in backups])
> + d = ''.join(['%s\0%s\0%s\0' % entry for entry in backups])
> self.backupsfile.write(d)
> self.backupsfile.flush()
>
> @active
> def add(self, file, offset, data=None):
> @@ -145,11 +147,11 @@ class transaction(object):
> # add enough data to the journal to do the truncate
> self.file.write("%s\0%d\n" % (file, offset))
> self.file.flush()
>
> @active
> - def addbackup(self, file, hardlink=True, vfs=None):
> + def addbackup(self, file, hardlink=True, location='store'):
> """Adds a backup of the file to the transaction
>
> Calling addbackup() creates a hardlink backup of the specified
> file
> that is used to recover the file in the event of the transaction
> aborting.
> @@ -159,12 +161,11 @@ class transaction(object):
> """
>
> if file in self.map or file in self.backupmap:
> return
> backupfile = "%s.backup.%s" % (self.journal, file)
> - if vfs is None:
> - vfs = self.opener
> + vfs = self._vfsmap[location]
> if vfs.exists(file):
> filepath = vfs.join(file)
> backuppath = self.opener.join(backupfile)
> util.copyfiles(filepath, backuppath, hardlink=hardlink)
> else:
> @@ -173,13 +174,13 @@ class transaction(object):
>
> if self._queue:
> self._queue[-1][1].append((file, backupfile))
> return
>
> - self.backupentries.append((file, backupfile, None))
> + self.backupentries.append((location, file, backupfile, None))
> self.backupmap[file] = len(self.backupentries) - 1
> - self.backupsfile.write("%s\0%s\0" % (file, backupfile))
> + self.backupsfile.write("%s\0%s\0%s\0" % (location, file,
> backupfile))
> self.backupsfile.flush()
>
> @active
> def addfilegenerator(self, genid, filenames, genfunc, order=0,
> location='store'):
> @@ -278,12 +279,13 @@ class transaction(object):
> self.after()
> if self.opener.isfile(self.journal):
> self.opener.unlink(self.journal)
> if self.opener.isfile(self.backupjournal):
> self.opener.unlink(self.backupjournal)
> - for _f, b, _ignore in self.backupentries:
> - self.opener.unlink(b)
> + for l, _f, b, _ignore in self.backupentries:
> + vfs = self._vfsmap[l]
> + vfs.unlink(b)
> self.backupentries = []
> self.journal = None
>
> @active
> def abort(self):
> @@ -310,20 +312,20 @@ class transaction(object):
> return
>
> self.report(_("transaction abort!\n"))
>
> try:
> - _playback(self.journal, self.report, self.opener,
> + _playback(self.journal, self.report, self.opener,
> self._vfsmap,
> self.entries, self.backupentries, False)
> self.report(_("rollback completed\n"))
> except Exception:
> self.report(_("rollback failed - please run hg
> recover\n"))
> finally:
> self.journal = None
>
>
> -def rollback(opener, file, report):
> +def rollback(opener, vfsmap, file, report):
> """Rolls back the transaction contained in the given file
>
> Reads the entries in the specified file, and the corresponding
> '*.backupfiles' file, to recover from an incomplete transaction.
>
> @@ -350,10 +352,10 @@ def rollback(opener, file, report):
> if opener.exists(backupjournal):
> fp = opener.open(backupjournal)
> data = fp.read()
> if len(data) > 0:
> parts = data.split('\0')
> - for i in xrange(0, len(parts), 2):
> - f, b = parts[i:i + 1]
> - backupentries.append((f, b, None))
> + for i in xrange(0, len(parts), 3):
> + f, b = parts[i:i + 2]
> + backupentries.append((l, f, b, None))
>
> - _playback(file, report, opener, entries, backupentries)
> + _playback(file, report, opener, vfsmap, entries, backupentries)
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel at selenic.com
> http://selenic.com/mailman/listinfo/mercurial-devel
>
--
Olle
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.mercurial-scm.org/pipermail/mercurial-devel/attachments/20141018/c882c90d/attachment-0002.html>
More information about the Mercurial-devel
mailing list