import os import pytest import tarfile from pathlib import Path from tests.testutils import cli from buildstream import utils, _yaml from buildstream._exceptions import ErrorDomain, LoadErrorReason # Project directory DATA_DIR = os.path.join( os.path.dirname(os.path.realpath(__file__)), 'project', ) def generate_remote_import_element(input_path, output_path): return { 'kind': 'import', 'sources': [ { 'kind': 'remote', 'url': 'file://{}'.format(input_path), 'filename': output_path, 'ref': utils.sha256sum(input_path), } ] } @pytest.mark.datafiles(DATA_DIR) @pytest.mark.parametrize( "with_workspace,guess_element", [(True, True), (True, False), (False, False)], ids=["workspace-guess", "workspace-no-guess", "no-workspace-no-guess"] ) def test_source_checkout(datafiles, cli, tmpdir_factory, with_workspace, guess_element): tmpdir = tmpdir_factory.mktemp("") project = os.path.join(datafiles.dirname, datafiles.basename) checkout = os.path.join(cli.directory, 'source-checkout') target = 'checkout-deps.bst' workspace = os.path.join(str(tmpdir), 'workspace') elm_cmd = [target] if not guess_element else [] if with_workspace: ws_cmd = ['-C', workspace] result = cli.run(project=project, args=["workspace", "open", "--directory", workspace, target]) result.assert_success() else: ws_cmd = [] args = ws_cmd + ['source', 'checkout', '--deps', 'none'] + elm_cmd + [checkout] result = cli.run(project=project, args=args) result.assert_success() assert os.path.exists(os.path.join(checkout, 'checkout-deps', 'etc', 'buildstream', 'config')) @pytest.mark.datafiles(DATA_DIR) @pytest.mark.parametrize('force_flag', ['--force', '-f']) def test_source_checkout_force(datafiles, cli, force_flag): project = os.path.join(datafiles.dirname, datafiles.basename) checkout = os.path.join(cli.directory, 'source-checkout') target = 'checkout-deps.bst' os.makedirs(os.path.join(checkout, 'some-thing')) # Path(os.path.join(checkout, 'some-file')).touch() result = cli.run(project=project, args=['source', 'checkout', force_flag, target, '--deps', 'none', checkout]) result.assert_success() assert os.path.exists(os.path.join(checkout, 'checkout-deps', 'etc', 'buildstream', 'config')) @pytest.mark.datafiles(DATA_DIR) def test_source_checkout_tar(datafiles, cli): project = os.path.join(datafiles.dirname, datafiles.basename) checkout = os.path.join(cli.directory, 'source-checkout.tar') target = 'checkout-deps.bst' result = cli.run(project=project, args=['source', 'checkout', '--tar', target, '--deps', 'none', checkout]) result.assert_success() assert os.path.exists(checkout) with tarfile.open(checkout) as tf: expected_content = os.path.join(checkout, 'checkout-deps', 'etc', 'buildstream', 'config') tar_members = [f.name for f in tf] for member in tar_members: assert member in expected_content @pytest.mark.datafiles(DATA_DIR) @pytest.mark.parametrize('deps', [('build'), ('none'), ('run'), ('all')]) def test_source_checkout_deps(datafiles, cli, deps): project = os.path.join(datafiles.dirname, datafiles.basename) checkout = os.path.join(cli.directory, 'source-checkout') target = 'checkout-deps.bst' result = cli.run(project=project, args=['source', 'checkout', target, '--deps', deps, checkout]) result.assert_success() # Sources of the target if deps == 'build': assert not os.path.exists(os.path.join(checkout, 'checkout-deps')) else: assert os.path.exists(os.path.join(checkout, 'checkout-deps', 'etc', 'buildstream', 'config')) # Sources of the target's build dependencies if deps in ('build', 'all'): assert os.path.exists(os.path.join(checkout, 'import-dev', 'usr', 'include', 'pony.h')) else: assert not os.path.exists(os.path.join(checkout, 'import-dev')) # Sources of the target's runtime dependencies if deps in ('run', 'all'): assert os.path.exists(os.path.join(checkout, 'import-bin', 'usr', 'bin', 'hello')) else: assert not os.path.exists(os.path.join(checkout, 'import-bin')) @pytest.mark.datafiles(DATA_DIR) def test_source_checkout_except(datafiles, cli): project = os.path.join(datafiles.dirname, datafiles.basename) checkout = os.path.join(cli.directory, 'source-checkout') target = 'checkout-deps.bst' result = cli.run(project=project, args=['source', 'checkout', target, '--deps', 'all', '--except', 'import-bin.bst', checkout]) result.assert_success() # Sources for the target should be present assert os.path.exists(os.path.join(checkout, 'checkout-deps', 'etc', 'buildstream', 'config')) # Sources for import-bin.bst should not be present assert not os.path.exists(os.path.join(checkout, 'import-bin')) # Sources for other dependencies should be present assert os.path.exists(os.path.join(checkout, 'import-dev', 'usr', 'include', 'pony.h')) @pytest.mark.datafiles(DATA_DIR) @pytest.mark.parametrize('fetch', [(False), (True)]) def test_source_checkout_fetch(datafiles, cli, fetch): project = os.path.join(datafiles.dirname, datafiles.basename) checkout = os.path.join(cli.directory, 'source-checkout') target = 'remote-import-dev.bst' target_path = os.path.join(project, 'elements', target) # Create an element with remote source element = generate_remote_import_element( os.path.join(project, 'files', 'dev-files', 'usr', 'include', 'pony.h'), 'pony.h') _yaml.dump(element, target_path) # Testing --fetch option requires that we do not have the sources # cached already assert cli.get_element_state(project, target) == 'fetch needed' args = ['source', 'checkout'] if fetch: args += ['--fetch'] args += [target, checkout] result = cli.run(project=project, args=args) if fetch: result.assert_success() assert os.path.exists(os.path.join(checkout, 'remote-import-dev', 'pony.h')) else: result.assert_main_error(ErrorDomain.PIPELINE, 'uncached-sources') @pytest.mark.datafiles(DATA_DIR) def test_source_checkout_build_scripts(cli, tmpdir, datafiles): project_path = os.path.join(datafiles.dirname, datafiles.basename) element_name = 'source-bundle/source-bundle-hello.bst' normal_name = 'source-bundle-source-bundle-hello' checkout = os.path.join(str(tmpdir), 'source-checkout') args = ['source', 'checkout', '--include-build-scripts', element_name, checkout] result = cli.run(project=project_path, args=args) result.assert_success() # There sould be a script for each element (just one in this case) and a top level build script expected_scripts = ['build.sh', 'build-' + normal_name] for script in expected_scripts: assert script in os.listdir(checkout) @pytest.mark.datafiles(DATA_DIR) def test_source_checkout_tar_buildscripts(cli, tmpdir, datafiles): project_path = os.path.join(datafiles.dirname, datafiles.basename) element_name = 'source-bundle/source-bundle-hello.bst' normal_name = 'source-bundle-source-bundle-hello' tar_file = os.path.join(str(tmpdir), 'source-checkout.tar') args = ['source', 'checkout', '--include-build-scripts', '--tar', element_name, tar_file] result = cli.run(project=project_path, args=args) result.assert_success() expected_scripts = ['build.sh', 'build-' + normal_name] with tarfile.open(tar_file, 'r') as tf: for script in expected_scripts: assert script in tf.getnames()