Repository: conda/conda-build

Issue:
--dirty option is broken
```
$ conda build . --dirty
Traceback (most recent call last):
  File "/home/zah/anaconda3/bin/conda-build", line 6, in <module>
    sys.exit(conda_build.cli.main_build.main())
  File "/home/zah/anaconda3/lib/python3.5/site-packages/conda_build/cli/main_build.py", line 255, in main
    execute(sys.argv[1:])
  File "/home/zah/anaconda3/lib/python3.5/site-packages/conda_build/cli/main_build.py", line 247, in execute
    already_built=None, config=config, noverify=args.no_verify)
  File "/home/zah/anaconda3/lib/python3.5/site-packages/conda_build/api.py", line 75, in build
    need_source_download=need_source_download, config=config)
  File "/home/zah/anaconda3/lib/python3.5/site-packages/conda_build/build.py", line 1216, in build_tree
    config=recipe_config)
  File "/home/zah/anaconda3/lib/python3.5/site-packages/conda_build/render.py", line 159, in render_recipe
    config=config)
  File "/home/zah/anaconda3/lib/python3.5/site-packages/conda_build/render.py", line 112, in parse_or_try_download
    return metadata, need_source_download, need_reparse_in_env
UnboundLocalError: local variable 'need_source_download' referenced before assignment
```

Indeed the function `parse_or_try_download` does not define the value of that variable in all the cases.

This is for latest conda build (2.0.12)


Discussion:
Thanks, I will fix this for the next release.

Resolving patch:
diff --git a/conda_build/api.py b/conda_build/api.py
--- a/conda_build/api.py
+++ b/conda_build/api.py
@@ -42,8 +42,8 @@ def get_output_file_path(recipe_path_or_metadata, no_download_source=False, conf
         metadata = recipe_path_or_metadata
     else:
         metadata, _, _ = render_recipe(recipe_path_or_metadata,
-                                    no_download_source=no_download_source,
-                                    config=config)
+                                       no_download_source=no_download_source,
+                                       config=config)
     return bldpkg_path(metadata)
 
 
diff --git a/conda_build/render.py b/conda_build/render.py
--- a/conda_build/render.py
+++ b/conda_build/render.py
@@ -76,7 +76,8 @@ def bldpkg_path(m):
 def parse_or_try_download(metadata, no_download_source, config,
                           force_download=False):
 
-    need_reparse_in_env = False
+    need_reparse_in_env = True
+    need_source_download = True
     if (force_download or (not no_download_source and metadata.needs_source_for_render)):
         # this try/catch is for when the tool to download source is actually in
         #    meta.yaml, and not previously installed in builder env.
@@ -87,21 +88,18 @@ def parse_or_try_download(metadata, no_download_source, config,
                 need_source_download = False
             try:
                 metadata.parse_again(config=config, permit_undefined_jinja=False)
+                need_reparse_in_env = False
             except (ImportError, exceptions.UnableToParseMissingSetuptoolsDependencies):
-                need_reparse_in_env = True
+                pass  # we just don't alter the need_reparse_in_env variable
         except subprocess.CalledProcessError as error:
             print("Warning: failed to download source.  If building, will try "
                 "again after downloading recipe dependencies.")
             print("Error was: ")
             print(error)
-            need_source_download = True
 
     elif not metadata.get_section('source'):
         need_source_download = False
-    else:
-        # we have not downloaded source in the render phase.  Download it in
-        #     the build phase
-        need_source_download = not no_download_source
+        need_reparse_in_env = False
     if not need_reparse_in_env:
         try:
             metadata.parse_until_resolved(config=config)
@@ -157,6 +155,10 @@ def render_recipe(recipe_path, config, no_download_source=False):
     m, need_download, need_reparse_in_env = parse_or_try_download(m,
                                                 no_download_source=no_download_source,
                                                 config=config)
+    if need_download and no_download_source:
+        raise ValueError("no_download_source specified, but can't fully render recipe without"
+                         " downloading source.  Please fix the recipe, or don't use "
+                         "no_download_source.")
     config.noarch = bool(m.get_value('build/noarch'))
 
     if need_cleanup:


Test patch:
diff --git a/tests/test_api_render.py b/tests/test_api_render.py
--- a/tests/test_api_render.py
+++ b/tests/test_api_render.py
@@ -16,7 +16,8 @@
 def test_render_need_download(testing_workdir, test_config):
     # first, test that the download/render system renders all it can,
     #    and accurately returns its needs
-    with pytest.raises(SystemExit):
+
+    with pytest.raises(ValueError):
         metadata, need_download, need_reparse_in_env = api.render(
             os.path.join(metadata_dir, "source_git_jinja2"),
             config=test_config,
@@ -68,7 +69,7 @@ def test_get_output_file_path_jinja2(testing_workdir, test_config):
     #    being cleaned as it should.
 
     # First get metadata with a recipe that is known to need a download:
-    with pytest.raises(SystemExit):
+    with pytest.raises(ValueError):
         build_path = api.get_output_file_path(os.path.join(metadata_dir, "source_git_jinja2"),
                                               config=test_config,
                                               no_download_source=True)