diff options
author | Adam Coldrick <adam.coldrick@codethink.co.uk> | 2015-03-12 14:37:29 +0000 |
---|---|---|
committer | Adam Coldrick <adam.coldrick@codethink.co.uk> | 2015-03-12 14:38:41 +0000 |
commit | cd857ff295574589fb4cb61e7dbda16387c974e4 (patch) | |
tree | 5f5fffd27a60376a1301f4c5332f6db4be2b5f2e | |
parent | 8fcf5f3c68e24b96347aee0819ab18cf97b48721 (diff) | |
download | morph-cd857ff295574589fb4cb61e7dbda16387c974e4.tar.gz |
WIP: Implement partial builds
-rw-r--r-- | morphlib/app.py | 4 | ||||
-rw-r--r-- | morphlib/plugins/build_plugin.py | 72 |
2 files changed, 67 insertions, 9 deletions
diff --git a/morphlib/app.py b/morphlib/app.py index b8bae850..4e2253b4 100644 --- a/morphlib/app.py +++ b/morphlib/app.py @@ -139,6 +139,10 @@ class Morph(cliapp.Application): 'always push temporary build branches to the ' 'remote repository', group=group_build) + self.settings.boolean(['partial'], + 'only build up to a given chunk', + default=False, + group=group_build) self.settings.choice (['local-changes'], ['include', 'ignore'], 'the `build` and `deploy` commands detect ' diff --git a/morphlib/plugins/build_plugin.py b/morphlib/plugins/build_plugin.py index e9290b8d..b4c9900e 100644 --- a/morphlib/plugins/build_plugin.py +++ b/morphlib/plugins/build_plugin.py @@ -14,11 +14,13 @@ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -import cliapp +import collections import contextlib import uuid import logging +import cliapp + import morphlib @@ -150,7 +152,7 @@ class BuildPlugin(cliapp.Plugin): ''' - if len(args) != 1: + if len(args) != 1 and not self.app.settings['partial']: raise cliapp.AppException('morph build expects exactly one ' 'parameter: the system to build') @@ -166,6 +168,10 @@ class BuildPlugin(cliapp.Plugin): system_filename = morphlib.util.sanitise_morphology_path(args[0]) system_filename = sb.relative_to_root_repo(system_filename) + if self.app.settings['partial']: + chunk_filenames = self._sanitise_morphology_paths(args[1:], sb) + else: + chunk_filenames = [] logging.debug('System branch is %s' % sb.root_directory) @@ -179,11 +185,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, + chunk_filenames) else: - self._build_local_commit(build_command, sb, system_filename) + self._build_local_commit(build_command, sb, system_filename, + chunk_filenames) - def _build_with_local_changes(self, build_command, sb, system_filename): + def _build_with_local_changes(self, build_command, sb, system_filename, + chunk_filenames): '''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 @@ -212,10 +221,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, + chunk_filenames, original_ref=original_ref) - def _build_local_commit(self, build_command, sb, system_filename): + def _build_local_commit(self, build_command, sb, system_filename, + chunk_filenames): '''Build whatever commit the user has checked-out locally. This ignores any uncommitted changes. Also, if the user has a commit @@ -243,4 +253,48 @@ 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, chunk_filenames) + + def _sanitise_morphology_paths(self, paths, sb): + sanitised_paths = [] + for path in paths: + path = morphlib.util.sanitise_morphology_path(path) + sanitised_paths.append(sb.relative_to_root_repo(path)) + return sanitised_paths + + def _find_artifacts(self, filenames, root_artifact): + found = collections.OrderedDict() + for a in root_artifact.walk(): + if a.source.filename in filenames and a.source.name not in found: + found[a.source.name] = a + return found + + def start_build(self, repo, commit, bc, system_filename, + chunk_filenames, original_ref=None): + '''Actually run the build. + + If --partial was set on the command line, we expect that there is a + list of chunks for us to build. Decide on the correct order to build + these in and build each one in turn. + + ''' + if not self.app.settings['partial']: + if original_ref: + bc.build(repo, commit, system_filename, + original_ref=original_ref) + else: + bc.build(repo, commit, system_filename) + return + + self.app.status(msg='Deciding on task order') + srcpool = bc.create_source_pool(repo, commit, system_filename) + root = bc.resolve_artifacts(srcpool) + chunks = self._find_artifacts(chunk_filenames, root) + if not chunks: + raise ChunksNotInSystemError(chunk_filenames, system_filename) + + for name, chunk in chunks.iteritems(): + self.app.status(msg='Starting build of %s' % name) + chunk.build_env = root.build_env + bc.build_in_order(chunk) |