summaryrefslogtreecommitdiff
path: root/buildstream
diff options
context:
space:
mode:
authorJosh Smith <joshsmith@codethink.co.uk>2018-08-03 11:32:29 +0100
committerJosh Smith <qinusty@gmail.com>2018-08-15 12:15:58 +0100
commitf3d58233793cf0249cbac51f72d5c459eb256d44 (patch)
tree1ac54367e79ac7ac3e53f5e66484d05e916b7237 /buildstream
parent9f675c640d47e844712cb8917018fda163d5e070 (diff)
downloadbuildstream-f3d58233793cf0249cbac51f72d5c459eb256d44.tar.gz
_project.py: Add fatal-warnings configuration item
This allows for users to configure fatal-warnings to be either a list of warnings. This commit deprecates the use of fail-on-overlap within project.conf, this will now use the fatal-warnings configuration item. element.py: Cache key calculation now takes into account all of the fatal-warnings tests: This modifys the tests/frontend/overlaps.py tests to support the new fatal-warnings configuration. Backwards compatibility is also tested for `fail-on-overlap` _versions.py: BST_FORMAT_VERSION bumped to 15 for fatal-warnings BST_CORE_ARTIFACT_VERSION bumpted to 5 for fatal-warnings Fixes: #526
Diffstat (limited to 'buildstream')
-rw-r--r--buildstream/_project.py42
-rw-r--r--buildstream/_versions.py4
-rw-r--r--buildstream/data/projectconfig.yaml4
-rw-r--r--buildstream/element.py26
-rw-r--r--buildstream/plugin.py64
5 files changed, 108 insertions, 32 deletions
diff --git a/buildstream/_project.py b/buildstream/_project.py
index 951662e2b..702fd81f4 100644
--- a/buildstream/_project.py
+++ b/buildstream/_project.py
@@ -31,6 +31,7 @@ from ._options import OptionPool
from ._artifactcache import ArtifactCache
from ._elementfactory import ElementFactory
from ._sourcefactory import SourceFactory
+from .plugin import CoreWarnings
from ._projectrefs import ProjectRefs, ProjectRefStorage
from ._versions import BST_FORMAT_VERSION
from ._loader import Loader
@@ -105,7 +106,7 @@ class Project():
self.first_pass_config = ProjectConfig()
self.junction = junction # The junction Element object, if this is a subproject
- self.fail_on_overlap = False # Whether overlaps are treated as errors
+
self.ref_storage = None # ProjectRefStorage setting
self.base_environment = {} # The base set of environment variables
self.base_env_nocache = None # The base nocache mask (list) for the environment
@@ -120,6 +121,8 @@ class Project():
self._cli_options = cli_options
self._cache_key = None
+ self._fatal_warnings = [] # A list of warnings which should trigger an error
+
self._shell_command = [] # The default interactive shell command
self._shell_environment = {} # Statically set environment vars
self._shell_host_files = [] # A list of HostMount objects
@@ -456,7 +459,7 @@ class Project():
'split-rules', 'elements', 'plugins',
'aliases', 'name',
'artifacts', 'options',
- 'fail-on-overlap', 'shell',
+ 'fail-on-overlap', 'shell', 'fatal-warnings',
'ref-storage', 'sandbox', 'mirrors'
])
@@ -478,8 +481,25 @@ class Project():
# Load project split rules
self._splits = _yaml.node_get(config, Mapping, 'split-rules')
- # Fail on overlap
- self.fail_on_overlap = _yaml.node_get(config, bool, 'fail-on-overlap')
+ # Fatal warnings
+ self._fatal_warnings = _yaml.node_get(config, list, 'fatal-warnings', default_value=[])
+
+ # Support backwards compatibility for fail-on-overlap
+ fail_on_overlap = _yaml.node_get(config, bool, 'fail-on-overlap', default_value=None)
+
+ if (CoreWarnings.OVERLAPS not in self._fatal_warnings) and fail_on_overlap:
+ self._fatal_warnings.append(CoreWarnings.OVERLAPS)
+
+ # Deprecation check
+ if fail_on_overlap is not None:
+ self._context.message(
+ Message(
+ None,
+ MessageType.WARN,
+ "Use of fail-on-overlap within project.conf " +
+ "is deprecated. Consider using fatal-warnings instead."
+ )
+ )
# Load project.refs if it exists, this may be ignored.
if self.ref_storage == ProjectRefStorage.PROJECT_REFS:
@@ -712,3 +732,17 @@ class Project():
# paths are passed in relative to the project, but must be absolute
origin_dict['path'] = os.path.join(self.directory, path)
destination.append(origin_dict)
+
+ # _warning_is_fatal():
+ #
+ # Returns true if the warning in question should be considered fatal based on
+ # the project configuration.
+ #
+ # Args:
+ # warning_str (str): The warning configuration string to check against
+ #
+ # Returns:
+ # (bool): True if the warning should be considered fatal and cause an error.
+ #
+ def _warning_is_fatal(self, warning_str):
+ return warning_str in self._fatal_warnings
diff --git a/buildstream/_versions.py b/buildstream/_versions.py
index 3f32847ae..a722e11a5 100644
--- a/buildstream/_versions.py
+++ b/buildstream/_versions.py
@@ -23,7 +23,7 @@
# This version is bumped whenever enhancements are made
# to the `project.conf` format or the core element format.
#
-BST_FORMAT_VERSION = 14
+BST_FORMAT_VERSION = 15
# The base BuildStream artifact version
@@ -33,4 +33,4 @@ BST_FORMAT_VERSION = 14
# or if buildstream was changed in a way which can cause
# the same cache key to produce something that is no longer
# the same.
-BST_CORE_ARTIFACT_VERSION = 4
+BST_CORE_ARTIFACT_VERSION = 5
diff --git a/buildstream/data/projectconfig.yaml b/buildstream/data/projectconfig.yaml
index b4ad2dcb9..686040ee0 100644
--- a/buildstream/data/projectconfig.yaml
+++ b/buildstream/data/projectconfig.yaml
@@ -13,10 +13,6 @@ element-path: .
# Store source references in element files
ref-storage: inline
-# Overlaps are just warnings
-fail-on-overlap: False
-
-
# Variable Configuration
#
variables:
diff --git a/buildstream/element.py b/buildstream/element.py
index a099e934b..bb205c777 100644
--- a/buildstream/element.py
+++ b/buildstream/element.py
@@ -94,6 +94,7 @@ from . import _cachekey
from . import _signals
from . import _site
from ._platform import Platform
+from .plugin import CoreWarnings
from .sandbox._config import SandboxConfig
from .storage.directory import Directory
@@ -746,32 +747,23 @@ class Element(Plugin):
ignored[dep.name] = result.ignored
if overlaps:
- overlap_error = overlap_warning = False
- error_detail = warning_detail = "Staged files overwrite existing files in staging area:\n"
+ overlap_warning = False
+ warning_detail = "Staged files overwrite existing files in staging area:\n"
for f, elements in overlaps.items():
- overlap_error_elements = []
overlap_warning_elements = []
# The bottom item overlaps nothing
overlapping_elements = elements[1:]
for elm in overlapping_elements:
element = self.search(scope, elm)
- element_project = element._get_project()
if not element.__file_is_whitelisted(f):
- if element_project.fail_on_overlap:
- overlap_error_elements.append(elm)
- overlap_error = True
- else:
- overlap_warning_elements.append(elm)
- overlap_warning = True
+ overlap_warning_elements.append(elm)
+ overlap_warning = True
warning_detail += _overlap_error_detail(f, overlap_warning_elements, elements)
- error_detail += _overlap_error_detail(f, overlap_error_elements, elements)
if overlap_warning:
- self.warn("Non-whitelisted overlaps detected", detail=warning_detail)
- if overlap_error:
- raise ElementError("Non-whitelisted overlaps detected and fail-on-overlaps is set",
- detail=error_detail, reason="overlap-error")
+ self.warn("Non-whitelisted overlaps detected", detail=warning_detail,
+ warning_token=CoreWarnings.OVERLAPS)
if ignored:
detail = "Not staging files which would replace non-empty directories:\n"
@@ -2054,9 +2046,7 @@ class Element(Plugin):
'cache': type(self.__artifacts).__name__
}
- # fail-on-overlap setting cannot affect elements without dependencies
- if project.fail_on_overlap and dependencies:
- self.__cache_key_dict['fail-on-overlap'] = True
+ self.__cache_key_dict['fatal-warnings'] = sorted(project._fatal_warnings)
cache_key_dict = self.__cache_key_dict.copy()
cache_key_dict['dependencies'] = dependencies
diff --git a/buildstream/plugin.py b/buildstream/plugin.py
index 836b60834..64b38ff99 100644
--- a/buildstream/plugin.py
+++ b/buildstream/plugin.py
@@ -166,7 +166,6 @@ class Plugin():
# Infer the kind identifier
modulename = type(self).__module__
self.__kind = modulename.split('.')[-1]
-
self.debug("Created: {}".format(self))
def __del__(self):
@@ -473,14 +472,28 @@ class Plugin():
"""
self.__message(MessageType.INFO, brief, detail=detail)
- def warn(self, brief, *, detail=None):
- """Print a warning message
+ 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
"""
- self.__message(MessageType.WARN, brief, detail=detail)
+ 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):
+ raise PluginError(message="{}\n{}".format(brief, detail), reason=warning_token)
+
+ self.__message(MessageType.WARN, brief=brief, detail=detail)
def log(self, brief, *, detail=None):
"""Log a message into the plugin's log file
@@ -709,6 +722,32 @@ class Plugin():
return self.name
+class CoreWarnings():
+ """CoreWarnings()
+
+ Some common warnings which are raised by core functionalities within BuildStream are found in this class.
+ """
+
+ OVERLAPS = "overlaps"
+ """
+ This warning will be produced when buildstream detects an overlap on an element
+ which is not whitelisted.
+ """
+
+ REF_NOT_IN_TRACK = "ref-not-in-track"
+ """
+ This warning will be produced when a source is configured with a reference
+ which is found to be invalid based on the configured track
+ """
+
+
+__CORE_WARNINGS = [
+ value
+ for name, value in CoreWarnings.__dict__.items()
+ if not name.startswith("__")
+]
+
+
# Hold on to a lookup table by counter of all instantiated plugins.
# We use this to send the id back from child processes so we can lookup
# corresponding element/source in the master process.
@@ -739,6 +778,23 @@ def _plugin_lookup(unique_id):
return __PLUGINS_TABLE[unique_id]
+# _prefix_warning():
+#
+# Prefix a warning with the plugin kind. CoreWarnings are not prefixed.
+#
+# Args:
+# plugin (Plugin): The plugin which raised the warning
+# warning (str): The warning to prefix
+#
+# Returns:
+# (str): A prefixed warning
+#
+def _prefix_warning(plugin, warning):
+ if any((warning is core_warning for core_warning in __CORE_WARNINGS)):
+ return warning
+ return "{}:{}".format(plugin.get_kind(), warning)
+
+
# No need for unregister, WeakValueDictionary() will remove entries
# in itself when the referenced plugins are garbage collected.
def _plugin_register(plugin):