Repository: conda/conda-build

Issue:
Symbolic link folders don't work anymore
A symbolic link to a folder worked fine in conda-build 2.1.4, but it's not in conda-build 2.1.5 on osx (linux works fine).

conda-build 2.1.5 log
https://travis-ci.org/conda-forge/gap-feedstock/builds/204615074

conda-build 2.1.4 log
https://travis-ci.org/conda-forge/gap-feedstock/builds/200925407


Discussion:
Thanks for reporting.  I'm writing a test and will fix asap.
I've added further testing to make sure that symlinks in the package are still symlinks.  Currently those tests are failing.  Your links are probably copies right now.

Resolving patch:
diff --git a/conda_build/build.py b/conda_build/build.py
--- a/conda_build/build.py
+++ b/conda_build/build.py
@@ -82,7 +82,6 @@ def prefix_files(prefix):
             path = join(root, dn)
             if islink(path):
                 res.add(path[len(prefix) + 1:])
-    res = set(utils.expand_globs(res, prefix))
     return res
 
 
@@ -624,7 +623,8 @@ def filter_files(files_list, prefix, filter_patterns=('(.*[\\\\/])?\.git[\\\\/].
         r = re.compile(pattern)
         files_list = set(files_list) - set(filter(r.match, files_list))
     return [f.replace(prefix + os.path.sep, '') for f in files_list
-            if not os.path.isdir(os.path.join(prefix, f))]
+            if (not os.path.isdir(os.path.join(prefix, f)) or
+                os.path.islink(os.path.join(prefix, f)))]
 
 
 def post_process_files(m, initial_prefix_files):
@@ -697,7 +697,8 @@ def bundle_conda(output, metadata, env, **kw):
         # we exclude the list of files that we want to keep, so post-process picks them up as "new"
         keep_files = set(utils.expand_globs(files, metadata.config.build_prefix))
         pfx_files = set(prefix_files(metadata.config.build_prefix))
-        initial_files = pfx_files - keep_files
+        initial_files = set(item for item in (pfx_files - keep_files)
+                            if not any(keep_file.startswith(item) for keep_file in keep_files))
 
     files = post_process_files(metadata, initial_files)
 
@@ -1066,7 +1067,7 @@ def test(recipedir_or_package_or_metadata, config, move_broken=True):
             config.channel_urls = list(config.channel_urls)
             config.channel_urls.insert(0, local_url)
 
-            metadata_tuples, _ = render_recipe(recipe_dir, config=config)
+            metadata_tuples, _ = render_recipe(recipe_dir, config=config, reset_build_id=False)
 
             metadata = metadata_tuples[0][0]
             if (metadata.meta.get('test', {}).get('source_files') and
@@ -1348,7 +1349,7 @@ def build_tree(recipe_list, config, build_only=False, post=False, notest=False,
                             if pkg.endswith('.tar.bz2'):
                                 # we only know how to test conda packages
                                 try:
-                                    test(pkg, config=config)
+                                    test(pkg, config=metadata.config)
                                 # IOError means recipe was not included with package. use metadata
                                 except IOError:
                                     # force the build string to line up - recomputing it would
diff --git a/conda_build/render.py b/conda_build/render.py
--- a/conda_build/render.py
+++ b/conda_build/render.py
@@ -332,7 +332,7 @@ def distribute_variants(metadata, variants, index, permit_unsatisfiable_variants
 
 
 def render_recipe(recipe_path, config, no_download_source=False, variants=None,
-                  permit_unsatisfiable_variants=True):
+                  permit_unsatisfiable_variants=True, reset_build_id=True):
     arg = recipe_path
     # Don't use byte literals for paths in Python 2
     if not PY3:
@@ -364,7 +364,7 @@ def render_recipe(recipe_path, config, no_download_source=False, variants=None,
         sys.exit(1)
 
     if config.set_build_id:
-        m.config.compute_build_id(m.name(), reset=True)
+        m.config.compute_build_id(m.name(), reset=reset_build_id)
 
     if m.needs_source_for_render and (not os.path.isdir(m.config.work_dir) or
                                       len(os.listdir(m.config.work_dir)) == 0):


Test patch:
diff --git a/tests/test-recipes/metadata/symlinks/build.sh b/tests/test-recipes/metadata/symlinks/build.sh
--- a/tests/test-recipes/metadata/symlinks/build.sh
+++ b/tests/test-recipes/metadata/symlinks/build.sh
@@ -3,6 +3,8 @@ echo "echo weee" > $PREFIX/test/weee
 chmod +x $PREFIX/test/weee
 
 mkdir -p $PREFIX/bin
+# bin script is just a link
 ln -s $PREFIX/test/weee $PREFIX/bin/weee
 
+# link to folder itself
 ln -s $PREFIX/test $PREFIX/test_link
diff --git a/tests/test-recipes/metadata/symlinks/run_test.sh b/tests/test-recipes/metadata/symlinks/run_test.sh
--- a/tests/test-recipes/metadata/symlinks/run_test.sh
+++ b/tests/test-recipes/metadata/symlinks/run_test.sh
@@ -2,7 +2,15 @@
 sh $PREFIX/test/weee
 
 # the symlink to the file
-sh $PREFIX/test/weee
+sh $PREFIX/bin/weee
+if [ ! -L $PREFIX/bin/weee ]; then
+    echo "file in package is not a symlink"
+    exit 1
+fi
 
 # the symlink to the folder
 sh $PREFIX/test_link/weee
+if [ ! -L $PREFIX/test_link ]; then
+    echo "folder in package is not a symlink"
+    exit 1
+fi