From: Markus Lehtonen Date: Fri, 19 Apr 2013 13:44:52 +0000 (+0300) Subject: Support for config files X-Git-Tag: submit/devel/20190730.075437~86 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=58c374cf993aeca5dd13244b040bc3597a8c9dad;p=services%2Fobs-service-git-buildpackage.git Support for config files Initial support for reading service configuration from a file. For now, there is only one configuration setting, i.e. 'repo-cache-dir'. All configuration settings can be overridden with environment variables, if needed. By default, the service tries to read '/etc/obs/services/git-buildpackage' and '~/.obs/git-buildpackage'. Other file(s) can be defined with the --config cmdline option. Change-Id: I65d5ee26b3798646e49615d98019673ce5606d5d Signed-off-by: Markus Lehtonen --- diff --git a/config/git-buildpackage b/config/git-buildpackage new file mode 100644 index 0000000..31b9cfc --- /dev/null +++ b/config/git-buildpackage @@ -0,0 +1,10 @@ +## +## Configuration for the git-buildpackage OBS source service +## + +[general] +## Repository cache directory. +## Default is '/var/cache/obs/git-buildpackage-repos/' +## You probably need to define if the service is run on the client side as +## the default directory is likely not accessible by regular users. +#repo-cache-dir = /var/cache/obs/git-buildpackage-repos/ diff --git a/obs_service_gbp/__init__.py b/obs_service_gbp/__init__.py index 4488122..dce8ec3 100644 --- a/obs_service_gbp/__init__.py +++ b/obs_service_gbp/__init__.py @@ -89,8 +89,8 @@ class CachedRepoError(Exception): class CachedRepo(object): """Object representing a cached repository""" - def __init__(self, url, bare=False): - self.basedir = '/var/cache/obs/git-buildpackage-repos/' + def __init__(self, base_dir, url, bare=False): + self.basedir = base_dir self.repodir = None self.repo = None self.lock = None @@ -100,8 +100,6 @@ class CachedRepo(object): def _init_cache_base(self): """Check and initialize repository cache base directory""" - if 'CACHEDIR' in os.environ: - self.basedir = os.environ['CACHEDIR'] LOGGER.debug("Using cache basedir '%s'" % self.basedir) if not os.path.exists(self.basedir): LOGGER.debug('Creating missing cache basedir') diff --git a/obs_service_gbp/command.py b/obs_service_gbp/command.py index 46178db..e36d096 100644 --- a/obs_service_gbp/command.py +++ b/obs_service_gbp/command.py @@ -21,6 +21,7 @@ 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 @@ -43,9 +44,33 @@ def construct_gbp_args(args): 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) @@ -56,21 +81,25 @@ def parse_args(argv): 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)) @@ -78,12 +107,16 @@ def main(argv=None): # 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 diff --git a/packaging/obs-service-git-buildpackage.spec b/packaging/obs-service-git-buildpackage.spec index 12585b6..f056d2d 100644 --- a/packaging/obs-service-git-buildpackage.spec +++ b/packaging/obs-service-git-buildpackage.spec @@ -51,3 +51,6 @@ rm -rf %{buildroot}%{python_sitelib}/*info %dir /usr/lib/obs/service /usr/lib/obs/service/* %{python_sitelib}/obs_service_gbp +%dir %{_sysconfdir}/obs +%dir %{_sysconfdir}/obs/services +%config %{_sysconfdir}/obs/services/* diff --git a/setup.py b/setup.py index f424ae2..a9cea8a 100644 --- a/setup.py +++ b/setup.py @@ -37,5 +37,6 @@ setup(name='obs_service_gbp', author_email='markus.lehtonen@linux.intel.com', packages=['obs_service_gbp'], data_files=[('/usr/lib/obs/service', ['service/git-buildpackage', - 'service/git-buildpackage.service'])], + 'service/git-buildpackage.service']), + ('/etc/obs/services', ['config/git-buildpackage'])], ) diff --git a/tests/test_obs_service_gbp.py b/tests/test_obs_service_gbp.py index 1857420..8b1b19b 100644 --- a/tests/test_obs_service_gbp.py +++ b/tests/test_obs_service_gbp.py @@ -88,7 +88,7 @@ class UnitTestsBase(object): # 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) @@ -150,6 +150,23 @@ class TestBasicFunctionality(UnitTestsBase): 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""" @@ -163,28 +180,33 @@ class TestObsRepoGitRepository(UnitTestsBase): 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') @@ -193,14 +215,14 @@ class TestCachedRepo(UnitTestsBase): # 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') @@ -218,25 +240,25 @@ class TestCachedRepo(UnitTestsBase): 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 @@ -244,7 +266,7 @@ class TestCachedRepo(UnitTestsBase): 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') @@ -257,23 +279,23 @@ class TestCachedRepo(UnitTestsBase): 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): @@ -281,23 +303,23 @@ class TestCachedRepo(UnitTestsBase): # 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)