summaryrefslogtreecommitdiff
path: root/morphlib/app.py
diff options
context:
space:
mode:
Diffstat (limited to 'morphlib/app.py')
-rwxr-xr-xmorphlib/app.py338
1 files changed, 170 insertions, 168 deletions
diff --git a/morphlib/app.py b/morphlib/app.py
index 491adb16..3e4a0bf5 100755
--- a/morphlib/app.py
+++ b/morphlib/app.py
@@ -1,14 +1,14 @@
# Copyright (C) 2011-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.
@@ -29,21 +29,21 @@ import morphlib
defaults = {
'repo-alias': [
- 'upstream='
+ ('upstream='
'git://roadtrain.codethink.co.uk/delta/#'
- 'gitano@roadtrain.codethink.co.uk:delta/',
- 'baserock='
+ 'gitano@roadtrain.codethink.co.uk:delta/'),
+ ('baserock='
'git://roadtrain.codethink.co.uk/baserock/#'
- 'gitano@roadtrain.codethink.co.uk:baserock/',
- 'freedesktop='
+ 'gitano@roadtrain.codethink.co.uk:baserock/'),
+ ('freedesktop='
'git://anongit.freedesktop.org/#'
- 'ssh://git.freedesktop.org/',
- 'gnome='
+ 'ssh://git.freedesktop.org/'),
+ ('gnome='
'git://git.gnome.org/%s#'
- 'ssh://git.gnome.org/git/%s',
- 'github='
+ 'ssh://git.gnome.org/git/%s'),
+ ('github='
'git://github.com/%s#'
- 'git@github.com:%s',
+ 'git@github.com:%s'),
],
'cachedir': os.path.expanduser('~/.cache/morph'),
'max-jobs': morphlib.util.make_concurrency(),
@@ -57,13 +57,13 @@ defaults = {
class BuildCommand(object):
'''High level logic for building.
-
+
This controls how the whole build process goes. This is a separate
class to enable easy experimentation of different approaches to
the various parts of the process.
-
+
'''
-
+
def __init__(self, app):
self.app = app
self.build_env = self.new_build_env()
@@ -75,7 +75,7 @@ class BuildCommand(object):
'''Build triplets specified on command line.'''
self.app.status(msg='Build starts', chatty=True)
-
+
for repo_name, ref, filename in self.app._itertriplets(args):
self.app.status(msg='Building %(repo_name)s %(ref)s %(filename)s',
repo_name=repo_name, ref=ref, filename=filename)
@@ -111,7 +111,7 @@ class BuildCommand(object):
'''Create a new directory for the local artifact cache.'''
artifact_cachedir = os.path.join(
- self.app.settings['cachedir'], 'artifacts')
+ self.app.settings['cachedir'], 'artifacts')
if not os.path.exists(artifact_cachedir):
os.mkdir(artifact_cachedir)
return artifact_cachedir
@@ -124,8 +124,8 @@ class BuildCommand(object):
gits_dir = os.path.join(cachedir, 'gits')
bundle_base_url = self.app.settings['bundle-server']
repo_resolver = morphlib.repoaliasresolver.RepoAliasResolver(aliases)
- lrc = morphlib.localrepocache.LocalRepoCache(self.app,
- gits_dir, repo_resolver, bundle_base_url=bundle_base_url)
+ lrc = morphlib.localrepocache.LocalRepoCache(
+ self.app, gits_dir, repo_resolver, bundle_base_url=bundle_base_url)
url = self.app.settings['cache-server']
if url:
@@ -149,7 +149,7 @@ class BuildCommand(object):
self.app.status(msg='Creating source pool', chatty=True)
srcpool = self.app._create_source_pool(
- self.lrc, self.rrc, (repo_name, ref, filename))
+ self.lrc, self.rrc, (repo_name, ref, filename))
self.app.status(msg='Creating artifact resolver', chatty=True)
ar = morphlib.artifactresolver.ArtifactResolver()
@@ -164,7 +164,7 @@ class BuildCommand(object):
self.app.status(msg='Computing build order', chatty=True)
order = morphlib.buildorder.BuildOrder(artifacts)
-
+
return order
def build_in_order(self, order):
@@ -173,13 +173,13 @@ class BuildCommand(object):
chatty=True)
for group in order.groups:
self.build_artifacts(group)
-
+
def build_artifacts(self, artifacts):
'''Build a set of artifact.
-
+
Typically, this would be a build group, but might be anything.
At this level of abstraction we don't care.
-
+
'''
self.app.status(msg='Building a set of artifacts', chatty=True)
@@ -188,10 +188,10 @@ class BuildCommand(object):
def build_artifact(self, artifact):
'''Build one artifact.
-
+
All the dependencies are assumed to be built and available
in either the local or remote cache already.
-
+
'''
self.app.status(msg='Checking if %(kind)s %(name)s needs building',
@@ -213,7 +213,7 @@ class BuildCommand(object):
if self.app.settings['staging-chroot']:
if artifact.source.morphology.needs_staging_area:
self.install_fillers(staging_area)
- self.install_chunk_artifacts(staging_area,
+ self.install_chunk_artifacts(staging_area,
deps)
self.build_and_cache(staging_area, artifact)
if self.app.settings['bootstrap']:
@@ -270,8 +270,8 @@ class BuildCommand(object):
# Update submodules.
done = set()
self.app._cache_repo_and_submodules(
- self.lrc, artifact.source.repo.url,
- artifact.source.sha1, done)
+ self.lrc, artifact.source.repo.url,
+ artifact.source.sha1, done)
def cache_artifacts_locally(self, artifacts):
'''Get artifacts missing from local cache from remote cache.'''
@@ -280,22 +280,22 @@ class BuildCommand(object):
shutil.copyfileobj(remote, local)
remote.close()
local.close()
-
+
for artifact in artifacts:
if not self.lac.has(artifact):
self.app.status(msg='Fetching to local cache: '
'artifact %(name)s',
name=artifact.name)
copy(self.rac.get(artifact), self.lac.put(artifact))
-
+
if artifact.source.morphology.needs_artifact_metadata_cached:
if not self.lac.has_artifact_metadata(artifact, 'meta'):
self.app.status(msg='Fetching to local cache: '
'artifact metadata %(name)s',
name=artifact.name)
- copy(self.rac.get_artifact_metadata(artifact, 'meta'),
+ copy(self.rac.get_artifact_metadata(artifact, 'meta'),
self.lac.put_artifact_metadata(artifact, 'meta'))
-
+
def create_staging_area(self, artifact):
'''Create the staging area for building a single artifact.'''
@@ -318,36 +318,36 @@ class BuildCommand(object):
if staging_area.dirname != '/':
self.app.status(msg='Removing staging area')
staging_area.remove()
- if (staging_area.tempdir != '/' and
- os.path.exists(staging_area.tempdir)):
+ temp_path = staging_area.tempdir
+ if temp_path != '/' and os.path.exists(temp_path):
self.app.status(msg='Removing temporary staging directory')
- shutil.rmtree(staging_area.tempdir)
+ shutil.rmtree(temp_path)
def install_fillers(self, staging_area):
'''Install staging fillers into the staging area.
-
+
This must not be called in bootstrap mode.
-
+
'''
-
+
logging.debug('Pre-populating staging area %s' % staging_area.dirname)
- logging.debug('Fillers: %s' %
- repr(self.app.settings['staging-filler']))
+ logging.debug('Fillers: %s' %
+ repr(self.app.settings['staging-filler']))
for filename in self.app.settings['staging-filler']:
with open(filename, 'rb') as f:
- self.app.status(msg='Installing %(filename)s',
+ self.app.status(msg='Installing %(filename)s',
filename=filename)
staging_area.install_artifact(f)
def install_chunk_artifacts(self, staging_area, artifacts):
'''Install chunk artifacts into staging area.
-
+
We only ever care about chunk artifacts as build dependencies,
so this is not a generic artifact installer into staging area.
Any non-chunk artifacts are silently ignored.
-
+
All artifacts MUST be in the local artifact cache already.
-
+
'''
for artifact in artifacts:
@@ -363,9 +363,9 @@ class BuildCommand(object):
self.app.status(msg='Starting actual build')
setup_mounts = self.app.settings['staging-chroot']
- builder = morphlib.builder2.Builder(self.app,
- staging_area, self.lac, self.rac, self.lrc, self.build_env,
- self.app.settings['max-jobs'], setup_mounts)
+ builder = morphlib.builder2.Builder(
+ self.app, staging_area, self.lac, self.rac, self.lrc,
+ self.build_env, self.app.settings['max-jobs'], setup_mounts)
return builder.build_and_cache(artifact)
@@ -375,18 +375,19 @@ class Morph(cliapp.Application):
system_repo_name = 'baserock:%s' % system_repo_base
def add_settings(self):
- self.settings.boolean(['verbose', 'v'],
+ self.settings.boolean(['verbose', 'v'],
'show what is happening in much detail')
self.settings.boolean(['quiet', 'q'],
'show no output unless there is an error')
self.settings.string_list(['repo-alias'],
- 'define URL prefix aliases to allow repository '
- 'addresses to be shortened; '
- 'use alias=pullpattern=pushpattern '
- 'to allow alias:shortname to be used instead '
- 'of the full URL; the patterns must contain '
- 'a %s where the shortname gets replaced',
- default=defaults['repo-alias'])
+ 'define URL prefix aliases to allow '
+ 'repository addresses to be shortened; '
+ 'use alias=pullpattern=pushpattern '
+ 'to allow alias:shortname to be used '
+ 'instead of the full URL; the patterns must '
+ 'contain a %s where the shortname gets '
+ 'replaced',
+ default=defaults['repo-alias'])
self.settings.string(['bundle-server'],
'base URL to download bundles',
metavar='URL',
@@ -395,9 +396,9 @@ class Morph(cliapp.Application):
'HTTP URL of the morph cache server to use',
metavar='URL',
default=None)
- self.settings.string(['cachedir'],
+ self.settings.string(['cachedir'],
'put build results in DIR',
- metavar='DIR',
+ metavar='DIR',
default=defaults['cachedir'])
self.settings.string(['prefix'],
'build chunks with prefix PREFIX',
@@ -415,65 +416,65 @@ class Morph(cliapp.Application):
default='')
self.settings.string(['tempdir'],
'temporary directory to use for builds '
- '(this is separate from just setting $TMPDIR '
- 'or /tmp because those are used internally '
- 'by things that cannot be on NFS, but '
- 'this setting can point at a directory in '
- 'NFS)',
- metavar='DIR',
+ '(this is separate from just setting $TMPDIR '
+ 'or /tmp because those are used internally '
+ 'by things that cannot be on NFS, but '
+ 'this setting can point at a directory in '
+ 'NFS)',
+ metavar='DIR',
default=os.environ.get('TMPDIR'))
self.settings.boolean(['no-ccache'], 'do not use ccache')
self.settings.string(['ccache-remotedir'],
'allow ccache to download objects from REMOTEDIR '
- 'if they are not cached locally',
+ 'if they are not cached locally',
metavar='REMOTEDIR',
default=defaults['ccache-remotedir'])
self.settings.integer(['ccache-remotenlevels'],
'assume ccache directory objects are split into '
- 'NLEVELS levels of subdirectories',
+ 'NLEVELS levels of subdirectories',
metavar='NLEVELS',
default=defaults['ccache-remotenlevels'])
self.settings.boolean(['no-distcc'], 'do not use distcc')
- self.settings.integer(['max-jobs'],
+ self.settings.integer(['max-jobs'],
'run at most N parallel jobs with make (default '
- 'is to a value based on the number of CPUs '
- 'in the machine running morph',
+ 'is to a value based on the number of CPUs '
+ 'in the machine running morph',
metavar='N',
default=defaults['max-jobs'])
- self.settings.boolean(['keep-path'],
+ self.settings.boolean(['keep-path'],
'do not touch the PATH environment variable')
- self.settings.boolean(['bootstrap'],
+ self.settings.boolean(['bootstrap'],
'build stuff in bootstrap mode; this is '
- 'DANGEROUS and will install stuff on your '
- 'system')
+ 'DANGEROUS and will install stuff on your '
+ 'system')
self.settings.boolean(['ignore-submodules'],
'do not cache repositories of git submodules '
'or unpack them into the build directory')
self.settings.boolean(['no-git-update'],
'do not update the cached git repositories '
- 'during a build (user must have done that '
- 'already using the update-gits subcommand)')
+ 'during a build (user must have done that '
+ 'already using the update-gits subcommand)')
self.settings.string_list(['staging-filler'],
'unpack BLOB into staging area for '
- 'non-bootstrap builds (this will '
- 'eventually be replaced with proper '
- 'build dependencies)',
- metavar='BLOB')
+ 'non-bootstrap builds (this will '
+ 'eventually be replaced with proper '
+ 'build dependencies)',
+ metavar='BLOB')
self.settings.boolean(['staging-chroot'],
'build things in a staging chroot '
- '(require real root to use)')
+ '(require real root to use)')
def setup_plugin_manager(self):
cliapp.Application.setup_plugin_manager(self)
self.pluginmgr.locations += os.path.join(
- os.path.dirname(morphlib.__file__), 'plugins')
+ os.path.dirname(morphlib.__file__), 'plugins')
s = os.environ.get('MORPH_PLUGIN_PATH', '')
self.pluginmgr.locations += s.split(':')
-
+
self.hookmgr = cliapp.HookManager()
self.hookmgr.new('new-build-command', cliapp.FilterHook())
self.system_kind_builder_factory = \
@@ -481,10 +482,10 @@ class Morph(cliapp.Application):
def _itertriplets(self, args):
'''Generate repo, ref, filename triples from args.'''
-
+
if (len(args) % 3) != 0:
raise cliapp.AppException('Argument list must have full triplets')
-
+
while args:
assert len(args) >= 2, args
yield args[0], args[1], args[2]
@@ -505,17 +506,17 @@ class Morph(cliapp.Application):
def cmd_build(self, args):
'''Build a binary from a morphology.
-
+
Command line arguments are the repository, git tree-ish reference,
and morphology filename. Morph takes care of building all dependencies
before building the morphology. All generated binaries are put into the
cache.
-
+
(The triplet of command line arguments may be repeated as many
times as necessary.)
-
+
'''
-
+
build_command = BuildCommand(self)
build_command = self.hookmgr.call('new-build-command', build_command)
build_command.build(args)
@@ -528,12 +529,12 @@ class Morph(cliapp.Application):
cachedir = os.path.join(self.settings['cachedir'], 'gits')
bundle_base_url = self.settings['bundle-server']
repo_resolver = morphlib.repoaliasresolver.RepoAliasResolver(
- self.settings['repo-alias'])
- lrc = morphlib.localrepocache.LocalRepoCache(self,
- cachedir, repo_resolver, bundle_base_url)
+ self.settings['repo-alias'])
+ lrc = morphlib.localrepocache.LocalRepoCache(
+ self, cachedir, repo_resolver, bundle_base_url)
if self.settings['cache-server']:
rrc = morphlib.remoterepocache.RemoteRepoCache(
- self.settings['cache-server'], repo_resolver)
+ self.settings['cache-server'], repo_resolver)
else:
rrc = None
@@ -544,7 +545,7 @@ class Morph(cliapp.Application):
resolver = morphlib.artifactresolver.ArtifactResolver()
artifacts = resolver.resolve_artifacts(pool)
- self.output.write('dependency graph for %s|%s|%s:\n' %
+ self.output.write('dependency graph for %s|%s|%s:\n' %
(repo, ref, filename))
for artifact in sorted(artifacts, key=str):
self.output.write(' %s\n' % artifact)
@@ -563,7 +564,7 @@ class Morph(cliapp.Application):
'''Resolves the sha1 of the ref in reponame and returns it.
If update is True then this has the side-effect of updating
- or cloning the repository into the local repo cache.
+ or cloning the repository into the local repo cache.
'''
absref = None
@@ -574,12 +575,12 @@ class Morph(cliapp.Application):
reponame=reponame)
repo.update()
absref = repo.resolve_ref(ref)
- elif rrc != None:
+ elif rrc is not None:
try:
absref = rrc.resolve_ref(reponame, ref)
except:
pass
- if absref == None:
+ if absref is None:
if update:
self.status(msg='Caching git repository %(reponame)s',
reponame=reponame)
@@ -599,7 +600,7 @@ class Morph(cliapp.Application):
reponame, ref, filename = queue.popleft()
absref = self._resolveref(lrc, rrc, reponame, ref, update)
morphology = morph_factory.get_morphology(
- reponame, absref, filename)
+ reponame, absref, filename)
visit(reponame, ref, filename, absref, morphology)
if morphology['kind'] == 'system':
queue.extend((reponame, ref, '%s.morph' % s)
@@ -608,7 +609,7 @@ class Morph(cliapp.Application):
if morphology['build-depends']:
queue.extend((reponame, ref, '%s.morph' % s)
for s in morphology['build-depends'])
- queue.extend((c['repo'], c['ref'], '%s.morph' % c['morph'])
+ queue.extend((c['repo'], c['ref'], '%s.morph' % c['morph'])
for c in morphology['sources'])
def cmd_update_gits(self, args):
@@ -617,20 +618,20 @@ class Morph(cliapp.Application):
Parse the given morphologies, and their dependencies, and
update all the git repositories referred to by them in the
morph cache directory.
-
+
'''
if not os.path.exists(self.settings['cachedir']):
os.mkdir(self.settings['cachedir'])
cachedir = os.path.join(self.settings['cachedir'], 'gits')
repo_resolver = morphlib.repoaliasresolver.RepoAliasResolver(
- self.settings['repo-alias'])
+ self.settings['repo-alias'])
bundle_base_url = self.settings['bundle-server']
- cache = morphlib.localrepocache.LocalRepoCache(self,
- cachedir, repo_resolver, bundle_base_url)
+ cache = morphlib.localrepocache.LocalRepoCache(
+ self, cachedir, repo_resolver, bundle_base_url)
subs_to_process = set()
-
+
def visit(reponame, ref, filename, absref, morphology):
self.status(msg='Updating %(repo_name)s %(ref)s %(filename)s',
repo_name=reponame, ref=ref, filename=filename)
@@ -645,7 +646,7 @@ class Morph(cliapp.Application):
else:
for submod in submodules:
subs_to_process.add((submod.url, submod.commit))
-
+
self._traverse_morphs(self._itertriplets(args), cache, None,
update=True, visit=visit)
@@ -675,9 +676,9 @@ class Morph(cliapp.Application):
def cmd_make_patch(self, args):
'''Create a Trebuchet patch between two system images.'''
-
+
logging.debug('cmd_make_patch starting')
-
+
if len(args) != 7:
raise cliapp.AppException('make-patch requires arguments: '
'name of output file plus two triplest')
@@ -691,15 +692,15 @@ class Morph(cliapp.Application):
build_env = morphlib.buildenvironment.BuildEnvironment(self.settings)
ckc = morphlib.cachekeycomputer.CacheKeyComputer(build_env)
lac = morphlib.localartifactcache.LocalArtifactCache(
- os.path.join(cachedir, 'artifacts'))
+ os.path.join(cachedir, 'artifacts'))
repo_resolver = morphlib.repoaliasresolver.RepoAliasResolver(
- self.settings['repo-alias'])
- lrc = morphlib.localrepocache.LocalRepoCache(self,
- os.path.join(cachedir, 'gits'), repo_resolver,
- bundle_base_url=self.settings['bundle-server'])
+ self.settings['repo-alias'])
+ lrc = morphlib.localrepocache.LocalRepoCache(
+ self, os.path.join(cachedir, 'gits'), repo_resolver,
+ bundle_base_url=self.settings['bundle-server'])
if self.settings['cache-server']:
rrc = morphlib.remoterepocache.RemoteRepoCache(
- self.settings['cache-server'], repo_resolver)
+ self.settings['cache-server'], repo_resolver)
else:
rrc = None
@@ -710,14 +711,15 @@ class Morph(cliapp.Application):
def get_artifact(repo_name, ref, filename):
srcpool = self._create_source_pool(
- lrc, rrc, (repo_name, ref, filename))
+ lrc, rrc, (repo_name, ref, filename))
ar = morphlib.artifactresolver.ArtifactResolver()
artifacts = ar.resolve_artifacts(srcpool)
for artifact in artifacts:
artifact.cache_key = ckc.compute_key(artifact)
if the_one(artifact.source, repo_name, ref, filename):
- a = morphlib.artifact.Artifact(artifact.source,
- artifact.source.morphology['name']+'-rootfs')
+ a = morphlib.artifact.Artifact(
+ artifact.source,
+ artifact.source.morphology['name'] + '-rootfs')
a.cache_key = artifact.cache_key
return a
@@ -726,7 +728,7 @@ class Morph(cliapp.Application):
image_path_1 = lac.get(artifact1).name
image_path_2 = lac.get(artifact2).name
-
+
def setup(path):
part = morphlib.fsutils.setup_device_mapping(self.runcmd, path)
mount_point = tempfile.mkdtemp(dir=self.settings['tempdir'])
@@ -762,10 +764,10 @@ class Morph(cliapp.Application):
finally:
cleanup(image_path_1, mount_point_1)
cleanup(image_path_2, mount_point_2)
-
+
def cmd_init(self, args):
'''Initialize a mine.'''
-
+
if not args:
args = ['.']
elif len(args) > 1:
@@ -779,7 +781,7 @@ class Morph(cliapp.Application):
'directory: %s' % dirname)
else:
raise cliapp.AppException('can only initialize an existing '
- 'empty directory: %s' % dirname)
+ 'empty directory: %s' % dirname)
os.mkdir(os.path.join(dirname, '.morph'))
@@ -794,24 +796,24 @@ class Morph(cliapp.Application):
def cmd_minedir(self, args):
'''Find morph mine directory from current working directory.'''
-
+
dirname = self._deduce_mine_directory()
if dirname is None:
raise cliapp.AppException("Can't find the mine directory")
self.output.write('%s\n' % dirname)
-
+
def _resolve_reponame(self, reponame):
'''Return the full pull URL of a reponame.'''
resolver = morphlib.repoaliasresolver.RepoAliasResolver(
- self.settings['repo-alias'])
+ self.settings['repo-alias'])
return resolver.pull_url(reponame)
-
+
def _clone_to_directory(self, dirname, reponame, ref):
'''Clone a repository below a directory.
-
+
As a side effect, clone it into the morph repository.
-
+
'''
# Setup.
@@ -819,36 +821,37 @@ class Morph(cliapp.Application):
os.mkdir(self.settings['cachedir'])
cachedir = os.path.join(self.settings['cachedir'], 'gits')
repo_resolver = morphlib.repoaliasresolver.RepoAliasResolver(
- self.settings['repo-alias'])
+ self.settings['repo-alias'])
bundle_base_url = self.settings['bundle-server']
- cache = morphlib.localrepocache.LocalRepoCache(self,
- cachedir, repo_resolver, bundle_base_url)
+ cache = morphlib.localrepocache.LocalRepoCache(
+ self, cachedir, repo_resolver, bundle_base_url)
# Get the repository into the cache; make sure it is up to date.
repo = cache.cache_repo(reponame)
if not self.settings['no-git-update']:
repo.update()
-
+
# Clone it from cache to target directory.
repo.checkout(ref, os.path.abspath(dirname))
-
+
# Set the origin to point at the original repository.
morphlib.git.set_remote(self.runcmd, dirname, 'origin', repo.url)
-
+
# Add push url rewrite rule to .git/config.
self.runcmd(['git', 'config',
- 'url.%s.pushInsteadOf'% repo_resolver.push_url(reponame),
+ ('url.%s.pushInsteadOf' %
+ repo_resolver.push_url(reponame)),
repo_resolver.pull_url(reponame)], cwd=dirname)
-
+
# Update remotes.
self.runcmd(['git', 'remote', 'update'], cwd=dirname)
def cmd_branch(self, args):
'''Branch the whole system.'''
-
+
if len(args) not in [1, 2]:
raise cliapp.AppException('morph branch needs name of branch '
- 'as parameter')
+ 'as parameter')
new_branch = args[0]
commit = 'master' if len(args) == 1 else args[1]
@@ -859,7 +862,7 @@ class Morph(cliapp.Application):
# Clone into system branch directory.
new_repo = os.path.join(new_branch, self.system_repo_base)
self._clone_to_directory(new_repo, self.system_repo_name, commit)
-
+
# Create a new branch in the local morphs repository.
self.runcmd(['git', 'checkout', '-b', new_branch, commit],
cwd=new_repo)
@@ -869,7 +872,7 @@ class Morph(cliapp.Application):
if len(args) != 1:
raise cliapp.AppException('morph checkout needs name of '
- 'branch as parameter')
+ 'branch as parameter')
system_branch = args[0]
@@ -888,31 +891,31 @@ class Morph(cliapp.Application):
if not minedir.endswith('/'):
minedir += '/'
-
+
cwd = os.getcwd()
if not cwd.startswith(minedir):
return None
-
+
return os.path.dirname(cwd[len(minedir):])
-
+
def cmd_show_system_branch(self, args):
'''Print name of current system branch.
-
+
This must be run in the system branch's ``morphs`` repository.
-
+
'''
-
+
system_branch = self._deduce_system_branch()
if system_branch is None:
raise cliapp.AppException("Can't determine system branch")
self.output.write('%s\n' % system_branch)
-
+
def cmd_edit(self, args):
'''Edit a component in a system branch.'''
-
- if len(args) not in (1,2):
+
+ if len(args) not in (1, 2):
raise cliapp.AppException('morph edit must get a repository name '
- 'and commit ref as argument')
+ 'and commit ref as argument')
mine_directory = self._deduce_mine_directory()
system_branch = self._deduce_system_branch()
@@ -932,10 +935,10 @@ class Morph(cliapp.Application):
if ref is None:
raise morphlib.Error('Cannot deduce commit to start edit from')
- new_repo = os.path.join(mine_directory, system_branch,
+ new_repo = os.path.join(mine_directory, system_branch,
os.path.basename(repo))
self._clone_to_directory(new_repo, args[0], ref)
-
+
if system_branch == ref:
self.runcmd(['git', 'checkout', system_branch],
cwd=new_repo)
@@ -950,7 +953,7 @@ class Morph(cliapp.Application):
if spec_repo == repo and spec['ref'] != system_branch:
if self.settings['verbose']:
print ('Replacing ref "%s" with "%s" in %s' %
- (spec['ref'], system_branch, filename))
+ (spec['ref'], system_branch, filename))
spec['ref'] = system_branch
changed = True
if changed:
@@ -996,15 +999,15 @@ class Morph(cliapp.Application):
def cmd_merge(self, args):
'''Merge specified repositories from another system branch.'''
-
+
if len(args) == 0:
raise cliapp.AppException('morph merge must get a branch name '
- 'and some repo names as arguments')
+ 'and some repo names as arguments')
other_branch = args[0]
mine = self._deduce_mine_directory()
this_branch = self._deduce_system_branch()
-
+
for repo in args[1:]:
repo = self._resolve_reponame(repo)
basename = os.path.basename(repo)
@@ -1019,15 +1022,15 @@ class Morph(cliapp.Application):
os.mkdir(self.settings['cachedir'])
cachedir = os.path.join(self.settings['cachedir'], 'gits')
repo_resolver = morphlib.repoaliasresolver.RepoAliasResolver(
- self.settings['repo-alias'])
+ self.settings['repo-alias'])
bundle_base_url = self.settings['bundle-server']
- cache = morphlib.localrepocache.LocalRepoCache(self,
- cachedir, repo_resolver, bundle_base_url)
-
+ cache = morphlib.localrepocache.LocalRepoCache(
+ self, cachedir, repo_resolver, bundle_base_url)
+
for filename in args:
with open(filename) as f:
morph = json.load(f)
-
+
if morph['kind'] != 'stratum':
self.status(msg='Not a stratum: %(filename)s',
filename=filename)
@@ -1039,28 +1042,28 @@ class Morph(cliapp.Application):
reponame = source.get('repo', source['name'])
ref = source['ref']
self.status(msg='Looking up sha1 for %(repo_name)s %(ref)s',
- repo_name=reponame,
+ repo_name=reponame,
ref=ref)
repo = cache.get_repo(reponame)
source['ref'] = repo.resolve_ref(ref)
-
+
with open(filename, 'w') as f:
json.dump(morph, f, indent=2)
def status(self, **kwargs):
'''Show user a status update.
-
+
The keyword arguments are formatted and presented to the user in
a pleasing manner. Some keywords are special:
-
+
* ``msg`` is the message text; it can use ``%(foo)s`` to embed the
value of keyword argument ``foo``
* ``chatty`` should be true when the message is only informative,
and only useful for users who want to know everything (--verbose)
* ``error`` should be true when it is an error message
-
+
All other keywords are ignored unless embedded in ``msg``.
-
+
'''
assert 'msg' in kwargs
@@ -1077,7 +1080,7 @@ class Morph(cliapp.Application):
logging.debug(text)
else:
logging.info(text)
-
+
ok = verbose or error or (not quiet and not chatty)
if ok:
timestamp = time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime())
@@ -1100,11 +1103,10 @@ class Morph(cliapp.Application):
self.status(msg='# %(cmdline)s',
cmdline=' | '.join(commands),
chatty=True)
-
+
# Log the environment.
for name in kwargs['env']:
logging.debug('environment: %s=%s' % (name, kwargs['env'][name]))
# run the command line
return cliapp.Application.runcmd(self, argv, *args, **kwargs)
-