Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • willsalmon/buildstream
  • CumHoleZH/buildstream
  • tchaik/buildstream
  • DCotyPortfolio/buildstream
  • jesusoctavioas/buildstream
  • patrickmmartin/buildstream
  • franred/buildstream
  • tintou/buildstream
  • alatiera/buildstream
  • martinblanchard/buildstream
  • neverdie22042524/buildstream
  • Mattlk13/buildstream
  • PServers/buildstream
  • phamnghia610909/buildstream
  • chiaratolentino/buildstream
  • eysz7-x-x/buildstream
  • kerrick1/buildstream
  • matthew-yates/buildstream
  • twofeathers/buildstream
  • mhadjimichael/buildstream
  • pointswaves/buildstream
  • Mr.JackWilson/buildstream
  • Tw3akG33k/buildstream
  • AlexFazakas/buildstream
  • eruidfkiy/buildstream
  • clamotion2/buildstream
  • nanonyme/buildstream
  • wickyjaaa/buildstream
  • nmanchev/buildstream
  • bojorquez.ja/buildstream
  • mostynb/buildstream
  • highpit74/buildstream
  • Demo112/buildstream
  • ba2014sheer/buildstream
  • tonimadrino/buildstream
  • usuario2o/buildstream
  • Angelika123456/buildstream
  • neo355/buildstream
  • corentin-ferlay/buildstream
  • coldtom/buildstream
  • wifitvbox81/buildstream
  • 358253885/buildstream
  • seanborg/buildstream
  • SotK/buildstream
  • DouglasWinship/buildstream
  • karansthr97/buildstream
  • louib/buildstream
  • bwh-ct/buildstream
  • robjh/buildstream
  • we88c0de/buildstream
  • zhengxian5555/buildstream
