From 1f74bd72280b0e6712355625134af2758ec09717 Mon Sep 17 00:00:00 2001 From: Chandan Singh Date: Tue, 28 Apr 2020 20:16:11 +0000 Subject: _stream.py: Fetch sources while launching build shells Part of https://gitlab.com/BuildStream/buildstream/-/issues/1068. Make behavior of `shell` command similar to other commands that need sources like `build`, `workspace open`, `source checkout` etc. --- NEWS | 5 +++++ src/buildstream/_stream.py | 12 +++++------- tests/integration/shell.py | 40 +++++++++++++++++++++++++++++++++++++--- 3 files changed, 47 insertions(+), 10 deletions(-) diff --git a/NEWS b/NEWS index dcc9a60d3..ec6f5f352 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,11 @@ (unreleased) ============ +CLI +--- + + o `bst shell --build` will now automatically fetch missing sources. + ================== buildstream 1.93.3 diff --git a/src/buildstream/_stream.py b/src/buildstream/_stream.py index 09e6dfb17..48390ba14 100644 --- a/src/buildstream/_stream.py +++ b/src/buildstream/_stream.py @@ -205,13 +205,6 @@ class Stream: if unique_id and element is None: element = Plugin._lookup(unique_id) - # Assert we have everything we need built, using the element - # definitions to control the execution environment only. - if scope == Scope.BUILD and not element._has_all_sources_in_source_cache(): - raise StreamError( - "Sources for element {} are not cached." "Element must be fetched.".format(element._get_full_name()) - ) - missing_deps = [dep for dep in self._pipeline.dependencies([element], scope) if not dep._cached()] if missing_deps: if not pull_dependencies: @@ -251,6 +244,11 @@ class Stream: else: buildtree = True + # Ensure we have our sources if we are launching a build shell + if scope == Scope.BUILD and not buildtree: + self._fetch([element]) + self._pipeline.assert_sources_cached([element]) + return element._shell( scope, mounts=mounts, isolate=isolate, prompt=prompt, command=command, usebuildtree=buildtree ) diff --git a/tests/integration/shell.py b/tests/integration/shell.py index 7fa742f41..11aba87da 100644 --- a/tests/integration/shell.py +++ b/tests/integration/shell.py @@ -2,6 +2,8 @@ # pylint: disable=redefined-outer-name import os +import uuid + import pytest from buildstream import _yaml @@ -299,9 +301,6 @@ def test_workspace_visible(cli, datafiles): # Cat the hello.c file from a bst shell command, and assert # that we got the same content here # - result = cli.run(project=project, args=["source", "fetch", element_name]) - assert result.exit_code == 0 - result = cli.run(project=project, args=["shell", "--build", element_name, "--", "cat", "hello.c"]) assert result.exit_code == 0 assert result.output == workspace_hello @@ -400,3 +399,38 @@ def test_integration_partial_artifact(cli, datafiles, tmpdir, integration_cache) result = cli.run(project=project, args=["shell", "--pull", element_name, "--", "hello"]) result.assert_success() assert "autotools/amhello.bst" in result.get_pulled_elements() + + +# Test that the sources are fetched automatically when opening a build shell +@pytest.mark.datafiles(DATA_DIR) +@pytest.mark.skipif(not HAVE_SANDBOX, reason="Only available with a functioning sandbox") +def test_build_shell_fetch(cli, datafiles): + project = str(datafiles) + element_name = "build-shell-fetch.bst" + + # Create a file with unique contents such that it cannot be in the cache already + test_filepath = os.path.join(project, "files", "hello.txt") + test_message = "Hello World! {}".format(uuid.uuid4()) + with open(test_filepath, "w") as f: + f.write(test_message) + checksum = utils.sha256sum(test_filepath) + + # Create an element that has this unique file as a source + element = { + "kind": "manual", + "depends": ["base.bst"], + "sources": [{"kind": "remote", "url": "project_dir:/files/hello.txt", "ref": checksum}], + } + _yaml.roundtrip_dump(element, os.path.join(project, "elements", element_name)) + + # Ensure our dependencies are cached + result = cli.run(project=project, args=["build", "base.bst"]) + result.assert_success() + + # Ensure our sources are not cached + assert cli.get_element_state(project, element_name) == "fetch needed" + + # Launching a shell should fetch any uncached sources + result = cli.run(project=project, args=["shell", "--build", element_name, "cat", "hello.txt"]) + result.assert_success() + assert result.output == test_message -- cgit v1.2.1