import os
import argparse
+from ConfigParser import SafeConfigParser
from gbp.scripts.buildpackage_rpm import main as gbp_rpm
from obs_service_gbp import LOGGER, gbplog, CachedRepo, CachedRepoError
argv.append('--git-spec-vcs-tag=%s' % args.spec_vcs_tag)
return argv
+def read_config(filenames):
+ '''Read configuration file(s)'''
+ defaults = {'repo-cache-dir': '/var/cache/obs/git-buildpackage-repos/'}
+
+ filenames = [os.path.expanduser(fname) for fname in filenames]
+ LOGGER.debug('Trying %s config files: %s' % (len(filenames), filenames))
+ parser = SafeConfigParser(defaults=defaults)
+ read = parser.read(filenames)
+ LOGGER.debug('Read %s config files: %s' % (len(read), read))
+
+ # Add our one-and-only section, if it does not exist
+ if not parser.has_section('general'):
+ parser.add_section('general')
+
+ # Read overrides from environment
+ for key in defaults.keys():
+ envvar ='OBS_GIT_BUILDPACKAGE_%s' % key.replace('-', '_').upper()
+ if envvar in os.environ:
+ parser.set('general', key, os.environ[envvar])
+
+ # We only use keys from one section, for now
+ return dict(parser.items('general'))
def parse_args(argv):
"""Argument parser"""
+ default_configs = ['/etc/obs/services/git-buildpackage',
+ '~/.obs/git-buildpackage']
parser = argparse.ArgumentParser()
parser.add_argument('--url', help='Remote repository URL', required=True)
choices=['yes', 'no'])
parser.add_argument('--spec-vcs-tag', help='Set/update the VCS tag in the'
'spec file')
+ parser.add_argument('--config', default=default_configs, action='append',
+ help='Config file to use, can be given multiple times')
return parser.parse_args(argv)
def main(argv=None):
"""Main function"""
- LOGGER.info('Starting git-buildpackage source service')
args = parse_args(argv)
+ LOGGER.info('Starting git-buildpackage source service')
if args.verbose == 'yes':
gbplog.setup(color='auto', verbose=True)
LOGGER.setLevel(gbplog.DEBUG)
+ config = read_config(args.config)
+
# Create / update cached repository
try:
- repo = CachedRepo(args.url)
+ repo = CachedRepo(config['repo-cache-dir'], args.url)
args.revision = repo.update_working_copy(args.revision)
except CachedRepoError as err:
LOGGER.error('RepoCache: %s' % str(err))
# Export sources with GBP
gbp_args = construct_gbp_args(args)
- os.chdir(repo.repodir)
- LOGGER.info('Exporting packaging files with GBP')
- ret = gbp_rpm(gbp_args)
+ orig_dir = os.path.abspath(os.curdir)
+ try:
+ os.chdir(repo.repodir)
+ LOGGER.info('Exporting packaging files with GBP')
+ ret = gbp_rpm(gbp_args)
+ finally:
+ os.chdir(orig_dir)
if ret:
LOGGER.error('Git-buildpackage-rpm failed, unable to export packaging '
- 'files')
+ 'files')
return 2
return 0
# Use cache in our tmpdir
suffix = os.path.basename(self.tmpdir).replace('test', '')
self.cachedir = os.path.join(self.workdir, 'cache' + suffix)
- os.environ['CACHEDIR'] = self.cachedir
+ os.environ['OBS_GIT_BUILDPACKAGE_REPO_CACHE_DIR'] = self.cachedir
# Create temporary "orig" repository
repo_dir = os.path.join(self.workdir, 'orig' + suffix)
shutil.copytree(self._template_repo.path, repo_dir)
assert service(['--url', self.orig_repo.path,
'--spec-vcs-tag=orig/%(tagname)s']) == 0
+ def test_options_config(self):
+ """Test the --config option"""
+ # Create config file
+ with open('my.conf', 'w') as conf:
+ conf.write('[general]\n')
+ conf.write('repo-cache-dir = my-repo-cache\n')
+
+ # Mangle environment
+ default_cache = os.environ['OBS_GIT_BUILDPACKAGE_REPO_CACHE_DIR']
+ del os.environ['OBS_GIT_BUILDPACKAGE_REPO_CACHE_DIR']
+
+ # Check that the repo cache we configured is actually used
+ assert (service(['--url', self.orig_repo.path, '--config', 'my.conf'])
+ == 0)
+ assert not os.path.exists(default_cache), os.listdir('.')
+ assert os.path.exists('my-repo-cache'), os.listdir('.')
+
class TestObsRepoGitRepository(UnitTestsBase):
"""Test the special GitRepository class"""
repo.set_config('foo.bar', 'bax', replace=True)
assert repo.get_config('foo.bar') == 'bax'
+
class TestCachedRepo(UnitTestsBase):
"""Test CachedRepo class"""
+ def MockCachedRepo(self, url, **kwargs):
+ """Automatically use suitable cache dir"""
+ return CachedRepo(self.cachedir, url, **kwargs)
+
def test_invalid_url(self):
"""Test invalid url"""
with assert_raises(CachedRepoError):
- CachedRepo('foo/bar.git')
+ self.MockCachedRepo('foo/bar.git')
with assert_raises(CachedRepoError):
- CachedRepo('foo/baz.git', bare=True)
+ self.MockCachedRepo('foo/baz.git', bare=True)
# Try updating from non-existing repo
- repo = CachedRepo(self.orig_repo.path)
+ repo = self.MockCachedRepo(self.orig_repo.path)
del repo
shutil.move(self.orig_repo.path, self.orig_repo.path + '.tmp')
with assert_raises(CachedRepoError):
- repo = CachedRepo(self.orig_repo.path)
+ repo = self.MockCachedRepo(self.orig_repo.path)
shutil.move(self.orig_repo.path + '.tmp', self.orig_repo.path)
def test_clone_and_fetch(self):
"""Basic test for cloning and fetching"""
# Clone
- repo = CachedRepo(self.orig_repo.path)
+ repo = self.MockCachedRepo(self.orig_repo.path)
assert repo
assert repo.repo.bare is not True
sha = repo.repo.rev_parse('master')
# Make new commit in "upstream"
self.update_repository_file(self.orig_repo, 'foo.txt', 'more data\n')
# Fetch
- repo = CachedRepo(self.orig_repo.path)
+ repo = self.MockCachedRepo(self.orig_repo.path)
assert repo
assert path == repo.repo.path
assert sha != repo.repo.rev_parse('master')
def test_update_working_copy(self):
"""Test update functionality"""
- repo = CachedRepo(self.orig_repo.path)
+ repo = self.MockCachedRepo(self.orig_repo.path)
# Check that the refs are mapped correctly
sha = repo.update_working_copy('HEAD~1')
assert sha == self.orig_repo.rev_parse('HEAD~1')
shas = [self.orig_repo.rev_parse('HEAD~2'),
self.orig_repo.rev_parse('HEAD~1'),
self.orig_repo.rev_parse('HEAD')]
- repo = CachedRepo(self.orig_repo.path)
+ repo = self.MockCachedRepo(self.orig_repo.path)
repo.update_working_copy(shas[-1])
del repo
# Change upstream, after this index cached repo will be out-of-sync
# from orig HEAD
self.orig_repo.set_branch('HEAD~1')
- repo = CachedRepo(self.orig_repo.path)
+ repo = self.MockCachedRepo(self.orig_repo.path)
assert repo.update_working_copy(shas[0]) == shas[0]
def test_update_bare(self):
"""Test update for bare repository"""
- repo = CachedRepo(self.orig_repo.path, bare=True)
+ repo = self.MockCachedRepo(self.orig_repo.path, bare=True)
with assert_raises(CachedRepoError):
repo.update_working_copy('HEAD')
def test_invalid_remote_head(self):
"""Test clone/update from remote whose HEAD is invalid"""
- repo = CachedRepo(self.orig_repo.path)
+ repo = self.MockCachedRepo(self.orig_repo.path)
del repo
# Make remote HEAD point to a non-existent branch
with open(os.path.join(self.orig_repo.git_dir, 'HEAD'), 'w') as head:
head.write('ref: refs/heads/non-existent-branch\n')
- repo = CachedRepo(self.orig_repo.path)
+ repo = self.MockCachedRepo(self.orig_repo.path)
# Local HEAD should be invalid, now
with assert_raises(CachedRepoError):
repo.update_working_copy('HEAD')
def test_corrupted_cache(self):
"""Test recovering from corrupted cache"""
# Clone
- repo = CachedRepo(self.orig_repo.path)
+ repo = self.MockCachedRepo(self.orig_repo.path)
# Corrupt repo
shutil.rmtree(os.path.join(repo.repo.path, '.git/refs'))
with assert_raises(GitRepositoryError):
repo.repo.rev_parse('HEAD')
del repo
# Update and check status
- repo = CachedRepo(self.orig_repo.path)
+ repo = self.MockCachedRepo(self.orig_repo.path)
assert repo.repo.rev_parse('HEAD')
def test_changing_repotype(self):
"""Test changing repo type from bare -> normal"""
# Clone
- repo = CachedRepo(self.orig_repo.path, bare=True)
+ repo = self.MockCachedRepo(self.orig_repo.path, bare=True)
assert repo.repo.bare == True
del repo
- repo = CachedRepo(self.orig_repo.path, bare=False)
+ repo = self.MockCachedRepo(self.orig_repo.path, bare=False)
assert repo.repo.bare == False
def test_cache_access_error(self):
# Check base cachedir creation access error
os.chmod(self.workdir, 0)
with assert_raises(CachedRepoError):
- repo = CachedRepo(self.orig_repo.path)
+ repo = self.MockCachedRepo(self.orig_repo.path)
os.chmod(self.workdir, stat.S_IREAD | stat.S_IWRITE | stat.S_IEXEC)
- repo = CachedRepo(self.orig_repo.path)
+ repo = self.MockCachedRepo(self.orig_repo.path)
del repo
# Check cache base dir access error
os.chmod(self.cachedir, 0)
with assert_raises(CachedRepoError):
- repo = CachedRepo(self.orig_repo.path)
+ repo = self.MockCachedRepo(self.orig_repo.path)
os.chmod(self.cachedir, stat.S_IREAD | stat.S_IWRITE | stat.S_IEXEC)
- repo = CachedRepo(self.orig_repo.path)
+ repo = self.MockCachedRepo(self.orig_repo.path)
del repo
# Check repodir delete eror
os.chmod(self.cachedir, stat.S_IREAD | stat.S_IEXEC)
with assert_raises(CachedRepoError):
# Change repo type -> tries to delete
- repo = CachedRepo(self.orig_repo.path, bare=True)
+ repo = self.MockCachedRepo(self.orig_repo.path, bare=True)
os.chmod(self.cachedir, stat.S_IREAD | stat.S_IWRITE | stat.S_IEXEC)