summaryrefslogtreecommitdiff
path: root/morphlib
diff options
context:
space:
mode:
authorRichard Maw <richard.maw@codethink.co.uk>2012-11-12 17:28:57 +0000
committerRichard Maw <richard.maw@codethink.co.uk>2012-11-12 17:28:57 +0000
commit2ac6f661130322e63b8d2737145ea11d445aaa79 (patch)
treedd30179d22c09cc73898d7db6218e0d620d74ac8 /morphlib
parent19b16a2cc6d67871d0a4298354eb446ada136a8e (diff)
parenta5b913a83db94380fc91d15571f55cbf7b5c741b (diff)
downloadmorph-2ac6f661130322e63b8d2737145ea11d445aaa79.tar.gz
Merge branch 'samthursfield/build-without-push' of git://git.baserock.org/baserock/morph
Diffstat (limited to 'morphlib')
-rwxr-xr-xmorphlib/app.py4
-rw-r--r--morphlib/buildcommand.py1
-rw-r--r--morphlib/cachedrepo.py7
-rw-r--r--morphlib/cachedrepo_tests.py6
-rw-r--r--morphlib/git.py7
-rw-r--r--morphlib/localrepocache.py10
-rw-r--r--morphlib/localrepocache_tests.py5
-rw-r--r--morphlib/plugins/branch_and_merge_plugin.py43
8 files changed, 66 insertions, 17 deletions
diff --git a/morphlib/app.py b/morphlib/app.py
index 8769b41c..0a11c716 100755
--- a/morphlib/app.py
+++ b/morphlib/app.py
@@ -139,6 +139,10 @@ class Morph(cliapp.Application):
'build chunks with prefix PREFIX',
metavar='PREFIX', default=defaults['prefix'],
group=group_build)
+ self.settings.boolean(['push-build-branches'],
+ 'always push temporary build branches to the '
+ 'remote repository',
+ group=group_build)
self.settings.boolean(['staging-chroot'],
'build things in an isolated chroot '
'(default: true)',
diff --git a/morphlib/buildcommand.py b/morphlib/buildcommand.py
index aa6c7d0e..95f3812e 100644
--- a/morphlib/buildcommand.py
+++ b/morphlib/buildcommand.py
@@ -38,6 +38,7 @@ class BuildCommand(object):
self.ckc = self.new_cache_key_computer(self.build_env)
self.lac, self.rac = self.new_artifact_caches()
self.lrc, self.rrc = self.new_repo_caches()
+ self.supports_local_build = True
def build(self, args):
'''Build triplets specified on command line.'''
diff --git a/morphlib/cachedrepo.py b/morphlib/cachedrepo.py
index c40cb657..0b5ce60f 100644
--- a/morphlib/cachedrepo.py
+++ b/morphlib/cachedrepo.py
@@ -102,6 +102,7 @@ class CachedRepo(object):
self.original_name = original_name
self.url = url
self.path = path
+ self.is_mirror = not url.startswith('file://')
def resolve_ref(self, ref):
'''Attempts to resolve a ref into its SHA1 and tree SHA1.
@@ -223,6 +224,9 @@ class CachedRepo(object):
'''
+ if not self.is_mirror:
+ return
+
try:
self._update()
except cliapp.AppException, e:
@@ -260,7 +264,8 @@ class CachedRepo(object):
def _copy_repository(self, source_dir, target_dir): # pragma: no cover
try:
- morphlib.git.copy_repository(self._runcmd, source_dir, target_dir)
+ morphlib.git.copy_repository(
+ self._runcmd, source_dir, target_dir, self.is_mirror)
except cliapp.AppException:
raise CopyError(self, target_dir)
diff --git a/morphlib/cachedrepo_tests.py b/morphlib/cachedrepo_tests.py
index 0ca0882f..81673880 100644
--- a/morphlib/cachedrepo_tests.py
+++ b/morphlib/cachedrepo_tests.py
@@ -246,6 +246,12 @@ class CachedRepoTests(unittest.TestCase):
self.repo._update = self.update_with_failure
self.assertRaises(cachedrepo.UpdateError, self.repo.update)
+ def test_no_update_if_local(self):
+ self.repo = cachedrepo.CachedRepo(
+ object(), 'local:repo', 'file:///local/repo/', '/local/repo/')
+ self.repo._update = self.update_with_failure
+ self.repo.update()
+
def test_clone_checkout(self):
self.repo.clone_checkout('master', '/.DOES_NOT_EXIST')
self.assertEqual(self.clone_target, '/.DOES_NOT_EXIST')
diff --git a/morphlib/git.py b/morphlib/git.py
index 973e4af7..7985b815 100644
--- a/morphlib/git.py
+++ b/morphlib/git.py
@@ -175,13 +175,18 @@ def set_remote(runcmd, gitdir, name, url):
return runcmd(['git', 'remote', 'set-url', name, url], cwd=gitdir)
-def copy_repository(runcmd, repo, destdir):
+def copy_repository(runcmd, repo, destdir, is_mirror=True):
'''Copies a cached repository into a directory using cp.
This also fixes up the repository afterwards, so that it can contain
code etc. It does not leave any given branch ready for use.
'''
+ if is_mirror == False:
+ runcmd(['cp', '-a', os.path.join(repo, '.git'),
+ os.path.join(destdir, '.git')])
+ return
+
runcmd(['cp', '-a', repo, os.path.join(destdir, '.git')])
# core.bare should be false so that git believes work trees are possible
runcmd(['git', 'config', 'core.bare', 'false'], cwd=destdir)
diff --git a/morphlib/localrepocache.py b/morphlib/localrepocache.py
index ae5fa655..465e9f03 100644
--- a/morphlib/localrepocache.py
+++ b/morphlib/localrepocache.py
@@ -193,9 +193,13 @@ class LocalRepoCache(object):
return quote_url(url)
def _cache_name(self, url):
- basename = self._escape(url)
- path = os.path.join(self._cachedir, basename)
- return path
+ scheme, netloc, path, query, fragment = urlparse.urlsplit(url)
+ if scheme == 'file':
+ return path
+ else:
+ basename = self._escape(url)
+ path = os.path.join(self._cachedir, basename)
+ return path
def has_repo(self, reponame):
'''Have we already got a cache of a given repo?'''
diff --git a/morphlib/localrepocache_tests.py b/morphlib/localrepocache_tests.py
index 26a92616..6c5410ce 100644
--- a/morphlib/localrepocache_tests.py
+++ b/morphlib/localrepocache_tests.py
@@ -163,3 +163,8 @@ class LocalRepoCacheTests(unittest.TestCase):
def test_noremote_error_message_contains_repo_name(self):
e = morphlib.localrepocache.NoRemote(self.repourl, [])
self.assertTrue(self.repourl in str(e))
+
+ def test_avoids_caching_local_repo(self):
+ self.lrc.cache_repo('file:///local/repo')
+ cached = self.lrc.get_repo('file:///local/repo')
+ assert cached.path == '/local/repo'
diff --git a/morphlib/plugins/branch_and_merge_plugin.py b/morphlib/plugins/branch_and_merge_plugin.py
index 21a5970c..efaa8dfe 100644
--- a/morphlib/plugins/branch_and_merge_plugin.py
+++ b/morphlib/plugins/branch_and_merge_plugin.py
@@ -1126,6 +1126,11 @@ class BranchAndMergePlugin(cliapp.Plugin):
# Generate a UUID for the build.
build_uuid = uuid.uuid4().hex
+ build_command = morphlib.buildcommand.BuildCommand(self.app)
+ build_command = self.app.hookmgr.call('new-build-command',
+ build_command)
+ push = self.app.settings['push-build-branches']
+
self.app.status(msg='Starting build %(uuid)s', uuid=build_uuid)
self.app.status(msg='Collecting morphologies involved in '
@@ -1143,26 +1148,34 @@ class BranchAndMergePlugin(cliapp.Plugin):
# Create the build refs for all these repositories and commit
# all uncommitted changes to them, updating all references
# to system branch refs to point to the build refs instead.
- self.update_build_refs(build_repos, branch, build_uuid)
+ self.update_build_refs(build_repos, branch, build_uuid, push)
- # Push the temporary build refs.
- self.push_build_refs(build_repos)
+ if push:
+ self.push_build_refs(build_repos)
+ build_branch_root = branch_root
+ else:
+ dirname = build_repos[branch_root]['dirname']
+ build_branch_root = urlparse.urljoin('file://', dirname)
# Run the build.
- build_command = morphlib.buildcommand.BuildCommand(self.app)
- build_command = self.app.hookmgr.call('new-build-command',
- build_command)
- build_command.build([branch_root,
+ build_command.build([build_branch_root,
build_repos[branch_root]['build-ref'],
system_name])
- # Delete the temporary refs on the server.
- self.delete_remote_build_refs(build_repos)
+ if push:
+ self.delete_remote_build_refs(build_repos)
self.app.status(msg='Finished build %(uuid)s', uuid=build_uuid)
def get_system_build_repos(self, system_branch, branch_dir,
branch_root, system_name):
+ '''Map upstream repository URLs to their checkouts in the system branch
+
+ Also provides the list of morphologies stored in each repository,
+ grouped by kind.
+
+ '''
+
build_repos = {}
def prepare_repo_info(repo, dirname):
@@ -1205,7 +1218,7 @@ class BranchAndMergePlugin(cliapp.Plugin):
return build_repos
- def inject_build_refs(self, morphology, build_repos):
+ def inject_build_refs(self, morphology, build_repos, will_push):
# Starting from a system or stratum morphology, update all ref
# pointers of strata or chunks involved in a system build (represented
# by build_repos) to point to temporary build refs of the repos
@@ -1215,6 +1228,9 @@ class BranchAndMergePlugin(cliapp.Plugin):
info['morph'] in build_repos[info['repo']]['strata'] or
info['morph'] in build_repos[info['repo']]['chunks']):
info['ref'] = build_repos[info['repo']]['build-ref']
+ if not will_push:
+ dirname = build_repos[info['repo']]['dirname']
+ info['repo'] = urlparse.urljoin('file://', dirname)
if morphology['kind'] == 'system':
for info in morphology['strata']:
inject_build_ref(info)
@@ -1230,7 +1246,10 @@ class BranchAndMergePlugin(cliapp.Plugin):
branch_uuid, repo_uuid)
info['build-ref'] = build_ref
- def update_build_refs(self, build_repos, system_branch, build_uuid):
+ def update_build_refs(self, build_repos, system_branch, build_uuid,
+ will_push):
+ '''Update build branches for each repository with any local changes '''
+
# Define the committer.
committer_name = 'Morph (on behalf of %s)' % \
(morphlib.git.get_user_name(self.app.runcmd))
@@ -1282,7 +1301,7 @@ class BranchAndMergePlugin(cliapp.Plugin):
for filename in filenames:
# Inject temporary refs in the right places in each morphology.
morphology = self.load_morphology(repo_dir, filename)
- self.inject_build_refs(morphology, build_repos)
+ self.inject_build_refs(morphology, build_repos, will_push)
handle, tmpfile = tempfile.mkstemp(suffix='.morph')
self.save_morphology(repo_dir, tmpfile, morphology)