diff options
author | James Ennis <james.ennis@codethink.com> | 2019-01-11 11:14:34 +0000 |
---|---|---|
committer | James Ennis <james.ennis@codethink.com> | 2019-01-17 12:36:02 +0000 |
commit | b8aea71b04b9a2c369997f606b5de25e7e00a85c (patch) | |
tree | 1b985b7cbeb3ffa3e5a616be8ce1017f2d116380 | |
parent | 0bdb5c111340713e88c97dc5ba29bca63bb502a3 (diff) | |
download | buildstream-jennis/new_artifact_subcommands.tar.gz |
cascache.py: Ensure path exists before trying to update the mtimejennis/new_artifact_subcommands
If an artifact is pulled from the cache without its buildtree,
CASCache.prune() will fail when it tries to update the mtimes
of the build tree's object files.
A new integration test has been added to tests/integration/artifact.py
which reflects this.
-rw-r--r-- | buildstream/_cas/cascache.py | 3 | ||||
-rw-r--r-- | tests/integration/artifact.py | 40 |
2 files changed, 43 insertions, 0 deletions
diff --git a/buildstream/_cas/cascache.py b/buildstream/_cas/cascache.py index f3eeb8876..8aa286225 100644 --- a/buildstream/_cas/cascache.py +++ b/buildstream/_cas/cascache.py @@ -740,6 +740,9 @@ class CASCache(): if tree.hash in reachable: return + if not os.path.exists(self.objpath(tree)): + return + if update_mtime: os.utime(self.objpath(tree)) diff --git a/tests/integration/artifact.py b/tests/integration/artifact.py index 607919e17..59f638741 100644 --- a/tests/integration/artifact.py +++ b/tests/integration/artifact.py @@ -180,3 +180,43 @@ def test_artifact_delete_unbuilt_artifact(cli, tmpdir, datafiles): expected_err = 'WARNING: {}, not found in local cache - no delete required\n'.format(artifact) assert result.stderr == expected_err + + +# Test that an artifact pulled from it's remote cache (without it's buildtree) will not +# throw an Exception when trying to prune the cache. +@pytest.mark.integration +@pytest.mark.datafiles(DATA_DIR) +@pytest.mark.skipif(IS_LINUX and not HAVE_BWRAP, reason='Only available with bubblewrap on Linux') +def test_artifact_delete_pulled_artifact_without_buildtree(cli, tmpdir, datafiles): + project = os.path.join(datafiles.dirname, datafiles.basename) + element = 'autotools/amhello.bst' + + # Set up remote and local shares + local_cache = os.path.join(str(tmpdir), 'artifacts') + with create_artifact_share(os.path.join(str(tmpdir), 'remote')) as remote: + cli.configure({ + 'artifacts': {'url': remote.repo, 'push': True}, + 'artifactdir': local_cache, + }) + + # Build the element + result = cli.run(project=project, args=['build', element]) + result.assert_success() + + # Make sure it's in the share + cache_key = cli.get_element_key(project, element) + assert remote.has_artifact('test', element, cache_key) + + # Delete and then pull the artifact (without its buildtree) + result = cli.run(project=project, args=['artifact', 'delete', element]) + result.assert_success() + assert cli.get_element_state(project, element) != 'cached' + result = cli.run(project=project, args=['pull', element]) + result.assert_success() + assert cli.get_element_state(project, element) == 'cached' + + # Now delete it again (it should have been pulled without the buildtree, but + # a digest of the buildtree is pointed to in the artifact's metadata + result = cli.run(project=project, args=['artifact', 'delete', element]) + result.assert_success() + assert cli.get_element_state(project, element) != 'cached' |