You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@buildstream.apache.org by ju...@apache.org on 2025/11/21 14:20:04 UTC
(buildstream) branch jbilleter/links created (now 78c3e4718)
This is an automated email from the ASF dual-hosted git repository.
juergbi pushed a change to branch jbilleter/links
in repository https://gitbox.apache.org/repos/asf/buildstream.git
at 78c3e4718 tests/format/link.py: Add test for multiple links with the same target
This branch includes the following new commits:
new 4392664c5 _loader: Drop unused dependency list
new 0dc98c02c _loader: Merge duplicate dependencies via link elements
new 78c3e4718 tests/format/link.py: Add test for multiple links with the same target
The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
(buildstream) 01/03: _loader: Drop unused dependency list
Posted by ju...@apache.org.
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 4392664c500364a5850fe16ce6dd8facbf6e6854
Author: Jürg Billeter <j...@bitron.ch>
AuthorDate: Fri Nov 21 14:55:30 2025 +0100
_loader: Drop unused dependency list
---
src/buildstream/_loader/loader.py | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/src/buildstream/_loader/loader.py b/src/buildstream/_loader/loader.py
index b36dfe068..42a7eb4a4 100644
--- a/src/buildstream/_loader/loader.py
+++ b/src/buildstream/_loader/loader.py
@@ -495,8 +495,7 @@ class Loader:
# The loader queue is a stack of tuples
# [0] is the LoadElement instance
# [1] is a stack of Dependency objects to load
- # [2] is a list of dependency names used to warn when all deps are loaded
- loader_queue = [(top_element, list(reversed(dependencies)), [])]
+ loader_queue = [(top_element, list(reversed(dependencies)))]
# Load all dependency files for the new LoadElement
while loader_queue:
@@ -505,8 +504,6 @@ class Loader:
# Process the first dependency of the last loaded element
dep = current_element[1].pop()
- # And record its name for checking later
- current_element[2].append(dep.name)
if dep.junction:
loader = self.get_loader(dep.junction, dep.node)
@@ -529,7 +526,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
(buildstream) 02/03: _loader: Merge duplicate dependencies via link elements
Posted by ju...@apache.org.
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 0dc98c02c0890f4c25e6aab9f54a77b2fe61bcd8
Author: Jürg Billeter <j...@bitron.ch>
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..1e4843242 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()
(buildstream) 03/03: tests/format/link.py: Add test for multiple links with the same target
Posted by ju...@apache.org.
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 78c3e47184071f8b9489062e13b176c37e4efb34
Author: Jürg Billeter <j...@bitron.ch>
AuthorDate: Fri Nov 21 10:28:02 2025 +0100
tests/format/link.py: Add test for multiple links with the same target
This is a regression test for #2002.
---
tests/format/link.py | 20 ++++++++++++++++++++
.../elements/hello-link-1.bst | 4 ++++
.../elements/hello-link-2.bst | 4 ++++
.../multiple-links-same-target/elements/hello.bst | 5 +++++
.../multiple-links-same-target/elements/target.bst | 5 +++++
.../link/multiple-links-same-target/files/hello.txt | 1 +
.../link/multiple-links-same-target/project.conf | 4 ++++
7 files changed, 43 insertions(+)
diff --git a/tests/format/link.py b/tests/format/link.py
index fee6de37b..ee8136bca 100644
--- a/tests/format/link.py
+++ b/tests/format/link.py
@@ -198,3 +198,23 @@ def test_cross_link_junction_include(cli, tmpdir, datafiles):
# Read back some of our project defaults from the env
variables = _yaml.load_data(result.output)
assert variables.get_str("test") == "the test"
+
+
+#
+# Test two links to the same element, both links are dependencies of the build target.
+#
+@pytest.mark.datafiles(DATA_DIR)
+def test_multiple_links_same_target(cli, tmpdir, datafiles):
+ project = os.path.join(str(datafiles), "multiple-links-same-target")
+ checkoutdir = os.path.join(str(tmpdir), "checkout")
+
+ target = "target.bst"
+
+ # Build, checkout
+ result = cli.run(project=project, args=["build", target])
+ result.assert_success()
+ result = cli.run(project=project, args=["artifact", "checkout", target, "--directory", checkoutdir])
+ result.assert_success()
+
+ # Check that the checkout contains the expected files from sub-sub-project
+ assert os.path.exists(os.path.join(checkoutdir, "hello.txt"))
diff --git a/tests/format/link/multiple-links-same-target/elements/hello-link-1.bst b/tests/format/link/multiple-links-same-target/elements/hello-link-1.bst
new file mode 100644
index 000000000..83b0fbe46
--- /dev/null
+++ b/tests/format/link/multiple-links-same-target/elements/hello-link-1.bst
@@ -0,0 +1,4 @@
+kind: link
+
+config:
+ target: hello.bst
diff --git a/tests/format/link/multiple-links-same-target/elements/hello-link-2.bst b/tests/format/link/multiple-links-same-target/elements/hello-link-2.bst
new file mode 100644
index 000000000..83b0fbe46
--- /dev/null
+++ b/tests/format/link/multiple-links-same-target/elements/hello-link-2.bst
@@ -0,0 +1,4 @@
+kind: link
+
+config:
+ target: hello.bst
diff --git a/tests/format/link/multiple-links-same-target/elements/hello.bst b/tests/format/link/multiple-links-same-target/elements/hello.bst
new file mode 100644
index 000000000..a04a856cd
--- /dev/null
+++ b/tests/format/link/multiple-links-same-target/elements/hello.bst
@@ -0,0 +1,5 @@
+kind: import
+
+sources:
+- kind: local
+ path: files/hello.txt
diff --git a/tests/format/link/multiple-links-same-target/elements/target.bst b/tests/format/link/multiple-links-same-target/elements/target.bst
new file mode 100644
index 000000000..a547ef44b
--- /dev/null
+++ b/tests/format/link/multiple-links-same-target/elements/target.bst
@@ -0,0 +1,5 @@
+kind: stack
+
+depends:
+- hello-link-1.bst
+- hello-link-2.bst
diff --git a/tests/format/link/multiple-links-same-target/files/hello.txt b/tests/format/link/multiple-links-same-target/files/hello.txt
new file mode 100644
index 000000000..ce0136250
--- /dev/null
+++ b/tests/format/link/multiple-links-same-target/files/hello.txt
@@ -0,0 +1 @@
+hello
diff --git a/tests/format/link/multiple-links-same-target/project.conf b/tests/format/link/multiple-links-same-target/project.conf
new file mode 100644
index 000000000..12a1b2551
--- /dev/null
+++ b/tests/format/link/multiple-links-same-target/project.conf
@@ -0,0 +1,4 @@
+name: multiple-links-single-target
+min-version: 2.0
+
+element-path: elements