Ensure util.mkdir_dash_p() fails if its target is a non-directory, and
authorTom Clegg <tom@curoverse.com>
Mon, 3 Feb 2014 16:21:05 +0000 (08:21 -0800)
committerTom Clegg <tom@curoverse.com>
Mon, 3 Feb 2014 16:21:05 +0000 (08:21 -0800)
succeeds if the target directory exists after an mkdir() race with
another process.

sdk/python/.gitignore
sdk/python/arvados/util.py
sdk/python/test_util.py [new file with mode: 0644]

index 2d2799ca78e000b701eeaf709154fcf6bb365e4c..7f9c17b7433633f9447d0b3cc575fbe5c7182bca 100644 (file)
@@ -1,3 +1,4 @@
 /build/
 /dist/
 /*.egg-info
+/tmp
index 4e0d6f05dcd9f78bcd239e65f4a3b7863e406509..552fbbe31fad1d106a0ff41f574e0455ec8ae7e8 100644 (file)
@@ -3,6 +3,7 @@ import hashlib
 import os
 import re
 import subprocess
+import errno
 
 def clear_tmpdir(path=None):
     """
@@ -242,8 +243,16 @@ def collection_extract(collection, path, files=[], decompress=True):
     return path
 
 def mkdir_dash_p(path):
-    if not os.path.exists(path):
-        os.makedirs(path)
+    if not os.path.isdir(path):
+        try:
+            os.makedirs(path)
+        except OSError as e:
+            if e.errno == errno.EEXIST and os.path.isdir(path):
+                # It is not an error if someone else creates the
+                # directory between our exists() and makedirs() calls.
+                pass
+            else:
+                raise
 
 def stream_extract(stream, path, files=[], decompress=True):
     """Retrieve a stream from Keep and extract it to a local
diff --git a/sdk/python/test_util.py b/sdk/python/test_util.py
new file mode 100644 (file)
index 0000000..f9e5d8c
--- /dev/null
@@ -0,0 +1,22 @@
+import unittest
+import os
+import arvados.util
+
+class MkdirDashPTest(unittest.TestCase):
+    def setUp(self):
+        try:
+            os.path.mkdir('./tmp')
+        except:
+            pass
+    def tearDown(self):
+        try:
+            os.unlink('./tmp/bar')
+            os.rmdir('./tmp/foo')
+            os.rmdir('./tmp')
+        except:
+            pass
+    def runTest(self):
+        arvados.util.mkdir_dash_p('./tmp/foo')
+        with open('./tmp/bar', 'wb') as f:
+            f.write('bar')
+        self.assertRaises(OSError, arvados.util.mkdir_dash_p, './tmp/bar')