From 2172c4332e8ee26aba28824293faa552867c4d35 Mon Sep 17 00:00:00 2001 From: Sam Thursfield Date: Fri, 20 Feb 2015 14:58:46 +0000 Subject: Revert "Remove petrify and unpetrify commands" This reverts commit d63f41dadf5aa96a8d9254d31e92711ee160245e. --- doc/branching-merging-systems.mdwn | 32 ++++- morphlib/morphset.py | 14 ++ morphlib/morphset_tests.py | 15 ++ morphlib/plugins/branch_and_merge_plugin.py | 98 +++++++++++++ ...hology-contents-do-not-change-cache-keys.script | 45 ++++++ tests.branching.disabled/workflow-petrify.script | 67 +++++++++ tests.branching.disabled/workflow-petrify.stdout | 152 +++++++++++++++++++++ tests.branching/ambiguous-refs.script | 46 +++++++ tests.branching/build-after-petrify.script | 31 +++++ tests.branching/petrify-no-double-petrify.script | 34 +++++ tests.branching/petrify-no-double-petrify.stdout | 9 ++ tests.branching/petrify.script | 42 ++++++ tests.branching/petrify.stdout | 31 +++++ yarns/branches-workspaces.yarn | 1 - 14 files changed, 615 insertions(+), 2 deletions(-) create mode 100755 tests.as-root/unimportant-morphology-contents-do-not-change-cache-keys.script create mode 100755 tests.branching.disabled/workflow-petrify.script create mode 100644 tests.branching.disabled/workflow-petrify.stdout create mode 100755 tests.branching/ambiguous-refs.script create mode 100755 tests.branching/build-after-petrify.script create mode 100755 tests.branching/petrify-no-double-petrify.script create mode 100644 tests.branching/petrify-no-double-petrify.stdout create mode 100755 tests.branching/petrify.script create mode 100644 tests.branching/petrify.stdout diff --git a/doc/branching-merging-systems.mdwn b/doc/branching-merging-systems.mdwn index 3bc19aab..c2e24d77 100644 --- a/doc/branching-merging-systems.mdwn +++ b/doc/branching-merging-systems.mdwn @@ -129,7 +129,7 @@ Also, clone the `morphs` git repository inside the system branch directory. cd ~/baserock/liw/foo/morphs - edit base-system.morph devel-system.morph + morph petrify base-system.morph devel-system.morph git commit -a Modify the specified morphologies (or the stratum morphologies they @@ -225,6 +225,36 @@ it to exist instead. * Run `git checkout BRANCH` in the `morphs` repository. +Implementation: `morph petrify` +-------------- + +Usage: + + morph petrify [MORPH]... + morph petrify --petrify-from-system FILE + +This needs to be run in the `morphs` git repository in a system branch. + +In the first form: + +* read each of the given morphologies; if the morphology is a system one, + follow references to stratum morphologies and process those instead +* in each stratum morphology, replace a reference to a chunk with the + absolute SHA-1: if the original reference was, say, `baserock/morph`, + get the SHA-1 of the current tip commit in that branch and replace + the reference in the morphology + +In the second form: + +* extract the system and stratum morphologies used in the system image file; + these are in a petrified form already +* copy the morphologies to the current working directory, overwriting the + files from git + +In either case, the results need to be committed (with normal git commands) +by the user. + + Implementation: `morph edit` -------------- diff --git a/morphlib/morphset.py b/morphlib/morphset.py index a4cb5dae..17c9cdc4 100644 --- a/morphlib/morphset.py +++ b/morphlib/morphset.py @@ -244,3 +244,17 @@ class MorphologySet(object): return True self.traverse_specs(process_chunk_spec, wanted_chunk_spec) + + def unpetrify_all(self): + '''If a spec is petrified, unpetrify it. + + ''' + + def wanted_spec(m, kind, spec): + return ('unpetrify-ref' in spec and + morphlib.git.is_valid_sha1(spec.get('ref'))) + def process_spec(m, kind, spec): + spec['ref'] = spec.pop('unpetrify-ref') + return True + + self.traverse_specs(process_spec, wanted_spec) diff --git a/morphlib/morphset_tests.py b/morphlib/morphset_tests.py index bf726d4c..f7378d39 100644 --- a/morphlib/morphset_tests.py +++ b/morphlib/morphset_tests.py @@ -199,3 +199,18 @@ class MorphologySetTests(unittest.TestCase): 'unpetrify-ref': 'master', } ]) + + def test_unpetrify_all(self): + self.morphs.add_morphology(self.system) + self.morphs.add_morphology(self.stratum) + self.morphs.petrify_chunks({('test:foo-chunk', 'master'): '0'*40}) + self.morphs.unpetrify_all() + self.assertEqual( + self.stratum['chunks'], + [ + { + 'repo': 'test:foo-chunk', + 'ref': 'master', + 'morph': 'foo-chunk', + } + ]) diff --git a/morphlib/plugins/branch_and_merge_plugin.py b/morphlib/plugins/branch_and_merge_plugin.py index 08589ea6..9a2851d8 100644 --- a/morphlib/plugins/branch_and_merge_plugin.py +++ b/morphlib/plugins/branch_and_merge_plugin.py @@ -36,6 +36,10 @@ class BranchAndMergePlugin(cliapp.Plugin): 'branch', self.branch, arg_synopsis='REPO NEW [OLD]') self.app.add_subcommand( 'edit', self.edit, arg_synopsis='CHUNK') + self.app.add_subcommand( + 'petrify', self.petrify, arg_synopsis='') + self.app.add_subcommand( + 'unpetrify', self.unpetrify, arg_synopsis='') self.app.add_subcommand( 'show-system-branch', self.show_system_branch, arg_synopsis='') self.app.add_subcommand( @@ -490,6 +494,100 @@ class BranchAndMergePlugin(cliapp.Plugin): morphs.add_morphology(morph) return morphs + def petrify(self, args): + '''Convert all chunk refs in a system branch to be fixed SHA1s. + + This modifies all git commit references in system and stratum + morphologies, in the current system branch, to be fixed SHA + commit identifiers, rather than symbolic branch or tag names. + This is useful for making sure none of the components in a system + branch change accidentally. + + Consider the following scenario: + + * The `master` system branch refers to `gcc` using the + `baserock/morph` ref. This is appropriate, since the main line + of development should use the latest curated code. + + * You create a system branch to prepare for a release, called + `TROVE_ID/release/2.0`. The reference to `gcc` is still + `baserock/morph`. + + * You test everything, and make a release. You deploy the release + images onto devices, which get shipped to your customers. + + * A new version GCC is committed to the `baserock/morph` branch. + + * Your release branch suddenly uses a new compiler, which may + or may not work for your particular system at that release. + + To avoid this, you need to _petrify_ all git references + so that they do not change accidentally. If you've tested + your release with the GCC release that is stored in commit + `94c50665324a7aeb32f3096393ec54b2e63bfb28`, then you should + continue to use that version of GCC, regardless of what might + happen in the master system branch. If, and only if, you decide + that a new compiler would be good for your release should you + include it in your release branch. This way, only the things + that you change intentionally change in your release branch. + + ''' + + if args: + raise cliapp.AppException('morph petrify takes no arguments') + + ws = morphlib.workspace.open('.') + sb = morphlib.sysbranchdir.open_from_within('.') + loader = morphlib.morphloader.MorphologyLoader() + lrc, rrc = morphlib.util.new_repo_caches(self.app) + update_repos = not self.app.settings['no-git-update'] + + morphs = self._load_all_sysbranch_morphologies(sb, loader) + + #TODO: Stop using app.resolve_ref + def resolve_refs(morphs): + for repo, ref in morphs.list_refs(): + # You can't resolve null refs, so don't attempt to. + if repo is None or ref is None: + continue + # TODO: Handle refs that are only in workspace in general + if (repo == sb.root_repository_url + and ref == sb.system_branch_name): + continue + commit_sha1, tree_sha1 = self.app.resolve_ref( + lrc, rrc, repo, ref, update=update_repos) + yield ((repo, ref), commit_sha1) + + morphs.repoint_refs(sb.root_repository_url, + sb.system_branch_name) + + morphs.petrify_chunks(dict(resolve_refs(morphs))) + + # Write morphologies back out again. + self._save_dirty_morphologies(loader, sb, morphs.morphologies) + + def unpetrify(self, args): + '''Reverse the process of petrification. + + This undoes the changes `morph petrify` did. + + ''' + + if args: + raise cliapp.AppException('morph petrify takes no arguments') + + ws = morphlib.workspace.open('.') + sb = morphlib.sysbranchdir.open_from_within('.') + loader = morphlib.morphloader.MorphologyLoader() + + morphs = self._load_all_sysbranch_morphologies(sb, loader) + + # Restore the ref for each stratum and chunk + morphs.unpetrify_all() + + # Write morphologies back out again. + self._save_dirty_morphologies(loader, sb, morphs.morphologies) + def status(self, args): '''Show information about the current system branch or workspace diff --git a/tests.as-root/unimportant-morphology-contents-do-not-change-cache-keys.script b/tests.as-root/unimportant-morphology-contents-do-not-change-cache-keys.script new file mode 100755 index 00000000..a540cdee --- /dev/null +++ b/tests.as-root/unimportant-morphology-contents-do-not-change-cache-keys.script @@ -0,0 +1,45 @@ +#!/bin/bash +# +# 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 +# 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, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +## Some contents of morphologies (description, build-depends, chunks) +## should not change the cache keys of those morphs because they are +## either already considered (build-depends and chunks) or do not affect +## building (description). This test checks that changes to these parts +## of a morphology do not force rebuilds. + +# FIXME: This seems to break because the new "morph edit" makes correct +# changes to build-dependencies, which breaks the old "morph build". +# Disable test now, re-enable it after "morph build" is fixed. --liw +exit 0 + +set -eu + +source "$SRCDIR/tests.as-root/setup-build" + +# Build once. +cd "$DATADIR/workspace" +"$SRCDIR/scripts/test-morph" build linux-system +ARTIFACT_COUNT="$(ls "$DATADIR/cache/artifacts" | wc -l)" + +# Petrify the refs, so the morphologies will be different +(set -e && cd branch1/test/morphs && git push --quiet origin HEAD) +(set -e && cd branch1/test/kernel-repo && git push --quiet origin HEAD) +"$SRCDIR/scripts/test-morph" petrify + +# Build with the petrified morphologies. +"$SRCDIR/scripts/test-morph" build linux-system +[ "$ARTIFACT_COUNT" -eq $(ls "$DATADIR/cache/artifacts" | wc -l) ] diff --git a/tests.branching.disabled/workflow-petrify.script b/tests.branching.disabled/workflow-petrify.script new file mode 100755 index 00000000..3c561d5b --- /dev/null +++ b/tests.branching.disabled/workflow-petrify.script @@ -0,0 +1,67 @@ +#!/bin/sh +# +# 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 +# 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, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + +## Do a complete workflow test, with strata outside the main morphologies +## repository. + +set -eu + +. "$SRCDIR/scripts/setup-3rd-party-strata" + +cd "$DATADIR/workspace" +"$SRCDIR/scripts/test-morph" branch test:morphs test/petrify + +cd test/petrify +"$SRCDIR/scripts/test-morph" petrify + +echo "test/petrify after petrifying:" +cat test:morphs/hello-system.morph +cat test:external-strata/stratum2.morph +cat test:external-strata/stratum3.morph + +"$SRCDIR/scripts/test-morph" edit hello + +echo +echo "test/petrify after editing a chunk:" +cat test:morphs/hello-system.morph +cat test:external-strata/stratum2.morph +cat test:external-strata/stratum3.morph + +# me/readme-fixes in test:stratum2-hello should be 'master', but +# that's the only ref upstream so we can infer that it is if we got here + +cd test:morphs +git commit --quiet --all -m "Petrify branch test/petrify" +git push --quiet origin test/petrify +cd ../test:external-strata +git commit --quiet --all -m "Petrify branch test/petrify" +git push --quiet origin test/petrify + +# unpetrify is easy enough. Let's try unpetrifying a different branch that +# was forked off the original while it was petrified, instead. +cd "$DATADIR/workspace" +"$SRCDIR/scripts/test-morph" branch test:morphs test/unpetrify test/petrify + +cd test/unpetrify +"$SRCDIR/scripts/test-morph" unpetrify + +echo +echo "test/unpetrify after unpetrifying:" +cat test:morphs/hello-system.morph +cat test:external-strata/stratum2.morph +cat test:external-strata/stratum3.morph diff --git a/tests.branching.disabled/workflow-petrify.stdout b/tests.branching.disabled/workflow-petrify.stdout new file mode 100644 index 00000000..a0ce82f4 --- /dev/null +++ b/tests.branching.disabled/workflow-petrify.stdout @@ -0,0 +1,152 @@ +test/petrify after petrifying: +{ + "name": "hello-system", + "kind": "system", + "arch": "x86_64", + "strata": [ + { + "morph": "hello-stratum", + "repo": "test:morphs", + "ref": "test/petrify" + }, + { + "morph": "stratum2", + "repo": "test:external-strata", + "ref": "test/petrify" + }, + { + "morph": "stratum3", + "repo": "test:external-strata", + "ref": "test/petrify" + } + ] +} +{ + "name": "stratum2", + "kind": "stratum", + "chunks": [ + { + "name": "hello", + "repo": "test:stratum2-hello", + "ref": "f4730636e429149bb923fa16be3aa9802d484b23", + "build-mode": "test", + "build-depends": [], + "unpetrify-ref": "master" + } + ] +} +{ + "name": "stratum3", + "kind": "stratum", + "chunks": [ + { + "name": "hello", + "repo": "test:stratum3-hello", + "ref": "f4730636e429149bb923fa16be3aa9802d484b23", + "build-mode": "test", + "build-depends": [], + "unpetrify-ref": "master" + } + ] +} + +test/petrify after editing a chunk: +{ + "name": "hello-system", + "kind": "system", + "arch": "x86_64", + "strata": [ + { + "morph": "hello-stratum", + "repo": "test:morphs", + "ref": "test/petrify" + }, + { + "morph": "stratum2", + "repo": "test:external-strata", + "ref": "test/petrify" + }, + { + "morph": "stratum3", + "repo": "test:external-strata", + "ref": "test/petrify" + } + ] +} +{ + "name": "stratum2", + "kind": "stratum", + "chunks": [ + { + "name": "hello", + "repo": "test:stratum2-hello", + "ref": "test/petrify", + "build-mode": "test", + "build-depends": [] + } + ] +} +{ + "name": "stratum3", + "kind": "stratum", + "chunks": [ + { + "name": "hello", + "repo": "test:stratum3-hello", + "ref": "f4730636e429149bb923fa16be3aa9802d484b23", + "build-mode": "test", + "build-depends": [], + "unpetrify-ref": "master" + } + ] +} + +test/unpetrify after unpetrifying: +{ + "name": "hello-system", + "kind": "system", + "arch": "x86_64", + "strata": [ + { + "morph": "hello-stratum", + "repo": "test:morphs", + "ref": "test/unpetrify" + }, + { + "morph": "stratum2", + "repo": "test:external-strata", + "ref": "test/unpetrify" + }, + { + "morph": "stratum3", + "repo": "test:external-strata", + "ref": "test/unpetrify" + } + ] +} +{ + "name": "stratum2", + "kind": "stratum", + "chunks": [ + { + "name": "hello", + "repo": "test:stratum2-hello", + "ref": "test/petrify", + "build-mode": "test", + "build-depends": [] + } + ] +} +{ + "name": "stratum3", + "kind": "stratum", + "chunks": [ + { + "name": "hello", + "repo": "test:stratum3-hello", + "ref": "master", + "build-mode": "test", + "build-depends": [] + } + ] +} diff --git a/tests.branching/ambiguous-refs.script b/tests.branching/ambiguous-refs.script new file mode 100755 index 00000000..aeec61a1 --- /dev/null +++ b/tests.branching/ambiguous-refs.script @@ -0,0 +1,46 @@ +#!/bin/sh +# +# 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 +# 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, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + +## Guard against a bug that occurs if 'git show-ref' is used to resolve refs +## instead of 'git rev-parse --verify': show-ref returns a list of partial +## matches sorted alphabetically, so any code using it may resolve refs +## incorrectly. + +set -eu + +. "$SRCDIR/scripts/fix-committer-info" + +cd "$DATADIR/morphs" +git mv hello-stratum.morph goodbye-stratum.morph +sed -e '/morph: hello-stratum/s/hello-stratum/goodbye-stratum/' \ + -i hello-system.morph + +git commit --quiet -am "Rename hello-system" + +cd "$DATADIR/workspace" +"$SRCDIR/scripts/test-morph" init +"$SRCDIR/scripts/test-morph" branch test:morphs release + +# Create an extra ref to confuse any users of git show-ref +cd release/test/morphs +git checkout --quiet -b alpha/master HEAD~1 +git checkout --quiet release + +# The petrify will fail if we resolved 'master' as 'alpha/master' by mistake. +cd "$DATADIR/workspace/release/test/morphs" +"$SRCDIR/scripts/test-morph" petrify diff --git a/tests.branching/build-after-petrify.script b/tests.branching/build-after-petrify.script new file mode 100755 index 00000000..d3b75f07 --- /dev/null +++ b/tests.branching/build-after-petrify.script @@ -0,0 +1,31 @@ +#!/bin/sh +# +# Copyright (C) 2013 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, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + +## Verify systems can be built after "morph petrify" + +set -eu + +. "$SRCDIR/tests.branching/setup-second-chunk" + +cd "$DATADIR/workspace" +"$SRCDIR/scripts/test-morph" init +"$SRCDIR/scripts/test-morph" branch test:morphs test/build-petrify master + +"$SRCDIR/scripts/test-morph" petrify + +"$SRCDIR/scripts/test-morph" build hello-system diff --git a/tests.branching/petrify-no-double-petrify.script b/tests.branching/petrify-no-double-petrify.script new file mode 100755 index 00000000..3c9185dc --- /dev/null +++ b/tests.branching/petrify-no-double-petrify.script @@ -0,0 +1,34 @@ +#!/bin/sh +# +# 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 +# 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, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + +## It should be impossible to lose the original refs, or we risk making +## unpetrify impossible. + +set -eu + +cd "$DATADIR/workspace" +"$SRCDIR/scripts/test-morph" init +"$SRCDIR/scripts/test-morph" branch test:morphs test/petrify + +cd test/petrify/test/morphs +git push --quiet origin HEAD +"$SRCDIR/scripts/test-morph" petrify +"$SRCDIR/scripts/test-morph" petrify +"$SRCDIR/scripts/test-morph" petrify + +cat hello-stratum.morph diff --git a/tests.branching/petrify-no-double-petrify.stdout b/tests.branching/petrify-no-double-petrify.stdout new file mode 100644 index 00000000..50da61ba --- /dev/null +++ b/tests.branching/petrify-no-double-petrify.stdout @@ -0,0 +1,9 @@ +name: hello-stratum +kind: stratum +chunks: +- name: hello + repo: test:hello + ref: 293fa0b08f0382c63181c36b6efa602876aa8c87 + unpetrify-ref: master + build-depends: [] + build-mode: test diff --git a/tests.branching/petrify.script b/tests.branching/petrify.script new file mode 100755 index 00000000..f8e7c1e9 --- /dev/null +++ b/tests.branching/petrify.script @@ -0,0 +1,42 @@ +#!/bin/sh +# +# 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 +# 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, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + +## Verify "morph petrify", and ensure it doesn't petrify chunks that have +## already been edited. + +set -eu + +. "$SRCDIR/tests.branching/setup-second-chunk" + +cd "$DATADIR/workspace" +"$SRCDIR/scripts/test-morph" init +"$SRCDIR/scripts/test-morph" branch test:morphs test/petrify master + +cd test/petrify/test/morphs +git push --quiet origin HEAD +"$SRCDIR/scripts/test-morph" edit goodbye +(cd ../goodbye && git push --quiet origin HEAD) + +"$SRCDIR/scripts/test-morph" petrify +echo "Petrified:" +cat hello-stratum.morph + +"$SRCDIR/scripts/test-morph" unpetrify +echo +echo "Unpetrified:" +cat hello-stratum.morph diff --git a/tests.branching/petrify.stdout b/tests.branching/petrify.stdout new file mode 100644 index 00000000..f9f35342 --- /dev/null +++ b/tests.branching/petrify.stdout @@ -0,0 +1,31 @@ +Petrified: +name: hello-stratum +kind: stratum +chunks: +- name: hello + repo: test:hello + ref: 293fa0b08f0382c63181c36b6efa602876aa8c87 + unpetrify-ref: master + build-depends: [] + build-mode: test +- name: goodbye + repo: test:goodbye + ref: 717c4a523fb5a94ca2f0a61e665fbc2da6a1f6ac + unpetrify-ref: test/petrify + build-depends: [] + build-mode: test + +Unpetrified: +name: hello-stratum +kind: stratum +chunks: +- name: hello + repo: test:hello + ref: master + build-depends: [] + build-mode: test +- name: goodbye + repo: test:goodbye + ref: test/petrify + build-depends: [] + build-mode: test diff --git a/yarns/branches-workspaces.yarn b/yarns/branches-workspaces.yarn index 3b765b57..bd520ff1 100644 --- a/yarns/branches-workspaces.yarn +++ b/yarns/branches-workspaces.yarn @@ -202,6 +202,5 @@ artifact in a system. This name includes the cache key of the artifact. SCENARIO using morph list-artifacts GIVEN a git server - WHEN the user lists the artifacts which make up the system systems/test-system.morph at ref HEAD in repository test:morphs THEN morph succeeded -- cgit v1.2.1