You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@buildstream.apache.org by tv...@apache.org on 2021/02/04 07:24:31 UTC

[buildstream] 01/01: Allow junctions to inject dependencies from current project to junctioned one

This is an automated email from the ASF dual-hosted git repository.

tvb pushed a commit to branch valentindavid/junction-replacements-1.4
in repository https://gitbox.apache.org/repos/asf/buildstream.git

commit cd6d0572ef70b93636d7940d06ad0b13e0aca486
Author: Valentin David <va...@codethink.co.uk>
AuthorDate: Sun May 10 17:07:06 2020 +0200

    Allow junctions to inject dependencies from current project to junctioned one
    
    There are cases where downstream projects want to overwrite upstream
    elements.
    
    So far, either the downstream project just allows overlaps and hopes
    that ABI is compatible. There are also files left from original
    elements when not overwritten.
    
    Or downstream adds an "overlay" with local source to the
    junctions. However on the latter, elements in the overlay are
    considered as part of upstream, which means in cannot depend on
    element outside of upstream (unless cyclic junction maybe?).
    
    Here we add a feature to junctions to allow injecting elements from
    current project to junctions.
    
    This is useful for example in the case of GNOME SDK needing to override
    GLib, GObjectIntrospection, libsoup, etc. from Freedesktop SDK.
---
 buildstream/_loader/loader.py                         | 13 +++++++++++++
 buildstream/plugins/elements/junction.py              |  1 +
 tests/loader/junctions.py                             | 16 ++++++++++++++++
 tests/loader/junctions/replacements-base/a.bst        |  4 ++++
 tests/loader/junctions/replacements-base/compose.bst  |  3 +++
 tests/loader/junctions/replacements-base/original.txt |  1 +
 tests/loader/junctions/replacements-base/project.conf |  1 +
 tests/loader/junctions/replacements/base.bst          |  7 +++++++
 tests/loader/junctions/replacements/injected.bst      |  6 ++++++
 tests/loader/junctions/replacements/injected.txt      |  1 +
 tests/loader/junctions/replacements/project.conf      |  5 +++++
 tests/loader/junctions/replacements/stack.bst         |  3 +++
 12 files changed, 61 insertions(+)

diff --git a/buildstream/_loader/loader.py b/buildstream/_loader/loader.py
index ec929ea..dc15109 100644
--- a/buildstream/_loader/loader.py
+++ b/buildstream/_loader/loader.py
@@ -217,6 +217,13 @@ class Loader():
         if ticker:
             ticker(filename)
 
+        if self.project.junction and filename in self.project.junction.replacements:
+            replacement = _yaml.node_get(self.project.junction.replacements, str, filename)
+            elt = self._parent._load_file(replacement,
+                                          rewritable, ticker, fetch_subprojects, provenance=provenance)
+            self._elements[filename] = elt
+            return elt
+
         # Load the data and process any conditional statements therein
         fullpath = os.path.join(self._basedir, filename)
         try:
@@ -311,6 +318,8 @@ class Loader():
             validated = {}
 
         element = self._elements[element_name]
+        if getattr(element, '_loader', self) != self:
+            return element._loader._check_circular_deps(element.name, check_elements, validated)
 
         # element name must be unique across projects
         # to be usable as key for the check_elements and validated dicts
@@ -353,6 +362,8 @@ class Loader():
             visited = {}
 
         element = self._elements[element_name]
+        if getattr(element, '_loader', self) != self:
+            return element._loader._sort_dependencies(element.name, visited)
 
         # element name must be unique across projects
         # to be usable as key for the visited dict
@@ -424,6 +435,8 @@ class Loader():
     def _collect_element(self, element_name):
 
         element = self._elements[element_name]
+        if element._loader != self:
+            return element._loader._collect_element(element.name)
 
         # Return the already built one, if we already built it
         meta_element = self._meta_elements.get(element_name)
diff --git a/buildstream/plugins/elements/junction.py b/buildstream/plugins/elements/junction.py
index d2c62fe..f87ac22 100644
--- a/buildstream/plugins/elements/junction.py
+++ b/buildstream/plugins/elements/junction.py
@@ -142,6 +142,7 @@ class JunctionElement(Element):
     def configure(self, node):
         self.path = self.node_get_member(node, str, 'path', default='')
         self.options = self.node_get_member(node, Mapping, 'options', default={})
+        self.replacements = self.node_get_member(node, Mapping, 'replacements', default={})
 
     def preflight(self):
         pass
