mercurial/transaction.py
changeset 33278 87bca10a06ed
parent 33087 fcd1c483f5ea
child 33279 7912404b70f2
--- a/mercurial/transaction.py	Tue Jul 04 23:13:46 2017 +0900
+++ b/mercurial/transaction.py	Tue Jul 04 23:13:46 2017 +0900
@@ -44,11 +44,12 @@
     return _active
 
 def _playback(journal, report, opener, vfsmap, entries, backupentries,
-              unlink=True):
+              unlink=True, checkambigfiles=None):
     for f, o, _ignore in entries:
         if o or not unlink:
+            checkambig = checkambigfiles and (f, '') in checkambigfiles
             try:
-                fp = opener(f, 'a', checkambig=True)
+                fp = opener(f, 'a', checkambig=checkambig)
                 fp.truncate(o)
                 fp.close()
             except IOError:
@@ -101,7 +102,8 @@
 
 class transaction(object):
     def __init__(self, report, opener, vfsmap, journalname, undoname=None,
-                 after=None, createmode=None, validator=None, releasefn=None):
+                 after=None, createmode=None, validator=None, releasefn=None,
+                 checkambigfiles=None):
         """Begin a new transaction
 
         Begins a new transaction that allows rolling back writes in the event of
@@ -110,6 +112,10 @@
         * `after`: called after the transaction has been committed
         * `createmode`: the mode of the journal file that will be created
         * `releasefn`: called after releasing (with transaction and result)
+
+        `checkambigfiles` is a set of (path, vfs-location) tuples,
+        which determine whether file stat ambiguity should be avoided
+        for corresponded files.
         """
         self.count = 1
         self.usages = 1
@@ -137,6 +143,10 @@
             releasefn = lambda tr, success: None
         self.releasefn = releasefn
 
+        self.checkambigfiles = set()
+        if checkambigfiles:
+            self.checkambigfiles.update(checkambigfiles)
+
         # A dict dedicated to precisely tracking the changes introduced in the
         # transaction.
         self.changes = {}
@@ -564,7 +574,8 @@
                 # Prevent double usage and help clear cycles.
                 self._abortcallback = None
                 _playback(self.journal, self.report, self.opener, self._vfsmap,
-                          self.entries, self._backupentries, False)
+                          self.entries, self._backupentries, False,
+                          checkambigfiles=self.checkambigfiles)
                 self.report(_("rollback completed\n"))
             except BaseException:
                 self.report(_("rollback failed - please run hg recover\n"))
@@ -573,7 +584,7 @@
             self.releasefn(self, False) # notify failure of transaction
             self.releasefn = None # Help prevent cycles.
 
-def rollback(opener, vfsmap, file, report):
+def rollback(opener, vfsmap, file, report, checkambigfiles=None):
     """Rolls back the transaction contained in the given file
 
     Reads the entries in the specified file, and the corresponding
@@ -584,6 +595,10 @@
     file\0offset pairs, delimited by newlines. The corresponding
     '*.backupfiles' file should contain a list of file\0backupfile
     pairs, delimited by \0.
+
+    `checkambigfiles` is a set of (path, vfs-location) tuples,
+    which determine whether file stat ambiguity should be avoided at
+    restoring corresponded files.
     """
     entries = []
     backupentries = []
@@ -615,4 +630,5 @@
                 report(_("journal was created by a different version of "
                          "Mercurial\n"))
 
-    _playback(file, report, opener, vfsmap, entries, backupentries)
+    _playback(file, report, opener, vfsmap, entries, backupentries,
+              checkambigfiles=checkambigfiles)