summaryrefslogtreecommitdiff
path: root/baserockimport/app.py
diff options
context:
space:
mode:
authorSam Thursfield <sam.thursfield@codethink.co.uk>2014-10-21 13:42:03 +0100
committerSam Thursfield <sam.thursfield@codethink.co.uk>2014-10-21 14:28:13 +0100
commit44ee17802dc04b4ecfa7ec812a5a0318bf69c62f (patch)
tree38b6b01cc9af8c62c537009cdab14f808c107daf /baserockimport/app.py
parentf9c68e022952307b51efb9fd6badeb6c44d3de0c (diff)
downloadimport-44ee17802dc04b4ecfa7ec812a5a0318bf69c62f.tar.gz
Reorganise, tidy and document code of main application
Diffstat (limited to 'baserockimport/app.py')
-rw-r--r--baserockimport/app.py178
1 files changed, 178 insertions, 0 deletions
diff --git a/baserockimport/app.py b/baserockimport/app.py
new file mode 100644
index 0000000..c7f0e05
--- /dev/null
+++ b/baserockimport/app.py
@@ -0,0 +1,178 @@
+# Copyright (C) 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.
+
+
+import ansicolor
+import cliapp
+
+import logging
+import os
+import pipes
+import sys
+
+import baserockimport
+
+
+class BaserockImportApplication(cliapp.Application):
+ def add_settings(self):
+ self.settings.string(['lorries-dir'],
+ "location for Lorry files",
+ metavar="PATH",
+ default=os.path.abspath('./lorries'))
+ self.settings.string(['definitions-dir'],
+ "location for morphology files",
+ metavar="PATH",
+ default=os.path.abspath('./definitions'))
+ self.settings.string(['checkouts-dir'],
+ "location for Git checkouts",
+ metavar="PATH",
+ default=os.path.abspath('./checkouts'))
+ self.settings.string(['lorry-working-dir'],
+ "Lorry working directory",
+ metavar="PATH",
+ default=os.path.abspath('./lorry-working-dir'))
+
+ self.settings.boolean(['update-existing'],
+ "update all the checked-out Git trees and "
+ "generated definitions",
+ default=False)
+ self.settings.boolean(['use-local-sources'],
+ "use file:/// URLs in the stratum 'repo' "
+ "fields, instead of upstream: URLs",
+ default=False)
+ self.settings.boolean(['use-master-if-no-tag'],
+ "if the correct tag for a version can't be "
+ "found, use 'master' instead of raising an "
+ "error",
+ default=False)
+
+ def _stream_has_colours(self, stream):
+ # http://blog.mathieu-leplatre.info/colored-output-in-console-with-python.html
+ if not hasattr(stream, "isatty"):
+ return False
+ if not stream.isatty():
+ return False # auto color only on TTYs
+ try:
+ import curses
+ curses.setupterm()
+ return curses.tigetnum("colors") > 2
+ except:
+ # guess false in case of error
+ return False
+
+ def setup(self):
+ self.add_subcommand('omnibus', self.import_omnibus,
+ arg_synopsis='REPO PROJECT_NAME SOFTWARE_NAME')
+ self.add_subcommand('rubygems', self.import_rubygems,
+ arg_synopsis='GEM_NAME')
+
+ self.stdout_has_colours = self._stream_has_colours(sys.stdout)
+
+ def setup_logging_formatter_for_file(self):
+ root_logger = logging.getLogger()
+ root_logger.name = 'main'
+
+ # You need recent cliapp for this to work, with commit "Split logging
+ # setup into further overrideable methods".
+ return logging.Formatter("%(name)s: %(levelname)s: %(message)s")
+
+ def process_args(self, args):
+ if len(args) == 0:
+ # Cliapp default is to just say "ERROR: must give subcommand" if
+ # no args are passed, I prefer this.
+ args = ['help']
+
+ super(BaserockImportApplication, self).process_args(args)
+
+ def status(self, msg, *args, **kwargs):
+ text = msg % args
+ if kwargs.get('error') == True:
+ logging.error(text)
+ if self.stdout_has_colours:
+ sys.stdout.write(ansicolor.red(text))
+ else:
+ sys.stdout.write(text)
+ else:
+ logging.info(text)
+ sys.stdout.write(text)
+ sys.stdout.write('\n')
+
+ def import_omnibus(self, args):
+ '''Import a software component from an Omnibus project.
+
+ Omnibus is a tool for generating application bundles for various
+ platforms. See <https://github.com/opscode/omnibus> for more
+ information.
+
+ '''
+ if len(args) != 3:
+ raise cliapp.AppException(
+ 'Please give the location of the Omnibus definitions repo, '
+ 'and the name of the project and the top-level software '
+ 'component.')
+
+ def running_inside_bundler():
+ return 'BUNDLE_GEMFILE' in os.environ
+
+ def command_to_run_python_in_directory(directory, args):
+ # Bundler requires that we run it from the Omnibus project
+ # directory. That messes up any relative paths the user may have
+ # passed on the commandline, so we do a bit of a hack to change
+ # back to the original directory inside the `bundle exec` process.
+ subshell_command = "(cd %s; exec python %s)" % \
+ (pipes.quote(directory), ' '.join(map(pipes.quote, args)))
+ shell_command = "sh -c %s" % pipes.quote(subshell_command)
+ return shell_command
+
+ def reexecute_self_with_bundler(path):
+ script = sys.argv[0]
+
+ logging.info('Reexecuting %s within Bundler, so that extensions '
+ 'use the correct dependencies for Omnibus and the '
+ 'Omnibus project definitions.', script)
+ command = command_to_run_python_in_directory(os.getcwd(), sys.argv)
+
+ logging.debug('Running: `bundle exec %s` in dir %s', command, path)
+ os.chdir(path)
+ os.execvp('bundle', [script, 'exec', command])
+
+ # Omnibus definitions are spread across multiple repos, and there is
+ # no stability guarantee for the definition format. The official advice
+ # is to use Bundler to execute Omnibus, so let's do that.
+ if not running_inside_bundler():
+ reexecute_self_with_bundler(args[0])
+
+ definitions_dir = args[0]
+ project_name = args[1]
+
+ loop = baserockimport.mainloop.ImportLoop(
+ app=self,
+ goal_kind='omnibus', goal_name=args[2], goal_version='master')
+ loop.enable_importer('omnibus',
+ extra_args=[definitions_dir, project_name])
+ loop.enable_importer('rubygems')
+ loop.run()
+
+ def import_rubygems(self, args):
+ '''Import one or more RubyGems.'''
+ if len(args) != 1:
+ raise cliapp.AppException(
+ 'Please pass the name of a RubyGem on the commandline.')
+
+ loop = baserockimport.mainloop.ImportLoop(
+ app=self,
+ goal_kind='rubygems', goal_name=args[0], goal_version='master')
+ loop.enable_importer('rubygems')
+ loop.run()