summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Thursfield <sam.thursfield@codethink.co.uk>2015-07-28 15:23:09 +0000
committerSam Thursfield <sam.thursfield@codethink.co.uk>2015-09-17 10:39:25 +0000
commitb652fc3cb55a238293c246f2bfad2a18ade39aef (patch)
treeaf68bafdb62574e22e38e2e68cbbf55a514d34f7
parentb548e0e5094b1bfdc6f9242c4f26ce191c7b8aad (diff)
downloadmorph-b652fc3cb55a238293c246f2bfad2a18ade39aef.tar.gz
Add support for Baserock definitions version 7
This adds a new 'Defaults' class to represent definitions defaults The Python 'jsonschema' module is used to validate the contents of the Defaults file. This module is already included in Baserock 'build' and 'devel' reference systems by way of the 'openstack-common' stratum. This commit embeds a copy of the JSON-Schema schema for the DEFAULTS file. I think the canonical location of this schema should be in the reference definitions.git, for now. In future, the schemas should maybe have their own repos. Either way, Morph should embed a copy for the time being so that we are sure the schema matches how Morph expects to parse the file. Morph's automated tests are all updated to use definitions version 7. I removed most of the tests for built-in build systems, because the built-ins themselves are no longer part of Morph. Only the mechanism for defining them needs to be tested now. Change-Id: I65f8f1c967683ef605852bfae5c68518e53f9981
-rwxr-xr-xcheck1
-rw-r--r--morphlib/__init__.py1
-rw-r--r--morphlib/artifactresolver_tests.py88
-rw-r--r--morphlib/artifactsplitrule.py18
-rw-r--r--morphlib/buildsystem.py19
-rw-r--r--morphlib/buildsystem_tests.py9
-rw-r--r--morphlib/cachekeycomputer_tests.py12
-rw-r--r--morphlib/defaults.py108
-rw-r--r--morphlib/definitions_repo.py19
-rw-r--r--morphlib/definitions_version.py2
-rw-r--r--morphlib/morphloader.py38
-rw-r--r--morphlib/morphloader_tests.py43
-rw-r--r--morphlib/morphologyfinder.py14
-rw-r--r--morphlib/morphologyfinder_tests.py4
-rw-r--r--morphlib/schemas/defaults.json-schema66
-rw-r--r--morphlib/source.py9
-rw-r--r--morphlib/sourceresolver.py84
-rw-r--r--morphlib/sourceresolver_tests.py8
-rw-r--r--morphlib/util.py6
-rw-r--r--tests.branching/branch-creates-new-system-branch-not-from-master.stdout1
-rw-r--r--tests.branching/branch-creates-new-system-branch.stdout1
-rw-r--r--tests.branching/branch-works-anywhere.stdout10
-rw-r--r--tests.branching/checkout-existing-branch.stdout1
-rw-r--r--tests.branching/checkout-works-anywhere.stdout3
-rwxr-xr-xtests.branching/setup5
-rwxr-xr-xtests.build/build-chunk-failures-dump-log.script8
-rwxr-xr-xtests.build/build-stratum-with-submodules.script19
-rw-r--r--tests.build/build-system-autotools-fails-if-autogen-fails.exit1
-rwxr-xr-xtests.build/build-system-autotools-fails-if-autogen-fails.script40
-rwxr-xr-xtests.build/build-system-autotools.script21
-rwxr-xr-xtests.build/build-system-cmake.script55
-rw-r--r--tests.build/build-system-cmake.stdout2
-rwxr-xr-xtests.build/build-system-cpan.script77
-rw-r--r--tests.build/build-system-cpan.stdout1
-rwxr-xr-xtests.build/build-system-python-distutils.script80
-rw-r--r--tests.build/build-system-python-distutils.stdout6
-rwxr-xr-xtests.build/build-system-qmake.script65
-rw-r--r--tests.build/build-system-qmake.stdout8
-rwxr-xr-xtests.build/morphless-chunks.script47
-rw-r--r--tests.build/morphless-chunks.stdout0
-rwxr-xr-xtests.build/prefix.script12
-rwxr-xr-xtests.build/rebuild-cached-stratum.script4
-rw-r--r--tests.build/rebuild-cached-stratum.stdout26
-rwxr-xr-xtests.build/setup49
-rwxr-xr-xtests.build/setup-build-essential20
-rw-r--r--without-test-modules1
-rw-r--r--yarns/implementations.yarn34
-rw-r--r--yarns/regression.yarn6
48 files changed, 570 insertions, 582 deletions
diff --git a/check b/check
index e3af5992..ae3b9ec7 100755
--- a/check
+++ b/check
@@ -109,6 +109,7 @@ then
echo 'Checking source code for silliness'
if ! (git ls-files --cached |
grep -v '\.gz$' |
+ grep -v '\.json-schema$' |
grep -Ev 'tests[^/]*/.*\.std(out|err)' |
grep -vF 'tests.build/build-system-autotools.script' |
xargs -r scripts/check-silliness); then
diff --git a/morphlib/__init__.py b/morphlib/__init__.py
index 81540a31..36e5c3a8 100644
--- a/morphlib/__init__.py
+++ b/morphlib/__init__.py
@@ -60,6 +60,7 @@ import builder
import cachedrepo
import cachekeycomputer
import cmdline_parse_utils
+import defaults
import definitions_repo
import definitions_version
import extensions
diff --git a/morphlib/artifactresolver_tests.py b/morphlib/artifactresolver_tests.py
index 141ff948..52ed0811 100644
--- a/morphlib/artifactresolver_tests.py
+++ b/morphlib/artifactresolver_tests.py
@@ -20,6 +20,12 @@ import yaml
import morphlib
+default_split_rules = {
+ 'chunk': morphlib.artifactsplitrule.DEFAULT_CHUNK_RULES,
+ 'stratum': morphlib.artifactsplitrule.DEFAULT_STRATUM_RULES,
+}
+
+
def get_chunk_morphology(name, artifact_names=[]):
assert(isinstance(artifact_names, list))
@@ -88,9 +94,9 @@ class ArtifactResolverTests(unittest.TestCase):
pool = morphlib.sourcepool.SourcePool()
morph = get_chunk_morphology('chunk')
- sources = morphlib.source.make_sources('repo', 'ref',
- 'chunk.morph', 'sha1',
- 'tree', morph)
+ sources = morphlib.source.make_sources(
+ 'repo', 'ref', 'chunk.morph', 'sha1', 'tree', morph,
+ default_split_rules=default_split_rules)
for source in sources:
pool.add(source)
@@ -109,9 +115,9 @@ class ArtifactResolverTests(unittest.TestCase):
pool = morphlib.sourcepool.SourcePool()
morph = get_chunk_morphology('chunk', ['chunk-foobar'])
- sources = morphlib.source.make_sources('repo', 'ref',
- 'chunk.morph', 'sha1',
- 'tree', morph)
+ sources = morphlib.source.make_sources(
+ 'repo', 'ref', 'chunk.morph', 'sha1', 'tree', morph,
+ default_split_rules=default_split_rules)
for source in sources:
pool.add(source)
@@ -129,9 +135,9 @@ class ArtifactResolverTests(unittest.TestCase):
pool = morphlib.sourcepool.SourcePool()
morph = get_chunk_morphology('chunk', ['chunk-baz', 'chunk-qux'])
- sources = morphlib.source.make_sources('repo', 'ref',
- 'chunk.morph', 'sha1',
- 'tree', morph)
+ sources = morphlib.source.make_sources(
+ 'repo', 'ref', 'chunk.morph', 'sha1', 'tree', morph,
+ default_split_rules=default_split_rules)
for source in sources:
pool.add(source)
@@ -151,18 +157,18 @@ class ArtifactResolverTests(unittest.TestCase):
pool = morphlib.sourcepool.SourcePool()
morph = get_chunk_morphology('chunk')
- sources = morphlib.source.make_sources('repo', 'ref',
- 'chunk.morph', 'sha1',
- 'tree', morph)
+ sources = morphlib.source.make_sources(
+ 'repo', 'ref', 'chunk.morph', 'sha1', 'tree', morph,
+ default_split_rules=default_split_rules)
for chunk in sources:
pool.add(chunk)
morph = get_stratum_morphology(
'stratum', chunks=[('chunk', 'chunk', 'repo', 'ref')])
- stratum_sources = set(morphlib.source.make_sources('repo', 'ref',
- 'stratum.morph',
- 'sha1', 'tree',
- morph))
+ stratum_sources = set(
+ morphlib.source.make_sources(
+ 'repo', 'ref', 'stratum.morph', 'sha1', 'tree', morph,
+ default_split_rules=default_split_rules))
for stratum in stratum_sources:
pool.add(stratum)
@@ -197,9 +203,9 @@ class ArtifactResolverTests(unittest.TestCase):
pool = morphlib.sourcepool.SourcePool()
morph = get_chunk_morphology('chunk', ['chunk-foo', 'chunk-bar'])
- sources = morphlib.source.make_sources('repo', 'ref',
- 'chunk.morph', 'sha1',
- 'tree', morph)
+ sources = morphlib.source.make_sources(
+ 'repo', 'ref', 'chunk.morph', 'sha1', 'tree', morph,
+ default_split_rules=default_split_rules)
for chunk in sources:
pool.add(chunk)
@@ -208,10 +214,10 @@ class ArtifactResolverTests(unittest.TestCase):
chunks=[
('chunk', 'chunk', 'repo', 'ref'),
])
- stratum_sources = set(morphlib.source.make_sources('repo', 'ref',
- 'stratum.morph',
- 'sha1', 'tree',
- morph))
+ stratum_sources = set(
+ morphlib.source.make_sources(
+ 'repo', 'ref', 'stratum.morph', 'sha1', 'tree', morph,
+ default_split_rules=default_split_rules))
for stratum in stratum_sources:
pool.add(stratum)
@@ -246,7 +252,8 @@ class ArtifactResolverTests(unittest.TestCase):
chunk = get_chunk_morphology('chunk1')
chunk1, = morphlib.source.make_sources(
- 'repo', 'original/ref', 'chunk1.morph', 'sha1', 'tree', chunk)
+ 'repo', 'original/ref', 'chunk1.morph', 'sha1', 'tree', chunk,
+ default_split_rules=default_split_rules)
pool.add(chunk1)
morph = get_stratum_morphology(
@@ -254,15 +261,16 @@ class ArtifactResolverTests(unittest.TestCase):
chunks=[(loader.save_to_string(chunk), 'chunk1.morph',
'repo', 'original/ref')],
build_depends=['stratum2'])
- sources = morphlib.source.make_sources('repo', 'original/ref',
- 'stratum1.morph', 'sha1',
- 'tree', morph)
+ sources = morphlib.source.make_sources(
+ 'repo', 'original/ref', 'stratum1.morph', 'sha1', 'tree', morph,
+ default_split_rules=default_split_rules)
for stratum1 in sources:
pool.add(stratum1)
chunk = get_chunk_morphology('chunk2')
chunk2, = morphlib.source.make_sources(
- 'repo', 'original/ref', 'chunk2.morph', 'sha1', 'tree', chunk)
+ 'repo', 'original/ref', 'chunk2.morph', 'sha1', 'tree', chunk,
+ default_split_rules=default_split_rules)
pool.add(chunk2)
morph = get_stratum_morphology(
@@ -270,9 +278,9 @@ class ArtifactResolverTests(unittest.TestCase):
chunks=[(loader.save_to_string(chunk), 'chunk2.morph',
'repo', 'original/ref')],
build_depends=['stratum1'])
- sources = morphlib.source.make_sources('repo', 'original/ref',
- 'stratum2.morph', 'sha1',
- 'tree', morph)
+ sources = morphlib.source.make_sources(
+ 'repo', 'original/ref', 'stratum2.morph', 'sha1', 'tree', morph,
+ default_split_rules=default_split_rules)
for stratum2 in sources:
pool.add(stratum2)
@@ -299,23 +307,23 @@ class ArtifactResolverTests(unittest.TestCase):
ref: original/ref
build-depends: []
''')
- sources = morphlib.source.make_sources('repo', 'original/ref',
- 'stratum.morph', 'sha1',
- 'tree', morph)
+ sources = morphlib.source.make_sources(
+ 'repo', 'original/ref', 'stratum.morph', 'sha1', 'tree', morph,
+ default_split_rules=default_split_rules)
for stratum in sources:
pool.add(stratum)
morph = get_chunk_morphology('chunk1')
- sources = morphlib.source.make_sources('repo', 'original/ref',
- 'chunk1.morph', 'sha1',
- 'tree', morph)
+ sources = morphlib.source.make_sources(
+ 'repo', 'original/ref', 'chunk1.morph', 'sha1', 'tree', morph,
+ default_split_rules=default_split_rules)
for chunk1 in sources:
pool.add(chunk1)
morph = get_chunk_morphology('chunk2')
- sources = morphlib.source.make_sources('repo', 'original/ref',
- 'chunk2.morph', 'sha1',
- 'tree', morph)
+ sources = morphlib.source.make_sources(
+ 'repo', 'original/ref', 'chunk2.morph', 'sha1', 'tree', morph,
+ default_split_rules=default_split_rules)
for chunk2 in sources:
pool.add(chunk2)
diff --git a/morphlib/artifactsplitrule.py b/morphlib/artifactsplitrule.py
index b5ebdf83..ba5abe02 100644
--- a/morphlib/artifactsplitrule.py
+++ b/morphlib/artifactsplitrule.py
@@ -189,10 +189,6 @@ class SplitRules(collections.Iterable):
for artifact, rule in self._rules)
-# TODO: Work out a good way to feed new defaults in. This is good for
-# the usual Linux userspace, but we may find issues and need a
-# migration path to a more useful set, or develop a system with
-# a different layout, like Android.
DEFAULT_CHUNK_RULES = [
('-bins', [ r"(usr/)?s?bin/.*" ]),
('-libs', [
@@ -229,6 +225,14 @@ DEFAULT_STRATUM_RULES = [
]
+# A 'no-op' set of split rules. An empty list would cause everything to be
+# ignored, which is unlikely to ever be what a user wants, and breaks some
+# internal bits of Morph.
+EMPTY_RULES = [
+ ('', [r'.*'])
+]
+
+
def unify_chunk_matches(morphology, default_rules=DEFAULT_CHUNK_RULES):
'''Create split rules including defaults and per-chunk rules.
@@ -237,6 +241,8 @@ def unify_chunk_matches(morphology, default_rules=DEFAULT_CHUNK_RULES):
by building the chunk to the chunk artifact they should be put in.
'''
+ if default_rules is None or len(default_rules) == 0:
+ default_rules = EMPTY_RULES
split_rules = SplitRules()
@@ -265,6 +271,8 @@ def unify_stratum_matches(morphology, default_rules=DEFAULT_STRATUM_RULES):
strata to the stratum artifact they should be put in.
'''
+ if default_rules is None or len(default_rules) == 0:
+ default_rules = EMPTY_RULES
assignment_split_rules = SplitRules()
for spec in morphology['chunks']:
@@ -296,7 +304,7 @@ def unify_stratum_matches(morphology, default_rules=DEFAULT_STRATUM_RULES):
match_split_rules))
-def unify_system_matches(morphology):
+def unify_system_matches(morphology, default_rules=[]):
'''Create split rules including defaults and per-chunk rules.
With rules specified in the morphology's 'products' field and the
diff --git a/morphlib/buildsystem.py b/morphlib/buildsystem.py
index 4655f2ee..95bf4116 100644
--- a/morphlib/buildsystem.py
+++ b/morphlib/buildsystem.py
@@ -44,15 +44,10 @@ _STRIP_COMMAND = r'''find "$DESTDIR" -type f \
class BuildSystem(object):
- '''An abstraction of an upstream build system.
+ '''Predefined command sequences for a given build system.
- Some build systems are well known: autotools, for example.
- Others are purely manual: there's a set of commands to run that
- are specific for that project, and (almost) no other project uses them.
- The Linux kernel would be an example of that.
-
- This class provides an abstraction for these, including a method
- to autodetect well known build systems.
+ For example, you can have an 'autotools' build system, which runs
+ 'configure', 'make' and 'make install'.
'''
@@ -73,6 +68,14 @@ class BuildSystem(object):
self.strip_commands = []
self.post_strip_commands = []
+ def from_dict(self, name, commands):
+ self.name = name
+
+ self.configure_commands = commands.get('configure-commands', [])
+ self.build_commands = commands.get('build-commands', [])
+ self.install_commands = commands.get('install-commands', [])
+ self.strip_commands = commands.get('strip-commands', [])
+
def __getitem__(self, key):
key = '_'.join(key.split('-'))
return getattr(self, key)
diff --git a/morphlib/buildsystem_tests.py b/morphlib/buildsystem_tests.py
index 80898ebd..506698a5 100644
--- a/morphlib/buildsystem_tests.py
+++ b/morphlib/buildsystem_tests.py
@@ -53,6 +53,15 @@ class BuildSystemTests(unittest.TestCase):
morph = self.bs.get_morphology('foobar')
self.assertTrue(morph.__class__.__name__ == 'Morphology')
+ def test_construct_from_dict(self):
+ '''Test parsing a dict of information from a DEFAULTS file.'''
+
+ commands_dict = {
+ 'configure-commands': 'foo'
+ }
+ self.bs.from_dict('test', commands_dict)
+ self.assertEqual(self.bs.configure_commands, 'foo')
+
class ManualBuildSystemTests(unittest.TestCase):
diff --git a/morphlib/cachekeycomputer_tests.py b/morphlib/cachekeycomputer_tests.py
index aa217dfc..2a5852fe 100644
--- a/morphlib/cachekeycomputer_tests.py
+++ b/morphlib/cachekeycomputer_tests.py
@@ -28,6 +28,12 @@ class DummyBuildEnvironment:
self.env = env
+default_split_rules = {
+ 'chunk': morphlib.artifactsplitrule.DEFAULT_CHUNK_RULES,
+ 'stratum': morphlib.artifactsplitrule.DEFAULT_STRATUM_RULES,
+}
+
+
class CacheKeyComputerTests(unittest.TestCase):
def setUp(self):
@@ -83,9 +89,9 @@ class CacheKeyComputerTests(unittest.TestCase):
''',
}.iteritems():
morph = loader.load_from_string(text)
- sources = morphlib.source.make_sources('repo', 'original/ref',
- name, 'sha1',
- 'tree', morph)
+ sources = morphlib.source.make_sources(
+ 'repo', 'original/ref', name, 'sha1', 'tree', morph,
+ default_split_rules=default_split_rules)
for source in sources:
self.source_pool.add(source)
self.build_env = DummyBuildEnvironment({
diff --git a/morphlib/defaults.py b/morphlib/defaults.py
new file mode 100644
index 00000000..9e695a90
--- /dev/null
+++ b/morphlib/defaults.py
@@ -0,0 +1,108 @@
+# Copyright (C) 2015 Codethink Limited
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# =*= License: GPL-2 =*=
+
+
+import cliapp
+import jsonschema
+import yaml
+
+import os
+
+import morphlib
+
+
+class Defaults(object):
+ '''Represents predefined default values specific to Baserock definitions.
+
+ The DEFAULTS file was added in definitions format version 7, which lets
+ users set these defaults. The text of DEFAULTS file can be passed in as
+ 'text', and will be validated and parsed if definitions_version >= 7.
+
+ Prior to version 7, the defaults were hardcoded in Morph. These defaults
+ will be returned if definitions_version < 7.
+
+ '''
+ def __init__(self, definitions_version, text=None):
+ self._build_systems = {}
+ self._split_rules = {}
+
+ schema_path = os.path.join(morphlib.util.schemas_directory(),
+ 'defaults.json-schema')
+ with open(schema_path) as f:
+ self.schema = yaml.load(f)
+
+ if definitions_version >= 7:
+ if text:
+ self._build_systems, self._split_rules = self._parse(text)
+ else:
+ self._build_systems, self._split_rules = self._builtins()
+
+ def _parse(self, text):
+ build_systems = {}
+ split_rules = {}
+
+ # This reports errors against <string> rather than the actual filename,
+ # which is sad.
+ data = yaml.safe_load(text)
+
+ if data is None:
+ # It's OK to be empty, I guess.
+ return build_systems, split_rules
+
+ try:
+ # It would be nice if this could give line numbers when it spotted
+ # errors. Seems tricky.
+ jsonschema.validate(data, self.schema)
+ except jsonschema.ValidationError as e:
+ raise cliapp.AppException('Invalid DEFAULTS file: %s' % e.message)
+
+ build_system_data = data.get('build-systems', {})
+ for name, commands in build_system_data.items():
+ build_system = morphlib.buildsystem.BuildSystem()
+ build_system.from_dict(name, commands)
+ build_systems[name] = build_system
+
+ # It would make sense to create artifactsplitrule.SplitRule instances
+ # here, instead of an unlabelled data structure. That would need some
+ # changes to source.make_sources() and the 'artifactsplitrule' module.
+ split_rules_data = data.get('split-rules', {})
+ for kind, rules in split_rules_data.items():
+ split_rules[kind] = []
+ for rule in rules:
+ rule_unlabelled = (rule['artifact'], rule['include'])
+ split_rules[kind].append(rule_unlabelled)
+
+ return build_systems, split_rules
+
+ def _builtins(self):
+ build_systems = {}
+ split_rules = {}
+
+ for build_system in morphlib.buildsystem.build_systems:
+ build_systems[build_system.name] = build_system
+
+ split_rules['chunk'] = \
+ morphlib.artifactsplitrule.DEFAULT_CHUNK_RULES
+ split_rules['stratum'] = \
+ morphlib.artifactsplitrule.DEFAULT_STRATUM_RULES
+
+ return build_systems, split_rules
+
+ def build_systems(self):
+ return self._build_systems
+
+ def split_rules(self):
+ return self._split_rules
diff --git a/morphlib/definitions_repo.py b/morphlib/definitions_repo.py
index 53328e85..143b5241 100644
--- a/morphlib/definitions_repo.py
+++ b/morphlib/definitions_repo.py
@@ -23,6 +23,7 @@ import logging
import os
import urlparse
import uuid
+import warnings
import morphlib
import gitdir
@@ -238,8 +239,24 @@ class DefinitionsRepo(gitdir.GitDirectory):
version_text = mf.read_file('VERSION')
version = morphlib.definitions_version.check_version_file(version_text)
+ defaults_text = mf.read_file('DEFAULTS', allow_missing=True)
+
+ if version < 7:
+ if defaults_text is not None:
+ warnings.warn(
+ "Ignoring DEFAULTS file, because these definitions are "
+ "version %i" % version)
+ defaults_text = None
+ else:
+ if defaults_text is None:
+ warnings.warn("No DEFAULTS file found.")
+
+ defaults = morphlib.defaults.Defaults(version,
+ text=defaults_text)
+
loader = morphlib.morphloader.MorphologyLoader(
- definitions_version=version)
+ definitions_version=version,
+ predefined_build_systems=defaults.build_systems())
return loader
diff --git a/morphlib/definitions_version.py b/morphlib/definitions_version.py
index 56cef164..ec2df928 100644
--- a/morphlib/definitions_version.py
+++ b/morphlib/definitions_version.py
@@ -24,7 +24,7 @@ import yaml
import morphlib
-SUPPORTED_VERSIONS = [3, 4, 5, 6]
+SUPPORTED_VERSIONS = [3, 4, 5, 6, 7]
class DefinitionsVersionError(cliapp.AppException):
diff --git a/morphlib/morphloader.py b/morphlib/morphloader.py
index 479bc8fb..e58b3164 100644
--- a/morphlib/morphloader.py
+++ b/morphlib/morphloader.py
@@ -111,6 +111,13 @@ class UnknownArchitectureError(MorphologyValidationError):
% (arch, morph_filename))
+class UnknownBuildSystemError(MorphologyValidationError):
+
+ def __init__(self, build_system, morph_filename):
+ self.msg = ('Undefined build system %s in morphology %s'
+ % (build_system, morph_filename))
+
+
class NoStratumBuildDependenciesError(MorphologyValidationError):
def __init__(self, stratum_name, morph_filename):
@@ -403,7 +410,7 @@ class MorphologyLoader(object):
}
def __init__(self, definitions_version=0,
- lookup_build_system=morphlib.buildsystem.lookup_build_system):
+ predefined_build_systems={}):
if definitions_version >= 5: # pragma: no cover
self._static_defaults = copy.deepcopy(self._static_defaults)
self._static_defaults['chunk'].update({
@@ -412,7 +419,12 @@ class MorphologyLoader(object):
'post-strip-commands': None})
self._definitions_version = definitions_version
- self._lookup_build_system = lookup_build_system
+
+ self._predefined_build_systems = predefined_build_systems.copy()
+
+ if 'manual' not in self._predefined_build_systems:
+ self._predefined_build_systems['manual'] = \
+ morphlib.buildsystem.ManualBuildSystem()
def parse_morphology_text(self, text, morph_filename):
'''Parse a textual morphology.
@@ -820,10 +832,12 @@ class MorphologyLoader(object):
if morph['max-jobs'] is not None:
morph['max-jobs'] = int(morph['max-jobs'])
- def _unset_chunk_defaults(self, morph): # pragma: no cover
+ def _unset_chunk_defaults(self, morph): # pragma: no cover
+ # This is only used by the deprecated branch-and-merge plugin, and
+ # probably doesn't work correctly for definitions V7 and newer.
default_bs = self._static_defaults['chunk']['build-system']
- bs = self._lookup_build_system(
- morph.get('build-system', default_bs))
+ bs_name = morph.get('build-system', default_bs)
+ bs = self._predefined_build_systems[bs_name]
for key in self._static_defaults['chunk']:
if key not in morph: continue
if 'commands' not in key: continue
@@ -832,11 +846,19 @@ class MorphologyLoader(object):
if morph[key] == default_value:
del morph[key]
+ def lookup_build_system(self, name):
+ return self._predefined_build_systems[name]
+
def set_commands(self, morph):
- default = self._static_defaults['chunk']['build-system']
- bs = self._lookup_build_system(
- morph.get('build-system', default))
if morph['kind'] == 'chunk':
+ default = self._static_defaults['chunk']['build-system']
+ bs_name = morph.get('build-system', default)
+
+ try:
+ bs = self.lookup_build_system(bs_name)
+ except KeyError:
+ raise UnknownBuildSystemError(bs_name, morph['name'])
+
for key in self._static_defaults['chunk']:
if 'commands' not in key: continue
if key not in morph:
diff --git a/morphlib/morphloader_tests.py b/morphlib/morphloader_tests.py
index 6cb93094..1a2ee107 100644
--- a/morphlib/morphloader_tests.py
+++ b/morphlib/morphloader_tests.py
@@ -50,7 +50,7 @@ class MorphologyLoaderTests(unittest.TestCase):
def setUp(self):
self.loader = morphlib.morphloader.MorphologyLoader(
- definitions_version=6)
+ definitions_version=7)
self.tempdir = tempfile.mkdtemp()
self.filename = os.path.join(self.tempdir, 'foo.morph')
@@ -61,12 +61,12 @@ class MorphologyLoaderTests(unittest.TestCase):
string = '''\
name: foo
kind: chunk
-build-system: dummy
+build-system: manual
'''
morph = self.loader.parse_morphology_text(string, 'test')
self.assertEqual(morph['kind'], 'chunk')
self.assertEqual(morph['name'], 'foo')
- self.assertEqual(morph['build-system'], 'dummy')
+ self.assertEqual(morph['build-system'], 'manual')
def test_fails_to_parse_utter_garbage(self):
self.assertRaises(
@@ -495,43 +495,43 @@ chunks:
string = '''\
name: foo
kind: chunk
-build-system: dummy
+build-system: manual
'''
morph = self.loader.load_from_string(string)
self.assertEqual(morph['kind'], 'chunk')
self.assertEqual(morph['name'], 'foo')
- self.assertEqual(morph['build-system'], 'dummy')
+ self.assertEqual(morph['build-system'], 'manual')
def test_loads_json_from_string(self):
string = '''\
{
"name": "foo",
"kind": "chunk",
- "build-system": "dummy"
+ "build-system": "manual"
}
'''
morph = self.loader.load_from_string(string)
self.assertEqual(morph['kind'], 'chunk')
self.assertEqual(morph['name'], 'foo')
- self.assertEqual(morph['build-system'], 'dummy')
+ self.assertEqual(morph['build-system'], 'manual')
def test_loads_from_file(self):
with open(self.filename, 'w') as f:
f.write('''\
name: foo
kind: chunk
-build-system: dummy
+build-system: manual
''')
morph = self.loader.load_from_file(self.filename)
self.assertEqual(morph['kind'], 'chunk')
self.assertEqual(morph['name'], 'foo')
- self.assertEqual(morph['build-system'], 'dummy')
+ self.assertEqual(morph['build-system'], 'manual')
def test_saves_to_string(self):
morph = morphlib.morphology.Morphology({
'name': 'foo',
'kind': 'chunk',
- 'build-system': 'dummy',
+ 'build-system': 'manual',
})
text = self.loader.save_to_string(morph)
@@ -540,14 +540,14 @@ build-system: dummy
self.assertEqual(text, '''\
name: foo
kind: chunk
-build-system: dummy
+build-system: manual
''')
def test_saves_to_file(self):
morph = morphlib.morphology.Morphology({
'name': 'foo',
'kind': 'chunk',
- 'build-system': 'dummy',
+ 'build-system': 'manual',
})
self.loader.save_to_file(self.filename, morph)
@@ -559,7 +559,7 @@ build-system: dummy
self.assertEqual(text, '''\
name: foo
kind: chunk
-build-system: dummy
+build-system: manual
''')
def test_validate_does_not_set_defaults(self):
@@ -967,12 +967,11 @@ build-system: dummy
)
s = self.loader.save_to_string(m)
- def test_smoketest_strip_commands(self):
- dummy_buildsystem = morphlib.buildsystem.DummyBuildSystem()
- loader = morphlib.morphloader.MorphologyLoader(
- definitions_version=5,
- lookup_build_system=lambda x: dummy_buildsystem)
- m = morphlib.morphology.Morphology(
- {'name': 'test', 'kind': 'chunk', 'build-system': 'dummy'})
- loader.set_commands(m)
- self.assertEqual(m['strip-commands'], dummy_buildsystem.strip_commands)
+ def test_unknown_build_system(self):
+ m = morphlib.morphology.Morphology({
+ 'kind': 'chunk',
+ 'name': 'foo',
+ 'build-system': 'monkey scientist',
+ })
+ with self.assertRaises(morphlib.morphloader.UnknownBuildSystemError):
+ s = self.loader.set_commands(m)
diff --git a/morphlib/morphologyfinder.py b/morphlib/morphologyfinder.py
index 335c01b6..2c864bea 100644
--- a/morphlib/morphologyfinder.py
+++ b/morphlib/morphologyfinder.py
@@ -15,9 +15,7 @@
# =*= License: GPL-2 =*=
-import cliapp
-
-import morphlib
+import errno
class MorphologyFinder(object):
@@ -33,7 +31,7 @@ class MorphologyFinder(object):
self.gitdir = gitdir
self.ref = ref
- def read_file(self, filename):
+ def read_file(self, filename, allow_missing=False):
'''Return the un-parsed text of a morphology.
For the given morphology name, locate and return the contents
@@ -43,7 +41,13 @@ class MorphologyFinder(object):
is handled by the MorphologyLoader class.
'''
- return self.gitdir.read_file(filename, self.ref)
+ try:
+ return self.gitdir.read_file(filename, self.ref)
+ except IOError as e:
+ if allow_missing and e.errno == errno.ENOENT:
+ return None
+ else:
+ raise
def list_morphologies(self):
'''Return the filenames of all morphologies in the (repo, ref).
diff --git a/morphlib/morphologyfinder_tests.py b/morphlib/morphologyfinder_tests.py
index 59772e23..3312b627 100644
--- a/morphlib/morphologyfinder_tests.py
+++ b/morphlib/morphologyfinder_tests.py
@@ -103,6 +103,10 @@ class MorphologyFinderTests(unittest.TestCase):
mf = morphlib.morphologyfinder.MorphologyFinder(gd)
self.assertEqual(mf.read_file('foo.morph'),
"altered morphology text")
+ with self.assertRaises(IOError):
+ mf.read_file('missing')
+ self.assertEqual(mf.read_file('missing', allow_missing=True),
+ None)
def test_read_morph_raises_no_worktree_no_ref(self):
gd = morphlib.gitdir.GitDirectory(self.mirror)
diff --git a/morphlib/schemas/defaults.json-schema b/morphlib/schemas/defaults.json-schema
new file mode 100644
index 00000000..2f713425
--- /dev/null
+++ b/morphlib/schemas/defaults.json-schema
@@ -0,0 +1,66 @@
+$schema: http://json-schema.org/draft-04/schema#
+id: http://git.baserock.org/cgi-bin/cgit.cgi/baserock/baserock/definitions.git/tree/schemas/defaults.json-schema
+
+description: |
+ This is a JSON-Schema description of the DEFAULTS file specified in the
+ Baserock definitions format. DEFAULTS is a YAML file that contains global
+ defaults for a set of Baserock definitions.
+
+ This JSON-Schema file is valid for VERSION 7 of the Baserock definitions
+ YAML serialisation format.
+
+ The Baserock definitions YAML serialisation format is the recommended way of
+ representing Baserock definitions on disk. The actual data model is described
+ separately. See <https://wiki.baserock.org/definitions> for more information.
+
+ This schema is represented as YAML, so that it can be edited more easily.
+ You may need to convert to JSON if using a JSON-Schema tool that expects
+ its input to be an actual string containing data serialised as JSON.
+
+definitions:
+ command-sequence:
+ type: array
+ items: {type: string}
+
+ build-system:
+ type: object
+ additionalProperties: false
+ properties:
+ build-commands: {$ref: '#/definitions/command-sequence'}
+ configure-commands: {$ref: '#/definitions/command-sequence'}
+ install-commands: {$ref: '#/definitions/command-sequence'}
+ strip-commands: {$ref: '#/definitions/command-sequence'}
+
+ split-rules:
+ type: array
+ items:
+ type: object
+
+ required: [artifact, include]
+ additionalProperties: false
+
+ properties:
+ artifact: {type: string}
+ include:
+ type: array
+ items:
+ type: string
+ format: regex
+
+type: object
+additionalProperties: false
+
+properties:
+ # Predefined build systems.
+ build-systems:
+ type: object
+ patternProperties:
+ ^.*$: {$ref: '#/definitions/build-system'}
+
+ # Predefined artifact splitting rules.
+ split-rules:
+ type: object
+ additionalProperties: false
+ properties:
+ chunk: {$ref: '#/definitions/split-rules'}
+ stratum: {$ref: '#/definitions/split-rules'}
diff --git a/morphlib/source.py b/morphlib/source.py
index 2c96bcbd..135c14cc 100644
--- a/morphlib/source.py
+++ b/morphlib/source.py
@@ -77,12 +77,14 @@ class Source(object):
return artifact in self.dependencies
-def make_sources(reponame, ref, filename, absref, tree, morphology):
+def make_sources(reponame, ref, filename, absref, tree, morphology,
+ default_split_rules={}):
kind = morphology['kind']
if kind in ('system', 'chunk'):
unifier = getattr(morphlib.artifactsplitrule,
'unify_%s_matches' % kind)
- split_rules = unifier(morphology)
+ split_rules = unifier(morphology,
+ default_rules=default_split_rules.get(kind, {}))
# chunk and system sources are named after the morphology
source_name = morphology['name']
source = morphlib.source.Source(source_name, reponame, ref,
@@ -93,7 +95,8 @@ def make_sources(reponame, ref, filename, absref, tree, morphology):
yield source
elif kind == 'stratum': # pragma: no cover
unifier = morphlib.artifactsplitrule.unify_stratum_matches
- split_rules = unifier(morphology)
+ split_rules = unifier(morphology,
+ default_rules=default_split_rules.get(kind, {}))
for name in split_rules.artifacts:
source = morphlib.source.Source(
name, # stratum source name is artifact name
diff --git a/morphlib/sourceresolver.py b/morphlib/sourceresolver.py
index cbab0f7f..42398ce7 100644
--- a/morphlib/sourceresolver.py
+++ b/morphlib/sourceresolver.py
@@ -21,6 +21,7 @@ import os
import pylru
import shutil
import tempfile
+import warnings
import yaml
import cliapp
@@ -289,6 +290,36 @@ class SourceResolver(object):
return morphlib.definitions_version.check_version_file(version_text)
+ def _get_defaults(self, definitions_checkout_dir,
+ definitions_version=7): # pragma: no cover
+ '''Return the default build system commands, and default split rules.
+
+ This function returns a tuple with two dicts.
+
+ The defaults are read from a file named DEFAULTS in the definitions
+ directory, if the definitions follow format version 7 or later. If the
+ definitions follow version 6 or earlier, hardcoded defaults are used.
+
+ '''
+ # Read default build systems and split rules from DEFAULTS file.
+ defaults_text = self._get_file_contents_from_definitions(
+ definitions_checkout_dir, 'DEFAULTS')
+
+ if definitions_version < 7:
+ if defaults_text is not None:
+ warnings.warn(
+ "Ignoring DEFAULTS file, because these definitions are "
+ "version %i" % definitions_version)
+ defaults_text = None
+ else:
+ if defaults_text is None:
+ warnings.warn("No DEFAULTS file found.")
+
+ defaults = morphlib.defaults.Defaults(definitions_version,
+ text=defaults_text)
+
+ return defaults.build_systems(), defaults.split_rules()
+
def _get_morphology(self, resolved_morphologies, definitions_checkout_dir,
definitions_repo, definitions_absref, morph_loader,
reponame, sha1, filename): # pragma: no cover
@@ -311,17 +342,12 @@ class SourceResolver(object):
return morph
- def _process_definitions_with_children(self,
- resolved_morphologies,
- definitions_checkout_dir,
- definitions_repo,
- definitions_ref,
- definitions_absref,
- definitions_tree,
- definitions_version,
- morph_loader,
- system_filenames,
- visit): # pragma: no cover
+ def _process_definitions_with_children(
+ self, resolved_morphologies, definitions_checkout_dir,
+ definitions_repo, definitions_ref, definitions_absref,
+ definitions_tree, definitions_version, morph_loader,
+ system_filenames, visit,
+ predefined_split_rules): # pragma: no cover
definitions_queue = collections.deque(system_filenames)
chunk_queue = set()
@@ -341,7 +367,8 @@ class SourceResolver(object):
raise MorphologyNotFoundError(filename)
visit(definitions_repo, definitions_ref, filename,
- definitions_absref, definitions_tree, morphology)
+ definitions_absref, definitions_tree, morphology,
+ predefined_split_rules)
if morphology['kind'] == 'cluster':
raise cliapp.AppException(
@@ -462,7 +489,8 @@ class SourceResolver(object):
resolved_buildsystems, definitions_checkout_dir,
definitions_repo, definitions_absref,
definitions_version, morph_loader, chunk_repo, chunk_ref,
- filename, chunk_buildsystem, visit): # pragma: no cover
+ filename, chunk_buildsystem, visit,
+ predefined_split_rules): # pragma: no cover
absref = None
tree = None
chunk_key = None
@@ -483,7 +511,8 @@ class SourceResolver(object):
if morphology:
absref, tree = self._resolve_ref(resolved_trees, chunk_repo,
chunk_ref)
- visit(chunk_repo, chunk_ref, filename, absref, tree, morphology)
+ visit(chunk_repo, chunk_ref, filename, absref, tree, morphology,
+ predefined_split_rules)
return
absref, tree = self._resolve_ref(resolved_trees, chunk_repo, chunk_ref)
@@ -552,7 +581,8 @@ class SourceResolver(object):
morphology = generate_morph_and_cache_buildsystem(
buildsystem)
- visit(chunk_repo, chunk_ref, filename, absref, tree, morphology)
+ visit(chunk_repo, chunk_ref, filename, absref, tree, morphology,
+ predefined_split_rules)
def traverse_morphs(self, definitions_repo, definitions_ref,
system_filenames,
@@ -582,9 +612,15 @@ class SourceResolver(object):
definitions_absref, definitions_checkout_dir)
definitions_version = self._check_version_file(
- definitions_checkout_dir)
+ definitions_checkout_dir)
+
+ predefined_build_systems, predefined_split_rules = \
+ self._get_defaults(
+ definitions_checkout_dir, definitions_version)
+
morph_loader = morphlib.morphloader.MorphologyLoader(
- definitions_version=definitions_version)
+ definitions_version=definitions_version,
+ predefined_build_systems=predefined_build_systems)
# First, process the system and its stratum morphologies. These
# will all live in the same Git repository, and will point to
@@ -593,7 +629,7 @@ class SourceResolver(object):
resolved_morphologies, definitions_checkout_dir,
definitions_repo, definitions_ref, definitions_absref,
definitions_tree, definitions_version, morph_loader,
- system_filenames, visit)
+ system_filenames, visit, predefined_split_rules)
# Now process all the chunks involved in the build.
for repo, ref, filename, buildsystem in chunk_queue:
@@ -602,7 +638,8 @@ class SourceResolver(object):
definitions_checkout_dir,
definitions_repo, definitions_absref,
definitions_version, morph_loader, repo,
- ref, filename, buildsystem, visit)
+ ref, filename, buildsystem, visit,
+ predefined_split_rules)
def create_source_pool(lrc, rrc, repo, ref, filenames, cachedir,
@@ -624,10 +661,11 @@ def create_source_pool(lrc, rrc, repo, ref, filenames, cachedir,
'''
pool = morphlib.sourcepool.SourcePool()
- def add_to_pool(reponame, ref, filename, absref, tree, morphology):
- sources = morphlib.source.make_sources(reponame, ref,
- filename, absref,
- tree, morphology)
+ def add_to_pool(reponame, ref, filename, absref, tree, morphology,
+ predefined_split_rules):
+ sources = morphlib.source.make_sources(
+ reponame, ref, filename, absref, tree, morphology,
+ predefined_split_rules)
for source in sources:
pool.add(source)
diff --git a/morphlib/sourceresolver_tests.py b/morphlib/sourceresolver_tests.py
index 5985579c..58512172 100644
--- a/morphlib/sourceresolver_tests.py
+++ b/morphlib/sourceresolver_tests.py
@@ -32,7 +32,7 @@ class FakeRemoteRepoCache(object):
return '''{
"name": "%s",
"kind": "chunk",
- "build-system": "dummy"
+ "build-system": "manual"
}''' % filename[:-len('.morph')]
return 'text'
@@ -46,12 +46,12 @@ class FakeLocalRepo(object):
'chunk.morph': '''
name: chunk
kind: chunk
- build-system: dummy
+ build-system: manual
''',
'chunk-split.morph': '''
name: chunk-split
kind: chunk
- build-system: dummy
+ build-system: manual
products:
- artifact: chunk-split-runtime
include: []
@@ -119,7 +119,7 @@ class FakeLocalRepo(object):
return '''
name: %s
kind: chunk
- build-system: dummy''' % filename[:-len('.morph')]
+ build-system: manual''' % filename[:-len('.morph')]
return 'text'
def list_files(self, ref, recurse):
diff --git a/morphlib/util.py b/morphlib/util.py
index a92b7f37..27139c66 100644
--- a/morphlib/util.py
+++ b/morphlib/util.py
@@ -731,3 +731,9 @@ def temp_dir(*args, **kwargs): #pragma: no cover
else:
if cleanup_on_success:
shutil.rmtree(td, ignore_errors=True)
+
+
+def schemas_directory(): # pragma: no cover
+ '''Returns a path to the schemas/ subdirectory of the 'morphlib' module.'''
+ code_dir = os.path.dirname(morphlib.__file__)
+ return os.path.join(code_dir, 'schemas')
diff --git a/tests.branching/branch-creates-new-system-branch-not-from-master.stdout b/tests.branching/branch-creates-new-system-branch-not-from-master.stdout
index 78b3ca33..c5682475 100644
--- a/tests.branching/branch-creates-new-system-branch-not-from-master.stdout
+++ b/tests.branching/branch-creates-new-system-branch-not-from-master.stdout
@@ -7,6 +7,7 @@ d ./newbranch/test
d ./newbranch/test/morphs
d ./newbranch/test/morphs/.git
f ./newbranch/.morph-system-branch/config
+f ./newbranch/test/morphs/DEFAULTS
f ./newbranch/test/morphs/VERSION
f ./newbranch/test/morphs/hello-stratum.morph
f ./newbranch/test/morphs/hello-system.morph
diff --git a/tests.branching/branch-creates-new-system-branch.stdout b/tests.branching/branch-creates-new-system-branch.stdout
index 882d5401..238afe5e 100644
--- a/tests.branching/branch-creates-new-system-branch.stdout
+++ b/tests.branching/branch-creates-new-system-branch.stdout
@@ -7,6 +7,7 @@ d ./newbranch/test
d ./newbranch/test/morphs
d ./newbranch/test/morphs/.git
f ./newbranch/.morph-system-branch/config
+f ./newbranch/test/morphs/DEFAULTS
f ./newbranch/test/morphs/VERSION
f ./newbranch/test/morphs/hello-stratum.morph
f ./newbranch/test/morphs/hello-system.morph
diff --git a/tests.branching/branch-works-anywhere.stdout b/tests.branching/branch-works-anywhere.stdout
index 4e6c3e27..e3c7bfb2 100644
--- a/tests.branching/branch-works-anywhere.stdout
+++ b/tests.branching/branch-works-anywhere.stdout
@@ -7,6 +7,7 @@ d ./branch1/test
d ./branch1/test/morphs
d ./branch1/test/morphs/.git
f ./branch1/.morph-system-branch/config
+f ./branch1/test/morphs/DEFAULTS
f ./branch1/test/morphs/VERSION
f ./branch1/test/morphs/hello-stratum.morph
f ./branch1/test/morphs/hello-system.morph
@@ -24,10 +25,12 @@ d ./branch2/test
d ./branch2/test/morphs
d ./branch2/test/morphs/.git
f ./branch1/.morph-system-branch/config
+f ./branch1/test/morphs/DEFAULTS
f ./branch1/test/morphs/VERSION
f ./branch1/test/morphs/hello-stratum.morph
f ./branch1/test/morphs/hello-system.morph
f ./branch2/.morph-system-branch/config
+f ./branch2/test/morphs/DEFAULTS
f ./branch2/test/morphs/VERSION
f ./branch2/test/morphs/hello-stratum.morph
f ./branch2/test/morphs/hello-system.morph
@@ -50,14 +53,17 @@ d ./branch3/test
d ./branch3/test/morphs
d ./branch3/test/morphs/.git
f ./branch1/.morph-system-branch/config
+f ./branch1/test/morphs/DEFAULTS
f ./branch1/test/morphs/VERSION
f ./branch1/test/morphs/hello-stratum.morph
f ./branch1/test/morphs/hello-system.morph
f ./branch2/.morph-system-branch/config
+f ./branch2/test/morphs/DEFAULTS
f ./branch2/test/morphs/VERSION
f ./branch2/test/morphs/hello-stratum.morph
f ./branch2/test/morphs/hello-system.morph
f ./branch3/.morph-system-branch/config
+f ./branch3/test/morphs/DEFAULTS
f ./branch3/test/morphs/VERSION
f ./branch3/test/morphs/hello-stratum.morph
f ./branch3/test/morphs/hello-system.morph
@@ -85,18 +91,22 @@ d ./branch4/test
d ./branch4/test/morphs
d ./branch4/test/morphs/.git
f ./branch1/.morph-system-branch/config
+f ./branch1/test/morphs/DEFAULTS
f ./branch1/test/morphs/VERSION
f ./branch1/test/morphs/hello-stratum.morph
f ./branch1/test/morphs/hello-system.morph
f ./branch2/.morph-system-branch/config
+f ./branch2/test/morphs/DEFAULTS
f ./branch2/test/morphs/VERSION
f ./branch2/test/morphs/hello-stratum.morph
f ./branch2/test/morphs/hello-system.morph
f ./branch3/.morph-system-branch/config
+f ./branch3/test/morphs/DEFAULTS
f ./branch3/test/morphs/VERSION
f ./branch3/test/morphs/hello-stratum.morph
f ./branch3/test/morphs/hello-system.morph
f ./branch4/.morph-system-branch/config
+f ./branch4/test/morphs/DEFAULTS
f ./branch4/test/morphs/VERSION
f ./branch4/test/morphs/hello-stratum.morph
f ./branch4/test/morphs/hello-system.morph
diff --git a/tests.branching/checkout-existing-branch.stdout b/tests.branching/checkout-existing-branch.stdout
index f2b704e9..c3a806e2 100644
--- a/tests.branching/checkout-existing-branch.stdout
+++ b/tests.branching/checkout-existing-branch.stdout
@@ -7,6 +7,7 @@ d ./master/test
d ./master/test/morphs
d ./master/test/morphs/.git
f ./master/.morph-system-branch/config
+f ./master/test/morphs/DEFAULTS
f ./master/test/morphs/VERSION
f ./master/test/morphs/hello-stratum.morph
f ./master/test/morphs/hello-system.morph
diff --git a/tests.branching/checkout-works-anywhere.stdout b/tests.branching/checkout-works-anywhere.stdout
index d7f6903a..737a605e 100644
--- a/tests.branching/checkout-works-anywhere.stdout
+++ b/tests.branching/checkout-works-anywhere.stdout
@@ -7,6 +7,7 @@ d ./master/test
d ./master/test/morphs
d ./master/test/morphs/.git
f ./master/.morph-system-branch/config
+f ./master/test/morphs/DEFAULTS
f ./master/test/morphs/VERSION
f ./master/test/morphs/hello-stratum.morph
f ./master/test/morphs/hello-system.morph
@@ -24,10 +25,12 @@ d ./newbranch/test
d ./newbranch/test/morphs
d ./newbranch/test/morphs/.git
f ./master/.morph-system-branch/config
+f ./master/test/morphs/DEFAULTS
f ./master/test/morphs/VERSION
f ./master/test/morphs/hello-stratum.morph
f ./master/test/morphs/hello-system.morph
f ./newbranch/.morph-system-branch/config
+f ./newbranch/test/morphs/DEFAULTS
f ./newbranch/test/morphs/VERSION
f ./newbranch/test/morphs/hello-stratum.morph
f ./newbranch/test/morphs/hello-system.morph
diff --git a/tests.branching/setup b/tests.branching/setup
index 8e82f32c..0d645446 100755
--- a/tests.branching/setup
+++ b/tests.branching/setup
@@ -46,7 +46,10 @@ mkdir "$DATADIR/morphs"
## Create a link to this repo that has a .git suffix
ln -s "$DATADIR/morphs" "$DATADIR/morphs.git"
-echo 'version: 6' > "$DATADIR/morphs/VERSION"
+echo 'version: 7' > "$DATADIR/morphs/VERSION"
+
+# We don't build anything, so empty DEFAULTS file is fine.
+echo '' > "$DATADIR/morphs/DEFAULTS"
cat <<EOF > "$DATADIR/morphs/hello-system.morph"
name: hello-system
diff --git a/tests.build/build-chunk-failures-dump-log.script b/tests.build/build-chunk-failures-dump-log.script
index 81361ad0..75c3caf2 100755
--- a/tests.build/build-chunk-failures-dump-log.script
+++ b/tests.build/build-chunk-failures-dump-log.script
@@ -20,13 +20,13 @@
set -eu
# Make 'hello' chunk fail to build
-chunkrepo="$DATADIR/chunk-repo"
-cd "$chunkrepo"
-git checkout --quiet farrokh
+morphsrepo="$DATADIR/morphs-repo"
+cd "$morphsrepo"
cat <<EOF >hello.morph
name: hello
kind: chunk
-build-system: dummy
+configure-commands:
+ - echo dummy configure
build-commands:
- echo The next command will fail
- "false"
diff --git a/tests.build/build-stratum-with-submodules.script b/tests.build/build-stratum-with-submodules.script
index bd6b97ce..6753d899 100755
--- a/tests.build/build-stratum-with-submodules.script
+++ b/tests.build/build-stratum-with-submodules.script
@@ -24,13 +24,7 @@ set -eu
parent="$DATADIR/parent-repo"
mkdir "$parent"
-cat <<EOF > "$parent/parent.morph"
-name: parent
-kind: chunk
-build-system: manual
-build-commands:
- - test -f le-sub/README
-EOF
+echo "This is nothing interesting" > "$parent/README"
"$SRCDIR/scripts/run-git-in" "$parent" init --quiet
"$SRCDIR/scripts/run-git-in" "$parent" add .
@@ -42,17 +36,26 @@ EOF
# Modify the stratum to refer to the parent, not the submodule.
morphs="$DATADIR/morphs-repo"
+cat <<EOF > "$morphs/parent.morph"
+name: parent
+kind: chunk
+build-system: manual
+build-commands:
+ - test -f le-sub/README
+EOF
+
cat <<EOF > "$morphs/hello-stratum.morph"
name: hello-stratum
kind: stratum
chunks:
- name: parent
+ morph: parent.morph
repo: test:parent-repo
ref: master
build-depends: []
build-mode: test
EOF
-"$SRCDIR/scripts/run-git-in" "$morphs" add hello-stratum.morph
+"$SRCDIR/scripts/run-git-in" "$morphs" add hello-stratum.morph parent.morph
"$SRCDIR/scripts/run-git-in" "$morphs" commit --quiet -m 'foo'
diff --git a/tests.build/build-system-autotools-fails-if-autogen-fails.exit b/tests.build/build-system-autotools-fails-if-autogen-fails.exit
deleted file mode 100644
index d00491fd..00000000
--- a/tests.build/build-system-autotools-fails-if-autogen-fails.exit
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/tests.build/build-system-autotools-fails-if-autogen-fails.script b/tests.build/build-system-autotools-fails-if-autogen-fails.script
deleted file mode 100755
index 0b009b54..00000000
--- a/tests.build/build-system-autotools-fails-if-autogen-fails.script
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/bin/sh
-#
-# Copyright (C) 2012-2013,2015 Codethink Limited
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; version 2 of the License.
-#
-# This program 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 General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program. If not, see <http://www.gnu.org/licenses/>.
-
-
-## Test that the autotools build system fails if it runs autogen.sh and that
-## fails.
-
-set -eu
-
-cd "$DATADIR/chunk-repo"
-git checkout -q farrokh
-
-cat <<EOF > autogen.sh
-#!/bin/sh
-echo "in failing autogen.sh"
-exit 1
-EOF
-chmod a+x autogen.sh
-
-git add autogen.sh
-git rm -q hello.morph
-git commit -q -m "Convert hello to a broken autotools project"
-
-"$SRCDIR/scripts/test-morph" build-morphology \
- test:morphs-repo master hello-system \
- >/dev/null 2> /dev/null
-
diff --git a/tests.build/build-system-autotools.script b/tests.build/build-system-autotools.script
index 710a8f98..a421eaeb 100755
--- a/tests.build/build-system-autotools.script
+++ b/tests.build/build-system-autotools.script
@@ -18,8 +18,20 @@
## Convert the hello-chunk project to something autotools-like, then
## build it.
+## The 'autotools' build system is defined in the DEFAULTS file created
+## by the 'setup' script.
+
set -eu
+morphsrepo="$DATADIR/morphs-repo"
+cd "$morphsrepo"
+
+cat <<EOF >> hello.morph
+build-system: autotools
+configure-commands: []
+EOF
+git commit --quiet --all -m "Make hello into an autotools project"
+
chunkrepo="$DATADIR/chunk-repo"
cd "$chunkrepo"
@@ -35,14 +47,7 @@ install: all
EOF
git add Makefile
-cat <<EOF > hello.morph
-name: hello
-kind: chunk
-build-system: autotools
-configure-commands: []
-EOF
-git add hello.morph
-git commit --quiet -m "Convert hello to an autotools project"
+git commit --quiet -m "Make hello a real autotools project"
"$SRCDIR/scripts/test-morph" build-morphology \
test:morphs-repo master hello-system
diff --git a/tests.build/build-system-cmake.script b/tests.build/build-system-cmake.script
deleted file mode 100755
index fe02f9dc..00000000
--- a/tests.build/build-system-cmake.script
+++ /dev/null
@@ -1,55 +0,0 @@
-#!/bin/sh
-#
-# Copyright (C) 2011-2015 Codethink Limited
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; version 2 of the License.
-#
-# This program 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 General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program. If not, see <http://www.gnu.org/licenses/>.
-
-
-## Convert the hello-chunk project to something cmake-like, then
-## build it.
-
-set -eu
-
-chunkrepo="$DATADIR/chunk-repo"
-cd "$chunkrepo"
-
-git checkout --quiet farrokh
-
-cat <<'EOF' >CMakeLists.txt
-cmake_minimum_required(VERSION 2.8)
-project(hello)
-
-set(hello_SOURCES hello.c)
-add_executable(hello ${hello_SOURCES})
-install(TARGETS hello RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
-EOF
-
-git add CMakeLists.txt
-
-cat <<EOF > hello.morph
-name: hello
-kind: chunk
-build-system: cmake
-install-commands:
- - make DESTDIR="\$DESTDIR" install
-EOF
-git add hello.morph
-git commit --quiet -m "Convert hello to a cmake project"
-
-"$SRCDIR/scripts/test-morph" build-morphology \
- test:morphs-repo master hello-system
-
-for chunk in "$DATADIR/cache/artifacts/"*.chunk.*
-do
- tar -tf "$chunk"
-done | LC_ALL=C sort -u | sed '/^\.\/./s:^\./::' | grep -Ee '^(usr/)?(bin|etc)'
diff --git a/tests.build/build-system-cmake.stdout b/tests.build/build-system-cmake.stdout
deleted file mode 100644
index 3410b113..00000000
--- a/tests.build/build-system-cmake.stdout
+++ /dev/null
@@ -1,2 +0,0 @@
-usr/bin/
-usr/bin/hello
diff --git a/tests.build/build-system-cpan.script b/tests.build/build-system-cpan.script
deleted file mode 100755
index 103d5466..00000000
--- a/tests.build/build-system-cpan.script
+++ /dev/null
@@ -1,77 +0,0 @@
-#!/bin/sh
-#
-# Copyright (C) 2011-2015 Codethink Limited
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; version 2 of the License.
-#
-# This program 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 General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program. If not, see <http://www.gnu.org/licenses/>.
-
-
-## Convert the hello-chunk project to perl with CPAN and build.
-
-set -eu
-
-chunkrepo="$DATADIR/chunk-repo"
-cd "$chunkrepo"
-
-git checkout --quiet farrokh
-
-git rm --quiet hello.c
-
-cat <<EOF >hello
-#!/usr/bin/perl
-print "hello, world\n"
-EOF
-git add hello
-
-cat <<EOF >Makefile.PL
-use strict;
-use warnings;
-use ExtUtils::MakeMaker;
-WriteMakefile(
- EXE_FILES => ['hello'],
-)
-EOF
-git add Makefile.PL
-
-cat <<EOF >hello.morph
-name: hello
-kind: chunk
-build-system: cpan
-EOF
-git add hello.morph
-
-git commit --quiet -m 'convert hello into a perl cpan project'
-
-# Set 'prefix' of hello to something custom
-cd "$DATADIR/morphs-repo"
-cat <<EOF > hello-stratum.morph
-name: hello-stratum
-kind: stratum
-chunks:
- - name: hello
- repo: test:chunk-repo
- ref: farrokh
- build-depends: []
- build-mode: test
- prefix: /
-EOF
-git add hello-stratum.morph
-git commit -q -m "Set custom install prefix for hello"
-
-
-"$SRCDIR/scripts/test-morph" build-morphology \
- test:morphs-repo master hello-system
-
-for chunk in "$DATADIR/cache/artifacts/"*.chunk.*
-do
- tar -tf "$chunk"
-done | LC_ALL=C sort | sed '/^\.\/./s:^\./::' | grep -F 'bin/hello'
diff --git a/tests.build/build-system-cpan.stdout b/tests.build/build-system-cpan.stdout
deleted file mode 100644
index 180e949b..00000000
--- a/tests.build/build-system-cpan.stdout
+++ /dev/null
@@ -1 +0,0 @@
-bin/hello
diff --git a/tests.build/build-system-python-distutils.script b/tests.build/build-system-python-distutils.script
deleted file mode 100755
index e5c0ea74..00000000
--- a/tests.build/build-system-python-distutils.script
+++ /dev/null
@@ -1,80 +0,0 @@
-#!/bin/sh
-#
-# Copyright (C) 2011-2015 Codethink Limited
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; version 2 of the License.
-#
-# This program 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 General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program. If not, see <http://www.gnu.org/licenses/>.
-
-
-## Convert the hello-chunk project to python with distutils and build.
-
-set -eu
-
-chunkrepo="$DATADIR/chunk-repo"
-cd "$chunkrepo"
-
-git checkout --quiet farrokh
-
-git rm --quiet hello.c
-cat <<EOF >hello
-#!/usr/bin/python
-print "hello, world"
-EOF
-git add hello
-
-cat <<EOF >setup.py
-#!/usr/bin/python
-from distutils.core import setup
-setup(name='hello',
- scripts=['hello'])
-EOF
-git add setup.py
-
-cat <<EOF >hello.morph
-name: hello
-kind: chunk
-build-system: python-distutils
-EOF
-git add hello.morph
-
-git commit --quiet -m 'convert hello into a python project'
-
-
-# Set 'prefix' of hello to something custom
-cd "$DATADIR/morphs-repo"
-cat <<EOF > hello-stratum.morph
-name: hello-stratum
-kind: stratum
-chunks:
- - name: hello
- repo: test:chunk-repo
- ref: farrokh
- build-depends: []
- build-mode: test
- prefix: ""
-EOF
-git add hello-stratum.morph
-git commit -q -m "Set custom install prefix for hello"
-
-
-"$SRCDIR/scripts/test-morph" build-morphology \
- test:morphs-repo master hello-system
-
-for chunk in "$DATADIR/cache/artifacts/"*.chunk.*
-do
- tar -tf "$chunk"
-done | LC_ALL=C sort -u | sed '/^\.\/./s:^\./::' | grep -Ee '^(bin|lib)' |
-sed -e 's:^local/::' \
- -e 's:lib/python2.[6-9]/:lib/python2.x/:' \
- -e 's:/hello-0\.0\.0[^/]*\.egg-info$:/hello.egg-info/:' \
- -e 's:[^/]*-packages:packages:' \
- -e '/^$/d'
diff --git a/tests.build/build-system-python-distutils.stdout b/tests.build/build-system-python-distutils.stdout
deleted file mode 100644
index 4d4c3a1e..00000000
--- a/tests.build/build-system-python-distutils.stdout
+++ /dev/null
@@ -1,6 +0,0 @@
-bin/
-bin/hello
-lib/
-lib/python2.x/
-lib/python2.x/packages/
-lib/python2.x/packages/hello.egg-info/
diff --git a/tests.build/build-system-qmake.script b/tests.build/build-system-qmake.script
deleted file mode 100755
index d430fba7..00000000
--- a/tests.build/build-system-qmake.script
+++ /dev/null
@@ -1,65 +0,0 @@
-#!/bin/sh
-#
-# Copyright (C) 2011-2015 Codethink Limited
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; version 2 of the License.
-#
-# This program 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 General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program. If not, see <http://www.gnu.org/licenses/>.
-
-
-## Convert the hello-chunk project to something qmake-like, then
-## build it.
-
-set -eu
-
-if ! command -v qmake > /dev/null ; then
- # There is no qmake, so skip this test.
- cat "$SRCDIR/tests.build/build-system-qmake.stdout"
- exit 0
-fi
-
-chunkrepo="$DATADIR/chunk-repo"
-cd "$chunkrepo"
-
-git checkout --quiet farrokh
-
-cat <<'EOF' >hello.pro
-TEMPLATE = app
-TARGET = hello
-DEPENDPATH += .
-INCLUDEPATH += .
-
-SOURCES += hello.c
-hello.path = /usr/bin
-hello.files = hello
-INSTALLS += hello
-EOF
-git add hello.pro
-
-cat <<EOF > hello.morph
-name: hello
-kind: chunk
-build-system: qmake
-install-commands:
- - make INSTALL_ROOT="\$DESTDIR" install
-EOF
-git add hello.morph
-git commit --quiet -m "Convert hello to an qmake project"
-
-"$SRCDIR/scripts/test-morph" build-morphology \
- test:morphs-repo master hello-system
-
-for chunk in "$DATADIR/cache/artifacts/"*.chunk.*
-do
- echo "$chunk:" | sed 's/[^.]*//'
- tar -tf "$chunk" | LC_ALL=C sort | sed '/^\.\/./s:^\./::'
- echo
-done
diff --git a/tests.build/build-system-qmake.stdout b/tests.build/build-system-qmake.stdout
deleted file mode 100644
index ccf80a86..00000000
--- a/tests.build/build-system-qmake.stdout
+++ /dev/null
@@ -1,8 +0,0 @@
-.chunk.hello:
-./
-baserock/
-baserock/hello.meta
-usr/
-usr/bin/
-usr/bin/hello
-
diff --git a/tests.build/morphless-chunks.script b/tests.build/morphless-chunks.script
deleted file mode 100755
index 5b19bc4a..00000000
--- a/tests.build/morphless-chunks.script
+++ /dev/null
@@ -1,47 +0,0 @@
-#!/bin/sh
-#
-# Copyright (C) 2012-2015 Codethink Limited
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; version 2 of the License.
-#
-# This program 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 General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program. If not, see <http://www.gnu.org/licenses/>.
-
-
-## Try to build a morphless chunk.
-
-set -eu
-
-# Make 'hello' chunk into an auto-detectable chunk.
-
-cd "$DATADIR/chunk-repo"
-git checkout -q farrokh
-
-touch configure
-chmod +x configure
-# FIXME: If we leave the file empty, busybox sh on ARMv7 fails to execute it.
-echo '#!/bin/sh' > configure
-
-cat << EOF > Makefile
-all install:
-EOF
-
-git rm -q hello.morph
-git add Makefile configure
-git commit -q -m "Convert hello into an autodetectable chunk"
-
-
-"$SRCDIR/scripts/test-morph" build-morphology \
- test:morphs-repo master hello-system
-
-for chunk in "$DATADIR/cache/artifacts/"*.chunk.*
-do
- tar -tf "$chunk"
-done | cat >/dev/null # No files get installed apart from metadata
diff --git a/tests.build/morphless-chunks.stdout b/tests.build/morphless-chunks.stdout
deleted file mode 100644
index e69de29b..00000000
--- a/tests.build/morphless-chunks.stdout
+++ /dev/null
diff --git a/tests.build/prefix.script b/tests.build/prefix.script
index 662be704..5713e125 100755
--- a/tests.build/prefix.script
+++ b/tests.build/prefix.script
@@ -19,9 +19,10 @@
set -eu
-# Create two chunks which print out PATH and PREFIX from their environment.
-cd "$DATADIR/chunk-repo"
+cd "$DATADIR/morphs-repo"
git checkout -q master
+
+# Create two chunks which print out PATH and PREFIX from their environment.
cat <<\EOF > xyzzy.morph
name: xyzzy
kind: chunk
@@ -44,18 +45,19 @@ git add plugh.morph
git commit -q -m "Add chunks"
# Change stratum to include those two chunks, and use a custom install prefix
-cd "$DATADIR/morphs-repo"
cat <<EOF > hello-stratum.morph
name: hello-stratum
kind: stratum
chunks:
- name: xyzzy
+ morph: xyzzy.morph
repo: test:chunk-repo
ref: master
build-depends: []
build-mode: test
prefix: /plover
- name: plugh
+ morph: plugh.morph
repo: test:chunk-repo
ref: master
build-mode: test
@@ -69,6 +71,6 @@ git commit -q -m "Update stratum"
test:morphs-repo master hello-system
cd "$DATADIR/cache/artifacts"
-first_chunk=$(ls -1 *.chunk.xyzzy-* | head -n1 | cut -c -64)
-second_chunk=$(ls -1 *.chunk.plugh-* | head -n1 | cut -c -64)
+first_chunk=$(ls -1 *.chunk.xyzzy* | head -n1 | cut -c -64)
+second_chunk=$(ls -1 *.chunk.plugh* | head -n1 | cut -c -64)
cat $first_chunk.build-log $second_chunk.build-log
diff --git a/tests.build/rebuild-cached-stratum.script b/tests.build/rebuild-cached-stratum.script
index e2e0face..bc1b83fd 100755
--- a/tests.build/rebuild-cached-stratum.script
+++ b/tests.build/rebuild-cached-stratum.script
@@ -41,7 +41,7 @@ cache="$DATADIR/cache/artifacts"
"$SRCDIR/scripts/test-morph" build-morphology \
test:morphs-repo rebuild-cached-stratum hello-system
echo "first build:"
-(cd "$cache" && ls *.chunk.* *hello-stratum-* | sed 's/^[^.]*\./ /' |
+(cd "$cache" && ls *.chunk.* *hello-stratum* | sed 's/^[^.]*\./ /' |
LC_ALL=C sort -u)
# Change the chunk.
@@ -53,6 +53,6 @@ echo "first build:"
"$SRCDIR/scripts/test-morph" build-morphology \
test:morphs-repo rebuild-cached-stratum hello-system
echo "second build:"
-(cd "$cache" && ls *.chunk.* *hello-stratum-* | sed 's/^[^.]*\./ /' |
+(cd "$cache" && ls *.chunk.* *hello-stratum* | sed 's/^[^.]*\./ /' |
LC_ALL=C sort -u)
diff --git a/tests.build/rebuild-cached-stratum.stdout b/tests.build/rebuild-cached-stratum.stdout
index 9c53ee60..4672e7f2 100644
--- a/tests.build/rebuild-cached-stratum.stdout
+++ b/tests.build/rebuild-cached-stratum.stdout
@@ -1,22 +1,8 @@
first build:
- chunk.hello-bins
- chunk.hello-devel
- chunk.hello-doc
- chunk.hello-libs
- chunk.hello-locale
- chunk.hello-misc
- stratum.hello-stratum-devel
- stratum.hello-stratum-devel.meta
- stratum.hello-stratum-runtime
- stratum.hello-stratum-runtime.meta
+ chunk.hello-chunk
+ stratum.hello-stratum
+ stratum.hello-stratum.meta
second build:
- chunk.hello-bins
- chunk.hello-devel
- chunk.hello-doc
- chunk.hello-libs
- chunk.hello-locale
- chunk.hello-misc
- stratum.hello-stratum-devel
- stratum.hello-stratum-devel.meta
- stratum.hello-stratum-runtime
- stratum.hello-stratum-runtime.meta
+ chunk.hello-chunk
+ stratum.hello-stratum
+ stratum.hello-stratum.meta
diff --git a/tests.build/setup b/tests.build/setup
index b7dc5074..7d7b51b5 100755
--- a/tests.build/setup
+++ b/tests.build/setup
@@ -54,22 +54,7 @@ int main(void)
}
EOF
git add hello.c
-
-cat <<EOF > hello.morph
-name: hello
-kind: chunk
-build-system: dummy
-build-commands:
- - gcc -o hello hello.c
-install-commands:
- - install -d "\$DESTDIR"/etc
- - install -d "\$DESTDIR"/bin
- - install hello "\$DESTDIR"/bin/hello
-EOF
-git add hello.morph
-
-git commit --quiet -m "add a hello world program and morph"
-
+git commit --quiet -m "add a hello world program"
git checkout --quiet master
@@ -81,14 +66,44 @@ mkdir "$morphsrepo"
cd "$morphsrepo"
git init --quiet
-echo 'version: 5' > VERSION
+echo 'version: 7' > VERSION
git add VERSION
+cat <<'EOF' > DEFAULTS
+# This is a deliberately minimal DEFAULTS file.
+
+# There are no splitting rules defined, because it's important that Morph
+# still works correctly when the user didn't define any.
+
+build-systems:
+ autotools:
+ configure-commands:
+ - ./configure
+ build-commands:
+ - make
+ install-commands:
+ - make DESTDIR="$DESTDIR" install
+EOF
+git add DEFAULTS
+
+cat <<EOF > hello.morph
+name: hello-chunk
+kind: chunk
+build-commands:
+ - gcc -o hello hello.c
+install-commands:
+ - install -d "\$DESTDIR"/etc
+ - install -d "\$DESTDIR"/bin
+ - install hello "\$DESTDIR"/bin/hello
+EOF
+git add hello.morph
+
cat <<EOF > hello-stratum.morph
name: hello-stratum
kind: stratum
chunks:
- name: hello
+ morph: hello.morph
repo: test:chunk-repo
ref: farrokh
build-mode: test
diff --git a/tests.build/setup-build-essential b/tests.build/setup-build-essential
index 281ff7ec..474c831c 100755
--- a/tests.build/setup-build-essential
+++ b/tests.build/setup-build-essential
@@ -17,6 +17,7 @@
# Set up a stratum which resembles Baserock's 'build-essential' slightly. Used
# for testing 'morph cross-bootstrap' and the 'bootstrap' build mode.
+# Add a mock compiler chunk.
mkdir -p "$DATADIR/cc-repo"
cd "$DATADIR/cc-repo"
@@ -26,6 +27,12 @@ echo "I'm a compiler!"
EOF
chmod +x morph-test-cc
+git init -q
+git add morph-test-cc
+git commit -q -m "Create compiler chunk"
+
+cd "$DATADIR/morphs-repo"
+
cat <<EOF > "stage1-cc.morph"
name: stage1-cc
kind: chunk
@@ -43,15 +50,11 @@ install-commands:
- install -d "\$DESTDIR\$PREFIX/bin"
- install -m 755 morph-test-cc "\$DESTDIR\$PREFIX/bin/morph-test-cc"
EOF
-
-git init -q
-git add morph-test-cc cc.morph stage1-cc.morph
-git commit -q -m "Create compiler chunk"
+git add cc.morph stage1-cc.morph
+git commit -q -m "Add build instructions for mock compiler."
# Require 'cc' in hello-chunk. We should have the second version available
# but *not* the first one.
-cd "$DATADIR/chunk-repo"
-git checkout -q farrokh
cat <<EOF > "hello.morph"
name: hello
kind: chunk
@@ -70,18 +73,20 @@ git commit -q -m "Make 'hello' require our mock compiler"
# Add 'build-essential' stratum and make hello-stratum depend upon it. Only
# the *second* 'cc' chunk should make it into the build-essential stratum
# artifact, and neither should make it into the system.
-cd "$DATADIR/morphs-repo"
+
cat <<EOF > "build-essential.morph"
name: build-essential
kind: stratum
chunks:
- name: stage1-cc
+ morph: stage1-cc.morph
repo: test:cc-repo
ref: master
build-depends: []
build-mode: bootstrap
prefix: /tools
- name: cc
+ morph: cc.morph
repo: test:cc-repo
ref: master
build-depends:
@@ -96,6 +101,7 @@ build-depends:
- morph: build-essential
chunks:
- name: hello
+ morph: hello.morph
repo: test:chunk-repo
ref: farrokh
build-depends: []
diff --git a/without-test-modules b/without-test-modules
index 95f5c13e..a008e03f 100644
--- a/without-test-modules
+++ b/without-test-modules
@@ -62,3 +62,4 @@ distbuild/worker_build_scheduler.py
# Not unit tested, since it needs a full system branch
morphlib/buildbranch.py
morphlib/definitions_repo.py
+morphlib/defaults.py
diff --git a/yarns/implementations.yarn b/yarns/implementations.yarn
index 3bef0374..a7f3d070 100644
--- a/yarns/implementations.yarn
+++ b/yarns/implementations.yarn
@@ -238,7 +238,37 @@ another to hold a chunk.
mkdir "$DATADIR/gits/morphs"
cd "$DATADIR/gits/morphs"
git init .
- echo 'version: 6' > VERSION
+ echo 'version: 7' > VERSION
+
+ install -m644 -D /dev/stdin << EOF "DEFAULTS"
+ # This is a simplified version of the DEFAULTS file supplied with the
+ # Baserock reference system definitions.
+ build-systems:
+ autotools:
+ configure-commands:
+ - ./configure
+ build-commands:
+ - make
+ install-commands:
+ - make install
+ split-rules:
+ chunk:
+ - artifact: -devel
+ include:
+ - (usr/)?include/.*
+ - (usr/)?lib/.*\.a
+ - (usr/)?share/man/.*
+ - artifact: -runtime
+ include:
+ - .*
+ stratum:
+ - artifact: -devel
+ include:
+ - .*-devel
+ - artifact: -runtime
+ include:
+ - .*-runtime
+ EOF
arch=$(run_morph print-architecture)
install -m644 -D /dev/stdin << EOF "systems/test-system.morph"
@@ -321,7 +351,7 @@ another to hold a chunk.
install-commands:
- copy files
system-integration:
- test-chunk-bins:
+ test-chunk-runtime:
00-passwd:
- |
create file /etc/passwd
diff --git a/yarns/regression.yarn b/yarns/regression.yarn
index c424f437..aa98eec5 100644
--- a/yarns/regression.yarn
+++ b/yarns/regression.yarn
@@ -59,17 +59,17 @@ source it depended on.
GIVEN a workspace
AND a git server
AND system systems/test-system.morph uses core-runtime from core
- AND stratum strata/core.morph has match rules: [{artifact: core-runtime, include: [.*-(bins|libs|locale)]}, {artifact: core-devel, include: [.*-(devel|doc|misc)]}]
+ AND stratum strata/core.morph has match rules: [{artifact: core-runtime, include: [.*-devel]}, {artifact: core-devel, include: [.*-runtime]}]
WHEN the user checks out the system branch called master
GIVEN a cluster called test-cluster.morph in system branch master
AND a system in cluster test-cluster.morph in branch master called test-system
AND system test-system in cluster test-cluster.morph in branch master builds systems/test-system.morph
AND system test-system in cluster test-cluster.morph in branch master has deployment type: tar
WHEN the user builds the system systems/test-system.morph in branch master
- GIVEN stratum strata/core.morph in system branch master has match rules: [{artifact: core-runtime, include: [.*-(bins|libs|misc)]}, {artifact: core-devel, include: [.*-(devel|doc|locale)]}]
+ GIVEN stratum strata/core.morph in system branch master has match rules: [{artifact: core-runtime, include: [.*-runtime]}, {artifact: core-devel, include: [.*-devel]}]
WHEN the user builds the system systems/test-system.morph in branch master
AND the user deploys the cluster test-cluster.morph in branch master with options test-system.location="$DATADIR/test.tar"
- THEN tarball test.tar contains baserock/test-chunk-misc.meta
+ THEN tarball test.tar contains baserock/test-chunk-runtime.meta
FINALLY the git server is shut down