Qinusty pushed to branch Qinusty/597-non-alias-url-fix at BuildStream / buildstream
Commits:
-
d1bd8c0b
by Chandan Singh at 2018-08-21T12:46:57Z
-
12d1cec2
by Chandan Singh at 2018-08-21T12:46:57Z
-
320b9562
by Tristan Van Berkom at 2018-08-21T13:57:00Z
-
ef606229
by Josh Smith at 2018-08-21T14:49:57Z
-
d8256c74
by Qinusty at 2018-08-21T15:46:14Z
-
ab1caac1
by Chandan Singh at 2018-08-21T23:47:32Z
-
81278f84
by Tristan Van Berkom at 2018-08-22T05:23:33Z
-
3d4e649d
by Tristan Van Berkom at 2018-08-22T05:24:42Z
-
c8bafb68
by Tristan Van Berkom at 2018-08-22T06:24:12Z
-
eeaddbac
by William Salmon at 2018-08-22T08:05:28Z
-
e15f5fa3
by William Salmon at 2018-08-22T08:05:28Z
-
ff52ae18
by Will Salmon at 2018-08-22T09:33:04Z
-
f4e51cf1
by Sam Thursfield at 2018-08-22T10:38:41Z
-
5b79bbb7
by Tristan Van Berkom at 2018-08-22T11:39:32Z
-
91d62d2f
by Chandan Singh at 2018-08-22T18:38:01Z
-
cd0775eb
by Chandan Singh at 2018-08-22T23:44:36Z
-
b0d1aa83
by Tristan Van Berkom at 2018-08-23T05:54:05Z
-
2215859c
by Valentin David at 2018-08-23T06:40:19Z
-
e37ac3bc
by Tristan Van Berkom at 2018-08-23T07:45:49Z
-
2ac654a8
by Valentin David at 2018-08-23T08:02:50Z
-
176aa09f
by Tristan Van Berkom at 2018-08-23T09:10:51Z
-
f1e3f10f
by Mathieu Bridon at 2018-08-23T09:11:47Z
-
bea01531
by Tristan Van Berkom at 2018-08-23T09:14:40Z
-
da19bcf1
by Tristan Van Berkom at 2018-08-23T09:14:40Z
-
8216ff8d
by Tristan Van Berkom at 2018-08-23T10:13:23Z
-
56096b60
by Chandan Singh at 2018-08-24T02:12:03Z
-
86e4729d
by Tristan Van Berkom at 2018-08-24T06:42:03Z
-
d88568ef
by Valentin David at 2018-08-24T06:48:08Z
-
f7ef151b
by Tristan Van Berkom at 2018-08-24T07:36:19Z
-
6c7ec7b5
by Josh Smith at 2018-08-28T14:45:45Z
28 changed files:
- .gitlab-ci.yml
- MANIFEST.in
- README.rst
- buildstream/_artifactcache/cascache.py
- buildstream/_frontend/linuxapp.py
- buildstream/_pipeline.py
- buildstream/_version.py
- buildstream/data/projectconfig.yaml
- buildstream/plugin.py
- buildstream/source.py
- buildstream/utils.py
- dev-requirements.txt
- setup.cfg
- setup.py
- tests/artifactcache/expiry.py
- tests/cachekey/project/elements/build1.expected
- tests/cachekey/project/elements/build2.expected
- tests/cachekey/project/target.expected
- tests/examples/autotools.py
- tests/examples/developing.py
- tests/examples/flatpak-autotools.py
- tests/frontend/workspace.py
- tests/integration/autotools.py
- tests/integration/cmake.py
- tests/integration/compose.py
- tests/integration/source-determinism.py
- tests/testutils/runcli.py
- versioneer.py
Changes:
1 |
-image: buildstream/testsuite-debian:9-master-112-a9f63c5e
|
|
1 |
+image: buildstream/testsuite-debian:9-master-114-4cab18e3
|
|
2 | 2 |
|
3 | 3 |
cache:
|
4 | 4 |
key: "$CI_JOB_NAME-"
|
... | ... | @@ -10,6 +10,16 @@ stages: |
10 | 10 |
- test
|
11 | 11 |
- post
|
12 | 12 |
|
13 |
+# Avoid running all the tests post merge on
|
|
14 |
+# master or on any release branch.
|
|
15 |
+#
|
|
16 |
+.tests-condition-template: &tests-condition
|
|
17 |
+ only:
|
|
18 |
+ - branches
|
|
19 |
+ except:
|
|
20 |
+ - master
|
|
21 |
+ - /bst-1\..*/
|
|
22 |
+ |
|
13 | 23 |
#####################################################
|
14 | 24 |
# Prepare stage #
|
15 | 25 |
#####################################################
|
... | ... | @@ -26,6 +36,11 @@ source_dist: |
26 | 36 |
- tar -ztf dist/*
|
27 | 37 |
- tarball=$(cd dist && echo $(ls *))
|
28 | 38 |
|
39 |
+ # Verify that the source distribution tarball can be installed correctly
|
|
40 |
+ #
|
|
41 |
+ - pip3 install dist/*.tar.gz
|
|
42 |
+ - bst --version
|
|
43 |
+ |
|
29 | 44 |
# unpack tarball as `dist/buildstream` directory
|
30 | 45 |
- |
|
31 | 46 |
cat > dist/unpack.sh << EOF
|
... | ... | @@ -79,25 +94,31 @@ source_dist: |
79 | 94 |
- coverage-linux/
|
80 | 95 |
|
81 | 96 |
tests-debian-9:
|
82 |
- image: buildstream/testsuite-debian:9-master-112-a9f63c5e
|
|
97 |
+ image: buildstream/testsuite-debian:9-master-114-4cab18e3
|
|
83 | 98 |
<<: *linux-tests
|
99 |
+ <<: *tests-condition
|
|
84 | 100 |
|
85 | 101 |
tests-fedora-27:
|
86 |
- image: buildstream/testsuite-fedora:27-master-112-a9f63c5e
|
|
102 |
+ image: buildstream/testsuite-fedora:27-master-114-4cab18e3
|
|
87 | 103 |
<<: *linux-tests
|
104 |
+ <<: *tests-condition
|
|
88 | 105 |
|
89 | 106 |
tests-fedora-28:
|
90 |
- image: buildstream/testsuite-fedora:28-master-112-a9f63c5e
|
|
107 |
+ image: buildstream/testsuite-fedora:28-master-114-4cab18e3
|
|
91 | 108 |
<<: *linux-tests
|
109 |
+ <<: *tests-condition
|
|
92 | 110 |
|
93 | 111 |
tests-ubuntu-18.04:
|
94 |
- image: buildstream/testsuite-ubuntu:18.04-master-112-a9f63c5e
|
|
112 |
+ image: buildstream/testsuite-ubuntu:18.04-master-114-4cab18e3
|
|
95 | 113 |
<<: *linux-tests
|
114 |
+ <<: *tests-condition
|
|
96 | 115 |
|
97 | 116 |
tests-unix:
|
117 |
+ <<: *tests-condition
|
|
118 |
+ |
|
98 | 119 |
# Use fedora here, to a) run a test on fedora and b) ensure that we
|
99 | 120 |
# can get rid of ostree - this is not possible with debian-8
|
100 |
- image: buildstream/testsuite-fedora:27-master-112-a9f63c5e
|
|
121 |
+ image: buildstream/testsuite-fedora:27-master-114-4cab18e3
|
|
101 | 122 |
stage: test
|
102 | 123 |
variables:
|
103 | 124 |
BST_FORCE_BACKEND: "unix"
|
... | ... | @@ -133,6 +154,15 @@ tests-unix: |
133 | 154 |
# Note: We still do not enforce a consistent installation of python3-sphinx,
|
134 | 155 |
# as it will significantly grow the backing image.
|
135 | 156 |
docs:
|
157 |
+ |
|
158 |
+ # Here we build the docs for every pre-merge CI, but avoid
|
|
159 |
+ # the job on post-merge to stable branches, because we only
|
|
160 |
+ # ever publish them from master
|
|
161 |
+ only:
|
|
162 |
+ - branches
|
|
163 |
+ except:
|
|
164 |
+ - /bst-1\..*/
|
|
165 |
+ |
|
136 | 166 |
stage: test
|
137 | 167 |
script:
|
138 | 168 |
- export BST_SOURCE_CACHE="$(pwd)/cache/integration-cache/sources"
|
... | ... | @@ -157,6 +187,8 @@ docs: |
157 | 187 |
# as an output of radon, with some conversion
|
158 | 188 |
#
|
159 | 189 |
codequality:
|
190 |
+ <<: *tests-condition
|
|
191 |
+ |
|
160 | 192 |
image: docker:stable
|
161 | 193 |
stage: post
|
162 | 194 |
variables:
|
... | ... | @@ -175,6 +207,8 @@ codequality: |
175 | 207 |
paths: [codeclimate.json]
|
176 | 208 |
|
177 | 209 |
analysis:
|
210 |
+ <<: *tests-condition
|
|
211 |
+ |
|
178 | 212 |
stage: post
|
179 | 213 |
script:
|
180 | 214 |
- |
|
... | ... | @@ -203,6 +237,8 @@ analysis: |
203 | 237 |
# Collate coverage reports
|
204 | 238 |
#
|
205 | 239 |
coverage:
|
240 |
+ <<: *tests-condition
|
|
241 |
+ |
|
206 | 242 |
stage: post
|
207 | 243 |
coverage: '/TOTAL +\d+ +\d+ +(\d+\.\d+)%/'
|
208 | 244 |
script:
|
... | ... | @@ -23,4 +23,4 @@ recursive-include tests *.expected |
23 | 23 |
recursive-include buildstream/_protos *.proto
|
24 | 24 |
|
25 | 25 |
# Requirements files
|
26 |
-dev-requirements.txt
|
|
26 |
+include dev-requirements.txt
|
1 | 1 |
About
|
2 | 2 |
-----
|
3 |
-.. image:: https://gitlab.com/BuildStream/buildstream/badges/master/pipeline.svg
|
|
4 |
- :target: https://gitlab.com/BuildStream/buildstream/commits/master
|
|
5 |
- |
|
6 |
-.. image:: https://gitlab.com/BuildStream/buildstream/badges/master/coverage.svg?job=coverage
|
|
7 |
- :target: https://gitlab.com/BuildStream/buildstream/commits/master
|
|
8 | 3 |
|
9 | 4 |
|
10 | 5 |
What is BuildStream?
|
... | ... | @@ -30,6 +30,8 @@ from urllib.parse import urlparse |
30 | 30 |
|
31 | 31 |
import grpc
|
32 | 32 |
|
33 |
+from .. import _yaml
|
|
34 |
+ |
|
33 | 35 |
from .._protos.google.bytestream import bytestream_pb2, bytestream_pb2_grpc
|
34 | 36 |
from .._protos.build.bazel.remote.execution.v2 import remote_execution_pb2, remote_execution_pb2_grpc
|
35 | 37 |
from .._protos.buildstream.v2 import buildstream_pb2, buildstream_pb2_grpc
|
... | ... | @@ -526,6 +528,25 @@ class CASCache(ArtifactCache): |
526 | 528 |
#
|
527 | 529 |
def remove(self, ref, *, defer_prune=False):
|
528 | 530 |
|
531 |
+ # Remove extract if not used by other ref
|
|
532 |
+ tree = self.resolve_ref(ref)
|
|
533 |
+ ref_name, ref_hash = os.path.split(ref)
|
|
534 |
+ extract = os.path.join(self.extractdir, ref_name, tree.hash)
|
|
535 |
+ keys_file = os.path.join(extract, 'meta', 'keys.yaml')
|
|
536 |
+ if os.path.exists(keys_file):
|
|
537 |
+ keys_meta = _yaml.load(keys_file)
|
|
538 |
+ keys = [keys_meta['strong'], keys_meta['weak']]
|
|
539 |
+ remove_extract = True
|
|
540 |
+ for other_hash in keys:
|
|
541 |
+ if other_hash == ref_hash:
|
|
542 |
+ continue
|
|
543 |
+ remove_extract = False
|
|
544 |
+ break
|
|
545 |
+ |
|
546 |
+ if remove_extract:
|
|
547 |
+ utils._force_rmtree(extract)
|
|
548 |
+ |
|
549 |
+ # Remove cache ref
|
|
529 | 550 |
refpath = self._refpath(ref)
|
530 | 551 |
if not os.path.exists(refpath):
|
531 | 552 |
raise ArtifactError("Could not find artifact for ref '{}'".format(ref))
|
... | ... | @@ -22,12 +22,43 @@ import click |
22 | 22 |
from .app import App
|
23 | 23 |
|
24 | 24 |
|
25 |
+# This trick is currently only supported on some terminals,
|
|
26 |
+# avoid using it where it can cause garbage to be printed
|
|
27 |
+# to the terminal.
|
|
28 |
+#
|
|
29 |
+def _osc_777_supported():
|
|
30 |
+ |
|
31 |
+ term = os.environ.get('TERM')
|
|
32 |
+ |
|
33 |
+ if term and (term.startswith('xterm') or term.startswith('vte')):
|
|
34 |
+ |
|
35 |
+ # Since vte version 4600, upstream silently ignores
|
|
36 |
+ # the OSC 777 without printing garbage to the terminal.
|
|
37 |
+ #
|
|
38 |
+ # For distros like Fedora who have patched vte, this
|
|
39 |
+ # will trigger a desktop notification and bring attention
|
|
40 |
+ # to the terminal.
|
|
41 |
+ #
|
|
42 |
+ vte_version = os.environ.get('VTE_VERSION')
|
|
43 |
+ try:
|
|
44 |
+ vte_version_int = int(vte_version)
|
|
45 |
+ except (ValueError, TypeError):
|
|
46 |
+ return False
|
|
47 |
+ |
|
48 |
+ if vte_version_int >= 4600:
|
|
49 |
+ return True
|
|
50 |
+ |
|
51 |
+ return False
|
|
52 |
+ |
|
53 |
+ |
|
25 | 54 |
# A linux specific App implementation
|
26 | 55 |
#
|
27 | 56 |
class LinuxApp(App):
|
28 | 57 |
|
29 | 58 |
def notify(self, title, text):
|
30 | 59 |
|
31 |
- term = os.environ['TERM']
|
|
32 |
- if term in ('xterm', 'vte'):
|
|
33 |
- click.echo("\033]777;notify;{};{}\007".format(title, text))
|
|
60 |
+ # Currently we only try this notification method
|
|
61 |
+ # of sending an escape sequence to the terminal
|
|
62 |
+ #
|
|
63 |
+ if _osc_777_supported():
|
|
64 |
+ click.echo("\033]777;notify;{};{}\007".format(title, text), err=True)
|
... | ... | @@ -28,6 +28,7 @@ from ._message import Message, MessageType |
28 | 28 |
from ._profile import Topics, profile_start, profile_end
|
29 | 29 |
from . import Scope, Consistency
|
30 | 30 |
from ._project import ProjectRefStorage
|
31 |
+from .plugin import CoreWarnings
|
|
31 | 32 |
|
32 | 33 |
|
33 | 34 |
# PipelineSelection()
|
... | ... | @@ -110,6 +111,8 @@ class Pipeline(): |
110 | 111 |
rewritable=rewritable,
|
111 | 112 |
fetch_subprojects=fetch_subprojects)
|
112 | 113 |
|
114 |
+ self._check_unaliased_urls(elements)
|
|
115 |
+ |
|
113 | 116 |
# Now create element groups to match the input target groups
|
114 | 117 |
elt_iter = iter(elements)
|
115 | 118 |
element_groups = [
|
... | ... | @@ -355,10 +358,14 @@ class Pipeline(): |
355 | 358 |
#
|
356 | 359 |
def assert_consistent(self, elements):
|
357 | 360 |
inconsistent = []
|
361 |
+ inconsistent_workspaced = []
|
|
358 | 362 |
with self._context.timed_activity("Checking sources"):
|
359 | 363 |
for element in elements:
|
360 | 364 |
if element._get_consistency() == Consistency.INCONSISTENT:
|
361 |
- inconsistent.append(element)
|
|
365 |
+ if element._get_workspace():
|
|
366 |
+ inconsistent_workspaced.append(element)
|
|
367 |
+ else:
|
|
368 |
+ inconsistent.append(element)
|
|
362 | 369 |
|
363 | 370 |
if inconsistent:
|
364 | 371 |
detail = "Exact versions are missing for the following elements:\n\n"
|
... | ... | @@ -372,6 +379,13 @@ class Pipeline(): |
372 | 379 |
|
373 | 380 |
raise PipelineError("Inconsistent pipeline", detail=detail, reason="inconsistent-pipeline")
|
374 | 381 |
|
382 |
+ if inconsistent_workspaced:
|
|
383 |
+ detail = "Some workspaces do not exist but are not closed\n" + \
|
|
384 |
+ "Try closing them with `bst workspace close`\n\n"
|
|
385 |
+ for element in inconsistent_workspaced:
|
|
386 |
+ detail += " " + element._get_full_name() + "\n"
|
|
387 |
+ raise PipelineError("Inconsistent pipeline", detail=detail, reason="inconsistent-pipeline-workspaced")
|
|
388 |
+ |
|
375 | 389 |
#############################################################
|
376 | 390 |
# Private Methods #
|
377 | 391 |
#############################################################
|
... | ... | @@ -422,6 +436,30 @@ class Pipeline(): |
422 | 436 |
|
423 | 437 |
raise PipelineError("Untrackable sources", detail=detail, reason="untrackable-sources")
|
424 | 438 |
|
439 |
+ # _check_unaliased_urls():
|
|
440 |
+ #
|
|
441 |
+ # Checks all dependencies sources for urls not using an alias. Raises an appropriate warning.
|
|
442 |
+ #
|
|
443 |
+ # Args:
|
|
444 |
+ # elements (list of Element): The list of elements loaded to check.
|
|
445 |
+ #
|
|
446 |
+ def _check_unaliased_urls(self, elements):
|
|
447 |
+ unaliased_urls = []
|
|
448 |
+ for element in self.dependencies(elements, Scope.ALL):
|
|
449 |
+ sources = element.sources()
|
|
450 |
+ unaliased_urls.extend(itertools.chain(*[
|
|
451 |
+ source._get_unaliased_urls() for source in sources
|
|
452 |
+ ]))
|
|
453 |
+ |
|
454 |
+ if unaliased_urls:
|
|
455 |
+ message = "The use of an alias in urls is strongly advised."
|
|
456 |
+ unaliased_urls_strs = [
|
|
457 |
+ "{}: {}".format(prov, url)
|
|
458 |
+ for url, prov in unaliased_urls
|
|
459 |
+ ]
|
|
460 |
+ detail = "Unaliased URLs:\n\t" + "\n\t".join(unaliased_urls_strs)
|
|
461 |
+ elements[0].warn(message, detail=detail, warning_token=CoreWarnings.URL_WITHOUT_ALIAS)
|
|
462 |
+ |
|
425 | 463 |
# _message()
|
426 | 464 |
#
|
427 | 465 |
# Local message propagator
|
... | ... | @@ -43,6 +43,7 @@ def get_config(): |
43 | 43 |
cfg.VCS = "git"
|
44 | 44 |
cfg.style = "pep440"
|
45 | 45 |
cfg.tag_prefix = ""
|
46 |
+ cfg.tag_regex = "*.*.*"
|
|
46 | 47 |
cfg.parentdir_prefix = "BuildStream-"
|
47 | 48 |
cfg.versionfile_source = "buildstream/_version.py"
|
48 | 49 |
cfg.verbose = False
|
... | ... | @@ -215,7 +216,7 @@ def git_versions_from_keywords(keywords, tag_prefix, verbose): |
215 | 216 |
|
216 | 217 |
|
217 | 218 |
@register_vcs_handler("git", "pieces_from_vcs")
|
218 |
-def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command):
|
|
219 |
+def git_pieces_from_vcs(tag_prefix, tag_regex, root, verbose, run_command=run_command):
|
|
219 | 220 |
"""Get version from 'git describe' in the root of the source tree.
|
220 | 221 |
|
221 | 222 |
This only gets called if the git-archive 'subst' keywords were *not*
|
... | ... | @@ -237,7 +238,7 @@ def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): |
237 | 238 |
# if there isn't one, this yields HEX[-dirty] (no NUM)
|
238 | 239 |
describe_out, rc = run_command(GITS, ["describe", "--tags", "--dirty",
|
239 | 240 |
"--always", "--long",
|
240 |
- "--match", "%s*" % tag_prefix],
|
|
241 |
+ "--match", "%s%s" % (tag_prefix, tag_regex)],
|
|
241 | 242 |
cwd=root)
|
242 | 243 |
# --long was added in git-1.5.5
|
243 | 244 |
if describe_out is None:
|
... | ... | @@ -505,7 +506,7 @@ def get_versions(): |
505 | 506 |
"date": None}
|
506 | 507 |
|
507 | 508 |
try:
|
508 |
- pieces = git_pieces_from_vcs(cfg.tag_prefix, root, verbose)
|
|
509 |
+ pieces = git_pieces_from_vcs(cfg.tag_prefix, cfg.tag_regex, root, verbose)
|
|
509 | 510 |
return render(pieces, cfg.style)
|
510 | 511 |
except NotThisMethod:
|
511 | 512 |
pass
|
... | ... | @@ -68,7 +68,7 @@ variables: |
68 | 68 |
# Generic implementation for stripping debugging symbols
|
69 | 69 |
strip-binaries: |
|
70 | 70 |
|
71 |
- find "%{install-root}" -type f \
|
|
71 |
+ cd "%{install-root}" && find -type f \
|
|
72 | 72 |
'(' -perm -111 -o -name '*.so*' \
|
73 | 73 |
-o -name '*.cmxs' -o -name '*.node' ')' \
|
74 | 74 |
-exec sh -ec \
|
... | ... | @@ -76,7 +76,7 @@ variables: |
76 | 76 |
if [ "$hdr" != "$(printf \\x7fELF)" ]; then
|
77 | 77 |
exit 0
|
78 | 78 |
fi
|
79 |
- debugfile="%{install-root}%{debugdir}/$(basename "$1")"
|
|
79 |
+ debugfile="%{install-root}%{debugdir}/$1"
|
|
80 | 80 |
mkdir -p "$(dirname "$debugfile")"
|
81 | 81 |
objcopy %{objcopy-extract-args} "$1" "$debugfile"
|
82 | 82 |
chmod 644 "$debugfile"
|
... | ... | @@ -508,6 +508,7 @@ class Plugin(): |
508 | 508 |
project = self._get_project()
|
509 | 509 |
|
510 | 510 |
if project._warning_is_fatal(warning_token):
|
511 |
+ detail = detail if detail else ""
|
|
511 | 512 |
raise PluginError(message="{}\n{}".format(brief, detail), reason=warning_token)
|
512 | 513 |
|
513 | 514 |
self.__message(MessageType.WARN, brief=brief, detail=detail)
|
... | ... | @@ -757,6 +758,16 @@ class CoreWarnings(): |
757 | 758 |
which is found to be invalid based on the configured track
|
758 | 759 |
"""
|
759 | 760 |
|
761 |
+ URL_WITHOUT_ALIAS = "url-without-alias"
|
|
762 |
+ """
|
|
763 |
+ This warning will be produced when a source is configured with a url which does not contain an alias.
|
|
764 |
+ """
|
|
765 |
+ |
|
766 |
+ UNKNOWN_ALIAS = "unknown-alias"
|
|
767 |
+ """
|
|
768 |
+ This warning will be produced when a source is configured with a url which does not contain an alias.
|
|
769 |
+ """
|
|
770 |
+ |
|
760 | 771 |
|
761 | 772 |
__CORE_WARNINGS = [
|
762 | 773 |
value
|
... | ... | @@ -137,6 +137,7 @@ from . import Plugin |
137 | 137 |
from . import _yaml, utils
|
138 | 138 |
from ._exceptions import BstError, ImplError, ErrorDomain
|
139 | 139 |
from ._projectrefs import ProjectRefStorage
|
140 |
+from .plugin import CoreWarnings
|
|
140 | 141 |
|
141 | 142 |
|
142 | 143 |
class Consistency():
|
... | ... | @@ -219,10 +220,7 @@ class SourceFetcher(): |
219 | 220 |
Args:
|
220 | 221 |
url (str): The url used to download.
|
221 | 222 |
"""
|
222 |
- # Not guaranteed to be a valid alias yet.
|
|
223 |
- # Ensuring it's a valid alias currently happens in Project.get_alias_uris
|
|
224 |
- alias, _ = url.split(utils._ALIAS_SEPARATOR, 1)
|
|
225 |
- self.__alias = alias
|
|
223 |
+ self.__alias = _extract_alias(url)
|
|
226 | 224 |
|
227 | 225 |
#############################################################
|
228 | 226 |
# Private Methods used in BuildStream #
|
... | ... | @@ -282,7 +280,7 @@ class Source(Plugin): |
282 | 280 |
self.__consistency = Consistency.INCONSISTENT # Cached consistency state
|
283 | 281 |
self.__alias_override = alias_override # Tuple of alias and its override to use instead
|
284 | 282 |
self.__expected_alias = None # A hacky way to store the first alias used
|
285 |
- |
|
283 |
+ self.__configuring = False
|
|
286 | 284 |
# FIXME: Reconstruct a MetaSource from a Source instead of storing it.
|
287 | 285 |
self.__meta = meta # MetaSource stored so we can copy this source later.
|
288 | 286 |
|
... | ... | @@ -291,8 +289,9 @@ class Source(Plugin): |
291 | 289 |
self.__init_defaults(meta)
|
292 | 290 |
self.__config = self.__extract_config(meta)
|
293 | 291 |
self.__first_pass = meta.first_pass
|
292 |
+ self.__unaliased_urls = []
|
|
294 | 293 |
|
295 |
- self.configure(self.__config)
|
|
294 |
+ self.__do_configure()
|
|
296 | 295 |
|
297 | 296 |
COMMON_CONFIG_KEYS = ['kind', 'directory']
|
298 | 297 |
"""Common source config keys
|
... | ... | @@ -459,8 +458,7 @@ class Source(Plugin): |
459 | 458 |
|
460 | 459 |
*Since: 1.2*
|
461 | 460 |
"""
|
462 |
- alias, _ = url.split(utils._ALIAS_SEPARATOR, 1)
|
|
463 |
- self.__expected_alias = alias
|
|
461 |
+ self.__expected_alias = self.__alias_from_url(url)
|
|
464 | 462 |
|
465 | 463 |
def get_source_fetchers(self):
|
466 | 464 |
"""Get the objects that are used for fetching
|
... | ... | @@ -525,8 +523,7 @@ class Source(Plugin): |
525 | 523 |
else:
|
526 | 524 |
# Sneakily store the alias if it hasn't already been stored
|
527 | 525 |
if not self.__expected_alias and url and utils._ALIAS_SEPARATOR in url:
|
528 |
- url_alias, _ = url.split(utils._ALIAS_SEPARATOR, 1)
|
|
529 |
- self.__expected_alias = url_alias
|
|
526 |
+ self.mark_download_url(url)
|
|
530 | 527 |
|
531 | 528 |
project = self._get_project()
|
532 | 529 |
return project.translate_url(url, first_pass=self.__first_pass)
|
... | ... | @@ -861,10 +858,24 @@ class Source(Plugin): |
861 | 858 |
else:
|
862 | 859 |
return None
|
863 | 860 |
|
861 |
+ # Gets the URLs which don't use an alias.
|
|
862 |
+ #
|
|
863 |
+ def _get_unaliased_urls(self):
|
|
864 |
+ return self.__unaliased_urls
|
|
865 |
+ |
|
864 | 866 |
#############################################################
|
865 | 867 |
# Local Private Methods #
|
866 | 868 |
#############################################################
|
867 | 869 |
|
870 |
+ # __do_configure()
|
|
871 |
+ #
|
|
872 |
+ # Performs self.configure() and sets self.__configuring to True whilst the source configures.
|
|
873 |
+ #
|
|
874 |
+ def __do_configure(self):
|
|
875 |
+ self.__configuring = True
|
|
876 |
+ self.configure(self.__config)
|
|
877 |
+ self.__configuring = False
|
|
878 |
+ |
|
868 | 879 |
# Tries to call fetch for every mirror, stopping once it succeeds
|
869 | 880 |
def __do_fetch(self, **kwargs):
|
870 | 881 |
project = self._get_project()
|
... | ... | @@ -914,12 +925,12 @@ class Source(Plugin): |
914 | 925 |
# Tries to call track for every mirror, stopping once it succeeds
|
915 | 926 |
def __do_track(self, **kwargs):
|
916 | 927 |
project = self._get_project()
|
917 |
- # If there are no mirrors, or no aliases to replace, there's nothing to do here.
|
|
918 | 928 |
alias = self._get_alias()
|
919 | 929 |
if self.__first_pass:
|
920 | 930 |
mirrors = project.first_pass_config.mirrors
|
921 | 931 |
else:
|
922 | 932 |
mirrors = project.config.mirrors
|
933 |
+ # If there are no mirrors, or no aliases to replace, there's nothing to do here.
|
|
923 | 934 |
if not mirrors or not alias:
|
924 | 935 |
return self.track(**kwargs)
|
925 | 936 |
|
... | ... | @@ -988,3 +999,18 @@ class Source(Plugin): |
988 | 999 |
|
989 | 1000 |
if src.get_consistency() == Consistency.RESOLVED:
|
990 | 1001 |
src._fetch(previous_sources[0:index])
|
1002 |
+ |
|
1003 |
+ |
|
1004 |
+ def __alias_from_url(self, url):
|
|
1005 |
+ alias = _extract_alias(url)
|
|
1006 |
+ if not alias:
|
|
1007 |
+ self.__unaliased_urls.append((url, self._get_provenance()))
|
|
1008 |
+ return alias
|
|
1009 |
+ |
|
1010 |
+ |
|
1011 |
+def _extract_alias(url):
|
|
1012 |
+ parts = url.split(utils._ALIAS_SEPARATOR, 1)
|
|
1013 |
+ if len(parts) > 1 and not parts[0].lower() in utils._URI_SCHEMES:
|
|
1014 |
+ return parts[0]
|
|
1015 |
+ else:
|
|
1016 |
+ return ""
|
... | ... | @@ -47,6 +47,7 @@ _magic_timestamp = calendar.timegm([2011, 11, 11, 11, 11, 11]) |
47 | 47 |
|
48 | 48 |
# The separator we use for user specified aliases
|
49 | 49 |
_ALIAS_SEPARATOR = ':'
|
50 |
+_URI_SCHEMES = ["http", "https", "ftp", "file", "git", "sftp", "ssh"]
|
|
50 | 51 |
|
51 | 52 |
|
52 | 53 |
class UtilError(BstError):
|
... | ... | @@ -484,7 +485,16 @@ def get_bst_version(): |
484 | 485 |
raise UtilError("Your git repository has no tags - BuildStream can't "
|
485 | 486 |
"determine its version. Please run `git fetch --tags`.")
|
486 | 487 |
|
487 |
- return (int(versions[0]), int(versions[1]))
|
|
488 |
+ try:
|
|
489 |
+ return (int(versions[0]), int(versions[1]))
|
|
490 |
+ except IndexError:
|
|
491 |
+ raise UtilError("Cannot detect Major and Minor parts of the version\n"
|
|
492 |
+ "Version: {} not in XX.YY.whatever format"
|
|
493 |
+ .format(__version__))
|
|
494 |
+ except ValueError:
|
|
495 |
+ raise UtilError("Cannot convert version to integer numbers\n"
|
|
496 |
+ "Version: {} not in Integer.Integer.whatever format"
|
|
497 |
+ .format(__version__))
|
|
488 | 498 |
|
489 | 499 |
|
490 | 500 |
@contextmanager
|
1 | 1 |
coverage == 4.4.0
|
2 | 2 |
pep8
|
3 |
-pytest >= 3.1.0
|
|
3 |
+pylint == 2.1.1
|
|
4 |
+pytest >= 3.7
|
|
4 | 5 |
pytest-cov >= 2.5.0
|
5 | 6 |
pytest-datafiles
|
6 | 7 |
pytest-env
|
... | ... | @@ -4,6 +4,7 @@ style = pep440 |
4 | 4 |
versionfile_source = buildstream/_version.py
|
5 | 5 |
versionfile_build = buildstream/_version.py
|
6 | 6 |
tag_prefix =
|
7 |
+tag_regex = *.*.*
|
|
7 | 8 |
parentdir_prefix = BuildStream-
|
8 | 9 |
|
9 | 10 |
[aliases]
|
... | ... | @@ -224,6 +224,13 @@ def get_cmdclass(): |
224 | 224 |
with open('dev-requirements.txt') as dev_reqs:
|
225 | 225 |
dev_requires = dev_reqs.read().splitlines()
|
226 | 226 |
|
227 |
+#####################################################
|
|
228 |
+# Prepare package description from README #
|
|
229 |
+#####################################################
|
|
230 |
+with open(os.path.join(os.path.dirname(os.path.realpath(__file__)),
|
|
231 |
+ 'README.rst')) as readme:
|
|
232 |
+ long_description = readme.read()
|
|
233 |
+ |
|
227 | 234 |
|
228 | 235 |
#####################################################
|
229 | 236 |
# Main setup() Invocation #
|
... | ... | @@ -233,8 +240,13 @@ setup(name='BuildStream', |
233 | 240 |
version=versioneer.get_version(),
|
234 | 241 |
cmdclass=get_cmdclass(),
|
235 | 242 |
|
243 |
+ author='BuildStream Developers',
|
|
244 |
+ author_email='buildstream-list gnome org',
|
|
236 | 245 |
description='A framework for modelling build pipelines in YAML',
|
237 | 246 |
license='LGPL',
|
247 |
+ long_description=long_description,
|
|
248 |
+ long_description_content_type='text/x-rst; charset=UTF-8',
|
|
249 |
+ url='https://gitlab.com/BuildStream/buildstream',
|
|
238 | 250 |
packages=find_packages(exclude=('tests', 'tests.*')),
|
239 | 251 |
package_data={'buildstream': ['plugins/*/*.py', 'plugins/*/*.yaml',
|
240 | 252 |
'data/*.yaml', 'data/*.sh.in']},
|
... | ... | @@ -261,7 +273,7 @@ setup(name='BuildStream', |
261 | 273 |
'ruamel.yaml < 0.15.52',
|
262 | 274 |
'pluginbase',
|
263 | 275 |
'Click',
|
264 |
- 'blessings',
|
|
276 |
+ 'blessings >= 1.6',
|
|
265 | 277 |
'jinja2 >= 2.10',
|
266 | 278 |
'protobuf >= 3.5',
|
267 | 279 |
'grpcio >= 1.10',
|
... | ... | @@ -268,3 +268,38 @@ def test_invalid_cache_quota(cli, datafiles, tmpdir, quota, success): |
268 | 268 |
res.assert_success()
|
269 | 269 |
else:
|
270 | 270 |
res.assert_main_error(ErrorDomain.LOAD, LoadErrorReason.INVALID_DATA)
|
271 |
+ |
|
272 |
+ |
|
273 |
+@pytest.mark.datafiles(DATA_DIR)
|
|
274 |
+def test_extract_expiry(cli, datafiles, tmpdir):
|
|
275 |
+ project = os.path.join(datafiles.dirname, datafiles.basename)
|
|
276 |
+ element_path = 'elements'
|
|
277 |
+ |
|
278 |
+ cli.configure({
|
|
279 |
+ 'cache': {
|
|
280 |
+ 'quota': 10000000,
|
|
281 |
+ }
|
|
282 |
+ })
|
|
283 |
+ |
|
284 |
+ create_element_size('target.bst', project, element_path, [], 6000000)
|
|
285 |
+ res = cli.run(project=project, args=['build', 'target.bst'])
|
|
286 |
+ res.assert_success()
|
|
287 |
+ assert cli.get_element_state(project, 'target.bst') == 'cached'
|
|
288 |
+ |
|
289 |
+ # Force creating extract
|
|
290 |
+ res = cli.run(project=project, args=['checkout', 'target.bst', os.path.join(str(tmpdir), 'checkout')])
|
|
291 |
+ res.assert_success()
|
|
292 |
+ |
|
293 |
+ extractdir = os.path.join(project, 'cache', 'artifacts', 'extract', 'test', 'target')
|
|
294 |
+ extracts = os.listdir(extractdir)
|
|
295 |
+ assert(len(extracts) == 1)
|
|
296 |
+ extract = os.path.join(extractdir, extracts[0])
|
|
297 |
+ |
|
298 |
+ # Remove target.bst from artifact cache
|
|
299 |
+ create_element_size('target2.bst', project, element_path, [], 6000000)
|
|
300 |
+ res = cli.run(project=project, args=['build', 'target2.bst'])
|
|
301 |
+ res.assert_success()
|
|
302 |
+ assert cli.get_element_state(project, 'target.bst') != 'cached'
|
|
303 |
+ |
|
304 |
+ # Now the extract should be removed.
|
|
305 |
+ assert not os.path.exists(extract)
|
1 |
-90fa9c1b5334aac3bfd8956d92af0a91e2f2bbcbcac73861957165e577bc8768
|
|
\ No newline at end of file | ||
1 |
+05429485dff08bdb968f7d10c2cdda63be49c8a783d54863a0d4abce44bbebe9
|
|
\ No newline at end of file |
1 |
-a62c29fe4e05820412e391430f61aa88a1a82e138de8cac726a9dc4fcd7ed8b9
|
|
\ No newline at end of file | ||
1 |
+4155c7bc836cdb092de3241fa92883bd8c7dd94c55affa406e559aeb6252c669
|
|
\ No newline at end of file |
1 |
-09620aa58875d96611d22632b7585a0f22f88f5ecca6f5d1915d3e529d036bd8
|
|
\ No newline at end of file | ||
1 |
+f5affaacd3ac724f5415a7a8349c6dca6122841dd7f9769de4f9d6cb7185f9b8
|
|
\ No newline at end of file |
... | ... | @@ -28,7 +28,9 @@ def test_autotools_build(cli, tmpdir, datafiles): |
28 | 28 |
|
29 | 29 |
assert_contains(checkout, ['/usr', '/usr/lib', '/usr/bin',
|
30 | 30 |
'/usr/share', '/usr/lib/debug',
|
31 |
- '/usr/lib/debug/hello', '/usr/bin/hello',
|
|
31 |
+ '/usr/lib/debug/usr', '/usr/lib/debug/usr/bin',
|
|
32 |
+ '/usr/lib/debug/usr/bin/hello',
|
|
33 |
+ '/usr/bin/hello',
|
|
32 | 34 |
'/usr/share/doc', '/usr/share/doc/amhello',
|
33 | 35 |
'/usr/share/doc/amhello/README'])
|
34 | 36 |
|
... | ... | @@ -29,7 +29,9 @@ def test_autotools_build(cli, tmpdir, datafiles): |
29 | 29 |
|
30 | 30 |
assert_contains(checkout, ['/usr', '/usr/lib', '/usr/bin',
|
31 | 31 |
'/usr/share', '/usr/lib/debug',
|
32 |
- '/usr/lib/debug/hello', '/usr/bin/hello'])
|
|
32 |
+ '/usr/lib/debug/usr', '/usr/lib/debug/usr/bin',
|
|
33 |
+ '/usr/lib/debug/usr/bin/hello',
|
|
34 |
+ '/usr/bin/hello'])
|
|
33 | 35 |
|
34 | 36 |
|
35 | 37 |
# Test the unmodified hello command works as expected.
|
... | ... | @@ -47,8 +47,10 @@ def test_autotools_build(cli, tmpdir, datafiles): |
47 | 47 |
|
48 | 48 |
assert_contains(checkout, ['/usr', '/usr/lib', '/usr/bin',
|
49 | 49 |
'/usr/share', '/usr/lib/debug',
|
50 |
- '/usr/lib/debug/hello', '/usr/bin/hello',
|
|
51 |
- '/usr/share/doc', '/usr/share/doc/amhello',
|
|
50 |
+ '/usr/lib/debug/usr', '/usr/lib/debug/usr/bin',
|
|
51 |
+ '/usr/lib/debug/usr/bin/hello',
|
|
52 |
+ '/usr/bin/hello', '/usr/share/doc',
|
|
53 |
+ '/usr/share/doc/amhello',
|
|
52 | 54 |
'/usr/share/doc/amhello/README'])
|
53 | 55 |
|
54 | 56 |
|
... | ... | @@ -767,3 +767,16 @@ def test_list_supported_workspace(cli, tmpdir, datafiles, workspace_cfg, expecte |
767 | 767 |
# Check that workspace config is converted correctly if necessary
|
768 | 768 |
loaded_config = _yaml.node_sanitize(_yaml.load(workspace_config_path))
|
769 | 769 |
assert loaded_config == parse_dict_as_yaml(expected)
|
770 |
+ |
|
771 |
+ |
|
772 |
+@pytest.mark.datafiles(DATA_DIR)
|
|
773 |
+@pytest.mark.parametrize("kind", repo_kinds)
|
|
774 |
+def test_inconsitent_pipeline_message(cli, tmpdir, datafiles, kind):
|
|
775 |
+ element_name, project, workspace = open_workspace(cli, tmpdir, datafiles, kind, False)
|
|
776 |
+ |
|
777 |
+ shutil.rmtree(workspace)
|
|
778 |
+ |
|
779 |
+ result = cli.run(project=project, args=[
|
|
780 |
+ 'build', element_name
|
|
781 |
+ ])
|
|
782 |
+ result.assert_main_error(ErrorDomain.PIPELINE, "inconsistent-pipeline-workspaced")
|
... | ... | @@ -31,8 +31,10 @@ def test_autotools_build(cli, tmpdir, datafiles): |
31 | 31 |
|
32 | 32 |
assert_contains(checkout, ['/usr', '/usr/lib', '/usr/bin',
|
33 | 33 |
'/usr/share', '/usr/lib/debug',
|
34 |
- '/usr/lib/debug/hello', '/usr/bin/hello',
|
|
35 |
- '/usr/share/doc', '/usr/share/doc/amhello',
|
|
34 |
+ '/usr/lib/debug/usr', '/usr/lib/debug/usr/bin',
|
|
35 |
+ '/usr/lib/debug/usr/bin/hello',
|
|
36 |
+ '/usr/bin/hello', '/usr/share/doc',
|
|
37 |
+ '/usr/share/doc/amhello',
|
|
36 | 38 |
'/usr/share/doc/amhello/README'])
|
37 | 39 |
|
38 | 40 |
|
... | ... | @@ -27,7 +27,9 @@ def test_cmake_build(cli, tmpdir, datafiles): |
27 | 27 |
assert result.exit_code == 0
|
28 | 28 |
|
29 | 29 |
assert_contains(checkout, ['/usr', '/usr/bin', '/usr/bin/hello',
|
30 |
- '/usr/lib/debug', '/usr/lib/debug/hello'])
|
|
30 |
+ '/usr/lib/debug', '/usr/lib/debug/usr',
|
|
31 |
+ '/usr/lib/debug/usr/bin',
|
|
32 |
+ '/usr/lib/debug/usr/bin/hello'])
|
|
31 | 33 |
|
32 | 34 |
|
33 | 35 |
@pytest.mark.datafiles(DATA_DIR)
|
... | ... | @@ -39,7 +39,8 @@ def create_compose_element(name, path, config={}): |
39 | 39 |
# Test flat inclusion
|
40 | 40 |
([], [], ['/usr', '/usr/lib', '/usr/bin',
|
41 | 41 |
'/usr/share', '/usr/lib/debug',
|
42 |
- '/usr/lib/debug/hello', '/usr/bin/hello',
|
|
42 |
+ '/usr/lib/debug/usr', '/usr/lib/debug/usr/bin',
|
|
43 |
+ '/usr/lib/debug/usr/bin/hello', '/usr/bin/hello',
|
|
43 | 44 |
'/usr/share/doc', '/usr/share/doc/amhello',
|
44 | 45 |
'/usr/share/doc/amhello/README',
|
45 | 46 |
'/tests', '/tests/test']),
|
... | ... | @@ -53,13 +54,17 @@ def create_compose_element(name, path, config={}): |
53 | 54 |
'/usr/share/doc/amhello/README']),
|
54 | 55 |
# Test with only runtime excluded
|
55 | 56 |
([], ['runtime'], ['/usr', '/usr/lib', '/usr/share',
|
56 |
- '/usr/lib/debug', '/usr/lib/debug/hello',
|
|
57 |
+ '/usr/lib/debug', '/usr/lib/debug/usr',
|
|
58 |
+ '/usr/lib/debug/usr/bin',
|
|
59 |
+ '/usr/lib/debug/usr/bin/hello',
|
|
57 | 60 |
'/usr/share/doc', '/usr/share/doc/amhello',
|
58 | 61 |
'/usr/share/doc/amhello/README',
|
59 | 62 |
'/tests', '/tests/test']),
|
60 | 63 |
# Test with runtime and doc excluded
|
61 | 64 |
([], ['runtime', 'doc'], ['/usr', '/usr/lib', '/usr/share',
|
62 |
- '/usr/lib/debug', '/usr/lib/debug/hello',
|
|
65 |
+ '/usr/lib/debug', '/usr/lib/debug/usr',
|
|
66 |
+ '/usr/lib/debug/usr/bin',
|
|
67 |
+ '/usr/lib/debug/usr/bin/hello',
|
|
63 | 68 |
'/tests', '/tests/test']),
|
64 | 69 |
# Test with runtime simultaneously in- and excluded
|
65 | 70 |
(['runtime'], ['runtime'], ['/usr', '/usr/lib', '/usr/share']),
|
... | ... | @@ -72,7 +77,8 @@ def create_compose_element(name, path, config={}): |
72 | 77 |
# Test excluding a custom 'test' domain
|
73 | 78 |
([], ['test'], ['/usr', '/usr/lib', '/usr/bin',
|
74 | 79 |
'/usr/share', '/usr/lib/debug',
|
75 |
- '/usr/lib/debug/hello', '/usr/bin/hello',
|
|
80 |
+ '/usr/lib/debug/usr', '/usr/lib/debug/usr/bin',
|
|
81 |
+ '/usr/lib/debug/usr/bin/hello', '/usr/bin/hello',
|
|
76 | 82 |
'/usr/share/doc', '/usr/share/doc/amhello',
|
77 | 83 |
'/usr/share/doc/amhello/README'])
|
78 | 84 |
])
|
... | ... | @@ -2,7 +2,8 @@ import os |
2 | 2 |
import pytest
|
3 | 3 |
|
4 | 4 |
from buildstream import _yaml, utils
|
5 |
-from tests.testutils import cli, create_repo, ALL_REPO_KINDS
|
|
5 |
+from tests.testutils import create_repo, ALL_REPO_KINDS
|
|
6 |
+from tests.testutils import cli_integration as cli
|
|
6 | 7 |
|
7 | 8 |
|
8 | 9 |
DATA_DIR = os.path.join(
|
... | ... | @@ -28,7 +29,7 @@ def create_test_directory(*path, mode=0o644): |
28 | 29 |
@pytest.mark.integration
|
29 | 30 |
@pytest.mark.datafiles(DATA_DIR)
|
30 | 31 |
@pytest.mark.parametrize("kind", [(kind) for kind in ALL_REPO_KINDS] + ['local'])
|
31 |
-def test_deterministic_source_umask(cli, tmpdir, datafiles, kind):
|
|
32 |
+def test_deterministic_source_umask(cli, tmpdir, datafiles, kind, integration_cache):
|
|
32 | 33 |
project = str(datafiles)
|
33 | 34 |
element_name = 'list'
|
34 | 35 |
element_path = os.path.join(project, 'elements', element_name)
|
... | ... | @@ -91,14 +92,16 @@ def test_deterministic_source_umask(cli, tmpdir, datafiles, kind): |
91 | 92 |
return f.read()
|
92 | 93 |
finally:
|
93 | 94 |
os.umask(old_umask)
|
94 |
- cli.remove_artifact_from_cache(project, element_name)
|
|
95 |
+ cache_dir = os.path.join(integration_cache, 'artifacts')
|
|
96 |
+ cli.remove_artifact_from_cache(project, element_name,
|
|
97 |
+ cache_dir=cache_dir)
|
|
95 | 98 |
|
96 | 99 |
assert get_value_for_umask(0o022) == get_value_for_umask(0o077)
|
97 | 100 |
|
98 | 101 |
|
99 | 102 |
@pytest.mark.integration
|
100 | 103 |
@pytest.mark.datafiles(DATA_DIR)
|
101 |
-def test_deterministic_source_local(cli, tmpdir, datafiles):
|
|
104 |
+def test_deterministic_source_local(cli, tmpdir, datafiles, integration_cache):
|
|
102 | 105 |
"""Only user rights should be considered for local source.
|
103 | 106 |
"""
|
104 | 107 |
project = str(datafiles)
|
... | ... | @@ -150,6 +153,8 @@ def test_deterministic_source_local(cli, tmpdir, datafiles): |
150 | 153 |
with open(os.path.join(checkoutdir, 'ls-l'), 'r') as f:
|
151 | 154 |
return f.read()
|
152 | 155 |
finally:
|
153 |
- cli.remove_artifact_from_cache(project, element_name)
|
|
156 |
+ cache_dir = os.path.join(integration_cache, 'artifacts')
|
|
157 |
+ cli.remove_artifact_from_cache(project, element_name,
|
|
158 |
+ cache_dir=cache_dir)
|
|
154 | 159 |
|
155 | 160 |
assert get_value_for_mask(0o7777) == get_value_for_mask(0o0700)
|
... | ... | @@ -198,8 +198,10 @@ class Cli(): |
198 | 198 |
for key, val in config.items():
|
199 | 199 |
self.config[key] = val
|
200 | 200 |
|
201 |
- def remove_artifact_from_cache(self, project, element_name):
|
|
202 |
- cache_dir = os.path.join(project, 'cache', 'artifacts')
|
|
201 |
+ def remove_artifact_from_cache(self, project, element_name,
|
|
202 |
+ *, cache_dir=None):
|
|
203 |
+ if not cache_dir:
|
|
204 |
+ cache_dir = os.path.join(project, 'cache', 'artifacts')
|
|
203 | 205 |
|
204 | 206 |
cache_dir = os.path.join(cache_dir, 'cas', 'refs', 'heads')
|
205 | 207 |
|
... | ... | @@ -355,6 +355,7 @@ def get_config_from_root(root): |
355 | 355 |
cfg.versionfile_source = get(parser, "versionfile_source")
|
356 | 356 |
cfg.versionfile_build = get(parser, "versionfile_build")
|
357 | 357 |
cfg.tag_prefix = get(parser, "tag_prefix")
|
358 |
+ cfg.tag_regex = get(parser, "tag_regex") or "*"
|
|
358 | 359 |
if cfg.tag_prefix in ("''", '""'):
|
359 | 360 |
cfg.tag_prefix = ""
|
360 | 361 |
cfg.parentdir_prefix = get(parser, "parentdir_prefix")
|
... | ... | @@ -463,6 +464,7 @@ def get_config(): |
463 | 464 |
cfg.VCS = "git"
|
464 | 465 |
cfg.style = "%(STYLE)s"
|
465 | 466 |
cfg.tag_prefix = "%(TAG_PREFIX)s"
|
467 |
+ cfg.tag_regex = "%(TAG_REGEX)s"
|
|
466 | 468 |
cfg.parentdir_prefix = "%(PARENTDIR_PREFIX)s"
|
467 | 469 |
cfg.versionfile_source = "%(VERSIONFILE_SOURCE)s"
|
468 | 470 |
cfg.verbose = False
|
... | ... | @@ -635,7 +637,7 @@ def git_versions_from_keywords(keywords, tag_prefix, verbose): |
635 | 637 |
|
636 | 638 |
|
637 | 639 |
@register_vcs_handler("git", "pieces_from_vcs")
|
638 |
-def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command):
|
|
640 |
+def git_pieces_from_vcs(tag_prefix, tag_regex, root, verbose, run_command=run_command):
|
|
639 | 641 |
"""Get version from 'git describe' in the root of the source tree.
|
640 | 642 |
|
641 | 643 |
This only gets called if the git-archive 'subst' keywords were *not*
|
... | ... | @@ -657,7 +659,7 @@ def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): |
657 | 659 |
# if there isn't one, this yields HEX[-dirty] (no NUM)
|
658 | 660 |
describe_out, rc = run_command(GITS, ["describe", "--tags", "--dirty",
|
659 | 661 |
"--always", "--long",
|
660 |
- "--match", "%%s*" %% tag_prefix],
|
|
662 |
+ "--match", "%%s%%s" %% (tag_prefix, tag_regex)],
|
|
661 | 663 |
cwd=root)
|
662 | 664 |
# --long was added in git-1.5.5
|
663 | 665 |
if describe_out is None:
|
... | ... | @@ -925,7 +927,7 @@ def get_versions(): |
925 | 927 |
"date": None}
|
926 | 928 |
|
927 | 929 |
try:
|
928 |
- pieces = git_pieces_from_vcs(cfg.tag_prefix, root, verbose)
|
|
930 |
+ pieces = git_pieces_from_vcs(cfg.tag_prefix, cfg.tag_regex, root, verbose)
|
|
929 | 931 |
return render(pieces, cfg.style)
|
930 | 932 |
except NotThisMethod:
|
931 | 933 |
pass
|
... | ... | @@ -1027,7 +1029,7 @@ def git_versions_from_keywords(keywords, tag_prefix, verbose): |
1027 | 1029 |
|
1028 | 1030 |
|
1029 | 1031 |
@register_vcs_handler("git", "pieces_from_vcs")
|
1030 |
-def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command):
|
|
1032 |
+def git_pieces_from_vcs(tag_prefix, tag_regex, root, verbose, run_command=run_command):
|
|
1031 | 1033 |
"""Get version from 'git describe' in the root of the source tree.
|
1032 | 1034 |
|
1033 | 1035 |
This only gets called if the git-archive 'subst' keywords were *not*
|
... | ... | @@ -1049,7 +1051,7 @@ def git_pieces_from_vcs(tag_prefix, root, verbose, run_command=run_command): |
1049 | 1051 |
# if there isn't one, this yields HEX[-dirty] (no NUM)
|
1050 | 1052 |
describe_out, rc = run_command(GITS, ["describe", "--tags", "--dirty",
|
1051 | 1053 |
"--always", "--long",
|
1052 |
- "--match", "%s*" % tag_prefix],
|
|
1054 |
+ "--match", "%s%s" % (tag_prefix, tag_regex)],
|
|
1053 | 1055 |
cwd=root)
|
1054 | 1056 |
# --long was added in git-1.5.5
|
1055 | 1057 |
if describe_out is None:
|
... | ... | @@ -1451,7 +1453,7 @@ def get_versions(verbose=False): |
1451 | 1453 |
from_vcs_f = handlers.get("pieces_from_vcs")
|
1452 | 1454 |
if from_vcs_f:
|
1453 | 1455 |
try:
|
1454 |
- pieces = from_vcs_f(cfg.tag_prefix, root, verbose)
|
|
1456 |
+ pieces = from_vcs_f(cfg.tag_prefix, cfg.tag_regex, root, verbose)
|
|
1455 | 1457 |
ver = render(pieces, cfg.style)
|
1456 | 1458 |
if verbose:
|
1457 | 1459 |
print("got version from VCS %s" % ver)
|
... | ... | @@ -1586,6 +1588,7 @@ def get_cmdclass(): |
1586 | 1588 |
{"DOLLAR": "$",
|
1587 | 1589 |
"STYLE": cfg.style,
|
1588 | 1590 |
"TAG_PREFIX": cfg.tag_prefix,
|
1591 |
+ "TAG_REGEX": cfg.tag_regex,
|
|
1589 | 1592 |
"PARENTDIR_PREFIX": cfg.parentdir_prefix,
|
1590 | 1593 |
"VERSIONFILE_SOURCE": cfg.versionfile_source,
|
1591 | 1594 |
})
|
... | ... | @@ -1615,6 +1618,7 @@ def get_cmdclass(): |
1615 | 1618 |
{"DOLLAR": "$",
|
1616 | 1619 |
"STYLE": cfg.style,
|
1617 | 1620 |
"TAG_PREFIX": cfg.tag_prefix,
|
1621 |
+ "TAG_REGEX": cfg.tag_regex,
|
|
1618 | 1622 |
"PARENTDIR_PREFIX": cfg.parentdir_prefix,
|
1619 | 1623 |
"VERSIONFILE_SOURCE": cfg.versionfile_source,
|
1620 | 1624 |
})
|
... | ... | @@ -1716,6 +1720,7 @@ def do_setup(): |
1716 | 1720 |
f.write(LONG % {"DOLLAR": "$",
|
1717 | 1721 |
"STYLE": cfg.style,
|
1718 | 1722 |
"TAG_PREFIX": cfg.tag_prefix,
|
1723 |
+ "TAG_REGEX": cfg.tag_regex,
|
|
1719 | 1724 |
"PARENTDIR_PREFIX": cfg.parentdir_prefix,
|
1720 | 1725 |
"VERSIONFILE_SOURCE": cfg.versionfile_source,
|
1721 | 1726 |
})
|