diff options
-rw-r--r-- | morphlib/buildcommand.py | 5 | ||||
-rw-r--r-- | morphlib/plugins/build_plugin.py | 108 | ||||
-rw-r--r-- | tests.build/only-build-systems.stderr | 4 |
3 files changed, 94 insertions, 23 deletions
diff --git a/morphlib/buildcommand.py b/morphlib/buildcommand.py index be8a1507..a6be8a8c 100644 --- a/morphlib/buildcommand.py +++ b/morphlib/buildcommand.py @@ -119,7 +119,10 @@ class BuildCommand(object): root_kind = root_artifact.source.morphology['kind'] if root_kind != 'system': raise morphlib.Error( - 'Building a %s directly is not supported' % root_kind) + 'In order to build this %s directly, please give the filename ' + 'of the system which contains it, and the name of the %s. ' + 'See `morph build --help` for more information.' + % (root_kind, root_kind)) def _validate_architecture(self, root_artifact): '''Perform the validation between root and target architectures.''' diff --git a/morphlib/plugins/build_plugin.py b/morphlib/plugins/build_plugin.py index a5502180..f6372aed 100644 --- a/morphlib/plugins/build_plugin.py +++ b/morphlib/plugins/build_plugin.py @@ -13,21 +13,33 @@ # with this program. If not, see <http://www.gnu.org/licenses/>. -import cliapp +import collections import contextlib import uuid import logging +import cliapp + import morphlib +class ComponentNotInSystemError(morphlib.Error): + + def __init__(self, components, system): + components = ', '.join(components) + self.msg = ('Components %s are not in %s. Ensure you provided ' + 'component names rather than filenames.' + % (components, system)) + + class BuildPlugin(cliapp.Plugin): def enable(self): self.app.add_subcommand('build-morphology', self.build_morphology, - arg_synopsis='(REPO REF FILENAME)...') + arg_synopsis='REPO REF FILENAME ' + '[COMPONENT...]') self.app.add_subcommand('build', self.build, - arg_synopsis='SYSTEM') + arg_synopsis='SYSTEM [COMPONENT...]') self.app.add_subcommand('distbuild-morphology', self.distbuild_morphology, arg_synopsis='SYSTEM') @@ -92,6 +104,8 @@ class BuildPlugin(cliapp.Plugin): * `REPO` is a git repository URL. * `REF` is a branch or other commit reference in that repository. * `FILENAME` is a morphology filename at that ref. + * `COMPONENT...` is the names of one or more chunks or strata to + build. If none are given then the system at FILENAME is built. You probably want `morph build` instead. However, in some cases it is more convenient to not have to create a Morph @@ -104,8 +118,14 @@ class BuildPlugin(cliapp.Plugin): Example: - morph build-morphology baserock:baserock/definitions \ - master devel-system-x86_64-generic.morph + morph build-morphology baserock:baserock/definitions \\ + master systems/devel-system-x86_64-generic.morph + + Partial build example: + + morph build-morphology baserock:baserock/definitions \\ + master systems/devel-system-x86_64-generic.morph \\ + build-essential ''' @@ -117,15 +137,21 @@ class BuildPlugin(cliapp.Plugin): self.app.settings['cachedir-min-space']) build_command = morphlib.buildcommand.BuildCommand(self.app) - for repo_name, ref, filename in self.app.itertriplets(args): - build_command.build(repo_name, ref, filename) + repo, ref, filename = args[0:3] + filename = morphlib.util.sanitise_morphology_path(filename) + component_names = [morphlib.util.sanitise_morphology_path(name) + for name in args[3:]] + self.start_build(repo, ref, build_command, filename, + component_names) def build(self, args): '''Build a system image in the current system branch Command line arguments: - * `SYSTEM` is the name of the system to build. + * `SYSTEM` is the filename of the system to build. + * `COMPONENT...` is the names of one or more chunks or strata to + build. If this is not given then the SYSTEM is built. This builds a system image, and any of its components that need building. The system name is the basename of the system @@ -145,14 +171,14 @@ class BuildPlugin(cliapp.Plugin): Example: - morph build devel-system-x86_64-generic.morph + morph build systems/devel-system-x86_64-generic.morph - ''' + Partial build example: - if len(args) != 1: - raise cliapp.AppException('morph build expects exactly one ' - 'parameter: the system to build') + morph build systems/devel-system-x86_64-generic.morph \\ + build-essential + ''' # Raise an exception if there is not enough space morphlib.util.check_disk_available( self.app.settings['tempdir'], @@ -165,6 +191,7 @@ class BuildPlugin(cliapp.Plugin): system_filename = morphlib.util.sanitise_morphology_path(args[0]) system_filename = sb.relative_to_root_repo(system_filename) + component_names = args[1:] logging.debug('System branch is %s' % sb.root_directory) @@ -178,11 +205,14 @@ class BuildPlugin(cliapp.Plugin): build_command = morphlib.buildcommand.BuildCommand(self.app) if self.app.settings['local-changes'] == 'include': - self._build_with_local_changes(build_command, sb, system_filename) + self._build_with_local_changes(build_command, sb, system_filename, + component_names) else: - self._build_local_commit(build_command, sb, system_filename) + self._build_local_commit(build_command, sb, system_filename, + component_names) - def _build_with_local_changes(self, build_command, sb, system_filename): + def _build_with_local_changes(self, build_command, sb, system_filename, + component_names): '''Construct a branch including user's local changes, and build that. It is often a slow process to check all repos in the system branch for @@ -214,10 +244,11 @@ class BuildPlugin(cliapp.Plugin): name=name, email=email, build_uuid=build_uuid, status=self.app.status) with pbb as (repo, commit, original_ref): - build_command.build(repo, commit, system_filename, - original_ref=original_ref) + self.start_build(repo, commit, build_command, system_filename, + component_names, original_ref=original_ref) - def _build_local_commit(self, build_command, sb, system_filename): + def _build_local_commit(self, build_command, sb, system_filename, + component_names): '''Build whatever commit the user has checked-out locally. This ignores any uncommitted changes. Also, if the user has a commit @@ -245,4 +276,41 @@ class BuildPlugin(cliapp.Plugin): definitions_repo = morphlib.gitdir.GitDirectory(definitions_repo_path) commit = definitions_repo.resolve_ref_to_commit(ref) - build_command.build(root_repo_url, commit, system_filename) + self.start_build(root_repo_url, commit, build_command, + system_filename, component_names) + + def _find_artifacts(self, names, root_artifact): + found = collections.OrderedDict() + not_found = names + for a in root_artifact.walk(): + name = a.source.morphology['name'] + if name in names and name not in found: + found[name] = a + not_found.remove(name) + return found, not_found + + def start_build(self, repo, commit, bc, system_filename, + component_names, original_ref=None): + '''Actually run the build. + + If a set of components was given, only build those. Otherwise, + build the whole system. + + ''' + self.app.status(msg='Deciding on task order') + srcpool = bc.create_source_pool(repo, commit, system_filename) + bc.validate_sources(srcpool) + root = bc.resolve_artifacts(srcpool) + if not component_names: + component_names = [root.source.name] + components, not_found = self._find_artifacts(component_names, root) + if not_found: + raise ComponentNotInSystemError(not_found, system_filename) + + for name, component in components.iteritems(): + component.build_env = root.build_env + bc.build_in_order(component) + self.app.status(msg='%(kind)s %(name)s is cached at %(path)s', + kind=component.source.morphology['kind'], + name=name, + path=bc.lac.artifact_filename(component)) diff --git a/tests.build/only-build-systems.stderr b/tests.build/only-build-systems.stderr index ba7339d2..ac24ab25 100644 --- a/tests.build/only-build-systems.stderr +++ b/tests.build/only-build-systems.stderr @@ -1,2 +1,2 @@ -ERROR: Building a stratum directly is not supported -ERROR: Building a chunk directly is not supported +ERROR: In order to build this stratum directly, please give the filename of the system which contains it, and the name of the stratum. See `morph build --help` for more information. +ERROR: In order to build this chunk directly, please give the filename of the system which contains it, and the name of the chunk. See `morph build --help` for more information. |