summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Coldrick <adam.coldrick@codethink.co.uk>2015-03-12 14:37:29 +0000
committerAdam Coldrick <adam.coldrick@codethink.co.uk>2015-03-12 14:38:41 +0000
commitcd857ff295574589fb4cb61e7dbda16387c974e4 (patch)
tree5f5fffd27a60376a1301f4c5332f6db4be2b5f2e
parent8fcf5f3c68e24b96347aee0819ab18cf97b48721 (diff)
downloadmorph-cd857ff295574589fb4cb61e7dbda16387c974e4.tar.gz
WIP: Implement partial builds
-rw-r--r--morphlib/app.py4
-rw-r--r--morphlib/plugins/build_plugin.py72
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)