diff --git a/tests/loader/junctions.py b/tests/loader/junctions.py
index aee1643..0daa7e9 100644
--- a/tests/loader/junctions.py
+++ b/tests/loader/junctions.py
@@ -330,3 +330,19 @@ def test_build_git_cross_junction_names(cli, tmpdir, datafiles):
 
     # Check that the checkout contains the expected files from both projects
     assert(os.path.exists(os.path.join(checkoutdir, 'base.txt')))
+
+
+@pytest.mark.datafiles(DATA_DIR)
+def test_replacements(cli, tmpdir, datafiles):
+    project = os.path.join(str(datafiles), "replacements")
+    copy_subprojects(project, datafiles, ["replacements-base"])
+    checkoutdir = os.path.join(str(tmpdir), "checkout")
+
+    # Build, checkout
+    result = cli.run(project=project, args=["build", "stack.bst"])
+    result.assert_success()
+    result = cli.run(project=project, args=["checkout", "stack.bst", checkoutdir])
+    result.assert_success()
+
+    assert os.path.exists(os.path.join(checkoutdir, "destination/injected.txt"))
+    assert not os.path.exists(os.path.join(checkoutdir, "original.txt"))
diff --git a/tests/loader/junctions/replacements-base/a.bst b/tests/loader/junctions/replacements-base/a.bst
new file mode 100644
index 0000000..61edc64
--- /dev/null
+++ b/tests/loader/junctions/replacements-base/a.bst
@@ -0,0 +1,4 @@
+kind: import
+sources:
+- kind: local
+  path: original.txt
diff --git a/tests/loader/junctions/replacements-base/compose.bst b/tests/loader/junctions/replacements-base/compose.bst
new file mode 100644
index 0000000..1b40242
--- /dev/null
+++ b/tests/loader/junctions/replacements-base/compose.bst
@@ -0,0 +1,3 @@
+kind: compose
+build-depends:
+- a.bst
diff --git a/tests/loader/junctions/replacements-base/original.txt b/tests/loader/junctions/replacements-base/original.txt
new file mode 100644
index 0000000..5762c89
--- /dev/null
+++ b/tests/loader/junctions/replacements-base/original.txt
@@ -0,0 +1 @@
+Original
diff --git a/tests/loader/junctions/replacements-base/project.conf b/tests/loader/junctions/replacements-base/project.conf
new file mode 100644
index 0000000..9e10eca
--- /dev/null
+++ b/tests/loader/junctions/replacements-base/project.conf
@@ -0,0 +1 @@
+name: replacements-base
diff --git a/tests/loader/junctions/replacements/base.bst b/tests/loader/junctions/replacements/base.bst
new file mode 100644
index 0000000..d128ae5
--- /dev/null
+++ b/tests/loader/junctions/replacements/base.bst
@@ -0,0 +1,7 @@
+kind: junction
+config:
+  replacements:
+    a.bst: injected.bst
+sources:
+- kind: local
+  path: replacements-base
diff --git a/tests/loader/junctions/replacements/injected.bst b/tests/loader/junctions/replacements/injected.bst
new file mode 100644
index 0000000..3f822c7
--- /dev/null
+++ b/tests/loader/junctions/replacements/injected.bst
@@ -0,0 +1,6 @@
+kind: import
+config:
+  target: "%{dest}"
+sources:
+- kind: local
+  path: injected.txt
diff --git a/tests/loader/junctions/replacements/injected.txt b/tests/loader/junctions/replacements/injected.txt
new file mode 100644
index 0000000..43a3eba
--- /dev/null
+++ b/tests/loader/junctions/replacements/injected.txt
@@ -0,0 +1 @@
+Injected
diff --git a/tests/loader/junctions/replacements/project.conf b/tests/loader/junctions/replacements/project.conf
new file mode 100644
index 0000000..b552209
--- /dev/null
+++ b/tests/loader/junctions/replacements/project.conf
@@ -0,0 +1,5 @@
+name: replacements
+
+variables:
+  # This variable is not defined in the junctioned project
+  dest: "/destination"
diff --git a/tests/loader/junctions/replacements/stack.bst b/tests/loader/junctions/replacements/stack.bst
new file mode 100644
index 0000000..0ab52e8
--- /dev/null
+++ b/tests/loader/junctions/replacements/stack.bst
@@ -0,0 +1,3 @@
+kind: stack
+runtime-depends:
+- base.bst:compose.bst