diff options
-rw-r--r-- | morphlib/morphloader.py | 57 | ||||
-rw-r--r-- | morphlib/morphloader_tests.py | 80 | ||||
-rw-r--r-- | morphlib/morphologyfactory.py | 10 | ||||
-rwxr-xr-x | scripts/test-morph | 10 | ||||
-rw-r--r-- | tests.branching/edit-updates-stratum.stdout | 12 | ||||
-rw-r--r-- | tests.branching/tag-creates-commit-and-tag.stdout | 18 | ||||
-rw-r--r-- | tests.branching/tag-tag-works-as-expected.stdout | 18 | ||||
-rw-r--r-- | tests.branching/workflow.stdout | 1 | ||||
-rw-r--r-- | yarns/branches-workspaces.yarn | 15 |
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 |