Benjamin Schubert pushed to branch bschubert/pipeline at BuildStream / buildstream
Commits:
-
542cdaf0
by Jürg Billeter at 2019-01-14T18:46:57Z
-
ff666e76
by James Ennis at 2019-01-14T18:46:57Z
-
273b0f55
by Tristan Van Berkom at 2019-01-14T20:24:57Z
-
2e3c2ea2
by Javier Jardón at 2019-01-14T22:26:04Z
-
d60d2e31
by Javier Jardón at 2019-01-15T00:39:22Z
-
605836c1
by Chandan Singh at 2019-01-15T00:57:05Z
-
006370af
by Chandan Singh at 2019-01-15T01:21:33Z
-
2028d982
by Benjamin Schubert at 2019-01-15T10:35:06Z
-
7ed23936
by Benjamin Schubert at 2019-01-15T10:35:45Z
7 changed files:
- .gitlab-ci.yml
- buildstream/_frontend/cli.py
- buildstream/_scheduler/queues/buildqueue.py
- buildstream/_scheduler/queues/fetchqueue.py
- buildstream/_scheduler/queues/pullqueue.py
- buildstream/element.py
- tests/completions/completions.py
Changes:
| ... | ... | @@ -96,7 +96,6 @@ tests-unix: |
| 96 | 96 |
# Since the unix platform is required to run as root, no user change required
|
| 97 | 97 |
- ${TEST_COMMAND}
|
| 98 | 98 |
|
| 99 |
- |
|
| 100 | 99 |
tests-fedora-missing-deps:
|
| 101 | 100 |
# Ensure that tests behave nicely while missing bwrap and ostree
|
| 102 | 101 |
image: buildstream/testsuite-fedora:28-5da27168-32c47d1c
|
| ... | ... | @@ -114,6 +113,22 @@ tests-fedora-missing-deps: |
| 114 | 113 |
|
| 115 | 114 |
- ${TEST_COMMAND}
|
| 116 | 115 |
|
| 116 |
+tests-fedora-update-deps:
|
|
| 117 |
+ # Check if the tests pass after updating requirements to their latest
|
|
| 118 |
+ # allowed version.
|
|
| 119 |
+ allow_failure: true
|
|
| 120 |
+ image: buildstream/testsuite-fedora:28-5da27168-32c47d1c
|
|
| 121 |
+ <<: *tests
|
|
| 122 |
+ |
|
| 123 |
+ script:
|
|
| 124 |
+ - useradd -Um buildstream
|
|
| 125 |
+ - chown -R buildstream:buildstream .
|
|
| 126 |
+ |
|
| 127 |
+ - make --always-make --directory requirements
|
|
| 128 |
+ - cat requirements/*.txt
|
|
| 129 |
+ |
|
| 130 |
+ - su buildstream -c "${TEST_COMMAND}"
|
|
| 131 |
+ |
|
| 117 | 132 |
# Lint separately from testing
|
| 118 | 133 |
lint:
|
| 119 | 134 |
stage: test
|
| ... | ... | @@ -146,7 +161,7 @@ docs: |
| 146 | 161 |
stage: test
|
| 147 | 162 |
variables:
|
| 148 | 163 |
BST_EXT_URL: git+https://gitlab.com/BuildStream/bst-external.git
|
| 149 |
- BST_EXT_REF: 573843768f4d297f85dc3067465b3c7519a8dcc3 # 0.7.0
|
|
| 164 |
+ BST_EXT_REF: 0.9.0-0-g63a19e8068bd777bd9cd59b1a9442f9749ea5a85
|
|
| 150 | 165 |
FD_SDK_REF: freedesktop-sdk-18.08.25-0-g250939d465d6dd7768a215f1fa59c4a3412fc337
|
| 151 | 166 |
before_script:
|
| 152 | 167 |
- |
|
| ... | ... | @@ -2,6 +2,7 @@ import os |
| 2 | 2 |
import sys
|
| 3 | 3 |
from contextlib import ExitStack
|
| 4 | 4 |
from fnmatch import fnmatch
|
| 5 |
+from functools import partial
|
|
| 5 | 6 |
from tempfile import TemporaryDirectory
|
| 6 | 7 |
|
| 7 | 8 |
import click
|
| ... | ... | @@ -111,14 +112,25 @@ def complete_target(args, incomplete): |
| 111 | 112 |
return complete_list
|
| 112 | 113 |
|
| 113 | 114 |
|
| 114 |
-def complete_artifact(args, incomplete):
|
|
| 115 |
+def complete_artifact(orig_args, args, incomplete):
|
|
| 115 | 116 |
from .._context import Context
|
| 116 | 117 |
ctx = Context()
|
| 117 | 118 |
|
| 118 | 119 |
config = None
|
| 119 |
- for i, arg in enumerate(args):
|
|
| 120 |
- if arg in ('-c', '--config'):
|
|
| 121 |
- config = args[i + 1]
|
|
| 120 |
+ if orig_args:
|
|
| 121 |
+ for i, arg in enumerate(orig_args):
|
|
| 122 |
+ if arg in ('-c', '--config'):
|
|
| 123 |
+ try:
|
|
| 124 |
+ config = orig_args[i + 1]
|
|
| 125 |
+ except IndexError:
|
|
| 126 |
+ pass
|
|
| 127 |
+ if args:
|
|
| 128 |
+ for i, arg in enumerate(args):
|
|
| 129 |
+ if arg in ('-c', '--config'):
|
|
| 130 |
+ try:
|
|
| 131 |
+ config = args[i + 1]
|
|
| 132 |
+ except IndexError:
|
|
| 133 |
+ pass
|
|
| 122 | 134 |
ctx.load(config)
|
| 123 | 135 |
|
| 124 | 136 |
# element targets are valid artifact names
|
| ... | ... | @@ -128,8 +140,9 @@ def complete_artifact(args, incomplete): |
| 128 | 140 |
return complete_list
|
| 129 | 141 |
|
| 130 | 142 |
|
| 131 |
-def override_completions(cmd, cmd_param, args, incomplete):
|
|
| 143 |
+def override_completions(orig_args, cmd, cmd_param, args, incomplete):
|
|
| 132 | 144 |
"""
|
| 145 |
+ :param orig_args: original, non-completion args
|
|
| 133 | 146 |
:param cmd_param: command definition
|
| 134 | 147 |
:param args: full list of args typed before the incomplete arg
|
| 135 | 148 |
:param incomplete: the incomplete text to autocomplete
|
| ... | ... | @@ -150,7 +163,7 @@ def override_completions(cmd, cmd_param, args, incomplete): |
| 150 | 163 |
cmd_param.opts == ['--track-except']):
|
| 151 | 164 |
return complete_target(args, incomplete)
|
| 152 | 165 |
if cmd_param.name == 'artifacts':
|
| 153 |
- return complete_artifact(args, incomplete)
|
|
| 166 |
+ return complete_artifact(orig_args, args, incomplete)
|
|
| 154 | 167 |
|
| 155 | 168 |
raise CompleteUnhandled()
|
| 156 | 169 |
|
| ... | ... | @@ -161,7 +174,7 @@ def override_main(self, args=None, prog_name=None, complete_var=None, |
| 161 | 174 |
# Hook for the Bash completion. This only activates if the Bash
|
| 162 | 175 |
# completion is actually enabled, otherwise this is quite a fast
|
| 163 | 176 |
# noop.
|
| 164 |
- if main_bashcomplete(self, prog_name, override_completions):
|
|
| 177 |
+ if main_bashcomplete(self, prog_name, partial(override_completions, args)):
|
|
| 165 | 178 |
|
| 166 | 179 |
# If we're running tests we cant just go calling exit()
|
| 167 | 180 |
# from the main process.
|
| ... | ... | @@ -71,9 +71,6 @@ class BuildQueue(Queue): |
| 71 | 71 |
return element._assemble()
|
| 72 | 72 |
|
| 73 | 73 |
def status(self, element):
|
| 74 |
- # state of dependencies may have changed, recalculate element state
|
|
| 75 |
- element._update_state()
|
|
| 76 |
- |
|
| 77 | 74 |
if not element._is_required():
|
| 78 | 75 |
# Artifact is not currently required but it may be requested later.
|
| 79 | 76 |
# Keep it in the queue.
|
| ... | ... | @@ -44,9 +44,6 @@ class FetchQueue(Queue): |
| 44 | 44 |
element._fetch()
|
| 45 | 45 |
|
| 46 | 46 |
def status(self, element):
|
| 47 |
- # state of dependencies may have changed, recalculate element state
|
|
| 48 |
- element._update_state()
|
|
| 49 |
- |
|
| 50 | 47 |
if not element._is_required():
|
| 51 | 48 |
# Artifact is not currently required but it may be requested later.
|
| 52 | 49 |
# Keep it in the queue.
|
| ... | ... | @@ -39,9 +39,6 @@ class PullQueue(Queue): |
| 39 | 39 |
raise SkipJob(self.action_name)
|
| 40 | 40 |
|
| 41 | 41 |
def status(self, element):
|
| 42 |
- # state of dependencies may have changed, recalculate element state
|
|
| 43 |
- element._update_state()
|
|
| 44 |
- |
|
| 45 | 42 |
if not element._is_required():
|
| 46 | 43 |
# Artifact is not currently required but it may be requested later.
|
| 47 | 44 |
# Keep it in the queue.
|
| ... | ... | @@ -197,6 +197,7 @@ class Element(Plugin): |
| 197 | 197 |
|
| 198 | 198 |
self.__runtime_dependencies = [] # Direct runtime dependency Elements
|
| 199 | 199 |
self.__build_dependencies = [] # Direct build dependency Elements
|
| 200 |
+ self.__reverse_build_dependencies = [] # Direct reverse dependency Elements
|
|
| 200 | 201 |
self.__sources = [] # List of Sources
|
| 201 | 202 |
self.__weak_cache_key = None # Our cached weak cache key
|
| 202 | 203 |
self.__strict_cache_key = None # Our cached cache key for strict builds
|
| ... | ... | @@ -439,6 +440,16 @@ class Element(Plugin): |
| 439 | 440 |
if should_yield and (recurse or recursed) and scope != Scope.BUILD:
|
| 440 | 441 |
yield self
|
| 441 | 442 |
|
| 443 |
+ def reverse_build_dependencies(self):
|
|
| 444 |
+ def recurse_rdeps(element):
|
|
| 445 |
+ yield element
|
|
| 446 |
+ |
|
| 447 |
+ for rdep in element.__reverse_build_dependencies:
|
|
| 448 |
+ yield from recurse_rdeps(rdep)
|
|
| 449 |
+ |
|
| 450 |
+ for rdep in self.__reverse_build_dependencies:
|
|
| 451 |
+ yield from recurse_rdeps(rdep)
|
|
| 452 |
+ |
|
| 442 | 453 |
def search(self, scope, name):
|
| 443 | 454 |
"""Search for a dependency by name
|
| 444 | 455 |
|
| ... | ... | @@ -930,6 +941,7 @@ class Element(Plugin): |
| 930 | 941 |
for meta_dep in meta.build_dependencies:
|
| 931 | 942 |
dependency = Element._new_from_meta(meta_dep)
|
| 932 | 943 |
element.__build_dependencies.append(dependency)
|
| 944 |
+ dependency.__reverse_build_dependencies.append(element)
|
|
| 933 | 945 |
|
| 934 | 946 |
return element
|
| 935 | 947 |
|
| ... | ... | @@ -1306,6 +1318,9 @@ class Element(Plugin): |
| 1306 | 1318 |
|
| 1307 | 1319 |
self._update_state()
|
| 1308 | 1320 |
|
| 1321 |
+ for reverse_dep in self.reverse_build_dependencies():
|
|
| 1322 |
+ reverse_dep._update_state()
|
|
| 1323 |
+ |
|
| 1309 | 1324 |
# _track():
|
| 1310 | 1325 |
#
|
| 1311 | 1326 |
# Calls track() on the Element sources
|
| ... | ... | @@ -1503,6 +1518,9 @@ class Element(Plugin): |
| 1503 | 1518 |
self._update_state()
|
| 1504 | 1519 |
|
| 1505 | 1520 |
if self._get_workspace() and self._cached_success():
|
| 1521 |
+ for rdep in self.reverse_build_dependencies():
|
|
| 1522 |
+ rdep._update_state()
|
|
| 1523 |
+ |
|
| 1506 | 1524 |
assert utils._is_main_process(), \
|
| 1507 | 1525 |
"Attempted to save workspace configuration from child process"
|
| 1508 | 1526 |
#
|
| ... | ... | @@ -281,3 +281,44 @@ def test_argument_element_invalid(datafiles, cli, project, cmd, word_idx, expect |
| 281 | 281 |
])
|
| 282 | 282 |
def test_help_commands(cli, cmd, word_idx, expected):
|
| 283 | 283 |
assert_completion(cli, cmd, word_idx, expected)
|
| 284 |
+ |
|
| 285 |
+ |
|
| 286 |
+@pytest.mark.datafiles(os.path.join(DATA_DIR, 'project'))
|
|
| 287 |
+def test_argument_artifact(cli, tmpdir, datafiles):
|
|
| 288 |
+ project = os.path.join(datafiles.dirname, datafiles.basename)
|
|
| 289 |
+ |
|
| 290 |
+ # Build an import element with no dependencies (as there will only be ONE cache key)
|
|
| 291 |
+ result = cli.run(project=project, args=['build', 'import-bin.bst']) # Has no dependencies
|
|
| 292 |
+ result.assert_success()
|
|
| 293 |
+ |
|
| 294 |
+ # Get the key and the artifact ref ($project/$element_name/$key)
|
|
| 295 |
+ key = cli.get_element_key(project, 'import-bin.bst')
|
|
| 296 |
+ artifact = os.path.join('test', 'import-bin', key)
|
|
| 297 |
+ |
|
| 298 |
+ # Test autocompletion of the artifact
|
|
| 299 |
+ cmds = [
|
|
| 300 |
+ 'bst artifact log ',
|
|
| 301 |
+ 'bst artifact log t',
|
|
| 302 |
+ 'bst artifact log test/'
|
|
| 303 |
+ ]
|
|
| 304 |
+ |
|
| 305 |
+ for i, cmd in enumerate(cmds):
|
|
| 306 |
+ word_idx = 3
|
|
| 307 |
+ result = cli.run(project=project, cwd=project, env={
|
|
| 308 |
+ '_BST_COMPLETION': 'complete',
|
|
| 309 |
+ 'COMP_WORDS': cmd,
|
|
| 310 |
+ 'COMP_CWORD': str(word_idx)
|
|
| 311 |
+ })
|
|
| 312 |
+ words = []
|
|
| 313 |
+ if result.output:
|
|
| 314 |
+ words = result.output.splitlines() # This leaves an extra space on each e.g. ['foo.bst ']
|
|
| 315 |
+ words = [word.strip() for word in words]
|
|
| 316 |
+ |
|
| 317 |
+ if i == 0:
|
|
| 318 |
+ expected = PROJECT_ELEMENTS + [artifact] # We should now be able to see the artifact
|
|
| 319 |
+ elif i == 1:
|
|
| 320 |
+ expected = ['target.bst', artifact]
|
|
| 321 |
+ elif i == 2:
|
|
| 322 |
+ expected = [artifact]
|
|
| 323 |
+ |
|
| 324 |
+ assert expected == words
|
