diff options
author | Lars Wirzenius <lars.wirzenius@codethink.co.uk> | 2013-08-05 11:31:26 +0000 |
---|---|---|
committer | Lars Wirzenius <lars.wirzenius@codethink.co.uk> | 2013-08-06 16:28:17 +0100 |
commit | faac98c8ae8773defbf2b7ba104c6e56d67e3c31 (patch) | |
tree | a3c78012d65fd52cb8ad748e0a96e060ae120612 /morphlib | |
parent | e14fa6e5c70fa35ff41742115e76a3358302086d (diff) | |
download | morph-faac98c8ae8773defbf2b7ba104c6e56d67e3c31.tar.gz |
Re-implement "morph checkout" using new infrastructure
Diffstat (limited to 'morphlib')
-rw-r--r-- | morphlib/plugins/branch_and_merge_new_plugin.py | 99 | ||||
-rw-r--r-- | morphlib/plugins/branch_and_merge_plugin.py | 37 |
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 |