Add support for Deb packages and selective building
[services/obs-service-git-buildpackage.git] / obs_service_gbp / command.py
1 # vim:fileencoding=utf-8:et:ts=4:sw=4:sts=4
2 #
3 # Copyright (C) 2013 Intel Corporation <markus.lehtonen@linux.intel.com>
4 #
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License
7 # as published by the Free Software Foundation; either version 2
8 # of the License, or (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 # MA 02110-1301, USA.
19 """The git-buildpackage source service for OBS"""
20
21 import os
22 import argparse
23 from ConfigParser import SafeConfigParser
24
25 from gbp.rpm import guess_spec, NoSpecError
26 from gbp.scripts.buildpackage import main as gbp_deb
27 from gbp.scripts.buildpackage_rpm import main as gbp_rpm
28
29 from obs_service_gbp import LOGGER, gbplog, CachedRepo, CachedRepoError
30
31
32 def have_spec(directory):
33     """Find if the package has spec files"""
34     try:
35         guess_spec(directory, recursive=True)
36     except NoSpecError as err:
37         if str(err).startswith('No spec file'):
38             return False
39     return True
40
41 def construct_gbp_args(args):
42     """Construct args list for git-buildpackage-rpm"""
43     # Args common to deb and rpm
44     argv_common = ['argv[0] stub',
45                    '--git-ignore-branch',
46                    '--git-no-hooks']
47     if args.outdir:
48         argv_common.append('--git-export-dir=%s' % os.path.abspath(args.outdir))
49     else:
50         argv_common.append('--git-export-dir=%s' % os.path.abspath(os.curdir))
51     if args.revision:
52         argv_common.append('--git-export=%s' % args.revision)
53     if args.verbose == 'yes':
54         argv_common.append('--git-verbose')
55
56     # Dermine deb and rpm specific args
57     argv_rpm = argv_common[:]
58     argv_rpm.extend(['--git-builder=osc',
59                      '--git-export-only',
60                      '--git-ignore-branch'])
61     if args.spec_vcs_tag:
62         argv_rpm.append('--git-spec-vcs-tag=%s' % args.spec_vcs_tag)
63
64     # We need to build this way (i.e. run outside the sources directory)
65     # because if run with '-b .' dpkg-source will put it's output to different
66     # directory, depending on the version of dpkg
67     deb_builder_script = 'cd ..; dpkg-source -b $GBP_BUILD_DIR'
68     argv_deb = argv_common[:]
69     argv_deb.extend(['--git-purge',
70                      '--git-builder=%s' % deb_builder_script])
71     LOGGER.debug('rpm args' % argv_rpm)
72     return (argv_rpm, argv_deb)
73
74 def read_config(filenames):
75     '''Read configuration file(s)'''
76     defaults = {'repo-cache-dir': '/var/cache/obs/git-buildpackage-repos/'}
77
78     filenames = [os.path.expanduser(fname) for fname in filenames]
79     LOGGER.debug('Trying %s config files: %s' % (len(filenames), filenames))
80     parser = SafeConfigParser(defaults=defaults)
81     read = parser.read(filenames)
82     LOGGER.debug('Read %s config files: %s' % (len(read), read))
83
84     # Add our one-and-only section, if it does not exist
85     if not parser.has_section('general'):
86         parser.add_section('general')
87
88     # Read overrides from environment
89     for key in defaults.keys():
90         envvar ='OBS_GIT_BUILDPACKAGE_%s' % key.replace('-', '_').upper()
91         if envvar in os.environ:
92             parser.set('general', key, os.environ[envvar])
93
94     # We only use keys from one section, for now
95     return dict(parser.items('general'))
96
97 def parse_args(argv):
98     """Argument parser"""
99     default_configs = ['/etc/obs/services/git-buildpackage',
100                        '~/.obs/git-buildpackage']
101
102     parser = argparse.ArgumentParser()
103     parser.add_argument('--url', help='Remote repository URL', required=True)
104     parser.add_argument('--outdir', help='Output direcory')
105     parser.add_argument('--revision', help='Remote repository URL',
106                         default='HEAD')
107     parser.add_argument('--rpm', choices=['auto', 'yes', 'no'], default='auto',
108                         help='Export RPM packaging files')
109     parser.add_argument('--deb', choices=['auto', 'yes', 'no'], default='auto',
110                         help='Export Debian packaging files')
111     parser.add_argument('--verbose', '-v', help='Verbose output',
112                         choices=['yes', 'no'])
113     parser.add_argument('--spec-vcs-tag', help='Set/update the VCS tag in the'
114                                                'spec file')
115     parser.add_argument('--config', default=default_configs, action='append',
116                         help='Config file to use, can be given multiple times')
117     return parser.parse_args(argv)
118
119 def main(argv=None):
120     """Main function"""
121
122     args = parse_args(argv)
123
124     LOGGER.info('Starting git-buildpackage source service')
125     if args.verbose == 'yes':
126         gbplog.setup(color='auto', verbose=True)
127         LOGGER.setLevel(gbplog.DEBUG)
128
129     config = read_config(args.config)
130
131     # Create / update cached repository
132     try:
133         repo = CachedRepo(config['repo-cache-dir'], args.url)
134         args.revision = repo.update_working_copy(args.revision)
135     except CachedRepoError as err:
136         LOGGER.error('RepoCache: %s' % str(err))
137         return 1
138
139     # Export sources with GBP
140     rpm_args, deb_args = construct_gbp_args(args)
141     orig_dir = os.path.abspath(os.curdir)
142     try:
143         os.chdir(repo.repodir)
144         specs_found = have_spec('.')
145         if args.rpm == 'yes' or (args.rpm == 'auto' and specs_found):
146             LOGGER.info('Exporting RPM packaging files with GBP')
147             LOGGER.debug('git-buildpackage-rpm args: %s' % ' '.join(rpm_args))
148             ret = gbp_rpm(rpm_args)
149             if ret:
150                 LOGGER.error('Git-buildpackage-rpm failed, unable to export '
151                              'RPM packaging files')
152                 return 2
153         if args.deb == 'yes' or (args.deb== 'auto' and os.path.isdir('debian')):
154             LOGGER.info('Exporting Debian source package with GBP')
155             LOGGER.debug('git-buildpackage args: %s' % ' '.join(deb_args))
156             ret = gbp_deb(deb_args)
157             if ret:
158                 LOGGER.error('Git-buildpackage failed, unable to export Debian '
159                              'sources package files')
160                 return 3
161     finally:
162         os.chdir(orig_dir)
163
164     return 0