Merge branch 'valentindavid/447-stack-trace-checkout' into 'bst-1.2'

Handle checkout failure for unbuilt elements

See merge request BuildStream/buildstream!653
diff --git a/buildstream/_stream.py b/buildstream/_stream.py
index 798ab9a..252bed2 100644
--- a/buildstream/_stream.py
+++ b/buildstream/_stream.py
@@ -437,7 +437,7 @@
 
         except BstError as e:
             raise StreamError("Error while staging dependencies into a sandbox"
-                              ": '{}'".format(e), reason=e.reason) from e
+                              ": '{}'".format(e), detail=e.detail, reason=e.reason) from e
 
     # workspace_open
     #
diff --git a/buildstream/element.py b/buildstream/element.py
index ffdead5..c181f76 100644
--- a/buildstream/element.py
+++ b/buildstream/element.py
@@ -613,6 +613,12 @@
               dep.stage_artifact(sandbox)
         """
 
+        if not self._cached():
+            detail = "No artifacts have been cached yet for that element\n" + \
+                     "Try building the element first with `bst build`\n"
+            raise ElementError("No artifacts to stage",
+                               detail=detail, reason="uncached-checkout-attempt")
+
         if update_mtimes is None:
             update_mtimes = []
 
diff --git a/tests/frontend/buildcheckout.py b/tests/frontend/buildcheckout.py
index b9d833f..d0f52d6 100644
--- a/tests/frontend/buildcheckout.py
+++ b/tests/frontend/buildcheckout.py
@@ -97,6 +97,16 @@
 
 
 @pytest.mark.datafiles(DATA_DIR)
+def test_build_checkout_unbuilt(datafiles, cli):
+    project = os.path.join(datafiles.dirname, datafiles.basename)
+    checkout = os.path.join(cli.directory, 'checkout')
+
+    # Check that checking out an unbuilt element fails nicely
+    result = cli.run(project=project, args=['checkout', 'target.bst', checkout])
+    result.assert_main_error(ErrorDomain.STREAM, "uncached-checkout-attempt")
+
+
+@pytest.mark.datafiles(DATA_DIR)
 def test_build_checkout_tarball(datafiles, cli):
     project = os.path.join(datafiles.dirname, datafiles.basename)
     checkout = os.path.join(cli.directory, 'checkout.tar')