summaryrefslogtreecommitdiff
path: root/src/buildstream/_loader/loadcontext.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/buildstream/_loader/loadcontext.py')
-rw-r--r--src/buildstream/_loader/loadcontext.py49
1 files changed, 37 insertions, 12 deletions
diff --git a/src/buildstream/_loader/loadcontext.py b/src/buildstream/_loader/loadcontext.py
index c6d256050..6183a192b 100644
--- a/src/buildstream/_loader/loadcontext.py
+++ b/src/buildstream/_loader/loadcontext.py
@@ -55,25 +55,29 @@ class ProjectLoaders:
#
def assert_loaders(self):
duplicates = {}
+ internal = {}
primary = []
for loader in self._collect:
- duplicating = self._search_duplicates(loader)
+ duplicating, internalizing = self._search_project_relationships(loader)
if duplicating:
duplicates[loader] = duplicating
- else:
+ if internalizing:
+ internal[loader] = internalizing
+
+ if not (duplicating or internalizing):
primary.append(loader)
if len(primary) > 1:
- self._raise_conflict(duplicates)
+ self._raise_conflict(duplicates, internal)
elif primary and duplicates:
- self._raise_conflict(duplicates)
+ self._raise_conflict(duplicates, internal)
- # _search_duplicates()
+ # _search_project_relationships()
#
# Searches this loader's ancestry for projects which mark this
- # loader as a duplicate.
+ # loader as internal or duplicate
#
# Args:
# loader (Loader): The loader to search for duplicate markers of
@@ -81,13 +85,18 @@ class ProjectLoaders:
# Returns:
# (list): A list of Loader objects who's project has marked
# this junction as a duplicate
+ # (list): A list of Loader objects who's project has marked
+ # this junction as internal
#
- def _search_duplicates(self, loader):
+ def _search_project_relationships(self, loader):
duplicates = []
+ internal = []
for parent in loader.ancestors():
if parent.project.junction_is_duplicated(self._name, loader):
duplicates.append(parent)
- return duplicates
+ if parent.project.junction_is_internal(loader):
+ internal.append(parent)
+ return duplicates, internal
# _raise_conflict()
#
@@ -98,16 +107,24 @@ class ProjectLoaders:
# Args:
# duplicates (dict): A table of duplicating Loaders, indexed
# by duplicated Loader
+ # internals (dict): A table of Loaders which mark a loader as internal,
+ # indexed by internal Loader
#
# Raises:
# (LoadError): In case there is a CONFLICTING_JUNCTION error
#
- def _raise_conflict(self, duplicates):
- lines = [self._loader_description(loader, duplicates) for loader in self._collect]
+ def _raise_conflict(self, duplicates, internals):
+ explanation = (
+ "Internal projects do not cause any conflicts. Conflicts can also be avoided\n"
+ + "by marking every instance of the project as a duplicate."
+ )
+ lines = [self._loader_description(loader, duplicates, internals) for loader in self._collect]
+ detail = "{}\n{}".format("\n".join(lines), explanation)
+
raise LoadError(
"Project '{}' was loaded in multiple contexts".format(self._name),
LoadErrorReason.CONFLICTING_JUNCTION,
- detail="\n".join(lines),
+ detail=detail,
)
# _loader_description()
@@ -116,11 +133,13 @@ class ProjectLoaders:
# loader (Loader): The loader to describe
# duplicates (dict): A table of duplicating Loaders, indexed
# by duplicated Loader
+ # internals (dict): A table of Loaders which mark a loader as internal,
+ # indexed by internal Loader
#
# Returns:
# (str): A string representing how this loader was loaded
#
- def _loader_description(self, loader, duplicates):
+ def _loader_description(self, loader, duplicates, internals):
line = "{}\n".format(loader)
@@ -130,6 +149,12 @@ class ProjectLoaders:
for dup in duplicating:
line += " Duplicated by: {}\n".format(dup)
+ # Mention projects which have marked this project as internal
+ internalizing = internals.get(loader)
+ if internalizing:
+ for internal in internalizing:
+ line += " Internal to: {}\n".format(internal)
+
return line