Repository: conda/conda-build

Issue:
Problem: When using output-folder the index doesn't get updated properly
Using the latest master, I get the following error while build patchelf:

```
Fixing permissions
patchelf: file: /[PREFIX]/_b_env_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold/bin/patchelf
    setting rpath to: $ORIGIN/../lib
Fixing permissions
Detected hard-coded path in binary file bin/patchelf
updating index in: /[PREFIX]/conda-bld/linux-64
updating index in: /builds/[TMP]/output-folder
TEST START: patchelf-0.9-2
Deleting work directory, /[PREFIX]/conda-bld/recipe_1482480512395/work/patchelf-0.9
updating index in: /[PREFIX]/conda-bld/linux-64
updating index in: /[PREFIX]/conda-bld/noarch
Traceback (most recent call last):
  File "/[PREFIX]/lib/python3.5/site-packages/conda/core/index.py", line 159, in fetch_repodata_remote_request
    resp.raise_for_status()
  File "/[PREFIX]/lib/python3.5/site-packages/requests/models.py", line 884, in raise_for_status
    raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 404 Client Error: None for url: file:///builds/[TMP]/output-folder/linux-64/repodata.json.bz2
```

I think the problem is, that the conda index does get created in output-folder but not in output-folder/linux-64...


Discussion:
Thanks @gabm - will fix this for the final 2.1.0 release.

Resolving patch:
diff --git a/conda_build/build.py b/conda_build/build.py
--- a/conda_build/build.py
+++ b/conda_build/build.py
@@ -849,6 +849,7 @@ def order(f):
         if os.path.isfile(final_output):
             os.remove(final_output)
         utils.copy_into(tmp_path, final_output, config.timeout, locking=config.locking)
+
     # remove files from build prefix.  This is so that they can be included in other packages.  If
     #     we were to leave them in place, then later scripts meant to also include them may not.
     for f in files:
@@ -1098,9 +1099,14 @@ def build(m, config, post=None, need_source_download=True, need_reparse_in_env=F
                 if made_meta and not any(m.name() in out.get('name', '') for out in outputs):
                     outputs.append({'name': m.name(), 'requirements': requirements})
 
+        output_folders = set()
         for output in outputs:
-            built_packages.append(bundlers[output.get('type', 'conda')](output, m, config, env))
-        update_index(config.bldpkgs_dir, config, could_be_mirror=False)
+            built_package = bundlers[output.get('type', 'conda')](output, m, config, env)
+            built_packages.append(built_package)
+            output_folders.add(os.path.dirname(built_package))
+
+        for folder in output_folders:
+            update_index(folder, config, could_be_mirror=False)
 
     else:
         print("STOPPING BUILD BEFORE POST:", m.dist())


Test patch:
diff --git a/tests/test_cli.py b/tests/test_cli.py
--- a/tests/test_cli.py
+++ b/tests/test_cli.py
@@ -15,6 +15,7 @@
 
 from conda_build import api
 from conda_build.utils import get_site_packages, on_win, get_build_folders, package_has_file
+from conda_build.conda_interface import TemporaryDirectory
 from .utils import (testing_workdir, metadata_dir, testing_env, test_config, test_metadata,
                     put_bad_conda_on_path)
 
@@ -30,7 +31,8 @@
 
 
 def test_build():
-    args = ['--no-anaconda-upload', os.path.join(metadata_dir, "empty_sections"), '--no-activate']
+    args = ['--no-anaconda-upload', os.path.join(metadata_dir, "empty_sections"), '--no-activate',
+            '--no-anaconda-upload']
     main_build.execute(args)
 
 
@@ -46,7 +48,7 @@ def test_build_add_channel():
     """This recipe requires the blinker package, which is only on conda-forge.
     This verifies that the -c argument works."""
 
-    args = ['--no-anaconda-upload', '-c', 'conda_build_test', '--no-activate',
+    args = ['--no-anaconda-upload', '-c', 'conda_build_test', '--no-activate', '--no-anaconda-upload',
             os.path.join(metadata_dir, "_recipe_requiring_external_channel")]
     main_build.execute(args)
 
@@ -86,7 +88,7 @@ def test_build_output_build_path(testing_workdir, test_config, test_metadata, ca
 def test_build_output_build_path_multiple_recipes(testing_workdir, test_config, test_metadata, capfd):
     skip_recipe = os.path.join(metadata_dir, "build_skip")
     api.output_yaml(test_metadata, 'meta.yaml')
-    args = ['--output', testing_workdir, skip_recipe]
+    args = ['--output', testing_workdir, skip_recipe, '--no-anaconda-upload']
 
     main_build.execute(args)
 
@@ -104,7 +106,8 @@ def test_build_output_build_path_multiple_recipes(testing_workdir, test_config,
 def test_slash_in_recipe_arg_keeps_build_id(testing_workdir, test_config):
     recipe_path = os.path.join(metadata_dir, "has_prefix_files" + os.path.sep)
     fn = api.get_output_file_path(recipe_path, config=test_config)
-    args = [os.path.join(metadata_dir, "has_prefix_files"), '--croot', test_config.croot]
+    args = [os.path.join(metadata_dir, "has_prefix_files"), '--croot', test_config.croot,
+            '--no-anaconda-upload']
     main_build.execute(args)
     data = package_has_file(fn, 'binary-has-prefix')
     assert data
@@ -113,9 +116,9 @@ def test_slash_in_recipe_arg_keeps_build_id(testing_workdir, test_config):
     assert 'has_prefix_files_1' in data
 
 
-def test_build_no_build_id(testing_workdir, test_config, capfd):
+def test_build_no_build_id(testing_workdir, test_config):
     args = [os.path.join(metadata_dir, "has_prefix_files"), '--no-build-id',
-            '--croot', test_config.croot, '--no-activate']
+            '--croot', test_config.croot, '--no-activate', '--no-anaconda-upload']
     main_build.execute(args)
     fn = api.get_output_file_path(os.path.join(metadata_dir, "has_prefix_files"),
                                   config=test_config)
@@ -126,6 +129,19 @@ def test_build_no_build_id(testing_workdir, test_config, capfd):
     assert 'has_prefix_files_1' not in data
 
 
+def test_build_output_folder(testing_workdir, test_metadata, capfd):
+    api.output_yaml(test_metadata, 'meta.yaml')
+    with TemporaryDirectory() as tmp:
+        out = os.path.join(tmp, 'out')
+        args = [testing_workdir, '--no-build-id',
+                '--croot', tmp, '--no-activate', '--no-anaconda-upload',
+                '--output-folder', out]
+        main_build.execute(args)
+        test_metadata.config.output_folder = out
+        output, error = capfd.readouterr()
+        assert "anaconda upload {}".format(out) in output
+
+
 def test_render_output_build_path_set_python(testing_workdir, test_metadata, capfd):
     api.output_yaml(test_metadata, 'meta.yaml')
     # build the other major thing, whatever it is