summaryrefslogtreecommitdiff
path: root/morphlib
diff options
context:
space:
mode:
authorLars Wirzenius <lars.wirzenius@codethink.co.uk>2013-08-05 11:31:26 +0000
committerLars Wirzenius <lars.wirzenius@codethink.co.uk>2013-08-06 16:28:17 +0100
commitfaac98c8ae8773defbf2b7ba104c6e56d67e3c31 (patch)
treea3c78012d65fd52cb8ad748e0a96e060ae120612 /morphlib
parente14fa6e5c70fa35ff41742115e76a3358302086d (diff)
downloadmorph-faac98c8ae8773defbf2b7ba104c6e56d67e3c31.tar.gz
Re-implement "morph checkout" using new infrastructure
Diffstat (limited to 'morphlib')
-rw-r--r--morphlib/plugins/branch_and_merge_new_plugin.py99
-rw-r--r--morphlib/plugins/branch_and_merge_plugin.py37
2 files changed, 99 insertions, 37 deletions
diff --git a/morphlib/plugins/branch_and_merge_new_plugin.py b/morphlib/plugins/branch_and_merge_new_plugin.py
index fb3be920..353f0bcc 100644
--- a/morphlib/plugins/branch_and_merge_new_plugin.py
+++ b/morphlib/plugins/branch_and_merge_new_plugin.py
@@ -15,6 +15,9 @@
import cliapp
+import logging
+import os
+import shutil
import morphlib
@@ -26,6 +29,8 @@ class SimpleBranchAndMergePlugin(cliapp.Plugin):
def enable(self):
self.app.add_subcommand('init', self.init, arg_synopsis='[DIR]')
self.app.add_subcommand('workspace', self.workspace, arg_synopsis='')
+ self.app.add_subcommand(
+ 'checkout', self.checkout, arg_synopsis='REPO BRANCH')
def disable(self):
pass
@@ -68,3 +73,97 @@ class SimpleBranchAndMergePlugin(cliapp.Plugin):
ws = morphlib.workspace.open('.')
self.app.output.write('%s\n' % ws.root)
+ def checkout(self, args):
+ '''Check out an existing system branch.
+
+ Command line arguments:
+
+ * `REPO` is the URL to the repository to the root repository of
+ a system branch.
+ * `BRANCH` is the name of the system branch.
+
+ This will check out an existing system branch to an existing
+ workspace. You must create the workspace first. This only checks
+ out the root repository, not the repositories for individual
+ components. You need to use `morph edit` to check out those.
+
+ Example:
+
+ cd /src/workspace
+ morph checkout baserock:baserock/morphs master
+
+ '''
+
+ if len(args) != 2:
+ raise cliapp.AppException('morph checkout needs a repo and the '
+ 'name of a branch as parameters')
+
+ root_url = args[0]
+ system_branch = args[1]
+
+ self._require_git_user_config()
+
+ # Open the workspace first thing, so user gets a quick error if
+ # we're not inside a workspace.
+ ws = morphlib.workspace.open('.')
+
+ # Make sure the root repository is in the local git repository
+ # cache, and is up to date.
+ lrc, rrc = morphlib.util.new_repo_caches(self.app)
+ cached_repo = lrc.get_updated_repo(root_url)
+
+ # Check the git branch exists.
+ cached_repo.resolve_ref(system_branch)
+
+ root_dir = ws.get_default_system_branch_directory_name(system_branch)
+
+ try:
+ # Create the system branch directory. This doesn't yet clone
+ # the root repository there.
+ sb = morphlib.sysbranchdir.create(
+ root_dir, root_url, system_branch)
+
+ gd = sb.clone_cached_repo(
+ cached_repo, system_branch, system_branch)
+ gd.update_submodules(self.app)
+ gd.update_remotes()
+ except BaseException as e:
+ # Oops. Clean up.
+ logging.error('Caught exception: %s' % str(e))
+ logging.info('Removing half-finished branch %s' % system_branch)
+ self._remove_branch_dir_safe(ws.root, root_dir)
+ raise
+
+ def _remove_branch_dir_safe(self, workspace_root, system_branch_root):
+ # This function avoids throwing any exceptions, so it is safe to call
+ # inside an 'except' block without altering the backtrace.
+
+ def handle_error(function, path, excinfo):
+ logging.warning ("Error while trying to clean up %s: %s" %
+ (path, excinfo))
+
+ shutil.rmtree(system_branch_root, onerror=handle_error)
+
+ # Remove parent directories that are empty too, avoiding exceptions
+ parent = os.path.dirname(system_branch_root)
+ while parent != os.path.abspath(workspace_root):
+ if len(os.listdir(parent)) > 0 or os.path.islink(parent):
+ break
+ os.rmdir(parent)
+ parent = os.path.dirname(parent)
+
+ def _require_git_user_config(self):
+ '''Warn if the git user.name and user.email variables are not set.'''
+
+ keys = {
+ 'user.name': 'My Name',
+ 'user.email': 'me@example.com',
+ }
+
+ try:
+ morphlib.git.check_config_set(self.app.runcmd, keys)
+ except morphlib.git.ConfigNotSetException as e:
+ self.app.status(
+ msg="WARNING: %(message)s",
+ message=str(e), error=True)
+
diff --git a/morphlib/plugins/branch_and_merge_plugin.py b/morphlib/plugins/branch_and_merge_plugin.py
index d39f815c..0485f317 100644
--- a/morphlib/plugins/branch_and_merge_plugin.py
+++ b/morphlib/plugins/branch_and_merge_plugin.py
@@ -59,8 +59,6 @@ class BranchAndMergePlugin(cliapp.Plugin):
# User-facing commands
self.app.add_subcommand('branch', self.branch,
arg_synopsis='REPO NEW [OLD]')
- self.app.add_subcommand('checkout', self.checkout,
- arg_synopsis='REPO BRANCH')
self.app.add_subcommand('merge', self.merge,
arg_synopsis='BRANCH')
self.app.add_subcommand('edit', self.edit,
@@ -623,41 +621,6 @@ class BranchAndMergePlugin(cliapp.Plugin):
workspace = self.deduce_workspace()
self._create_branch(workspace, new_branch, repo, commit)
- @warns_git_identity
- def checkout(self, args):
- '''Check out an existing system branch.
-
- Command line arguments:
-
- * `REPO` is the URL to the repository to the root repository of
- a system branch.
- * `BRANCH` is the name of the system branch.
-
- This will check out an existing system branch to an existing
- workspace. You must create the workspace first. This only checks
- out the root repository, not the repositories for individual
- components. You need to use `morph edit` to check out those.
-
- Example:
-
- cd /src/workspace
- morph checkout baserock:baserock/morphs master
-
- '''
-
- if len(args) != 2:
- raise cliapp.AppException('morph checkout needs a repo and the '
- 'name of a branch as parameters')
-
- repo = args[0]
- system_branch = args[1]
-
- self.lrc, self.rrc = morphlib.util.new_repo_caches(self.app)
-
- # Create the system branch directory.
- workspace = self.deduce_workspace()
- self._create_branch(workspace, system_branch, repo, system_branch)
-
def checkout_repository(self, branch_dir, repo, ref, parent_ref=None):
'''Make a chunk or stratum repository available for a system branch