summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Maw <richard.maw@codethink.co.uk>2013-09-19 11:16:30 +0000
committerRichard Maw <richard.maw@codethink.co.uk>2013-09-25 12:50:21 +0000
commita2468159c731dbcf26dbb6483bcf50b5a81bccd8 (patch)
tree9bb86c81b10250d071fb90f5239f2c95f3593b63
parent8a003f588136a9f8eda7df876ed6c059dd6658f4 (diff)
downloadmorph-a2468159c731dbcf26dbb6483bcf50b5a81bccd8.tar.gz
B&M: refactor branch-from-image
This changes the interface of branch-from-image to only take 1 parameter, the name of the new system branch, as the root repository is loaded from the metadata. This was also what the previous version of branch-from-image did, but that silently ignored the parameter. Given there are not many users of branch-from-image, I felt it was a reasonable change.
-rw-r--r--morphlib/plugins/branch_and_merge_new_plugin.py104
-rw-r--r--morphlib/plugins/branch_and_merge_plugin.py12
-rwxr-xr-xtests.as-root/branch-from-image-works.script3
3 files changed, 108 insertions, 11 deletions
diff --git a/morphlib/plugins/branch_and_merge_new_plugin.py b/morphlib/plugins/branch_and_merge_new_plugin.py
index 7cd84898..809699eb 100644
--- a/morphlib/plugins/branch_and_merge_new_plugin.py
+++ b/morphlib/plugins/branch_and_merge_new_plugin.py
@@ -56,6 +56,15 @@ class SimpleBranchAndMergePlugin(cliapp.Plugin):
arg_synopsis='-- COMMAND [ARGS...]')
self.app.add_subcommand('status', self.status,
arg_synopsis='')
+ self.app.add_subcommand('branch-from-image', self.branch_from_image,
+ arg_synopsis='BRANCH')
+ group_branch = 'Branching Options'
+ self.app.settings.string(['metadata-dir'],
+ 'Set metadata location for branch-from-image'
+ ' (default: /baserock)',
+ metavar='DIR',
+ default='/baserock',
+ group=group_branch)
def disable(self):
pass
@@ -790,3 +799,98 @@ class SimpleBranchAndMergePlugin(cliapp.Plugin):
if not has_uncommitted_changes:
self.app.output.write("\nNo repos have outstanding changes.\n")
+
+ def branch_from_image(self, args):
+ '''Produce a branch of an existing system image.
+
+ Given the metadata specified by --metadata-dir, create a new
+ branch then petrify it to the state of the commits at the time
+ the system was built.
+
+ If --metadata-dir is not specified, it defaults to your currently
+ running system.
+
+ '''
+ if len(args) != 1:
+ raise cliapp.AppException(
+ "branch-from-image needs exactly 1 argument "
+ "of the new system branch's name")
+ system_branch = args[0]
+ metadata_path = self.app.settings['metadata-dir']
+ alias_resolver = morphlib.repoaliasresolver.RepoAliasResolver(
+ self.app.settings['repo-alias'])
+
+ self._require_git_user_config()
+
+ ws = morphlib.workspace.open('.')
+
+ system, metadata = self._load_system_metadata(metadata_path)
+ resolved_refs = dict(self._resolve_refs_from_metadata(alias_resolver,
+ metadata))
+ logging.debug('Resolved refs: %r' % resolved_refs)
+ base_ref = system['sha1']
+ # The previous version would fall back to deducing this from the repo
+ # url and the repo alias resolver, but this does not always work, and
+ # new systems always have repo-alias in the metadata
+ root_url = system['repo-alias']
+
+ lrc, rrc = morphlib.util.new_repo_caches(self.app)
+ cached_repo = lrc.get_updated_repo(root_url)
+
+
+ with self._initializing_system_branch(
+ ws, root_url, system_branch, cached_repo, base_ref) as (sb, gd):
+
+ # TODO: It's nasty to clone to a sha1 then create a branch
+ # of that sha1 then check it out, a nicer API may be the
+ # initial clone not checking out a branch at all, then
+ # the user creates and checks out their own branches
+ gd.branch(system_branch, base_ref)
+ gd.checkout(system_branch)
+
+ loader = morphlib.morphloader.MorphologyLoader()
+ morphs = self._load_all_sysbranch_morphologies(sb, loader)
+
+ morphs.repoint_refs(sb.root_repository_url,
+ sb.system_branch_name)
+
+ morphs.petrify_chunks(resolved_refs)
+
+ self._save_dirty_morphologies(loader, sb, morphs.morphologies)
+
+ @staticmethod
+ def _load_system_metadata(path):
+ '''Load all metadata in `path` corresponding to a single System.
+ '''
+
+ smd = morphlib.systemmetadatadir.SystemMetadataDir(path)
+ metadata = smd.values()
+ systems = [md for md in metadata
+ if 'kind' in md and md['kind'] == 'system']
+
+ if not systems:
+ raise cliapp.AppException(
+ 'Metadata directory does not contain any systems.')
+ if len(systems) > 1:
+ raise cliapp.AppException(
+ 'Metadata directory contains multiple systems.')
+ system_metadatum = systems[0]
+
+ metadata_cache_id_lookup = dict((md['cache-key'], md)
+ for md in metadata)
+
+ return system_metadatum, metadata_cache_id_lookup
+
+ @staticmethod
+ def _resolve_refs_from_metadata(alias_resolver, metadata):
+ '''Pre-resolve a set of refs from existing metadata.
+
+ Given the metadata, generate a mapping of all the (repo, ref)
+ pairs defined in the metadata and the commit id they resolved to.
+
+ '''
+ for md in metadata.itervalues():
+ repourls = set((md['repo-alias'], md['repo']))
+ repourls.update(alias_resolver.aliases_from_url(md['repo']))
+ for repourl in repourls:
+ yield ((repourl, md['original_ref']), md['sha1'])
diff --git a/morphlib/plugins/branch_and_merge_plugin.py b/morphlib/plugins/branch_and_merge_plugin.py
index 37d5e40c..2f8560d0 100644
--- a/morphlib/plugins/branch_and_merge_plugin.py
+++ b/morphlib/plugins/branch_and_merge_plugin.py
@@ -68,15 +68,9 @@ class BranchAndMergePlugin(cliapp.Plugin):
self.app.add_subcommand('build', self.build,
arg_synopsis='SYSTEM')
self.app.add_subcommand('old-status', self.status)
- self.app.add_subcommand('branch-from-image', self.branch_from_image,
- arg_synopsis='REPO BRANCH')
- group_branch = 'Branching Options'
- self.app.settings.string(['metadata-dir'],
- 'Set metadata location for branch-from-image'
- ' (default: /baserock)',
- metavar='DIR',
- default='/baserock',
- group=group_branch)
+ self.app.add_subcommand('old-branch-from-image',
+ self.branch_from_image,
+ arg_synopsis='REPO BRANCH')
# Advanced commands
self.app.add_subcommand('old-foreach', self.foreach,
diff --git a/tests.as-root/branch-from-image-works.script b/tests.as-root/branch-from-image-works.script
index 9f82f629..942301e8 100755
--- a/tests.as-root/branch-from-image-works.script
+++ b/tests.as-root/branch-from-image-works.script
@@ -48,8 +48,7 @@ git commit --quiet -m 'Make hello say goodbye'
workspace="$DATADIR/workspace"
"$SRCDIR/scripts/test-morph" init "$workspace"
cd "$workspace"
-"$SRCDIR/scripts/test-morph" branch-from-image \
- test:morphs mybranch \
+"$SRCDIR/scripts/test-morph" branch-from-image mybranch \
--metadata-dir="$extracted/baserock"
cd mybranch/test:morphs
grep -qFe "$hello_chunk_commit" hello-stratum.morph