Skip to content
12 changes: 8 additions & 4 deletions easybuild/tools/filetools.py
Original file line number Diff line number Diff line change
Expand Up @@ -2270,6 +2270,9 @@ def copy_file(path, target_path, force_in_dry_run=False):
:param target_path: path to copy the file to
:param force_in_dry_run: force copying of file during dry run
"""
# NOTE: 'exists' will return False if 'path' is a broken symlink
if not os.path.exists(path) and not os.path.islink(path):
raise EasyBuildError("Could not copy '%s' it does not exist!" % path)
if not force_in_dry_run and build_option('extended_dry_run'):
dry_run_msg("copied file %s to %s" % (path, target_path))
else:
Expand All @@ -2285,13 +2288,14 @@ def copy_file(path, target_path, force_in_dry_run=False):
_log.info("Copied contents of file %s to %s", path, target_path)
else:
mkdir(os.path.dirname(target_path), parents=True)
if os.path.exists(path):
shutil.copy2(path, target_path)
elif os.path.islink(path):
if os.path.islink(path):
# special care for copying broken symlinks
link_target = os.readlink(path)
symlink(link_target, target_path)
_log.info("%s copied to %s", path, target_path)
_log.info("created symlink from %s to %s", path, target_path)
else:
shutil.copy2(path, target_path)
_log.info("%s copied to %s", path, target_path)
except (IOError, OSError, shutil.Error) as err:
raise EasyBuildError("Failed to copy file %s to %s: %s", path, target_path, err)

Expand Down
4 changes: 4 additions & 0 deletions test/framework/filetools.py
Original file line number Diff line number Diff line change
Expand Up @@ -1661,6 +1661,10 @@ def test_copy_file(self):
self.assertTrue(ft.read_file(to_copy) == ft.read_file(target_path))
self.assertEqual(txt, '')

# Test that a non-existing file raises an exception
src, target = os.path.join(self.test_prefix, 'this_file_does_not_exist'), os.path.join(self.test_prefix, 'toy')
self.assertErrorRegex(EasyBuildError, "Could not copy *", ft.copy_file, src, target)

def test_copy_files(self):
"""Test copy_files function."""
test_ecs = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'easyconfigs', 'test_ecs')
Expand Down