This is an automated email from the ASF dual-hosted git repository. juergbi pushed a commit to branch jbilleter/links in repository https://gitbox.apache.org/repos/asf/buildstream.git
commit 9ed6aa573839c17cfa61c31e4e7efe4ef9cffe29 Author: Jürg Billeter <[email protected]> AuthorDate: Fri Nov 21 15:09:52 2025 +0100 _loader: Merge duplicate dependencies via link elements Duplicate dependencies are normally merged already in `extract_depends_from_node()`. However, that only works for dependencies that are declared with the same filename. If a link element is in a dependency list, merging may still be required but can be done only after the link element has been loaded. The element state updates don't work correctly if there are duplicate dependencies that aren't merged. Fixes #2002. --- src/buildstream/_loader/loadelement.pyx | 2 +- src/buildstream/_loader/loader.py | 15 ++++++++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/buildstream/_loader/loadelement.pyx b/src/buildstream/_loader/loadelement.pyx index 52e9a8ecd..f4ebb673c 100644 --- a/src/buildstream/_loader/loadelement.pyx +++ b/src/buildstream/_loader/loadelement.pyx @@ -202,7 +202,7 @@ cdef class Dependency: # Args: # other (Dependency): The dependency to merge into this one # - cdef merge(self, Dependency other): + cpdef merge(self, Dependency other): self.dep_type = self.dep_type | other.dep_type self.strict = self.strict or other.strict diff --git a/src/buildstream/_loader/loader.py b/src/buildstream/_loader/loader.py index 42a7eb4a4..25548dd81 100644 --- a/src/buildstream/_loader/loader.py +++ b/src/buildstream/_loader/loader.py @@ -495,7 +495,8 @@ class Loader: # The loader queue is a stack of tuples # [0] is the LoadElement instance # [1] is a stack of Dependency objects to load - loader_queue = [(top_element, list(reversed(dependencies)))] + # [2] is a Dict[LoadElement, Dependency] of loaded dependencies + loader_queue = [(top_element, list(reversed(dependencies)), {})] # Load all dependency files for the new LoadElement while loader_queue: @@ -526,7 +527,7 @@ class Loader: dep_element.mark_fully_loaded() dep_deps = extract_depends_from_node(dep_element.node) - loader_queue.append((dep_element, list(reversed(dep_deps)))) + loader_queue.append((dep_element, list(reversed(dep_deps)), {})) # Pylint is not very happy about Cython and can't understand 'node' is a 'MappingNode' if dep_element.node.get_str(Symbol.KIND) == "junction": # pylint: disable=no-member @@ -539,7 +540,15 @@ class Loader: # LoadElement on the dependency and append the dependency to the owning # LoadElement dependency list. dep.set_element(dep_element) - current_element[0].dependencies.append(dep) # pylint: disable=no-member + + dep_dict = current_element[2] + if dep.element in dep_dict: + # Duplicate LoadElement in dependency list, this can happen if a dependency is + # a link element that points to an element that is already a dependency. + dep_dict[dep.element].merge(dep) + else: + current_element[0].dependencies.append(dep) # pylint: disable=no-member + dep_dict[dep.element] = dep else: # And pop the element off the queue loader_queue.pop()