51 results
Show changes
Commits on Source (4)
......@@ -2,6 +2,10 @@
buildstream 1.3.1
=================
o BREAKING CHANGE: Attempting to use an element that does not have the `.bst`
extension, will result in an error message.
All elements must now be suffixed with `.bst`
o BREAKING CHANGE: The 'manual' element lost its default 'MAKEFLAGS' and 'V'
environment variables. There is already a 'make' element with the same
variables. Note that this is a breaking change, it will require users to
......
......@@ -27,7 +27,7 @@ from . import _cachekey
from . import _signals
from . import _site
from . import _yaml
from ._exceptions import LoadError, LoadErrorReason, BstError
from ._exceptions import LoadError, LoadErrorReason, BstError, PluginError
from ._message import Message, MessageType
from ._profile import Topics, profile_start, profile_end
from ._artifactcache import ArtifactCache
......@@ -142,6 +142,37 @@ class Context():
self._log_handle = None
self._log_filename = None
# Print a warning message, checks warning_token against project configuration
#
# Args:
# project (Project): The related project
# brief (str): The brief message
# detail (str): An optional detailed message, can be multiline output
# warning_token (str): An optional configurable warning assosciated with this warning,
# this will cause PluginError to be raised if this warning is configured as fatal.
# (*Since 1.4*)
#
# Raises:
# (:class:`.PluginError`): When warning_token is considered fatal by the project configuration
#
def warn(self, project, plugin, brief, *, detail=None, warning_token=None):
# TODO _prefix_warning should probably move somewhere else
from .plugin import _prefix_warning
if warning_token:
warning_token = _prefix_warning(plugin, warning_token)
brief = "[{}]: {}".format(warning_token, brief)
if project._warning_is_fatal(warning_token):
detail = detail if detail else ""
raise PluginError(message="{}\n{}".format(brief, detail), reason=warning_token)
unique_id = None
if plugin:
unique_id = plugin._get_unique_id()
message = Message(unique_id, MessageType.WARN, brief, detail=detail)
self.message(message)
# load()
#
# Loads the configuration files
......
......@@ -109,7 +109,11 @@ def complete_target(args, incomplete):
if element_directory:
base_directory = os.path.join(base_directory, element_directory)
return complete_path("File", incomplete, base_directory=base_directory)
complete_list = []
for p in complete_path("File", incomplete, base_directory=base_directory):
if p.endswith(".bst ") or p.endswith("/") or p.endswith(".conf "):
complete_list.append(p)
return complete_list
def override_completions(cmd, cmd_param, args, incomplete):
......
......@@ -145,11 +145,14 @@ def _extract_depends_from_node(node, *, key=None):
depends = _yaml.node_get(node, list, key, default_value=[])
output_deps = []
invalid_elements = []
for index, dep in enumerate(depends):
dep_provenance = _yaml.node_get_provenance(node, key=key, indices=[index])
if isinstance(dep, str):
if not dep.endswith(".bst"):
invalid_elements.append(dep)
dependency = Dependency(dep, provenance=dep_provenance, dep_type=default_dep_type)
elif isinstance(dep, Mapping):
......@@ -182,6 +185,11 @@ def _extract_depends_from_node(node, *, key=None):
output_deps.append(dependency)
if invalid_elements:
raise LoadError(LoadErrorReason.INVALID_DATA,
"Target elements '{}' do not have expected file extension `.bst`\n"
"Improperly named elements will not be discoverable by commands".format(invalid_elements))
# Now delete the field, we dont want it anymore
del node[key]
......
......@@ -97,6 +97,7 @@ class Loader():
# Returns: The toplevel LoadElement
def load(self, targets, rewritable=False, ticker=None, fetch_subprojects=False):
invalid_elements = []
for filename in targets:
if os.path.isabs(filename):
# XXX Should this just be an assertion ?
......@@ -106,6 +107,18 @@ class Loader():
"path to the base project directory: {}"
.format(filename, self._basedir))
if not filename.endswith(".bst") and not filename.endswith("/") and not filename.endswith(".conf"):
invalid_elements.append(filename)
if invalid_elements:
# TODO CoreWarnings should probably move somewhere else
from ..plugin import CoreWarnings
self._context.warn(self.project, None,
"Target elements '{}' do not have expected file extension `.bst` "
"Improperly named elements will not be discoverable by commands"
.format(invalid_elements),
warning_token=CoreWarnings.BAD_ELEMENT_SUFFIX)
# First pass, recursively load files and populate our table of LoadElements
#
deps = []
......
......@@ -445,6 +445,9 @@ class Project():
self.config.options = OptionPool(self.element_path)
self.first_pass_config.options = OptionPool(self.element_path)
# Early initialise fatal warnings
self._fatal_warnings = _yaml.node_get(pre_config_node, list, 'fatal-warnings', default_value=[])
self.loader = Loader(self._context, self,
parent=parent_loader,
tempdir=tempdir)
......
......@@ -492,28 +492,8 @@ class Plugin():
self.__message(MessageType.INFO, brief, detail=detail)
def warn(self, brief, *, detail=None, warning_token=None):
"""Print a warning message, checks warning_token against project configuration
Args:
brief (str): The brief message
detail (str): An optional detailed message, can be multiline output
warning_token (str): An optional configurable warning assosciated with this warning,
this will cause PluginError to be raised if this warning is configured as fatal.
(*Since 1.4*)
Raises:
(:class:`.PluginError`): When warning_token is considered fatal by the project configuration
"""
if warning_token:
warning_token = _prefix_warning(self, warning_token)
brief = "[{}]: {}".format(warning_token, brief)
project = self._get_project()
if project._warning_is_fatal(warning_token):
detail = detail if detail else ""
raise PluginError(message="{}\n{}".format(brief, detail), reason=warning_token)
self.__message(MessageType.WARN, brief=brief, detail=detail)
context = self._get_context()
context.warn(self._get_project(), self, brief, detail=detail, warning_token=warning_token)
def log(self, brief, *, detail=None):
"""Log a message into the plugin's log file
......@@ -784,6 +764,12 @@ class CoreWarnings():
which is found to be invalid based on the configured track
"""
BAD_ELEMENT_SUFFIX = "bad-element-suffix"
"""
This warning will be produced when an element whose name doesn not end in .bst
is referenced either on the command line or by another element
"""
__CORE_WARNINGS = [
value
......
......@@ -66,6 +66,13 @@ PROJECT_ELEMENTS = [
"target.bst"
]
INVALID_ELEMENTS = [
"target.foo"
"target.bst.bar"
]
MIXED_ELEMENTS = PROJECT_ELEMENTS + INVALID_ELEMENTS
def assert_completion(cli, cmd, word_idx, expected, cwd=None):
result = cli.run(cwd=cwd, env={
......@@ -85,6 +92,24 @@ def assert_completion(cli, cmd, word_idx, expected, cwd=None):
assert words == expected
def assert_completion_failed(cli, cmd, word_idx, expected, cwd=None):
result = cli.run(cwd=cwd, env={
'_BST_COMPLETION': 'complete',
'COMP_WORDS': cmd,
'COMP_CWORD': str(word_idx)
})
words = []
if result.output:
words = result.output.splitlines()
# The order is meaningless, bash will
# take the results and order it by its
# own little heuristics
words = sorted(words)
expected = sorted(expected)
assert words != expected
@pytest.mark.parametrize("cmd,word_idx,expected", [
('bst', 0, []),
('bst ', 1, MAIN_COMMANDS),
......@@ -226,6 +251,19 @@ def test_argument_element(datafiles, cli, project, cmd, word_idx, expected, subd
assert_completion(cli, cmd, word_idx, expected, cwd=cwd)
@pytest.mark.datafiles(DATA_DIR)
@pytest.mark.parametrize("project,cmd,word_idx,expected,subdir", [
# When element has invalid suffix
('project', 'bst --directory ../ show ', 4, [e + ' ' for e in MIXED_ELEMENTS], 'files')
])
def test_argument_element_invalid(datafiles, cli, project, cmd, word_idx, expected, subdir):
cwd = os.path.join(str(datafiles), project)
if subdir:
cwd = os.path.join(cwd, subdir)
assert_completion_failed(cli, cmd, word_idx, expected, cwd=cwd)
@pytest.mark.parametrize("cmd,word_idx,expected", [
('bst he', 1, ['help ']),
('bst help ', 2, MAIN_COMMANDS),
......
......@@ -60,6 +60,31 @@ def test_build_checkout(datafiles, cli, strict, hardlinks):
assert os.path.exists(filename)
@pytest.mark.datafiles(DATA_DIR)
@pytest.mark.parametrize("strict,hardlinks", [
("non-strict", "hardlinks"),
])
def test_build_invalid_suffix(datafiles, cli, strict, hardlinks):
project = os.path.join(datafiles.dirname, datafiles.basename)
checkout = os.path.join(cli.directory, 'checkout')
result = cli.run(project=project, args=strict_args(['build', 'target.foo'], strict))
result.assert_main_error(ErrorDomain.LOAD, LoadErrorReason.INVALID_DATA)
@pytest.mark.datafiles(DATA_DIR)
@pytest.mark.parametrize("strict,hardlinks", [
("non-strict", "hardlinks"),
])
def test_build_invalid_suffix_dep(datafiles, cli, strict, hardlinks):
project = os.path.join(datafiles.dirname, datafiles.basename)
checkout = os.path.join(cli.directory, 'checkout')
# target2.bst depends on an element called target.foo
result = cli.run(project=project, args=strict_args(['build', 'target2.bst'], strict))
result.assert_main_error(ErrorDomain.LOAD, LoadErrorReason.INVALID_DATA)
@pytest.mark.datafiles(DATA_DIR)
@pytest.mark.parametrize("deps", [("run"), ("none")])
def test_build_checkout_deps(datafiles, cli, deps):
......
kind: stack
description: |
Main stack target for the bst build test
kind: stack
description: |
Main stack target for the bst build test
depends:
- target.foo
......@@ -33,7 +33,7 @@ def create_test_directory(*path, mode=0o644):
@pytest.mark.skipif(IS_LINUX and not HAVE_BWRAP, reason='Only available with bubblewrap on Linux')
def test_deterministic_source_umask(cli, tmpdir, datafiles, kind, integration_cache):
project = str(datafiles)
element_name = 'list'
element_name = 'list.bst'
element_path = os.path.join(project, 'elements', element_name)
repodir = os.path.join(str(tmpdir), 'repo')
sourcedir = os.path.join(project, 'source')
......@@ -108,7 +108,7 @@ def test_deterministic_source_local(cli, tmpdir, datafiles, integration_cache):
"""Only user rights should be considered for local source.
"""
project = str(datafiles)
element_name = 'test'
element_name = 'test.bst'
element_path = os.path.join(project, 'elements', element_name)
sourcedir = os.path.join(project, 'source')
......