Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • willsalmon/buildstream
  • CumHoleZH/buildstream
  • tchaik/buildstream
  • DCotyPortfolio/buildstream
  • jesusoctavioas/buildstream
  • patrickmmartin/buildstream
  • franred/buildstream
  • tintou/buildstream
  • alatiera/buildstream
  • martinblanchard/buildstream
  • neverdie22042524/buildstream
  • Mattlk13/buildstream
  • PServers/buildstream
  • phamnghia610909/buildstream
  • chiaratolentino/buildstream
  • eysz7-x-x/buildstream
  • kerrick1/buildstream
  • matthew-yates/buildstream
  • twofeathers/buildstream
  • mhadjimichael/buildstream
  • pointswaves/buildstream
  • Mr.JackWilson/buildstream
  • Tw3akG33k/buildstream
  • AlexFazakas/buildstream
  • eruidfkiy/buildstream
  • clamotion2/buildstream
  • nanonyme/buildstream
  • wickyjaaa/buildstream
  • nmanchev/buildstream
  • bojorquez.ja/buildstream
  • mostynb/buildstream
  • highpit74/buildstream
  • Demo112/buildstream
  • ba2014sheer/buildstream
  • tonimadrino/buildstream
  • usuario2o/buildstream
  • Angelika123456/buildstream
  • neo355/buildstream
  • corentin-ferlay/buildstream
  • coldtom/buildstream
  • wifitvbox81/buildstream
  • 358253885/buildstream
  • seanborg/buildstream
  • SotK/buildstream
  • DouglasWinship/buildstream
  • karansthr97/buildstream
  • louib/buildstream
  • bwh-ct/buildstream
  • robjh/buildstream
  • we88c0de/buildstream
  • zhengxian5555/buildstream
