Skip to content

Commit dc9d1d7

Browse files
committed
Add create_unused_dir to create a directory which does not yet exist
This will append _%d until a new folder could be created. If the base folder name does not exists, it is used directly, so the simple, most common case is the cleanest
1 parent a2be0c7 commit dc9d1d7

File tree

2 files changed

+58
-0
lines changed

2 files changed

+58
-0
lines changed

easybuild/tools/filetools.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2473,3 +2473,43 @@ def copy_framework_files(paths, target_dir):
24732473
raise EasyBuildError("Couldn't find parent folder of updated file: %s", path)
24742474

24752475
return file_info
2476+
2477+
2478+
def create_unused_dir(parent_folder, name):
2479+
"""
2480+
Create a new folder in parent_folder using name as the name.
2481+
When a folder of that name already exists, '_0' is appended which is retried for increasing numbers until
2482+
an unused name was found
2483+
"""
2484+
if not os.path.isabs(parent_folder):
2485+
parent_folder = os.path.abspath(parent_folder)
2486+
2487+
start_path = os.path.join(parent_folder, name)
2488+
number = None
2489+
while True:
2490+
if number is None:
2491+
path = start_path
2492+
number = 0
2493+
else:
2494+
path = start_path + '_' + str(number)
2495+
number += 1
2496+
try:
2497+
os.mkdir(path)
2498+
break
2499+
except OSError as err:
2500+
# Distinguish between error due to existing folder and anything else
2501+
if not os.path.exists(path):
2502+
raise EasyBuildError("Failed to create directory %s: %s", path, err)
2503+
2504+
# set group ID and sticky bits, if desired
2505+
bits = 0
2506+
if build_option('set_gid_bit'):
2507+
bits |= stat.S_ISGID
2508+
if build_option('sticky_bit'):
2509+
bits |= stat.S_ISVTX
2510+
if bits:
2511+
try:
2512+
adjust_permissions(path, bits, add=True, relative=True, recursive=True, onlydirs=True)
2513+
except OSError as err:
2514+
raise EasyBuildError("Failed to set group ID/sticky bit: %s", err)
2515+
return path

test/framework/filetools.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2888,6 +2888,24 @@ def test_locate_files(self):
28882888
error_pattern = r"One or more files not found: 2\.txt \(search paths: \)"
28892889
self.assertErrorRegex(EasyBuildError, error_pattern, ft.locate_files, ['2.txt'], [])
28902890

2891+
def test_create_unused_dir(self):
2892+
path = ft.create_unused_dir(self.test_prefix, 'folder')
2893+
self.assertEqual(path, os.path.join(self.test_prefix, 'folder'))
2894+
self.assertTrue(os.path.exists(path))
2895+
# Repeat with existing folder(s) should create new ones
2896+
for i in range(10):
2897+
path = ft.create_unused_dir(self.test_prefix, 'folder')
2898+
self.assertEqual(path, os.path.join(self.test_prefix, 'folder_%s' % i))
2899+
self.assertTrue(os.path.exists(path))
2900+
# Not influenced by similar folder
2901+
path = ft.create_unused_dir(self.test_prefix, 'folder2')
2902+
self.assertEqual(path, os.path.join(self.test_prefix, 'folder2'))
2903+
self.assertTrue(os.path.exists(path))
2904+
for i in range(10):
2905+
path = ft.create_unused_dir(self.test_prefix, 'folder2')
2906+
self.assertEqual(path, os.path.join(self.test_prefix, 'folder2_%s' % i))
2907+
self.assertTrue(os.path.exists(path))
2908+
28912909

28922910
def suite():
28932911
""" returns all the testcases in this module """

0 commit comments

Comments
 (0)