summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Maw <richard.maw@codethink.co.uk>2014-02-12 16:27:32 +0000
committerRichard Maw <richard.maw@codethink.co.uk>2014-02-13 15:39:37 +0000
commitfbf70e2e5595d0cc7edaf7240a732cc5d2632c34 (patch)
tree26b563899cecad7f1898c672f6cbf9856993a52b
parent070bcbd497583955e9069ced7aa2473bce2bc3b5 (diff)
downloadmorph-fbf70e2e5595d0cc7edaf7240a732cc5d2632c34.tar.gz
Warn and default to null if repo or ref are given
This now means that the system morphology is not altered when chunks are altered, so some tests had to change. Since this uses the python warnings API, these warnings can be ignored by running python -W ignore:"stratum morphology" \ -W ignore:"system morphology" \ "$(which morph)" ...` or turned into errors with python -W error:"stratum morphology" \ -W error:"system morphology" \ "$(which morph)" ...`
-rw-r--r--morphlib/morphloader.py57
-rw-r--r--morphlib/morphloader_tests.py80
-rw-r--r--morphlib/morphologyfactory.py10
-rwxr-xr-xscripts/test-morph10
-rw-r--r--tests.branching/edit-updates-stratum.stdout12
-rw-r--r--tests.branching/tag-creates-commit-and-tag.stdout18
-rw-r--r--tests.branching/tag-tag-works-as-expected.stdout18
-rw-r--r--tests.branching/workflow.stdout1
-rw-r--r--yarns/branches-workspaces.yarn15
9 files changed, 158 insertions, 63 deletions
diff --git a/morphlib/morphloader.py b/morphlib/morphloader.py
index 32b5b40b..e4367fa1 100644
--- a/morphlib/morphloader.py
+++ b/morphlib/morphloader.py
@@ -18,11 +18,27 @@
import collections
import logging
+import warnings
import yaml
import morphlib
+class MorphologyObsoleteFieldWarning(UserWarning):
+
+ def __init__(self, morphology, spec, field):
+ self.kind = morphology['kind']
+ self.morphology_name = morphology.get('name', '<unknown>')
+ self.stratum_name = spec.get('alias', spec['morph'])
+ self.field = field
+
+ def __str__(self):
+ format_string = ('%(kind)s morphology %(morphology_name)s refers to '
+ 'stratum %(stratum_name)s with the %(field)s field. '
+ 'Defaulting to null.')
+ return format_string % self.__dict__
+
+
class MorphologySyntaxError(morphlib.Error):
def __init__(self, morphology):
@@ -366,6 +382,9 @@ class MorphologyLoader(object):
raise DuplicateStratumError(morph['name'], name)
names.add(name)
+ # Validate stratum spec fields
+ self._validate_stratum_specs_fields(morph, 'strata')
+
# We allow the ARMv7 little-endian architecture to be specified
# as armv7 and armv7l. Normalise.
if morph['arch'] == 'armv7':
@@ -409,6 +428,9 @@ class MorphologyLoader(object):
raise NoStratumBuildDependenciesError(
morph['name'], morph.filename)
+ # Validate build-dependencies if specified
+ self._validate_stratum_specs_fields(morph, 'build-depends')
+
# Require build-dependencies for each chunk.
for spec in morph['chunks']:
if 'build-depends' not in spec:
@@ -496,6 +518,18 @@ class MorphologyLoader(object):
type(pattern), morphology_name)
errors.append(e)
+ @classmethod
+ def _warn_obsolete_field(cls, morphology, spec, field):
+ warnings.warn(MorphologyObsoleteFieldWarning(morphology, spec, field),
+ stacklevel=2)
+
+ @classmethod
+ def _validate_stratum_specs_fields(cls, morphology, specs_field):
+ for spec in morphology.get(specs_field, None) or []:
+ for obsolete_field in ('repo', 'ref'):
+ if obsolete_field in spec:
+ cls._warn_obsolete_field(morphology, spec, obsolete_field)
+
def _require_field(self, field, morphology):
if field not in morphology:
raise MissingFieldError(field, morphology.filename)
@@ -542,9 +576,23 @@ class MorphologyLoader(object):
if key in morphology and morphology[key] == defaults[key]:
del morphology[key]
- if kind in ('stratum', 'cluster'):
+ if kind in ('system', 'stratum', 'cluster'):
getattr(self, '_unset_%s_defaults' % kind)(morphology)
+ @classmethod
+ def _set_stratum_specs_defaults(cls, morphology, specs_field):
+ for spec in morphology.get(specs_field, None) or []:
+ for obsolete_field in ('repo', 'ref'):
+ if obsolete_field in spec:
+ del spec[obsolete_field]
+
+ @classmethod
+ def _unset_stratum_specs_defaults(cls, morphology, specs_field):
+ for spec in morphology.get(specs_field, []):
+ for obsolete_field in ('repo', 'ref'):
+ if obsolete_field in spec:
+ del spec[obsolete_field]
+
def _set_cluster_defaults(self, morph):
for system in morph.get('systems', []):
if 'deploy-defaults' not in system:
@@ -560,7 +608,10 @@ class MorphologyLoader(object):
del system['deploy']
def _set_system_defaults(self, morph):
- pass
+ self._set_stratum_specs_defaults(morph, 'strata')
+
+ def _unset_system_defaults(self, morph):
+ self._unset_stratum_specs_defaults(morph, 'strata')
def _set_stratum_defaults(self, morph):
for spec in morph['chunks']:
@@ -568,6 +619,7 @@ class MorphologyLoader(object):
spec['repo'] = spec['name']
if 'morph' not in spec:
spec['morph'] = spec['name']
+ self._set_stratum_specs_defaults(morph, 'build-depends')
def _unset_stratum_defaults(self, morph):
for spec in morph['chunks']:
@@ -575,6 +627,7 @@ class MorphologyLoader(object):
del spec['repo']
if 'morph' in spec and spec['morph'] == spec['name']:
del spec['morph']
+ self._unset_stratum_specs_defaults(morph, 'strata')
def _set_chunk_defaults(self, morph):
if morph['max-jobs'] is not None:
diff --git a/morphlib/morphloader_tests.py b/morphlib/morphloader_tests.py
index bd3e77e3..b8738804 100644
--- a/morphlib/morphloader_tests.py
+++ b/morphlib/morphloader_tests.py
@@ -16,12 +16,15 @@
# =*= License: GPL-2 =*=
+import contextlib
import os
import shutil
import tempfile
import unittest
+import warnings
import morphlib
+from morphlib.morphloader import MorphologyObsoleteFieldWarning
class MorphologyLoaderTests(unittest.TestCase):
@@ -648,10 +651,13 @@ name: foo
name='foo',
arch='testarch',
strata=[
- {'morph': 'bar'},
+ {
+ 'morph': 'bar',
+ 'repo': 'obsolete',
+ 'ref': 'obsolete',
+ },
])
self.loader.set_defaults(m)
- self.loader.validate(m)
self.assertEqual(
{
'kind': 'system',
@@ -675,7 +681,11 @@ name: foo
'name': 'foo',
'arch': 'testarch',
'strata': [
- {'morph': 'bar'},
+ {
+ 'morph': 'bar',
+ 'repo': None,
+ 'ref': None,
+ },
],
'configuration-extensions': [],
})
@@ -788,3 +798,67 @@ name: foo
self.assertEqual(m['name'], 'foo')
self.assertEqual(m['kind'], 'cluster')
self.assertEqual(m['systems'][0]['morph'], 'bar')
+
+ @contextlib.contextmanager
+ def catch_warnings(*warning_classes):
+ with warnings.catch_warnings(record=True) as caught_warnings:
+ warnings.resetwarnings()
+ for warning_class in warning_classes:
+ warnings.simplefilter("always", warning_class)
+ yield caught_warnings
+
+ def test_warns_when_systems_refer_to_strata_with_repo_or_ref(self):
+ for obsolete_field in ('repo', 'ref'):
+ m = morphlib.morph3.Morphology(
+ name="foo",
+ kind="system",
+ arch="testarch",
+ strata=[
+ {
+ 'morph': 'bar',
+ obsolete_field: 'obsolete',
+ }])
+
+ with self.catch_warnings(MorphologyObsoleteFieldWarning) \
+ as caught_warnings:
+
+ self.loader.validate(m)
+ self.assertEqual(len(caught_warnings), 1)
+ warning = caught_warnings[0].message
+ self.assertEqual(warning.kind, 'system')
+ self.assertEqual(warning.morphology_name, 'foo')
+ self.assertEqual(warning.stratum_name, 'bar')
+ self.assertEqual(warning.field, obsolete_field)
+
+ def test_warns_when_strata_refer_to_build_depends_with_repo_or_ref(self):
+ for obsolete_field in ('repo', 'ref'):
+ m = morphlib.morph3.Morphology(
+ {
+ 'name': 'foo',
+ 'kind': 'stratum',
+ 'build-depends': [
+ {
+ 'morph': 'bar',
+ obsolete_field: 'obsolete'
+ },
+ ],
+ 'chunks': [
+ {
+ 'morph': 'chunk',
+ 'name': 'chunk',
+ 'build-mode': 'test',
+ 'build-depends': [],
+ },
+ ],
+ })
+
+ with self.catch_warnings(MorphologyObsoleteFieldWarning) \
+ as caught_warnings:
+
+ self.loader.validate(m)
+ self.assertEqual(len(caught_warnings), 1)
+ warning = caught_warnings[0].message
+ self.assertEqual(warning.kind, 'stratum')
+ self.assertEqual(warning.morphology_name, 'foo')
+ self.assertEqual(warning.stratum_name, 'bar')
+ self.assertEqual(warning.field, obsolete_field)
diff --git a/morphlib/morphologyfactory.py b/morphlib/morphologyfactory.py
index 3462dd36..8a0b047a 100644
--- a/morphlib/morphologyfactory.py
+++ b/morphlib/morphologyfactory.py
@@ -145,6 +145,11 @@ class MorphologyFactory(object):
morphology.needs_artifact_metadata_cached = False
+ morphlib.morphloader.MorphologyLoader._validate_stratum_specs_fields(
+ morphology, 'strata')
+ morphlib.morphloader.MorphologyLoader._set_stratum_specs_defaults(
+ morphology, 'strata')
+
def _check_and_tweak_stratum(self, morphology, reponame, sha1, filename):
'''Check and tweak a stratum morphology.'''
@@ -164,6 +169,11 @@ class MorphologyFactory(object):
morphology.builds_artifacts = [morphology['name']]
morphology.needs_artifact_metadata_cached = True
+ morphlib.morphloader.MorphologyLoader._validate_stratum_specs_fields(
+ morphology, 'build-depends')
+ morphlib.morphloader.MorphologyLoader._set_stratum_specs_defaults(
+ morphology, 'build-depends')
+
def _check_and_tweak_chunk(self, morphology, reponame, sha1, filename):
'''Check and tweak a chunk morphology.'''
diff --git a/scripts/test-morph b/scripts/test-morph
index 46d87d9f..d8480d92 100755
--- a/scripts/test-morph
+++ b/scripts/test-morph
@@ -1,5 +1,5 @@
#!/bin/sh
-# Copyright (C) 2012,2013 Codethink Limited
+# Copyright (C) 2012,2014 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
@@ -27,10 +27,12 @@ set -eu
# distributed builds, which invoke morph as a sub-process.
export PATH="$SRCDIR:$PATH"
+WARNING_IGNORES='-W ignore:(stratum|system)\s+morphology'
if [ "$1" = "--find-system-artifact" ]; then
shift
- "$SRCDIR/morph" --no-default-config \
+ python $WARNING_IGNORES \
+ "$SRCDIR/morph" --no-default-config \
--tarball-server= --cache-server= \
--cachedir-min-space=0 --tempdir-min-space=0 \
--config="$DATADIR/morph.conf" --verbose "$@" > $DATADIR/stdout
@@ -46,7 +48,9 @@ if [ "$1" = "--find-system-artifact" ]; then
echo $ARTIFACT
else
- "$SRCDIR/scripts/cmd-filter" "$SRCDIR/morph" --no-default-config \
+ "$SRCDIR/scripts/cmd-filter" \
+ python $WARNING_IGNORES \
+ "$SRCDIR/morph" --no-default-config \
--cachedir-min-space=0 --tempdir-min-space=0 \
--tarball-server= --cache-server= \
--config="$DATADIR/morph.conf" "$@"
diff --git a/tests.branching/edit-updates-stratum.stdout b/tests.branching/edit-updates-stratum.stdout
index 7120ef50..ae1af132 100644
--- a/tests.branching/edit-updates-stratum.stdout
+++ b/tests.branching/edit-updates-stratum.stdout
@@ -12,15 +12,3 @@ index 73ed482..475fe0f 100644
+ unpetrify-ref: master
kind: stratum
name: hello-stratum
-diff --git a/hello-system.morph b/hello-system.morph
-index 3f7b4d3..199c924 100644
---- a/hello-system.morph
-+++ b/hello-system.morph
-@@ -3,5 +3,6 @@ kind: system
- name: hello-system
- strata:
- - morph: hello-stratum
-- ref: master
-+ ref: newbranch
- repo: test:morphs
-+ unpetrify-ref: master
diff --git a/tests.branching/tag-creates-commit-and-tag.stdout b/tests.branching/tag-creates-commit-and-tag.stdout
index b6098eb5..e1e2126a 100644
--- a/tests.branching/tag-creates-commit-and-tag.stdout
+++ b/tests.branching/tag-creates-commit-and-tag.stdout
@@ -5,7 +5,7 @@ Date: Tue Jul 31 16:51:54 2012 +0000
Message
-commit 6895ed63425bedb3dccaea3f258c705b1600f6be
+commit 53a2d5f00aead3f01c001da4b2b5677e25970b06
Author: developer <developer@example.com>
Date: Tue Jul 31 16:51:54 2012 +0000
@@ -25,21 +25,9 @@ index 73ed482..2218f63 100644
+ unpetrify-ref: master
kind: stratum
name: hello-stratum
-diff --git a/hello-system.morph b/hello-system.morph
-index 3f7b4d3..d909347 100644
---- a/hello-system.morph
-+++ b/hello-system.morph
-@@ -3,5 +3,6 @@ kind: system
- name: hello-system
- strata:
- - morph: hello-stratum
-- ref: master
-+ ref: example-tag
- repo: test:morphs
-+ unpetrify-ref: master
test:morphs
-commit 6895ed63425bedb3dccaea3f258c705b1600f6be
+commit 53a2d5f00aead3f01c001da4b2b5677e25970b06
Author: developer <developer@example.com>
AuthorDate: Tue Jul 31 16:51:54 2012 +0000
Commit: developer <developer@example.com>
@@ -47,7 +35,7 @@ CommitDate: Tue Jul 31 16:51:54 2012 +0000
Message
-commit e11a36aa9e4c998c41a3ec3209324b9318e484ae
+commit acb64a107d0ebdbbf0b6850b8272301a66c0a4b7
Author: developer <developer@example.com>
AuthorDate: Tue Jul 31 16:51:54 2012 +0000
Commit: developer <developer@example.com>
diff --git a/tests.branching/tag-tag-works-as-expected.stdout b/tests.branching/tag-tag-works-as-expected.stdout
index 98a3be81..9525db0b 100644
--- a/tests.branching/tag-tag-works-as-expected.stdout
+++ b/tests.branching/tag-tag-works-as-expected.stdout
@@ -9,7 +9,7 @@ Date: Tue Jul 31 16:51:54 2012 +0000
Second
-commit 476e4ff4b19c38eb64ad3a151b7c58a7ab95c9ee
+commit 332fc39a03b63a9586950e0826374dc6fa4ceaf8
Author: developer <developer@example.com>
Date: Tue Jul 31 16:51:54 2012 +0000
@@ -29,21 +29,9 @@ index 73ed482..2218f63 100644
+ unpetrify-ref: master
kind: stratum
name: hello-stratum
-diff --git a/hello-system.morph b/hello-system.morph
-index 3f7b4d3..431e15d 100644
---- a/hello-system.morph
-+++ b/hello-system.morph
-@@ -3,5 +3,6 @@ kind: system
- name: hello-system
- strata:
- - morph: hello-stratum
-- ref: master
-+ ref: tagged-tag
- repo: test:morphs
-+ unpetrify-ref: master
test:morphs
-commit 476e4ff4b19c38eb64ad3a151b7c58a7ab95c9ee
+commit 332fc39a03b63a9586950e0826374dc6fa4ceaf8
Author: developer <developer@example.com>
AuthorDate: Tue Jul 31 16:51:54 2012 +0000
Commit: developer <developer@example.com>
@@ -51,7 +39,7 @@ CommitDate: Tue Jul 31 16:51:54 2012 +0000
Second
-commit e11a36aa9e4c998c41a3ec3209324b9318e484ae
+commit acb64a107d0ebdbbf0b6850b8272301a66c0a4b7
Author: developer <developer@example.com>
AuthorDate: Tue Jul 31 16:51:54 2012 +0000
Commit: developer <developer@example.com>
diff --git a/tests.branching/workflow.stdout b/tests.branching/workflow.stdout
index 65985486..e69de29b 100644
--- a/tests.branching/workflow.stdout
+++ b/tests.branching/workflow.stdout
@@ -1 +0,0 @@
-WARNING: chunk "hello-system.hello-stratum.hello" is now petrified
diff --git a/yarns/branches-workspaces.yarn b/yarns/branches-workspaces.yarn
index 08627fe9..15d31cb1 100644
--- a/yarns/branches-workspaces.yarn
+++ b/yarns/branches-workspaces.yarn
@@ -187,21 +187,14 @@ all the refs are unchanged.
GIVEN a workspace
AND a git server
WHEN the user creates a system branch called foo
- THEN in branch foo, system test-system refs test-stratum in master
- AND in branch foo, stratum test-stratum refs test-chunk in master
-
-Then edit the stratum.
-
- WHEN the user edits the stratum test-stratum in the system test-system in branch foo
- THEN in branch foo, system test-system refs test-stratum in foo
+ THEN in branch foo, stratum test-stratum refs test-chunk in master
Edit the chunk. We make use of special knowledge here: `test:test-chunk`
is a chunk repository created in the mocked git server, for testing
purposes.
WHEN the user edits the chunk test-chunk in the stratum test-stratum in the system test-system in branch foo
- THEN in branch foo, system test-system refs test-stratum in foo
- AND in branch foo, stratum test-stratum refs test-chunk in foo
+ THEN in branch foo, stratum test-stratum refs test-chunk in foo
AND the edited chunk test:test-chunk has git branch foo
Morph edit should only work with a system argument.
@@ -228,9 +221,7 @@ repositories referenced in the system branch.
THEN morph reports no outstanding changes in foo
WHEN the user edits the stratum test-stratum in the system test-system in branch foo
- THEN morph reports changes in foo in test:morphs only
-
- WHEN the user edits the chunk test-chunk in the stratum test-stratum in the system test-system in branch foo
+ AND the user edits the chunk test-chunk in the stratum test-stratum in the system test-system in branch foo
THEN morph reports changes in foo in test:morphs only
WHEN creating file foo in test:test-chunk in branch foo