Repository: conda/conda-build

Issue:
"hoisting" unpacked source up one level fails names are identical
I ran into a problem writing a recipe for the package montage (source link is http://montage.ipac.caltech.edu/download/Montage_v5.0.tar.gz). The tarball unpacks into a directory called `Montage`, which contains in it a folder also called `Montage`. in [`hoist_single_extracted_folder`](https://github.com/conda/conda-build/blob/master/conda_build/source.py#L86) that causes a problem because the destination for the copy has the same name as the `nested_folder`. 


Discussion:
Same here for other packages, like:

https://heasarc.gsfc.nasa.gov/fitsio/ccfits/CCfits-2.5.tar.gz

Note that they used to work with conda build 2.1.17 (the last 2.x version)

Resolving patch:
diff --git a/conda_build/source.py b/conda_build/source.py
--- a/conda_build/source.py
+++ b/conda_build/source.py
@@ -91,7 +91,11 @@ def hoist_single_extracted_folder(nested_folder):
     flist = os.listdir(nested_folder)
     parent = os.path.dirname(nested_folder)
     for thing in flist:
-        shutil.move(os.path.join(nested_folder, thing), os.path.join(parent, thing))
+        if not os.path.isdir(os.path.join(parent, thing)):
+            shutil.move(os.path.join(nested_folder, thing), os.path.join(parent, thing))
+        else:
+            copy_into(os.path.join(nested_folder, thing), os.path.join(parent, thing))
+            nested_folder = os.path.join(nested_folder, thing)
     rm_rf(nested_folder)
 
 


Test patch:
diff --git a/tests/test_source.py b/tests/test_source.py
--- a/tests/test_source.py
+++ b/tests/test_source.py
@@ -66,8 +66,9 @@ def test_multiple_different_sources(testing_metadata):
     # Test get_value() indexing syntax.
     assert testing_metadata.get_value('source/url') == testing_metadata.meta['source'][0]['url']
     assert testing_metadata.get_value('source/0/url') == testing_metadata.meta['source'][0]['url']
-    assert (testing_metadata.get_value('source/1/git_url')
-            == testing_metadata.meta['source'][1]['git_url'])
+    assert (testing_metadata.get_value('source/1/git_url') ==
+            testing_metadata.meta['source'][1]['git_url'])
+
 
 def test_git_into_existing_populated_folder_raises(testing_metadata):
     """Git will not clone into a non-empty folder.  This should raise an exception."""
@@ -99,3 +100,24 @@ def test_source_user_expand(testing_workdir):
                 source_dict = {"url": os.path.join(prefix, os.path.basename(tmp), "cb-test.tar.bz2")}
                 with TemporaryDirectory() as tmp2:
                     download_to_cache(tmp2, '', source_dict)
+
+
+def test_hoist_same_name(testing_workdir):
+    testdir = os.path.join(testing_workdir, 'test', 'test')
+    outer_dir = os.path.join(testing_workdir, 'test')
+    os.makedirs(testdir)
+    with open(os.path.join(testdir, 'somefile'), 'w') as f:
+        f.write('weeeee')
+    source.hoist_single_extracted_folder(outer_dir)
+    assert os.path.isfile(os.path.join(outer_dir, 'somefile'))
+    assert not os.path.isdir(testdir)
+
+
+def test_hoist_different_name(testing_workdir):
+    testdir = os.path.join(testing_workdir, 'test')
+    os.makedirs(testdir)
+    with open(os.path.join(testdir, 'somefile'), 'w') as f:
+        f.write('weeeee')
+    source.hoist_single_extracted_folder(testdir)
+    assert os.path.isfile(os.path.join(testing_workdir, 'somefile'))
+    assert not os.path.isdir(testdir)