Add support for Deb packages and selective building
authorMarkus Lehtonen <markus.lehtonen@linux.intel.com>
Mon, 22 Apr 2013 14:02:40 +0000 (17:02 +0300)
committerMarkus Lehtonen <markus.lehtonen@linux.intel.com>
Thu, 25 Apr 2013 12:15:03 +0000 (15:15 +0300)
Add support for generating (exporting) Debian source package with
git-buildpackage.

Also, adds new options 'rpm' and 'deb' for selecting whether to generate
rpm and/or deb packaging sources. These options are tri-state with
'auto' trying to determine if the corresponding packaging is available.

Change-Id: Ie3dda1f471a64665009fb9557ed62c1d2d0f3610
Signed-off-by: Markus Lehtonen <markus.lehtonen@linux.intel.com>
obs_service_gbp/command.py
packaging/obs-service-git-buildpackage.spec
service/git-buildpackage.service
tests/data/debian/changelog [new file with mode: 0644]
tests/data/debian/control [new file with mode: 0644]
tests/data/packaging/test-package.spec
tests/test_obs_service_gbp.py

index e36d096..0fd6f7e 100644 (file)
 
 import os
 import argparse
-
 from ConfigParser import SafeConfigParser
+
+from gbp.rpm import guess_spec, NoSpecError
+from gbp.scripts.buildpackage import main as gbp_deb
 from gbp.scripts.buildpackage_rpm import main as gbp_rpm
 
 from obs_service_gbp import LOGGER, gbplog, CachedRepo, CachedRepoError
 
+
+def have_spec(directory):
+    """Find if the package has spec files"""
+    try:
+        guess_spec(directory, recursive=True)
+    except NoSpecError as err:
+        if str(err).startswith('No spec file'):
+            return False
+    return True
+
 def construct_gbp_args(args):
     """Construct args list for git-buildpackage-rpm"""
-    argv = ['argv[0] stub',
-            '--git-builder=osc',
-            '--git-export-only',
-            '--git-ignore-branch']
+    # Args common to deb and rpm
+    argv_common = ['argv[0] stub',
+                   '--git-ignore-branch',
+                   '--git-no-hooks']
     if args.outdir:
-        argv.append('--git-export-dir=%s' % os.path.abspath(args.outdir))
+        argv_common.append('--git-export-dir=%s' % os.path.abspath(args.outdir))
     else:
-        argv.append('--git-export-dir=%s' % os.path.abspath(os.curdir))
+        argv_common.append('--git-export-dir=%s' % os.path.abspath(os.curdir))
     if args.revision:
-        argv.append('--git-export=%s' % args.revision)
+        argv_common.append('--git-export=%s' % args.revision)
     if args.verbose == 'yes':
-        argv.append('--git-verbose')
+        argv_common.append('--git-verbose')
+
+    # Dermine deb and rpm specific args
+    argv_rpm = argv_common[:]
+    argv_rpm.extend(['--git-builder=osc',
+                     '--git-export-only',
+                     '--git-ignore-branch'])
     if args.spec_vcs_tag:
-        argv.append('--git-spec-vcs-tag=%s' % args.spec_vcs_tag)
-    return argv
+        argv_rpm.append('--git-spec-vcs-tag=%s' % args.spec_vcs_tag)
+
+    # We need to build this way (i.e. run outside the sources directory)
+    # because if run with '-b .' dpkg-source will put it's output to different
+    # directory, depending on the version of dpkg
+    deb_builder_script = 'cd ..; dpkg-source -b $GBP_BUILD_DIR'
+    argv_deb = argv_common[:]
+    argv_deb.extend(['--git-purge',
+                     '--git-builder=%s' % deb_builder_script])
+    LOGGER.debug('rpm args' % argv_rpm)
+    return (argv_rpm, argv_deb)
 
 def read_config(filenames):
     '''Read configuration file(s)'''
@@ -77,6 +104,10 @@ def parse_args(argv):
     parser.add_argument('--outdir', help='Output direcory')
     parser.add_argument('--revision', help='Remote repository URL',
                         default='HEAD')
