[PATCH 2 of 7 main-line-of-work] transaction: handle missing file in backupentries (instead of using entries)

Pierre-Yves David pierre-yves.david at ens-lyon.org
Tue Nov 11 11:35:09 CST 2014


# HG changeset patch
# User Pierre-Yves David <pierre-yves.david at fb.com>
# Date 1415151528 0
#      Wed Nov 05 01:38:48 2014 +0000
# Node ID 10b65c6db73ef5a94fc4933981a0403d38cb18a0
# Parent  24a121a4798948ed7eaa1bd3a730ad5c165ec4f0
transaction: handle missing file in backupentries (instead of using entries)

The case were a backup of a missing file was requested was previously handled by
the `entries` list. As the `backupentries` is about to gain ability to backup
files outside of `.hg/store`, we want it to be able to handle the missing file
too.

reminder: using `addbackup` on a missing file means that such file needs to be
deleted if we rollback the transaction.

diff --git a/mercurial/transaction.py b/mercurial/transaction.py
--- a/mercurial/transaction.py
+++ b/mercurial/transaction.py
@@ -42,18 +42,25 @@ def _playback(journal, report, opener, e
                 if inst.errno != errno.ENOENT:
                     raise
 
     backupfiles = []
     for f, b in backupentries:
-        filepath = opener.join(f)
-        backuppath = opener.join(b)
-        try:
-            util.copyfile(backuppath, filepath)
-            backupfiles.append(b)
-        except IOError:
-            report(_("failed to recover %s\n") % f)
-            raise
+        if b:
+            filepath = opener.join(f)
+            backuppath = opener.join(b)
+            try:
+                util.copyfile(backuppath, filepath)
+                backupfiles.append(b)
+            except IOError:
+                report(_("failed to recover %s\n") % f)
+                raise
+        else:
+            try:
+                opener.unlink(f)
+            except (IOError, OSError), inst:
+                if inst.errno != errno.ENOENT:
+                    raise
 
     opener.unlink(journal)
     backuppath = "%s.backupfiles" % journal
     if opener.exists(backuppath):
         opener.unlink(backuppath)
@@ -83,10 +90,11 @@ class transaction(object):
         self.onclose = onclose
         self.onabort = onabort
         self.entries = []
         self.map = {}
         # a list of ('path', 'backuppath') entries.
+        # if 'backuppath' is empty, no file existed at backup time
         self._backupentries = []
         self._backupmap = {}
         self.journal = journal
         self._queue = []
         # a dict of arguments to be passed to hooks
@@ -177,12 +185,11 @@ class transaction(object):
         if vfs.exists(file):
             filepath = vfs.join(file)
             backuppath = self.opener.join(backupfile)
             util.copyfiles(filepath, backuppath, hardlink=hardlink)
         else:
-            self.add(file, 0)
-            return
+            backupfile = ''
 
         self._backupentries.append((file, backupfile))
         self._backupmap[file] = len(self._backupentries) - 1
         self._backupsfile.write("%s\0%s\n" % (file, backupfile))
         self._backupsfile.flush()
@@ -329,11 +336,12 @@ class transaction(object):
         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 in self._backupentries:
-                self.opener.unlink(b)
+                if b:
+                    self.opener.unlink(b)
         self._backupentries = []
         self.journal = None
         # run post close action
         categories = sorted(self._postclosecallback)
         for cat in categories:


More information about the Mercurial-devel mailing list