summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Maw <richard.maw@codethink.co.uk>2012-09-17 12:58:23 +0000
committerRichard Maw <richard.maw@codethink.co.uk>2012-09-17 12:58:23 +0000
commitdebcb7429328880231a7659be5c71f322a78c235 (patch)
tree01e5e4fb7626fa100aabff657afa5ae80659cc8c
parentce118d0f5dbf1ca62fd0660a4a12283e9bd7c49e (diff)
parent8ed384ddee061e173b06949977a02b59ad6e1ea1 (diff)
downloadmorph-debcb7429328880231a7659be5c71f322a78c235.tar.gz
Merge branch 'samthursfield/complex-merges-2' of git://roadtrain.codethink.co.uk/baserock/morph
-rw-r--r--morphlib/git.py11
-rw-r--r--morphlib/plugins/branch_and_merge_plugin.py185
-rw-r--r--tests.branching/merge-handles-unmergable-cases.exit1
-rwxr-xr-xtests.branching/merge-handles-unmergable-cases.script30
-rw-r--r--tests.branching/merge-handles-unmergable-cases.stderr1
-rwxr-xr-xtests.branching/merge-not-to-master.script69
-rwxr-xr-xtests.branching/merge-with-chunk-renamed.script56
-rw-r--r--tests.branching/merge-with-chunk-repo-moved.exit1
-rwxr-xr-xtests.branching/merge-with-chunk-repo-moved.script53
-rw-r--r--tests.branching/merge-with-chunk-repo-moved.stderr1
-rw-r--r--tests.branching/merge-with-stratum-renamed.exit1
-rwxr-xr-xtests.branching/merge-with-stratum-renamed.script51
-rw-r--r--tests.branching/merge-with-stratum-renamed.stderr1
-rwxr-xr-xtests.branching/merge.script2
-rw-r--r--tests.branching/merge.stdout2
-rwxr-xr-xtests.branching/workflow-separate-stratum-repos.script48
16 files changed, 444 insertions, 69 deletions
diff --git a/morphlib/git.py b/morphlib/git.py
index 9ab98ad0..5862ef9b 100644
--- a/morphlib/git.py
+++ b/morphlib/git.py
@@ -196,6 +196,17 @@ def checkout_ref(runcmd, gitdir, ref):
'''Checks out a specific ref/SHA1 in a git working tree.'''
runcmd(['git', 'checkout', ref], cwd=gitdir)
+
+def index_has_changes(runcmd, gitdir):
+ '''Returns True if there are no staged changes to commit'''
+ try:
+ runcmd(['git', 'diff-index', '--cached', '--quiet',
+ '--ignore-submodules', 'HEAD'], cwd=gitdir)
+ except cliapp.AppException:
+ return True
+ return False
+
+
def reset_workdir(runcmd, gitdir):
'''Removes any differences between the current commit '''
'''and the status of the working directory'''
diff --git a/morphlib/plugins/branch_and_merge_plugin.py b/morphlib/plugins/branch_and_merge_plugin.py
index 82d83a58..75935b72 100644
--- a/morphlib/plugins/branch_and_merge_plugin.py
+++ b/morphlib/plugins/branch_and_merge_plugin.py
@@ -475,27 +475,34 @@ class BranchAndMergePlugin(cliapp.Plugin):
branch_root = self.get_branch_config(branch_dir, 'branch.root')
self.app.output.write('%s\n' % branch_root)
- def make_repository_available(self, system_branch, branch_dir, repo, ref):
- existing_repo = self.find_repository(branch_dir, repo)
- if existing_repo:
- # Reuse the existing clone and its system branch.
- self.app.runcmd(['git', 'checkout', system_branch],
- cwd=existing_repo)
- return existing_repo
- else:
- # Clone repo and create the system branch in the cloned repo.
+ def checkout_repository(self, branch_dir, repo, ref, parent_ref=None):
+ '''Make a chunk or stratum repository available for a system branch
+
+ We ensure the 'system_branch' ref within 'repo' is checked out,
+ creating it from 'parent_ref' if required.
+
+ The function aims for permissiveness, so users can try to fix any
+ weirdness they have caused in the repos with another call to 'morph
+ edit'.
+
+ '''
+
+ parent_ref = parent_ref or ref
+
+ repo_dir = self.find_repository(branch_dir, repo)
+ if repo_dir is None:
repo_url = self.resolve_reponame(repo)
repo_dir = os.path.join(branch_dir, self.convert_uri_to_path(repo))
- self.clone_to_directory(repo_dir, repo, ref)
- try:
- self.log_change(repo, 'branch "%s" created from "%s"' %
- (system_branch, ref))
- self.app.runcmd(['git', 'checkout', '-b', system_branch],
- cwd=repo_dir)
- except:
- self.app.runcmd(['git', 'checkout', system_branch],
- cwd=repo_dir)
- return repo_dir
+ self.clone_to_directory(repo_dir, repo, parent_ref)
+
+ if self.resolve_ref(repo_dir, ref) is None:
+ self.log_change(repo, 'branch "%s" created from "%s"' %
+ (ref, parent_ref))
+ self.app.runcmd(['git', 'checkout', '-b', ref], cwd=repo_dir)
+ else:
+ # git copes even if the system_branch ref is already checked out
+ self.app.runcmd(['git', 'checkout', ref], cwd=repo_dir)
+ return repo_dir
def edit(self, args):
'''Edit a component in a system branch.'''
@@ -523,8 +530,9 @@ class BranchAndMergePlugin(cliapp.Plugin):
stratum_name, collection='strata')
# Make the stratum repository and the ref available locally.
- stratum_repo_dir = self.make_repository_available(
- system_branch, branch_dir, stratum['repo'], stratum['ref'])
+ stratum_repo_dir = self.checkout_repository(
+ branch_dir, stratum['repo'], system_branch,
+ parent_ref=stratum['ref'])
# Check if we need to change anything at all.
if stratum['ref'] != system_branch:
@@ -560,8 +568,9 @@ class BranchAndMergePlugin(cliapp.Plugin):
chunk_name, collection='chunks')
# Make the chunk repository and the ref available locally.
- chunk_repo_dir = self.make_repository_available(
- system_branch, branch_dir, chunk['repo'], chunk['ref'])
+ chunk_repo_dir = self.checkout_repository(
+ branch_dir, chunk['repo'], system_branch,
+ parent_ref=chunk['ref'])
# Check if we need to update anything at all.
if chunk['ref'] != system_branch:
@@ -577,13 +586,38 @@ class BranchAndMergePlugin(cliapp.Plugin):
self.print_changelog('The following changes were made but have not '
'been comitted')
+ def load_morphology_pair(self, repo_dir, ref, name):
+ '''Load two versions of a morphology and check for major conflicts
+
+ Returns the version at 'ref' (if it exists) and the on-disk version.
+
+ '''
+
+ new = self.load_morphology(repo_dir, name)
+ try:
+ old = self.load_morphology(repo_dir, name, ref=ref)
+ except cliapp.AppException as e:
+ return None, new
+
+ if old['name'] != new['name']:
+ # We should enforce this in validation during load_morphology()
+ # rather than having to check it here
+ raise cliapp.AppException(
+ 'merge confict: "name" of morphology %s (name should '
+ 'always match filename)' % name)
+ if old['kind'] != new['kind']:
+ raise cliapp.AppException(
+ 'merge conflict: "kind" of morphology %s' % name)
+
+ return old, new
+
def merge_repo(self, name, from_dir, from_branch, to_dir, to_branch,
commit = False):
'''Merge changes for a system branch in a specific repository'''
if self.get_uncommitted_changes(from_dir) != []:
raise cliapp.AppException('repository %s has uncommitted '
- 'changes', name)
+ 'changes' % from_dir)
# repo must be made into a URL to avoid ':' in pathnames confusing git
from_url = urlparse.urljoin('file://', from_dir)
self.app.runcmd(['git', 'pull', '--no-commit', '--no-ff', from_url,
@@ -615,54 +649,87 @@ class BranchAndMergePlugin(cliapp.Plugin):
'repository : %s vs %s' %
(root_repo, other_root_repo))
- def _merge_chunk(ci):
- from_repo = self.find_repository(from_branch_dir, ci['repo'])
- to_repo = self.make_repository_available(
- to_branch, to_branch_dir, ci['repo'], to_branch)
+ def merge_chunk(old_ci, ci):
+ from_repo = self.find_repository(from_branch_dir, old_ci['repo'])
+ to_repo = self.checkout_repository(
+ to_branch_dir, ci['repo'], ci['ref'])
self.merge_repo(ci['repo'], from_repo, from_branch,
- to_repo, to_branch, commit=True)
+ to_repo, ci['ref'], commit=True)
- def _merge_stratum(si):
- if si['repo'] == root_repo:
- to_repo = to_root_dir
- else:
- from_repo = self.find_repository(from_branch_dir, si['repo'])
- to_repo = self.make_repository_available(
- to_branch, to_branch_dir, si['repo'], to_branch)
- # We will do a merge commit in this repo later on
- self.merge_repo(si['repo'], from_repo, from_branch,
- to_repo, to_branch, commit=False)
- morphs_repo_list.add(to_repo)
+ def merge_stratum(old_si, si):
+ from_repo = self.find_repository(from_branch_dir, old_si['repo'])
+ to_repo = self.checkout_repository(
+ to_branch_dir, si['repo'], si['ref'])
- stratum = self.load_morphology(to_repo, si['morph'])
- for ci in stratum['chunks']:
- if ci['ref'] == from_branch:
- _merge_chunk(ci)
- ci['ref'] = to_branch
- self.save_morphology(to_repo, si['morph'], stratum)
+ if to_repo not in dirty_repos:
+ self.merge_repo(si['repo'], from_repo, from_branch,
+ to_repo, si['ref'], commit=False)
+ dirty_repos.add(to_repo)
+ old_stratum, stratum = self.load_morphology_pair(
+ to_repo, old_si['ref'], si['morph'])
+
+ changed = False
+ edited_chunks = [ci for ci in stratum['chunks']
+ if ci['ref'] == from_branch]
+ for ci in edited_chunks:
+ for old_ci in old_stratum['chunks']:
+ if old_ci['repo'] == ci['repo']:
+ break
+ else:
+ raise cliapp.AppException(
+ 'chunk %s was added within this branch and '
+ 'subsequently edited. This is not yet supported: '
+ 'refusing to merge.' % ci['name'])
+ changed = True
+ ci['ref'] = old_ci['ref']
+ merge_chunk(old_ci, ci)
+ if changed:
+ self.save_morphology(to_repo, si['morph'], stratum)
+ self.app.runcmd(['git', 'add', si['morph'] + '.morph'],
+ cwd=to_repo)
from_root_dir = self.find_repository(from_branch_dir, root_repo)
to_root_dir = self.find_repository(to_branch_dir, root_repo)
self.app.runcmd(['git', 'checkout', to_branch], cwd=to_root_dir)
self.merge_repo(root_repo, from_root_dir, from_branch,
to_root_dir, to_branch, commit=False)
- morphs_repo_list = set([to_root_dir])
+ dirty_repos = set([to_root_dir])
for f in glob.glob(os.path.join(to_root_dir, '*.morph')):
- name = f[:-len('.morph')]
- morphology = self.load_morphology(to_root_dir, name)
+ name = os.path.basename(f)[:-len('.morph')]
+ old_morphology, morphology = self.load_morphology_pair(
+ to_root_dir, to_branch, name)
if morphology['kind'] == 'system':
- for si in morphology['strata']:
- if si['ref'] == from_branch:
- _merge_stratum(si)
- si['ref'] = to_branch
- self.save_morphology(to_root_dir, name, morphology)
-
- for repo in morphs_repo_list:
- msg = "Merge system branch '%s'" % from_branch
- self.app.runcmd(['git', 'commit', '--all', '--message=%s' % msg],
- cwd=repo)
+ changed = False
+ edited_strata = [si for si in morphology['strata']
+ if si['ref'] == from_branch]
+ for si in edited_strata:
+ for old_si in old_morphology['strata']:
+ # We make no attempt at rename / move detection
+ if old_si['morph'] == si['morph'] \
+ and old_si['repo'] == si['repo']:
+ break
+ else:
+ raise cliapp.AppException(
+ 'stratum %s was added within this branch and '
+ 'subsequently edited. This is not yet supported: '
+ 'refusing to merge.' % si['morph'])
+ changed = True
+ si['ref'] = old_si['ref']
+ merge_stratum(old_si, si)
+ if changed:
+ self.save_morphology(to_root_dir, name, morphology)
+ self.app.runcmd(['git', 'add', f], cwd=to_root_dir)
+
+ for repo_dir in dirty_repos:
+ # Repo will often turn out to not be dirty: if the changes we
+ # merged only updated refs to the system branch, we will have
+ # changed them back again so that the index will now be empty.
+ if morphlib.git.index_has_changes(self.app.runcmd, repo_dir):
+ msg = "Merge system branch '%s'" % from_branch
+ self.app.runcmd(['git', 'commit', '--all', '-m%s' % msg],
+ cwd=repo_dir)
def build(self, args):
if len(args) != 1:
diff --git a/tests.branching/merge-handles-unmergable-cases.exit b/tests.branching/merge-handles-unmergable-cases.exit
new file mode 100644
index 00000000..d00491fd
--- /dev/null
+++ b/tests.branching/merge-handles-unmergable-cases.exit
@@ -0,0 +1 @@
+1
diff --git a/tests.branching/merge-handles-unmergable-cases.script b/tests.branching/merge-handles-unmergable-cases.script
new file mode 100755
index 00000000..fd7f1478
--- /dev/null
+++ b/tests.branching/merge-handles-unmergable-cases.script
@@ -0,0 +1,30 @@
+#!/bin/sh
+# Copyright (C) 2012 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.
+
+# Things that "morph merge" isn't expected to handle (but shouldn't crash)
+
+set -eu
+
+cd "$DATADIR/workspace"
+"$SRCDIR/scripts/test-morph" init
+"$SRCDIR/scripts/test-morph" checkout baserock:morphs master
+"$SRCDIR/scripts/test-morph" branch baserock:morphs test/unmergable
+
+cd "$DATADIR/workspace/test/unmergable/baserock:morphs"
+sed -ie 's/"kind": "stratum"/"kind": "chunk"/' hello-stratum.morph
+git commit --quiet --all -m "Unmergeable because kind has changed"
+cd "$DATADIR/workspace/master/baserock:morphs"
+"$SRCDIR/scripts/test-morph" merge test/unmergable
diff --git a/tests.branching/merge-handles-unmergable-cases.stderr b/tests.branching/merge-handles-unmergable-cases.stderr
new file mode 100644
index 00000000..513db2b8
--- /dev/null
+++ b/tests.branching/merge-handles-unmergable-cases.stderr
@@ -0,0 +1 @@
+ERROR: merge conflict: "kind" of morphology hello-stratum
diff --git a/tests.branching/merge-not-to-master.script b/tests.branching/merge-not-to-master.script
new file mode 100755
index 00000000..3758ce3e
--- /dev/null
+++ b/tests.branching/merge-not-to-master.script
@@ -0,0 +1,69 @@
+#!/bin/sh
+# Copyright (C) 2012 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.
+
+# Check that "morph merge" merges a system branch into a newly created
+# system branch
+
+set -eu
+
+cd "$DATADIR/workspace"
+"$SRCDIR/scripts/test-morph" init
+
+# Create stable branch to merge TO
+"$SRCDIR/scripts/test-morph" branch baserock:morphs test/stable
+cd test/stable/baserock:morphs
+git push --quiet origin test/stable
+
+# Create feature branch to merge FROM
+"$SRCDIR/scripts/test-morph" branch baserock:morphs test/feature test/stable
+cd "$DATADIR/workspace/test/feature"
+
+# Edit hello in FROM
+"$SRCDIR/scripts/test-morph" edit hello-system hello-stratum hello
+cd baserock:hello
+touch newfile.txt
+git add newfile.txt
+git commit -m foo --quiet
+
+# Commit in morphs repo
+# FIXME: this should become unnecessary since only the refs have
+# changed.
+cd ../baserock:morphs
+git commit --all --quiet -m "Update morph refs for test/feature"
+
+# Merge changes back to test/stable
+cd "$DATADIR/workspace"
+cd test/stable
+"$SRCDIR/scripts/test-morph" merge test/feature
+
+# Check results: changes to 'hello' should have been merged back to
+# test/stable.
+cd baserock:hello
+[ -e newfile.txt ]
+
+# Make sure all changes are committed and to the correct branch ('hello'
+# was built from 'master' before branching, so the changes should be
+# merged back to 'master').
+git status --short
+[ $(git rev-parse master) = $(git rev-parse HEAD) ]
+
+# Changes here should be on test/stable.
+cd ../baserock:morphs
+git status --short
+[ $(git rev-parse test/stable) = $(git rev-parse HEAD) ]
+
+# Make sure all refs to the merged branch have gone.
+! grep "\"ref\": \"test/feature\"" *.morph
diff --git a/tests.branching/merge-with-chunk-renamed.script b/tests.branching/merge-with-chunk-renamed.script
new file mode 100755
index 00000000..1ca2ee48
--- /dev/null
+++ b/tests.branching/merge-with-chunk-renamed.script
@@ -0,0 +1,56 @@
+#!/bin/sh
+# Copyright (C) 2012 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.
+
+# "morph merge" should pull changes from a chunk even if its name was changed
+# in the branch
+
+set -eu
+
+# Create system branch.
+cd "$DATADIR/workspace"
+"$SRCDIR/scripts/test-morph" init
+"$SRCDIR/scripts/test-morph" branch baserock:morphs baserock/newbranch
+
+# Rename the chunk, and then commit a seperate change
+"$SRCDIR/scripts/test-morph" edit hello-system hello-stratum hello
+cd baserock/newbranch/baserock:hello
+
+cat hello.morph | sed -e 's/"name": "hello"/"name": "goodbye"/' > goodbye.morph
+git rm -q hello.morph
+git add goodbye.morph
+git commit -m "Rename chunk" --quiet
+
+touch newfile.txt
+git add newfile.txt
+git commit -m "Add new file" --quiet
+
+# Update stratum to point at the renamed chunk
+cd ../baserock:morphs
+sed -ie 's/"name": "hello"/"name": "goodbye"/' hello-stratum.morph
+git commit --all --quiet -m "Update morph refs for baserock/newbranch"
+
+# Merge changes back to master
+cd "$DATADIR/workspace"
+"$SRCDIR/scripts/test-morph" checkout baserock:morphs master
+cd master
+"$SRCDIR/scripts/test-morph" merge baserock/newbranch
+
+# Morph should have realised that 'goodbye' is not a new chunk,
+# and pulled in the changes from 'hello' in the old branch
+cd baserock:hello
+[ ! -e hello.morph ]
+[ -e goodbye.morph ]
+[ -e newfile.txt ]
diff --git a/tests.branching/merge-with-chunk-repo-moved.exit b/tests.branching/merge-with-chunk-repo-moved.exit
new file mode 100644
index 00000000..d00491fd
--- /dev/null
+++ b/tests.branching/merge-with-chunk-repo-moved.exit
@@ -0,0 +1 @@
+1
diff --git a/tests.branching/merge-with-chunk-repo-moved.script b/tests.branching/merge-with-chunk-repo-moved.script
new file mode 100755
index 00000000..c67ccc6d
--- /dev/null
+++ b/tests.branching/merge-with-chunk-repo-moved.script
@@ -0,0 +1,53 @@
+#!/bin/sh
+# Copyright (C) 2012 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.
+
+# "morph merge" should detect changes in a repo that was added as part of the
+# branch and warn the user that the changes will not be merged automatically
+
+set -eu
+
+# Create system branch.
+cd "$DATADIR/workspace"
+"$SRCDIR/scripts/test-morph" init
+"$SRCDIR/scripts/test-morph" branch baserock:morphs baserock/newbranch
+
+"$SRCDIR/scripts/test-morph" edit hello-system hello-stratum hello
+
+# Chunk moves to a new location (we manually update the ref back to master
+# here, so 'morph edit' can create a system branch in the new repo from it).
+git clone -q "$DATADIR/hello" "$DATADIR/hello-lorried"
+cd "$DATADIR/workspace/baserock/newbranch/baserock:morphs"
+sed -e 's/"repo": "baserock:hello"/"repo": "baserock:hello-lorried"/' \
+ -e 's/"ref": "baserock\/newbranch"/"ref": "master"/' \
+ -i hello-stratum.morph
+git commit -q --all -m "'hello' repository has moved"
+
+# Now we further edit the chunk, just for fun.
+"$SRCDIR/scripts/test-morph" edit hello-system hello-stratum hello
+cd "$DATADIR/workspace/baserock/newbranch/baserock:hello-lorried"
+touch newfile.txt
+git add newfile.txt
+git commit -m "Add new file" --quiet
+
+cd "$DATADIR/workspace/baserock/newbranch/baserock:morphs"
+git commit -q --all -m "Update system branch refs"
+
+# Try to merge changes back to master (should fail, because we don't support
+# adding chunks inside branches yet).
+cd "$DATADIR/workspace"
+"$SRCDIR/scripts/test-morph" checkout baserock:morphs master
+cd master
+"$SRCDIR/scripts/test-morph" merge baserock/newbranch
diff --git a/tests.branching/merge-with-chunk-repo-moved.stderr b/tests.branching/merge-with-chunk-repo-moved.stderr
new file mode 100644
index 00000000..95fe61e6
--- /dev/null
+++ b/tests.branching/merge-with-chunk-repo-moved.stderr
@@ -0,0 +1 @@
+ERROR: chunk hello was added within this branch and subsequently edited. This is not yet supported: refusing to merge.
diff --git a/tests.branching/merge-with-stratum-renamed.exit b/tests.branching/merge-with-stratum-renamed.exit
new file mode 100644
index 00000000..d00491fd
--- /dev/null
+++ b/tests.branching/merge-with-stratum-renamed.exit
@@ -0,0 +1 @@
+1
diff --git a/tests.branching/merge-with-stratum-renamed.script b/tests.branching/merge-with-stratum-renamed.script
new file mode 100755
index 00000000..8df2cd18
--- /dev/null
+++ b/tests.branching/merge-with-stratum-renamed.script
@@ -0,0 +1,51 @@
+#!/bin/sh
+# Copyright (C) 2012 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.
+
+# "morph merge" should deal with stratum renames; currently it doesn't deal
+# very well, but at least we don't crash.
+
+set -eu
+
+# Create system branch.
+cd "$DATADIR/workspace"
+"$SRCDIR/scripts/test-morph" init
+"$SRCDIR/scripts/test-morph" branch baserock:morphs baserock/newbranch
+
+# The user may 'morph edit hello-system hello-stratum hello' and commit here:
+# we currently silently ignore her changes on merge, because we don't
+# associate hello-stratum and goodbye-stratum at all.
+
+# Rename the stratum
+"$SRCDIR/scripts/test-morph" edit hello-system hello-stratum
+cd baserock/newbranch/baserock:morphs
+
+sed -e 's/"morph": "hello-stratum"/"morph": "goodbye-stratum"/'\
+ -i hello-system.morph
+sed -e 's/"name": "hello-stratum"/"name": "goodbye-stratum"/' \
+ hello-stratum.morph > goodbye-stratum.morph
+git rm -q hello-stratum.morph
+git add goodbye-stratum.morph
+git commit -q --all -m "Rename hello-stratum to goodbye-stratum"
+
+# The user may 'morph edit hello-system goodbye-stratum hello' and commit
+# here, too: same problem.
+
+# Merge changes back to master (this should fail, because we don't support
+# adding strata inside branches yet).
+cd "$DATADIR/workspace"
+"$SRCDIR/scripts/test-morph" checkout baserock:morphs master
+cd master
+"$SRCDIR/scripts/test-morph" merge baserock/newbranch
diff --git a/tests.branching/merge-with-stratum-renamed.stderr b/tests.branching/merge-with-stratum-renamed.stderr
new file mode 100644
index 00000000..ad144f93
--- /dev/null
+++ b/tests.branching/merge-with-stratum-renamed.stderr
@@ -0,0 +1 @@
+ERROR: stratum goodbye-stratum was added within this branch and subsequently edited. This is not yet supported: refusing to merge.
diff --git a/tests.branching/merge.script b/tests.branching/merge.script
index d8a28cb3..21a30116 100755
--- a/tests.branching/merge.script
+++ b/tests.branching/merge.script
@@ -49,6 +49,8 @@ git status --short # make sure all changes are committed
cd ../baserock:morphs
! grep "\"ref\": \"baserock/newbranch\"" *.morph
+# The only change here was the branch refs, which have now been
+# changed back - so there should not be any new commits.
echo "Commit message for baserock:morphs"
git cat-file commit HEAD | tail -n 1
diff --git a/tests.branching/merge.stdout b/tests.branching/merge.stdout
index e5127734..6806f75a 100644
--- a/tests.branching/merge.stdout
+++ b/tests.branching/merge.stdout
@@ -1,5 +1,5 @@
Commit message for baserock:morphs
-Merge system branch 'baserock/newbranch'
+initial
Commit message for baserock:hello
Merge system branch 'baserock/newbranch'
diff --git a/tests.branching/workflow-separate-stratum-repos.script b/tests.branching/workflow-separate-stratum-repos.script
index 3d0f6529..06c4f3b8 100755
--- a/tests.branching/workflow-separate-stratum-repos.script
+++ b/tests.branching/workflow-separate-stratum-repos.script
@@ -63,7 +63,6 @@ cat <<EOF > "$1/$2.morph"
EOF
}
-
# Create two more strata outside the baserock:morphs repository
EXTERNAL_STRATA_REPO="$DATADIR/external-strata"
@@ -84,14 +83,22 @@ git commit --quiet -m "Initial commit"
create_chunk "$DATADIR/stratum2-hello" "hello"
create_chunk "$DATADIR/stratum3-hello" "hello"
-# Update hello-system to include them
+# Update hello-system to include them ... using a system branch! Since the
+# strata refs are 'master' not 'me/add-external-strata' this does not cause
+# problems with merging.
-cd "$DATADIR/morphs"
-cat <<EOF > "$DATADIR/morphs/hello-system.morph"
+cd "$DATADIR/workspace"
+"$SRCDIR/scripts/test-morph" init
+"$SRCDIR/scripts/test-morph" branch baserock:morphs me/add-external-strata
+
+cd "$DATADIR/workspace/me/add-external-strata/baserock:morphs"
+
+cat <<EOF > "hello-system.morph"
{
"name": "hello-system",
"kind": "system",
"system-kind": "syslinux-disk",
+ "arch": "x86_64",
"disk-size": "1G",
"strata": [
{
@@ -114,14 +121,26 @@ cat <<EOF > "$DATADIR/morphs/hello-system.morph"
EOF
git commit --quiet --all -m "Add two more external strata"
-# Now try to branch and merge the system
-# FIXME: we should try and build it, too
+# Merge to master
+cd "$DATADIR/workspace"
+"$SRCDIR/scripts/test-morph" checkout baserock:morphs master
+cd master/baserock:morphs
+"$SRCDIR/scripts/test-morph" merge me/add-external-strata
+# In reality the user would do: 'git push origin master' here,
+# but since our remote repo is non-bare we must cheat a bit.
+# We should consider a separate fixture for the workflow tests.
+cd "$DATADIR/morphs"
+git pull -q \
+ "file://$DATADIR/workspace/master/baserock:morphs" master
+
+# Now make another change to the system
+# FIXME: we should try and build it, too
cd "$DATADIR/workspace"
-"$SRCDIR/scripts/test-morph" init
"$SRCDIR/scripts/test-morph" branch baserock:morphs me/readme-fixes
# Edit one chunk
+cd "me/readme-fixes"
"$SRCDIR/scripts/test-morph" edit hello-system stratum2 hello
cd "$DATADIR/workspace/me/readme-fixes/baserock:stratum2-hello"
echo > README yoyoyo
@@ -135,7 +154,7 @@ echo > README yoyoyo
git add README
git commit -m "Fix README in hello" --quiet
-# Update the morphologies repos
+# Update the morphology repos
cd ../baserock:external-strata
git commit --quiet --all -m "Commit changes for system branch"
@@ -144,6 +163,17 @@ git commit --quiet --all -m "Commit changes for system branch"
# Merge our system branch into master
cd "$DATADIR/workspace"
-"$SRCDIR/scripts/test-morph" checkout baserock:morphs master
cd master
"$SRCDIR/scripts/test-morph" merge me/readme-fixes
+
+# Check the changes have appeared
+cd baserock:morphs
+[ $(git rev-parse HEAD) = $(git rev-parse master) ]
+
+cd ../baserock:stratum2-hello
+[ -e README ]
+[ $(git rev-parse HEAD) = $(git rev-parse master) ]
+
+cd ../baserock:stratum3-hello
+[ -e README ]
+[ $(git rev-parse HEAD) = $(git rev-parse master) ]