+    parser.add_argument('--rpm', choices=['auto', 'yes', 'no'], default='auto',
+                        help='Export RPM packaging files')
+    parser.add_argument('--deb', choices=['auto', 'yes', 'no'], default='auto',
+                        help='Export Debian packaging files')
     parser.add_argument('--verbose', '-v', help='Verbose output',
                         choices=['yes', 'no'])
     parser.add_argument('--spec-vcs-tag', help='Set/update the VCS tag in the'
@@ -106,17 +137,28 @@ def main(argv=None):
         return 1
 
     # Export sources with GBP
-    gbp_args = construct_gbp_args(args)
+    rpm_args, deb_args = construct_gbp_args(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)
+        specs_found = have_spec('.')
+        if args.rpm == 'yes' or (args.rpm == 'auto' and specs_found):
+            LOGGER.info('Exporting RPM packaging files with GBP')
+            LOGGER.debug('git-buildpackage-rpm args: %s' % ' '.join(rpm_args))
+            ret = gbp_rpm(rpm_args)
+            if ret:
+                LOGGER.error('Git-buildpackage-rpm failed, unable to export '
+                             'RPM packaging files')
+                return 2
+        if args.deb == 'yes' or (args.deb== 'auto' and os.path.isdir('debian')):
+            LOGGER.info('Exporting Debian source package with GBP')
+            LOGGER.debug('git-buildpackage args: %s' % ' '.join(deb_args))
+            ret = gbp_deb(deb_args)
+            if ret:
+                LOGGER.error('Git-buildpackage failed, unable to export Debian '
+                             'sources package files')
+                return 3
     finally:
         os.chdir(orig_dir)
-    if ret:
-        LOGGER.error('Git-buildpackage-rpm failed, unable to export packaging '
-                 'files')
-        return 2
 
     return 0
index f056d2d..862d7a0 100644 (file)
@@ -6,6 +6,7 @@ Version:        0.1
 Release:        0
 URL:            http://www.tizen.org
 Source:         %{name}-%{version}.tar.bz2
+Requires:       git-buildpackage
 Requires:       git-buildpackage-rpm
 BuildRequires:  python
 BuildRequires:  python-setuptools
index 0911922..6652e71 100644 (file)
     <parameter name="spec-vcs-tag">
         <description>Set/update the VCS tag in the spec file</description>
     </parameter>
+    <parameter name="rpm">
+        <description>Build RPM package</description>
+        <allowedvalue>auto</allowedvalue>
+        <allowedvalue>yes</allowedvalue>
+        <allowedvalue>no</allowedvalue>
+    </parameter>
+    <parameter name="deb">
+        <description>Build Debian package</description>
+        <allowedvalue>auto</allowedvalue>
+        <allowedvalue>yes</allowedvalue>
+        <allowedvalue>no</allowedvalue>
+    </parameter>
     <parameter name="verbose">
         <description>Enable verbose output. For debugging purposes.</description>
         <allowedvalue>no</allowedvalue>
diff --git a/tests/data/debian/changelog b/tests/data/debian/changelog
new file mode 100644 (file)
index 0000000..c76dcb2
--- /dev/null
@@ -0,0 +1,5 @@
+test-package (0.1) unstable; urgency=low
+
+  * Initial version
+
+ -- Markus Lehtonen <marquiz@marquiz.fi.intel.com>  Mon, 22 Apr 2013 17:00:28 +0300
diff --git a/tests/data/debian/control b/tests/data/debian/control
new file mode 100644 (file)
index 0000000..4283ba8
--- /dev/null
@@ -0,0 +1,8 @@
+Source: test-package
+Maintainer: Markus Lehtonen <markus.lehtonen@linux.intel.com>
+Standards-Version: 3.9.3
+
+Package: test-package
+Architecture: all
+Description: Test package for the git-buildpackage OBS source service
+ Dummy package for testing the git-buildpackage OBS source service.
index 057c35e..1733cb5 100644 (file)
@@ -4,7 +4,7 @@ Version:    0.1
 Release:    0
 Group:      Development/Libraries
 License:    GPL-2.0
-Source:     %{name}-%{version}.tar.bz2
+Source:     %{name}_%{version}.tar.gz
 
 %description
 Dummy package for testing the git-buildpackage OBS source service.
index 8b1b19b..e092ec1 100644 (file)
@@ -38,13 +38,37 @@ class UnitTestsBase(object):
     @classmethod
     def create_orig_repo(cls, name):
         """Create test repo"""
-        orig_repo = GitRepository.create(os.path.join(cls.workdir, name))
-        orig_repo.commit_dir(TEST_DATA_DIR, 'Initial version', 'master',
-                             create_missing_branch=True)
-        orig_repo.force_head('master', hard=True)
-        # Make new commit
-        cls.update_repository_file(orig_repo, 'foo.txt', 'new data\n')
-        return orig_repo
+        repo_path = os.path.join(cls.workdir, name)
+        #shutil.copytree (TEST_DATA_DIR, orig_repo_path)
+        repo = GitRepository.create(repo_path)
+
+        # First, commit sources only and create branch 'sources'
+        sources = [src for src in os.listdir(TEST_DATA_DIR)
+                       if not src in ['packaging', 'debian']]
+        repo.add_files(sources, work_tree=TEST_DATA_DIR)
+        repo.commit_staged('Initial version')
+        # Make one new commit
+        cls.update_repository_file(repo, 'foo.txt', 'new data\n')
+        repo.create_branch('source')
+
+        # Create branch with rpm packaging only
+        repo.add_files('packaging', work_tree=TEST_DATA_DIR)
+        repo.commit_staged('Add rpm packaging files')
+        repo.create_branch('rpm')
+
+        # Master has both debian and rpm packaging
+        repo.add_files('debian', work_tree=TEST_DATA_DIR)
+        repo.commit_staged('Add debian packaging files')
+
+        # Create branch with deb packaging only
+        repo.create_branch('deb', 'source')
+        repo.set_branch('deb')
+        repo.add_files('debian', work_tree=TEST_DATA_DIR)
+        repo.commit_staged('Add deb packaging files')
+
+        repo.set_branch('master')
+        repo.force_head('master', hard=True)
+        return repo
 
     @classmethod
     def setup_class(cls):
@@ -105,9 +129,15 @@ class UnitTestsBase(object):
             shutil.rmtree(self.tmpdir)
 
 
-class TestBasicFunctionality(UnitTestsBase):
+class TestService(UnitTestsBase):
     """Base class for unit tests"""
 
+    def _check_files(self, files, directory=''):
+        """Check that the tmpdir content matches expectations"""
+        found = set(os.listdir(os.path.join(self.tmpdir, directory)))
+        expect = set(files)
+        assert found == expect, "Expected: %s, Found: %s" % (expect, found)
+
     def test_invalid_options(self):
         """Test invalid options"""
         # Non-existing option
@@ -119,24 +149,56 @@ class TestBasicFunctionality(UnitTestsBase):
         # Invalid repo
         assert service(['--url=foo/bar.git']) != 0
 
-    def test_basic_export(self):
-        """Test that export works"""
+    def test_basic_rpm_export(self):
+        """Test that rpm export works"""
+        assert service(['--url', self.orig_repo.path, '--revision=rpm']) == 0
+        self._check_files(['test-package.spec', 'test-package_0.1.tar.gz'])
+
+    def test_basic_deb_export(self):
+        """Test that deb export works"""
+        assert service(['--url', self.orig_repo.path, '--revision=deb']) == 0
+        self._check_files(['test-package_0.1.dsc', 'test-package_0.1.tar.gz'])
+
+    def test_empty_export(self):
+        """Test case where nothing is exported"""
+        assert service(['--url', self.orig_repo.path, '--revision=source']) == 0
+        self._check_files([])
+        assert service(['--url', self.orig_repo.path, '--rpm=no',
+                       '--deb=no']) == 0
+        self._check_files([])
+
+    def test_basic_dual_export(self):
+        """Test that simultaneous rpm and deb export works"""
         assert service(['--url', self.orig_repo.path]) == 0
+        self._check_files(['test-package.spec', 'test-package_0.1.dsc',
+                           'test-package_0.1.tar.gz'])
 
-    def test_gbp_failure(self):
-        """Test git-buildpackage failure"""
+    def test_gbp_rpm_failure(self):
+        """Test git-buildpackage-rpm failure"""
         assert service(['--url', self.orig_repo.path, '--outdir=foo/bar']) == 2
+        assert service(['--url', self.orig_repo.path, '--rpm=yes',
+                        '--revision=source']) == 2
+
+    def test_gbp_deb_failure(self):
+        """Test git-buildpackage (deb) failure"""
+        assert service(['--url', self.orig_repo.path, '--rpm=no',
+                        '--outdir=foo/bar']) == 3
+        assert service(['--url', self.orig_repo.path, '--deb=yes',
+                        '--revision=source']) == 3
 
     def test_options_outdir(self):
         """Test the --outdir option"""
         outdir = os.path.join(self.tmpdir, 'outdir')
         args = ['--url', self.orig_repo.path, '--outdir=%s' % outdir]
         assert service(args) == 0
-        assert os.path.isdir(outdir)
+        self._check_files(['test-package.spec', 'test-package_0.1.dsc',
+                           'test-package_0.1.tar.gz'], outdir)
 
     def test_options_revision(self):
         """Test the --revision option"""
         assert service(['--url', self.orig_repo.path, '--revision=master']) == 0
+        self._check_files(['test-package.spec', 'test-package_0.1.dsc',
+                           'test-package_0.1.tar.gz'])
         assert service(['--url', self.orig_repo.path, '--revision=foobar']) == 1
 
     def test_options_verbose(self):
@@ -316,7 +378,7 @@ class TestCachedRepo(UnitTestsBase):
         repo = self.MockCachedRepo(self.orig_repo.path)
         del repo
 
-        # Check repodir delete eror
+        # Check repodir delete error
         os.chmod(self.cachedir, stat.S_IREAD | stat.S_IEXEC)
         with assert_raises(CachedRepoError):
             # Change repo type -> tries to delete