summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorValentin David <valentin.david@codethink.co.uk>2020-05-10 17:07:06 +0200
committerValentin David <valentin.david@codethink.co.uk>2020-05-11 11:15:56 +0200
commit0d081b63b153be27a9b346994b6996aa5b790f1b (patch)
tree995ad38f32a4d9e85bc911b0c187825f5228be90
parent14dd3598024b58e9e626897e7062dd9563a1502a (diff)
downloadbuildstream-valentindavid/junction-replacements.tar.gz
Allow junctions to inject dependencies from current project to junctioned onevalentindavid/junction-replacements
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.
-rw-r--r--src/buildstream/_loader/loader.py7
-rw-r--r--src/buildstream/plugins/elements/junction.py5
-rw-r--r--tests/format/junctions.py32
-rw-r--r--tests/format/junctions/replacements-base/a.bst4
-rw-r--r--tests/format/junctions/replacements-base/compose.bst3
-rw-r--r--tests/format/junctions/replacements-base/original.txt1
-rw-r--r--tests/format/junctions/replacements-base/project.conf2
-rw-r--r--tests/format/junctions/replacements/base.bst7
-rw-r--r--tests/format/junctions/replacements/injected.bst6
-rw-r--r--tests/format/junctions/replacements/injected.txt1
-rw-r--r--tests/format/junctions/replacements/project.conf6
-rw-r--r--tests/format/junctions/replacements/stack.bst3
12 files changed, 76 insertions, 1 deletions
diff --git a/src/buildstream/_loader/loader.py b/src/buildstream/_loader/loader.py
index 3032f9036..06e3fbfd5 100644
--- a/src/buildstream/_loader/loader.py
+++ b/src/buildstream/_loader/loader.py
@@ -311,6 +311,10 @@ class Loader:
if filename in self._elements:
return self._elements[filename]
+ if self.project.junction and filename in self.project.junction.replacements:
+ replacement = self.project.junction.replacements.get_str(filename)
+ return self._parent._load_file(replacement, rewritable, ticker, provenance)
+
# Call the ticker
if ticker:
ticker(filename)
@@ -339,6 +343,9 @@ class Loader:
dep.junction, rewritable=rewritable, ticker=ticker, provenance=dep.provenance
)
dep_element = loader._load_file(dep.name, rewritable, ticker, dep.provenance)
+ elif self.project.junction and dep.name in self.project.junction.replacements:
+ replacement = self.project.junction.replacements.get_str(dep.name)
+ dep_element = self._parent._load_file(replacement, rewritable, ticker, dep.provenance)
else:
dep_element = self._elements.get(dep.name)
diff --git a/src/buildstream/plugins/elements/junction.py b/src/buildstream/plugins/elements/junction.py
index 86d1de8f8..f450d67f1 100644
--- a/src/buildstream/plugins/elements/junction.py
+++ b/src/buildstream/plugins/elements/junction.py
@@ -173,7 +173,9 @@ class JunctionElement(Element):
def configure(self, node):
- node.validate_keys(["path", "options", "target", "cache-junction-elements", "ignore-junction-remotes"])
+ node.validate_keys(
+ ["path", "options", "target", "cache-junction-elements", "ignore-junction-remotes", "replacements"]
+ )
self.path = node.get_str("path", default="")
self.options = node.get_mapping("options", default={})
@@ -182,6 +184,7 @@ class JunctionElement(Element):
self.target_junction = None
self.cache_junction_elements = node.get_bool("cache-junction-elements", default=False)
self.ignore_junction_remotes = node.get_bool("ignore-junction-remotes", default=False)
+ self.replacements = node.get_mapping("replacements", default={})
def preflight(self):
# "target" cannot be used in conjunction with:
diff --git a/tests/format/junctions.py b/tests/format/junctions.py
index 70572ee3e..500d3f628 100644
--- a/tests/format/junctions.py
+++ b/tests/format/junctions.py
@@ -471,3 +471,35 @@ def test_junction_show(cli, tmpdir, datafiles):
# Show, assert that it says junction
assert cli.get_element_state(project, "base.bst") == "junction"
+
+
+@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=["artifact", "checkout", "stack.bst", "--directory", 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"))
+
+
+@pytest.mark.datafiles(DATA_DIR)
+def test_replacements_top_element(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", "base.bst:a.bst"])
+ result.assert_success()
+ result = cli.run(project=project, args=["artifact", "checkout", "base.bst:a.bst", "--directory", 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/format/junctions/replacements-base/a.bst b/tests/format/junctions/replacements-base/a.bst
new file mode 100644
index 000000000..61edc6467
--- /dev/null
+++ b/tests/format/junctions/replacements-base/a.bst
@@ -0,0 +1,4 @@
+kind: import
+sources:
+- kind: local
+ path: original.txt
diff --git a/tests/format/junctions/replacements-base/compose.bst b/tests/format/junctions/replacements-base/compose.bst
new file mode 100644
index 000000000..1b4024228
--- /dev/null
+++ b/tests/format/junctions/replacements-base/compose.bst
@@ -0,0 +1,3 @@
+kind: compose
+build-depends:
+- a.bst
diff --git a/tests/format/junctions/replacements-base/original.txt b/tests/format/junctions/replacements-base/original.txt
new file mode 100644
index 000000000..5762c898d
--- /dev/null
+++ b/tests/format/junctions/replacements-base/original.txt
@@ -0,0 +1 @@
+Original
diff --git a/tests/format/junctions/replacements-base/project.conf b/tests/format/junctions/replacements-base/project.conf
new file mode 100644
index 000000000..9f5c000c9
--- /dev/null
+++ b/tests/format/junctions/replacements-base/project.conf
@@ -0,0 +1,2 @@
+name: replacements-base
+min-version: 2.0
diff --git a/tests/format/junctions/replacements/base.bst b/tests/format/junctions/replacements/base.bst
new file mode 100644
index 000000000..d128ae54d
--- /dev/null
+++ b/tests/format/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/format/junctions/replacements/injected.bst b/tests/format/junctions/replacements/injected.bst
new file mode 100644
index 000000000..3f822c711
--- /dev/null
+++ b/tests/format/junctions/replacements/injected.bst
@@ -0,0 +1,6 @@
+kind: import
+config:
+ target: "%{dest}"
+sources:
+- kind: local
+ path: injected.txt
diff --git a/tests/format/junctions/replacements/injected.txt b/tests/format/junctions/replacements/injected.txt
new file mode 100644
index 000000000..43a3eba08
--- /dev/null
+++ b/tests/format/junctions/replacements/injected.txt
@@ -0,0 +1 @@
+Injected
diff --git a/tests/format/junctions/replacements/project.conf b/tests/format/junctions/replacements/project.conf
new file mode 100644
index 000000000..625eae6f2
--- /dev/null
+++ b/tests/format/junctions/replacements/project.conf
@@ -0,0 +1,6 @@
+name: replacements
+min-version: 2.0
+
+variables:
+ # This variable is not defined in the junctioned project
+ dest: "/destination"
diff --git a/tests/format/junctions/replacements/stack.bst b/tests/format/junctions/replacements/stack.bst
new file mode 100644
index 000000000..0ab52e878
--- /dev/null
+++ b/tests/format/junctions/replacements/stack.bst
@@ -0,0 +1,3 @@
+kind: stack
+runtime-depends:
+- base.bst:compose.bst