51 results
Show changes
Commits on Source (20)
Showing
with 498 additions and 41 deletions
...@@ -74,6 +74,10 @@ buildstream 1.3.1 ...@@ -74,6 +74,10 @@ buildstream 1.3.1
o Add sandbox API for command batching and use it for build, script, and o Add sandbox API for command batching and use it for build, script, and
compose elements. compose elements.
o BREAKING CHANGE: The `git` plugin does not create a local `.git`
repository by default. If `git describe` is required to work, the
plugin has now a tag tracking feature instead. This can be enabled
by setting 'track-tags'.
================= =================
buildstream 1.1.5 buildstream 1.1.5
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
# Authors: # Authors:
# Tristan Van Berkom <tristan.vanberkom@codethink.co.uk> # Tristan Van Berkom <tristan.vanberkom@codethink.co.uk>
import os from .._platform import Platform
from .optionenum import OptionEnum from .optionenum import OptionEnum
...@@ -41,8 +41,7 @@ class OptionArch(OptionEnum): ...@@ -41,8 +41,7 @@ class OptionArch(OptionEnum):
super(OptionArch, self).load(node, allow_default_definition=False) super(OptionArch, self).load(node, allow_default_definition=False)
def load_default_value(self, node): def load_default_value(self, node):
_, _, _, _, machine_arch = os.uname() return Platform.get_host_arch()
return machine_arch
def resolve(self): def resolve(self):
......
#
# Copyright (C) 2017 Codethink Limited
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library. If not, see <http://www.gnu.org/licenses/>.
#
# Authors:
# Raoul Hidalgo Charman <raoul.hidalgocharman@codethink.co.uk>
import os
from .optionenum import OptionEnum
# OptionOS
#
class OptionOS(OptionEnum):
OPTION_TYPE = 'os'
def load(self, node):
super(OptionOS, self).load(node, allow_default_definition=False)
def load_default_value(self, node):
return os.uname()[0]
def resolve(self):
# Validate that the default OS reported by uname() is explicitly
# supported by the project, if not overridden by user config or cli.
self.validate(self.value)
...@@ -28,6 +28,7 @@ from .optionenum import OptionEnum ...@@ -28,6 +28,7 @@ from .optionenum import OptionEnum
from .optionflags import OptionFlags from .optionflags import OptionFlags
from .optioneltmask import OptionEltMask from .optioneltmask import OptionEltMask
from .optionarch import OptionArch from .optionarch import OptionArch
from .optionos import OptionOS
_OPTION_TYPES = { _OPTION_TYPES = {
...@@ -36,6 +37,7 @@ _OPTION_TYPES = { ...@@ -36,6 +37,7 @@ _OPTION_TYPES = {
OptionFlags.OPTION_TYPE: OptionFlags, OptionFlags.OPTION_TYPE: OptionFlags,
OptionEltMask.OPTION_TYPE: OptionEltMask, OptionEltMask.OPTION_TYPE: OptionEltMask,
OptionArch.OPTION_TYPE: OptionArch, OptionArch.OPTION_TYPE: OptionArch,
OptionOS.OPTION_TYPE: OptionOS,
} }
......
...@@ -25,6 +25,7 @@ from .. import utils ...@@ -25,6 +25,7 @@ from .. import utils
from ..sandbox import SandboxDummy from ..sandbox import SandboxDummy
from . import Platform from . import Platform
from .._exceptions import PlatformError
class Linux(Platform): class Linux(Platform):
...@@ -58,6 +59,9 @@ class Linux(Platform): ...@@ -58,6 +59,9 @@ class Linux(Platform):
else: else:
self._user_ns_available = False self._user_ns_available = False
# Set linux32 option
self._linux32 = False
def create_sandbox(self, *args, **kwargs): def create_sandbox(self, *args, **kwargs):
if not self._local_sandbox_available: if not self._local_sandbox_available:
return self._create_dummy_sandbox(*args, **kwargs) return self._create_dummy_sandbox(*args, **kwargs)
...@@ -71,11 +75,33 @@ class Linux(Platform): ...@@ -71,11 +75,33 @@ class Linux(Platform):
if self._user_ns_available: if self._user_ns_available:
# User namespace support allows arbitrary build UID/GID settings. # User namespace support allows arbitrary build UID/GID settings.
return True pass
else: elif (config.build_uid != self._uid or config.build_gid != self._gid):
# Without user namespace support, the UID/GID in the sandbox # Without user namespace support, the UID/GID in the sandbox
# will match the host UID/GID. # will match the host UID/GID.
return config.build_uid == self._uid and config.build_gid == self._gid return False
# We can't do builds for another host or architecture except x86-32 on
# x86-64
host_os = self.get_host_os()
host_arch = self.get_host_arch()
if config.build_os != host_os:
raise PlatformError("Configured and host OS don't match.")
elif config.build_arch != host_arch:
# We can use linux32 for building 32bit on 64bit machines
if (host_os == "Linux" and
((config.build_arch == "x86-32" and host_arch == "x86-64") or
(config.build_arch == "aarch32" and host_arch == "aarch64"))):
# check linux32 is available
try:
utils.get_host_tool('linux32')
self._linux32 = True
except utils.ProgramNotFoundError:
pass
else:
raise PlatformError("Configured architecture and host architecture don't match.")
return True
################################################ ################################################
# Private Methods # # Private Methods #
...@@ -100,6 +126,7 @@ class Linux(Platform): ...@@ -100,6 +126,7 @@ class Linux(Platform):
kwargs['user_ns_available'] = self._user_ns_available kwargs['user_ns_available'] = self._user_ns_available
kwargs['die_with_parent_available'] = self._die_with_parent_available kwargs['die_with_parent_available'] = self._die_with_parent_available
kwargs['json_status_available'] = self._json_status_available kwargs['json_status_available'] = self._json_status_available
kwargs['linux32'] = self._linux32
return SandboxBwrap(*args, **kwargs) return SandboxBwrap(*args, **kwargs)
def _check_user_ns_available(self): def _check_user_ns_available(self):
......
...@@ -73,6 +73,44 @@ class Platform(): ...@@ -73,6 +73,44 @@ class Platform():
else: else:
return min(cpu_count, cap) return min(cpu_count, cap)
@staticmethod
def get_host_os():
return os.uname()[0]
# get_host_arch():
#
# This returns the architecture of the host machine. The possible values
# map from uname -m in order to be a OS independent list.
#
# Returns:
# (string): String representing the architecture
@staticmethod
def get_host_arch():
# get the hardware identifier from uname
uname_machine = os.uname()[4]
uname_to_arch = {
"aarch64": "aarch64",
"aarch64_be": "aarch64-be",
"amd64": "x86-64",
"arm": "aarch32",
"armv8l": "aarch64",
"armv8b": "aarch64-be",
"i386": "x86-32",
"i486": "x86-32",
"i586": "x86-32",
"i686": "x86-32",
"ppc64": "power-isa-be",
"ppc64le": "power-isa-le",
"sparc": "sparc-v9",
"sparc64": "sparc-v9",
"x86_64": "x86-64"
}
try:
return uname_to_arch[uname_machine]
except KeyError:
raise PlatformError("uname gave unsupported machine architecture: {}"
.format(uname_machine))
################################################################## ##################################################################
# Sandbox functions # # Sandbox functions #
################################################################## ##################################################################
......
...@@ -44,4 +44,13 @@ class Unix(Platform): ...@@ -44,4 +44,13 @@ class Unix(Platform):
def check_sandbox_config(self, config): def check_sandbox_config(self, config):
# With the chroot sandbox, the UID/GID in the sandbox # With the chroot sandbox, the UID/GID in the sandbox
# will match the host UID/GID (typically 0/0). # will match the host UID/GID (typically 0/0).
return config.build_uid == self._uid and config.build_gid == self._gid if config.build_uid != self._uid or config.build_gid != self._gid:
return False
# Check host os and architecture match
if config.build_os != self.get_host_os():
raise PlatformError("Configured and host OS don't match.")
elif config.build_arch != self.get_host_arch():
raise PlatformError("Configured and host architecture don't match.")
return True
...@@ -106,10 +106,16 @@ class BuildQueue(Queue): ...@@ -106,10 +106,16 @@ class BuildQueue(Queue):
def done(self, job, element, result, success): def done(self, job, element, result, success):
if success: # Inform element in main process that assembly is done
# Inform element in main process that assembly is done element._assemble_done()
element._assemble_done()
# This has to be done after _assemble_done, such that the # This has to be done after _assemble_done, such that the
# element may register its cache key as required # element may register its cache key as required
#
# FIXME: Element._assemble() does not report both the failure state and the
# size of the newly cached failed artifact, so we can only adjust the
# artifact cache size for a successful build even though we know a
# failed build also grows the artifact cache size.
#
if success:
self._check_cache_size(job, element, result) self._check_cache_size(job, element, result)
...@@ -292,7 +292,6 @@ class Queue(): ...@@ -292,7 +292,6 @@ class Queue():
# See the Job object for an explanation of the call signature # See the Job object for an explanation of the call signature
# #
def _job_done(self, job, element, success, result): def _job_done(self, job, element, success, result):
element._update_state()
# Update values that need to be synchronized in the main task # Update values that need to be synchronized in the main task
# before calling any queue implementation # before calling any queue implementation
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
# This version is bumped whenever enhancements are made # This version is bumped whenever enhancements are made
# to the `project.conf` format or the core element format. # to the `project.conf` format or the core element format.
# #
BST_FORMAT_VERSION = 18 BST_FORMAT_VERSION = 19
# The base BuildStream artifact version # The base BuildStream artifact version
......
...@@ -2410,6 +2410,11 @@ class Element(Plugin): ...@@ -2410,6 +2410,11 @@ class Element(Plugin):
project.ensure_fully_loaded() project.ensure_fully_loaded()
sandbox_config = _yaml.node_chain_copy(project._sandbox) sandbox_config = _yaml.node_chain_copy(project._sandbox)
# Get the platform to ask for host architecture
platform = Platform.get_platform()
host_arch = platform.get_host_arch()
host_os = platform.get_host_os()
# The default config is already composited with the project overrides # The default config is already composited with the project overrides
sandbox_defaults = _yaml.node_get(self.__defaults, Mapping, 'sandbox', default_value={}) sandbox_defaults = _yaml.node_get(self.__defaults, Mapping, 'sandbox', default_value={})
sandbox_defaults = _yaml.node_chain_copy(sandbox_defaults) sandbox_defaults = _yaml.node_chain_copy(sandbox_defaults)
...@@ -2419,10 +2424,13 @@ class Element(Plugin): ...@@ -2419,10 +2424,13 @@ class Element(Plugin):
_yaml.node_final_assertions(sandbox_config) _yaml.node_final_assertions(sandbox_config)
# Sandbox config, unlike others, has fixed members so we should validate them # Sandbox config, unlike others, has fixed members so we should validate them
_yaml.node_validate(sandbox_config, ['build-uid', 'build-gid']) _yaml.node_validate(sandbox_config, ['build-uid', 'build-gid', 'build-os', 'build-arch'])
return SandboxConfig(self.node_get_member(sandbox_config, int, 'build-uid'), return SandboxConfig(
self.node_get_member(sandbox_config, int, 'build-gid')) self.node_get_member(sandbox_config, int, 'build-uid'),
self.node_get_member(sandbox_config, int, 'build-gid'),
self.node_get_member(sandbox_config, str, 'build-os', default=host_os),
self.node_get_member(sandbox_config, str, 'build-arch', default=host_arch))
# This makes a special exception for the split rules, which # This makes a special exception for the split rules, which
# elements may extend but whos defaults are defined in the project. # elements may extend but whos defaults are defined in the project.
......
...@@ -76,6 +76,56 @@ git - stage files from a git repository ...@@ -76,6 +76,56 @@ git - stage files from a git repository
url: upstream:baz.git url: upstream:baz.git
checkout: False checkout: False
# Enable tag tracking.
#
# This causes the `tags` metadata to be populated automatically
# as a result of tracking the git source.
#
# By default this is 'False'.
#
track-tags: True
# If the list of tags below is set, then a lightweight dummy
# git repository will be staged along with the content at
# build time.
#
# This is useful for a growing number of modules which use
# `git describe` at build time in order to determine the version
# which will be encoded into the built software.
#
# The 'tags' below is considered as a part of the git source
# reference and will be stored in the 'project.refs' file if
# that has been selected as your project's ref-storage.
#
# Migration notes:
#
# If you are upgrading from BuildStream 1.2, which used to
# stage the entire repository by default, you will notice that
# some modules which use `git describe` are broken, and will
# need to enable this feature in order to fix them.
#
# If you need to enable this feature without changing the
# the specific commit that you are building, then we recommend
# the following migration steps for any git sources where
# `git describe` is required:
#
# o Enable `track-tags` feature
# o Set the `track` parameter to the desired commit sha which
# the current `ref` points to
# o Run `bst track` for these elements, this will result in
# populating the `tags` portion of the refs without changing
# the refs
# o Restore the `track` parameter to the branches which you have
# previously been tracking afterwards.
#
tags:
- tag: lightweight-example
commit: 04ad0dc656cb7cc6feb781aa13bdbf1d67d0af78
annotated: false
- tag: annotated-example
commit: 10abe77fe8d77385d86f225b503d9185f4ef7f3a
annotated: true
See :ref:`built-in functionality doumentation <core_source_builtins>` for See :ref:`built-in functionality doumentation <core_source_builtins>` for
details on common configuration options for sources. details on common configuration options for sources.
...@@ -95,6 +145,7 @@ import re ...@@ -95,6 +145,7 @@ import re
import shutil import shutil
from collections.abc import Mapping from collections.abc import Mapping
from io import StringIO from io import StringIO
from tempfile import TemporaryFile
from configparser import RawConfigParser from configparser import RawConfigParser
...@@ -115,13 +166,14 @@ INCONSISTENT_SUBMODULE = "inconsistent-submodules" ...@@ -115,13 +166,14 @@ INCONSISTENT_SUBMODULE = "inconsistent-submodules"
# #
class GitMirror(SourceFetcher): class GitMirror(SourceFetcher):
def __init__(self, source, path, url, ref, *, primary=False): def __init__(self, source, path, url, ref, *, primary=False, tags=[]):
super().__init__() super().__init__()
self.source = source self.source = source
self.path = path self.path = path
self.url = url self.url = url
self.ref = ref self.ref = ref
self.tags = tags
self.primary = primary self.primary = primary
self.mirror = os.path.join(source.get_mirror_directory(), utils.url_directory_name(url)) self.mirror = os.path.join(source.get_mirror_directory(), utils.url_directory_name(url))
self.mark_download_url(url) self.mark_download_url(url)
...@@ -214,7 +266,7 @@ class GitMirror(SourceFetcher): ...@@ -214,7 +266,7 @@ class GitMirror(SourceFetcher):
raise SourceError("{}: expected ref '{}' was not found in git repository: '{}'" raise SourceError("{}: expected ref '{}' was not found in git repository: '{}'"
.format(self.source, self.ref, self.url)) .format(self.source, self.ref, self.url))
def latest_commit(self, tracking): def latest_commit_with_tags(self, tracking, track_tags=False):
_, output = self.source.check_output( _, output = self.source.check_output(
[self.source.host_git, 'rev-parse', tracking], [self.source.host_git, 'rev-parse', tracking],
fail="Unable to find commit for specified branch name '{}'".format(tracking), fail="Unable to find commit for specified branch name '{}'".format(tracking),
...@@ -230,7 +282,28 @@ class GitMirror(SourceFetcher): ...@@ -230,7 +282,28 @@ class GitMirror(SourceFetcher):
if exit_code == 0: if exit_code == 0:
ref = output.rstrip('\n') ref = output.rstrip('\n')
return ref if not track_tags:
return ref, []
tags = set()
for options in [[], ['--first-parent'], ['--tags'], ['--tags', '--first-parent']]:
exit_code, output = self.source.check_output(
[self.source.host_git, 'describe', '--abbrev=0', ref] + options,
cwd=self.mirror)
if exit_code == 0:
tag = output.strip()
_, commit_ref = self.source.check_output(
[self.source.host_git, 'rev-parse', tag + '^{commit}'],
fail="Unable to resolve tag '{}'".format(tag),
cwd=self.mirror)
exit_code = self.source.call(
[self.source.host_git, 'cat-file', 'tag', tag],
cwd=self.mirror)
annotated = (exit_code == 0)
tags.add((tag, commit_ref.strip(), annotated))
return ref, list(tags)
def stage(self, directory, track=None): def stage(self, directory, track=None):
fullpath = os.path.join(directory, self.path) fullpath = os.path.join(directory, self.path)
...@@ -246,13 +319,15 @@ class GitMirror(SourceFetcher): ...@@ -246,13 +319,15 @@ class GitMirror(SourceFetcher):
fail="Failed to checkout git ref {}".format(self.ref), fail="Failed to checkout git ref {}".format(self.ref),
cwd=fullpath) cwd=fullpath)
# Remove .git dir
shutil.rmtree(os.path.join(fullpath, ".git"))
self._rebuild_git(fullpath)
# Check that the user specified ref exists in the track if provided & not already tracked # Check that the user specified ref exists in the track if provided & not already tracked
if track: if track:
self.assert_ref_in_track(fullpath, track) self.assert_ref_in_track(fullpath, track)
# Remove .git dir
shutil.rmtree(os.path.join(fullpath, ".git"))
def init_workspace(self, directory, track=None): def init_workspace(self, directory, track=None):
fullpath = os.path.join(directory, self.path) fullpath = os.path.join(directory, self.path)
url = self.source.translate_url(self.url) url = self.source.translate_url(self.url)
...@@ -359,6 +434,78 @@ class GitMirror(SourceFetcher): ...@@ -359,6 +434,78 @@ class GitMirror(SourceFetcher):
.format(self.source, self.ref, track, self.url), .format(self.source, self.ref, track, self.url),
detail=detail, warning_token=CoreWarnings.REF_NOT_IN_TRACK) detail=detail, warning_token=CoreWarnings.REF_NOT_IN_TRACK)
def _rebuild_git(self, fullpath):
if not self.tags:
return
with self.source.tempdir() as tmpdir:
included = set()
shallow = set()
for _, commit_ref, _ in self.tags:
_, out = self.source.check_output([self.source.host_git, 'rev-list',
'--boundary', '{}..{}'.format(commit_ref, self.ref)],
fail="Failed to get git history {}..{} in directory: {}"
.format(commit_ref, self.ref, fullpath),
fail_temporarily=True,
cwd=self.mirror)
for line in out.splitlines():
rev = line.lstrip('-')
if line[0] == '-':
shallow.add(rev)
else:
included.add(rev)
shallow -= included
included |= shallow
self.source.call([self.source.host_git, 'init'],
fail="Cannot initialize git repository: {}".format(fullpath),
cwd=fullpath)
for rev in included:
with TemporaryFile(dir=tmpdir) as commit_file:
self.source.call([self.source.host_git, 'cat-file', 'commit', rev],
stdout=commit_file,
fail="Failed to get commit {}".format(rev),
cwd=self.mirror)
commit_file.seek(0, 0)
self.source.call([self.source.host_git, 'hash-object', '-w', '-t', 'commit', '--stdin'],
stdin=commit_file,
fail="Failed to add commit object {}".format(rev),
cwd=fullpath)
with open(os.path.join(fullpath, '.git', 'shallow'), 'w') as shallow_file:
for rev in shallow:
shallow_file.write('{}\n'.format(rev))
for tag, commit_ref, annotated in self.tags:
if annotated:
with TemporaryFile(dir=tmpdir) as tag_file:
tag_data = 'object {}\ntype commit\ntag {}\n'.format(commit_ref, tag)
tag_file.write(tag_data.encode('ascii'))
tag_file.seek(0, 0)
_, tag_ref = self.source.check_output(
[self.source.host_git, 'hash-object', '-w', '-t',
'tag', '--stdin'],
stdin=tag_file,
fail="Failed to add tag object {}".format(tag),
cwd=fullpath)
self.source.call([self.source.host_git, 'tag', tag, tag_ref.strip()],
fail="Failed to tag: {}".format(tag),
cwd=fullpath)
else:
self.source.call([self.source.host_git, 'tag', tag, commit_ref],
fail="Failed to tag: {}".format(tag),
cwd=fullpath)
with open(os.path.join(fullpath, '.git', 'HEAD'), 'w') as head:
self.source.call([self.source.host_git, 'rev-parse', self.ref],
stdout=head,
fail="Failed to parse commit {}".format(self.ref),
cwd=self.mirror)
class GitSource(Source): class GitSource(Source):
# pylint: disable=attribute-defined-outside-init # pylint: disable=attribute-defined-outside-init
...@@ -366,11 +513,20 @@ class GitSource(Source): ...@@ -366,11 +513,20 @@ class GitSource(Source):
def configure(self, node): def configure(self, node):
ref = self.node_get_member(node, str, 'ref', None) ref = self.node_get_member(node, str, 'ref', None)
config_keys = ['url', 'track', 'ref', 'submodules', 'checkout-submodules', 'ref-format'] config_keys = ['url', 'track', 'ref', 'submodules',
'checkout-submodules', 'ref-format',
'track-tags', 'tags']
self.node_validate(node, config_keys + Source.COMMON_CONFIG_KEYS) self.node_validate(node, config_keys + Source.COMMON_CONFIG_KEYS)
tags_node = self.node_get_member(node, list, 'tags', [])
for tag_node in tags_node:
self.node_validate(tag_node, ['tag', 'commit', 'annotated'])
tags = self._load_tags(node)
self.track_tags = self.node_get_member(node, bool, 'track-tags', False)
self.original_url = self.node_get_member(node, str, 'url') self.original_url = self.node_get_member(node, str, 'url')
self.mirror = GitMirror(self, '', self.original_url, ref, primary=True) self.mirror = GitMirror(self, '', self.original_url, ref, tags=tags, primary=True)
self.tracking = self.node_get_member(node, str, 'track', None) self.tracking = self.node_get_member(node, str, 'track', None)
self.ref_format = self.node_get_member(node, str, 'ref-format', 'sha1') self.ref_format = self.node_get_member(node, str, 'ref-format', 'sha1')
...@@ -417,6 +573,9 @@ class GitSource(Source): ...@@ -417,6 +573,9 @@ class GitSource(Source):
# the ref, if the user changes the alias to fetch the same sources # the ref, if the user changes the alias to fetch the same sources
# from another location, it should not affect the cache key. # from another location, it should not affect the cache key.
key = [self.original_url, self.mirror.ref] key = [self.original_url, self.mirror.ref]
if self.mirror.tags:
tags = {tag: (commit, annotated) for tag, commit, annotated in self.mirror.tags}
key.append({'tags': tags})
# Only modify the cache key with checkout_submodules if it's something # Only modify the cache key with checkout_submodules if it's something
# other than the default behaviour. # other than the default behaviour.
...@@ -442,12 +601,33 @@ class GitSource(Source): ...@@ -442,12 +601,33 @@ class GitSource(Source):
def load_ref(self, node): def load_ref(self, node):
self.mirror.ref = self.node_get_member(node, str, 'ref', None) self.mirror.ref = self.node_get_member(node, str, 'ref', None)
self.mirror.tags = self._load_tags(node)
def get_ref(self): def get_ref(self):
return self.mirror.ref return self.mirror.ref, self.mirror.tags
def set_ref(self, ref, node): def set_ref(self, ref_data, node):
node['ref'] = self.mirror.ref = ref if not ref_data:
self.mirror.ref = None
if 'ref' in node:
del node['ref']
self.mirror.tags = []
if 'tags' in node:
del node['tags']
else:
ref, tags = ref_data
node['ref'] = self.mirror.ref = ref
self.mirror.tags = tags
if tags:
node['tags'] = []
for tag, commit_ref, annotated in tags:
data = {'tag': tag,
'commit': commit_ref,
'annotated': annotated}
node['tags'].append(data)
else:
if 'tags' in node:
del node['tags']
def track(self): def track(self):
...@@ -470,7 +650,7 @@ class GitSource(Source): ...@@ -470,7 +650,7 @@ class GitSource(Source):
self.mirror._fetch() self.mirror._fetch()
# Update self.mirror.ref and node.ref from the self.tracking branch # Update self.mirror.ref and node.ref from the self.tracking branch
ret = self.mirror.latest_commit(self.tracking) ret = self.mirror.latest_commit_with_tags(self.tracking, self.track_tags)
# Set tracked attribute, parameter for if self.mirror.assert_ref_in_track is needed # Set tracked attribute, parameter for if self.mirror.assert_ref_in_track is needed
self.tracked = True self.tracked = True
...@@ -556,6 +736,16 @@ class GitSource(Source): ...@@ -556,6 +736,16 @@ class GitSource(Source):
self.submodules = submodules self.submodules = submodules
def _load_tags(self, node):
tags = []
tags_node = self.node_get_member(node, list, 'tags', [])
for tag_node in tags_node:
tag = self.node_get_member(tag_node, str, 'tag')
commit_ref = self.node_get_member(tag_node, str, 'commit')
annotated = self.node_get_member(tag_node, bool, 'annotated')
tags.append((tag, commit_ref, annotated))
return tags
# Plugin entry point # Plugin entry point
def setup(): def setup():
......
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
# #
# Authors: # Authors:
# Jim MacArthur <jim.macarthur@codethink.co.uk> # Jim MacArthur <jim.macarthur@codethink.co.uk>
import os
# SandboxConfig # SandboxConfig
...@@ -24,9 +23,11 @@ import os ...@@ -24,9 +23,11 @@ import os
# A container for sandbox configuration data. We want the internals # A container for sandbox configuration data. We want the internals
# of this to be opaque, hence putting it in its own private file. # of this to be opaque, hence putting it in its own private file.
class SandboxConfig(): class SandboxConfig():
def __init__(self, build_uid, build_gid): def __init__(self, build_uid, build_gid, build_os=None, build_arch=None):
self.build_uid = build_uid self.build_uid = build_uid
self.build_gid = build_gid self.build_gid = build_gid
self.build_os = build_os
self.build_arch = build_arch
# get_unique_key(): # get_unique_key():
# #
...@@ -45,10 +46,9 @@ class SandboxConfig(): ...@@ -45,10 +46,9 @@ class SandboxConfig():
# However this should be the right place to support # However this should be the right place to support
# such configurations in the future. # such configurations in the future.
# #
operating_system, _, _, _, machine_arch = os.uname()
unique_key = { unique_key = {
'os': operating_system, 'os': self.build_os,
'arch': machine_arch 'arch': self.build_arch
} }
# Avoid breaking cache key calculation with # Avoid breaking cache key calculation with
......
...@@ -57,6 +57,7 @@ class SandboxBwrap(Sandbox): ...@@ -57,6 +57,7 @@ class SandboxBwrap(Sandbox):
self.user_ns_available = kwargs['user_ns_available'] self.user_ns_available = kwargs['user_ns_available']
self.die_with_parent_available = kwargs['die_with_parent_available'] self.die_with_parent_available = kwargs['die_with_parent_available']
self.json_status_available = kwargs['json_status_available'] self.json_status_available = kwargs['json_status_available']
self.linux32 = kwargs['linux32']
def _run(self, command, flags, *, cwd, env): def _run(self, command, flags, *, cwd, env):
stdout, stderr = self._get_output() stdout, stderr = self._get_output()
...@@ -74,8 +75,14 @@ class SandboxBwrap(Sandbox): ...@@ -74,8 +75,14 @@ class SandboxBwrap(Sandbox):
mount_map = MountMap(self, flags & SandboxFlags.ROOT_READ_ONLY) mount_map = MountMap(self, flags & SandboxFlags.ROOT_READ_ONLY)
root_mount_source = mount_map.get_mount_source('/') root_mount_source = mount_map.get_mount_source('/')
# start command with linux32 if needed
if self.linux32:
bwrap_command = [utils.get_host_tool('linux32')]
else:
bwrap_command = []
# Grab the full path of the bwrap binary # Grab the full path of the bwrap binary
bwrap_command = [utils.get_host_tool('bwrap')] bwrap_command += [utils.get_host_tool('bwrap')]
for k, v in env.items(): for k, v in env.items():
bwrap_command += ['--setenv', k, v] bwrap_command += ['--setenv', k, v]
......
...@@ -126,13 +126,20 @@ class SandboxRemote(Sandbox): ...@@ -126,13 +126,20 @@ class SandboxRemote(Sandbox):
EnvironmentVariable(name=k, value=v) EnvironmentVariable(name=k, value=v)
for (k, v) in environment.items()] for (k, v) in environment.items()]
config = self._get_config()
platform = remote_execution_pb2.Platform()
platform.properties.extend([remote_execution_pb2.Platform.
Property(name="OSFamily", value=config.build_os),
remote_execution_pb2.Platform.
Property(name="ISA", value=config.build_arch)])
# Create and send the Command object. # Create and send the Command object.
remote_command = remote_execution_pb2.Command(arguments=command, remote_command = remote_execution_pb2.Command(arguments=command,
working_directory=working_directory, working_directory=working_directory,
environment_variables=environment_variables, environment_variables=environment_variables,
output_files=[], output_files=[],
output_directories=[self._output_directory], output_directories=[self._output_directory],
platform=None) platform=platform)
context = self._get_context() context = self._get_context()
cascache = context.get_cascache() cascache = context.get_cascache()
casremote = CASRemote(self.storage_remote_spec) casremote = CASRemote(self.storage_remote_spec)
......
#!/usr/bin/python3
#
# Copyright 2017 Bloomberg Finance LP
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library. If not, see <http://www.gnu.org/licenses/>.
#
# Authors:
# Phillip Smyth <phillip.smyth@codethink.co.uk>
# This is a helper script for building all the elements in a project
import os
import bstGetAllElements
import subprocess
def bst_build_all_elements():
elements = bstGetAllElements.get_all_buildable_elements()
command = ["bst", "build"] + elements
subprocess.call(command)
bst_build_all_elements()
#
# Copyright 2017 Bloomberg Finance LP
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library. If not, see <http://www.gnu.org/licenses/>.
#
# Authors:
# Phillip Smyth <phillip.smyth@codethink.co.uk>
# This is a helper script for returning all the elements in a project
import os
def get_all_buildable_elements():
elements = []
cwd = os.getcwd()
element_path = get_element_path("project.conf")
for root, _, files in os.walk(cwd):
for file in files:
if file.endswith(".bst"):
relDir = os.path.relpath(root, cwd)
relFile = os.path.join(relDir, file).strip("./")
if is_not_junction(relFile):
relFile = relFile.replace(element_path, '')
elements.append(relFile)
return elements
def is_not_junction(element):
with open(element) as search:
for line in search:
if "junction" in line:
return False
return True
def get_element_path(project_conf):
if os.path.isfile(project_conf):
with open(project_conf) as search:
for line in search:
if "element-path" in line:
line = line.rstrip()
line = line.replace("element-path: ","")
line += '/'
return line
return "."
raise Exception("No project.conf was found in this directory")
#!/usr/bin/python3
#
# Copyright 2017 Bloomberg Finance LP
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library. If not, see <http://www.gnu.org/licenses/>.
#
# Authors:
# Phillip Smyth <phillip.smyth@codethink.co.uk>
# This is a helper script for validating all the elements in a project
import os
import bstGetAllElements
import subprocess
def bst_show_all_elements():
elements = bstGetAllElements.get_all_buildable_elements()
command = ["bst", "show"] + elements
subprocess.call(command)
bst_show_all_elements()
...@@ -5,10 +5,10 @@ sources: ...@@ -5,10 +5,10 @@ sources:
url: gnomesdk:repo/ url: gnomesdk:repo/
gpg-key: keys/gnome-sdk.gpg gpg-key: keys/gnome-sdk.gpg
(?): (?):
- arch == "x86_64": - arch == "x86-64":
track: runtime/org.freedesktop.BaseSdk/x86_64/1.4 track: runtime/org.freedesktop.BaseSdk/x86_64/1.4
ref: 0d9d255d56b08aeaaffb1c820eef85266eb730cb5667e50681185ccf5cd7c882 ref: 0d9d255d56b08aeaaffb1c820eef85266eb730cb5667e50681185ccf5cd7c882
- arch == "i386": - arch == "x86-32":
track: runtime/org.freedesktop.BaseSdk/i386/1.4 track: runtime/org.freedesktop.BaseSdk/i386/1.4
ref: 16036b747c1ec8e7fe291f5b1f667cb942f0267d08fcad962e9b7627d6cf1981 ref: 16036b747c1ec8e7fe291f5b1f667cb942f0267d08fcad962e9b7627d6cf1981
config: config:
......
...@@ -10,6 +10,6 @@ options: ...@@ -10,6 +10,6 @@ options:
type: arch type: arch
description: The machine architecture description: The machine architecture
values: values:
- x86_64 - x86-64
- i386 - x86-32