Repository: easybuilders/easybuild-framework

Issue:
"eb --copy-ec example.eb" only creates empty 'foo.eb' directory, doesn't copy anything
```
$ eb --copy-ec bzip2-1.0.6.eb
== temporary log file in case of crash /tmp/eb-2IRQ16/easybuild-tkWY23.log
== Temporary log file(s) /tmp/eb-2IRQ16/easybuild-tkWY23.log* have been removed.
== Temporary directory /tmp/eb-2IRQ16 has been removed.

$  file bzip2-1.0.6.eb
bzip2-1.0.6.eb: directory
```


Discussion:

Resolving patch:
diff --git a/easybuild/main.py b/easybuild/main.py
--- a/easybuild/main.py
+++ b/easybuild/main.py
@@ -291,8 +291,12 @@ def main(args=None, logfile=None, do_build=None, testing=False, modtool=None):
             eb_file = find_easybuild_easyconfig()
             orig_paths.append(eb_file)
 
-    # last path is target when --copy-ec is used, so remove that from the list
-    target_path = orig_paths.pop() if options.copy_ec else None
+    if len(orig_paths) == 1:
+        # if only one easyconfig file is specified, use current directory as target directory
+        target_path = os.getcwd()
+    elif orig_paths:
+        # last path is target when --copy-ec is used, so remove that from the list
+        target_path = orig_paths.pop() if options.copy_ec else None
 
     categorized_paths = categorize_files_by_type(orig_paths)
 
@@ -310,8 +314,12 @@ def main(args=None, logfile=None, do_build=None, testing=False, modtool=None):
         if options.copy_ec:
             if len(determined_paths) == 1:
                 copy_file(determined_paths[0], target_path)
-            else:
+                print_msg("%s copied to %s" % (os.path.basename(determined_paths[0]), target_path), prefix=False)
+            elif len(determined_paths) > 1:
                 copy_files(determined_paths, target_path)
+                print_msg("%d file(s) copied to %s" % (len(determined_paths), target_path), prefix=False)
+            else:
+                raise EasyBuildError("One of more files to copy should be specified!")
 
         elif options.fix_deprecated_easyconfigs:
             fix_deprecated_easyconfigs(determined_paths)


Test patch:
diff --git a/test/framework/options.py b/test/framework/options.py
--- a/test/framework/options.py
+++ b/test/framework/options.py
@@ -836,6 +836,16 @@ def test_show_ec(self):
     def test_copy_ec(self):
         """Test --copy-ec."""
 
+        def mocked_main(args):
+            self.mock_stderr(True)
+            self.mock_stdout(True)
+            self.eb_main(args, raise_error=True)
+            stderr, stdout = self.get_stderr(), self.get_stdout()
+            self.mock_stderr(False)
+            self.mock_stdout(False)
+            self.assertEqual(stderr, '')
+            return stdout.strip()
+
         topdir = os.path.dirname(os.path.abspath(__file__))
         test_easyconfigs_dir = os.path.join(topdir, 'easyconfigs', 'test_ecs')
 
@@ -845,7 +855,8 @@ def test_copy_ec(self):
         # basic test: copying one easyconfig file to a non-existing absolute path
         test_ec = os.path.join(self.test_prefix, 'test.eb')
         args = ['--copy-ec', 'toy-0.0.eb', test_ec]
-        self.eb_main(args)
+        stdout = mocked_main(args)
+        self.assertEqual(stdout, 'toy-0.0.eb copied to %s' % test_ec)
 
         self.assertTrue(os.path.exists(test_ec))
         self.assertEqual(toy_ec_txt, read_file(test_ec))
@@ -858,7 +869,8 @@ def test_copy_ec(self):
         self.assertFalse(os.path.exists(target_fn))
 
         args = ['--copy-ec', 'toy-0.0.eb', target_fn]
-        self.eb_main(args)
+        stdout = mocked_main(args)
+        self.assertEqual(stdout, 'toy-0.0.eb copied to test.eb')
 
         change_dir(cwd)
 
@@ -869,7 +881,8 @@ def test_copy_ec(self):
         test_target_dir = os.path.join(self.test_prefix, 'test_target_dir')
         mkdir(test_target_dir)
         args = ['--copy-ec', 'toy-0.0.eb', test_target_dir]
-        self.eb_main(args)
+        stdout = mocked_main(args)
+        self.assertEqual(stdout, 'toy-0.0.eb copied to %s' % test_target_dir)
 
         copied_toy_ec = os.path.join(test_target_dir, 'toy-0.0.eb')
         self.assertTrue(os.path.exists(copied_toy_ec))
@@ -890,7 +903,8 @@ def check_copied_files():
 
         # copying multiple easyconfig files to a non-existing target directory (which is created automatically)
         args = ['--copy-ec', 'toy-0.0.eb', 'bzip2-1.0.6-GCC-4.9.2.eb', test_target_dir]
-        self.eb_main(args)
+        stdout = mocked_main(args)
+        self.assertEqual(stdout, '2 file(s) copied to %s' % test_target_dir)
 
         check_copied_files()
 
@@ -901,7 +915,8 @@ def check_copied_files():
         args[-1] = os.path.basename(test_target_dir)
         self.assertFalse(os.path.exists(args[-1]))
 
-        self.eb_main(args)
+        stdout = mocked_main(args)
+        self.assertEqual(stdout, '2 file(s) copied to test_target_dir')
 
         check_copied_files()
 
@@ -912,6 +927,24 @@ def check_copied_files():
         error_pattern = ".*/test.eb exists but is not a directory"
         self.assertErrorRegex(EasyBuildError, error_pattern, self.eb_main, args, raise_error=True)
 
+        # test use of --copy-ec with only one argument: copy to current working directory
+        test_working_dir = os.path.join(self.test_prefix, 'test_working_dir')
+        mkdir(test_working_dir)
+        change_dir(test_working_dir)
+        self.assertEqual(len(os.listdir(os.getcwd())), 0)
+        args = ['--copy-ec', 'toy-0.0.eb']
+        stdout = mocked_main(args)
+        regex = re.compile('toy-0.0.eb copied to .*/%s' % os.path.basename(test_working_dir))
+        self.assertTrue(regex.match(stdout), "Pattern '%s' found in: %s" % (regex.pattern, stdout))
+        copied_toy_cwd = os.path.join(test_working_dir, 'toy-0.0.eb')
+        self.assertTrue(os.path.exists(copied_toy_cwd))
+        self.assertEqual(read_file(copied_toy_cwd), toy_ec_txt)
+
+        # --copy-ec without arguments results in a proper error
+        args = ['--copy-ec']
+        error_pattern = "One of more files to copy should be specified!"
+        self.assertErrorRegex(EasyBuildError, error_pattern, self.eb_main, args, raise_error=True)
+
     def test_dry_run(self):
         """Test dry run (long format)."""
         fd, dummylogfn = tempfile.mkstemp(prefix='easybuild-dummy', suffix='.log')