Commits

Bryan O'Sullivan committed 4034b8d

scmutil: create directories in a race-safe way during update

With the new parallel update code, it is possible for multiple
workers to try to create a hierarchy of directories at the same
time. This is hard to trigger in general, but most likely during
initial checkout.

To deal with these races, we introduce a new ensuredirs function
whose contract is to ensure that a directory hierarchy exists - it
will ignore a failure that implies that the desired directory already
exists.

  • Participants
  • Parent commits f12804d

Comments (0)

Files changed (2)

mercurial/scmutil.py

             if basename:
                 if atomictemp:
                     if not os.path.isdir(dirname):
-                        util.makedirs(dirname, self.createmode)
+                        util.ensuredirs(dirname, self.createmode)
                     return util.atomictempfile(f, mode, self.createmode)
                 try:
                     if 'w' in mode:
                         raise
                     nlink = 0
                     if not os.path.isdir(dirname):
-                        util.makedirs(dirname, self.createmode)
+                        util.ensuredirs(dirname, self.createmode)
                 if nlink > 0:
                     if self._trustnlink is None:
                         self._trustnlink = nlink > 1 or util.checknlink(f)
 
         dirname = os.path.dirname(linkname)
         if not os.path.exists(dirname):
-            util.makedirs(dirname, self.createmode)
+            util.ensuredirs(dirname, self.createmode)
 
         if self._cansymlink:
             try:

mercurial/util.py

     if mode is not None:
         os.chmod(name, mode)
 
+def ensuredirs(name, mode=None):
+    """race-safe recursive directory creation"""
+    try:
+        makedirs(name, mode)
+    except OSError, err:
+        if err.errno == errno.EEXIST and os.path.isdir(name):
+            # someone else seems to have won a directory creation race
+            return
+        raise
+
 def readfile(path):
     fp = open(path, 'rb')
     try: