Introduce git-buildpackage-rpm tool
authorMarkus Lehtonen <markus.lehtonen@linux.intel.com>
Thu, 12 Jan 2012 13:39:12 +0000 (15:39 +0200)
committerMarkus Lehtonen <markus.lehtonen@linux.intel.com>
Tue, 7 Jan 2014 14:21:28 +0000 (16:21 +0200)
Initial version of git-buildpackage-rpm: git-buildpackage tool for rpms.

Also adds some new options to config.py that are exclusively used in
this tool.

Signed-off-by: Markus Lehtonen <markus.lehtonen@linux.intel.com>
Signed-off-by: Ed Bartosh <eduard.bartosh@intel.com>
Signed-off-by: Zhang Qiang <qiang.z.zhang@intel.com>
bin/git-buildpackage-rpm [new file with mode: 0755]
gbp/config.py
gbp/scripts/buildpackage_rpm.py [new file with mode: 0755]
setup.py
tests/01_test_help.py

diff --git a/bin/git-buildpackage-rpm b/bin/git-buildpackage-rpm
new file mode 100755 (executable)
index 0000000..393f1ae
--- /dev/null
@@ -0,0 +1,5 @@
+#! /usr/bin/python -u
+import sys
+from gbp.scripts.buildpackage_rpm import main
+
+sys.exit(main(sys.argv))
index 4eb9f9c642743447c214cb8bcf969f544a0bb193..259b5318537cc92d033614bc8296c2e42b3f97a6 100644 (file)
@@ -97,7 +97,6 @@ class GbpOptionParser(OptionParser):
                  'snapshot-number' : 'snapshot + 1',
                  'git-log'         : '--no-merges',
                  'export'          : 'HEAD',
-                 'export-dir'      : '',
                  'overlay'         : 'False',
                  'tarball-dir'     : '',
                  'ignore-new'      : 'False',
@@ -525,6 +524,7 @@ class GbpOptionParserDebian(GbpOptionParser):
     defaults.update( {
                        'builder'            : 'debuild -i -I',
                        'cleaner'            : '/bin/true',
+                       'export-dir'         : '',
                      } )
 
 class GbpOptionParserRpm(GbpOptionParser):
@@ -533,12 +533,20 @@ class GbpOptionParserRpm(GbpOptionParser):
     """
     defaults = dict(GbpOptionParser.defaults)
     defaults.update( {
-                       'builder'                : '',
-                       'cleaner'                : '',
+                       'builder'                : 'rpmbuild',
+                       'cleaner'                : '/bin/true',
                        'packaging-dir'          : '',
                        'packaging-tag'          : 'packaging/%(version)s',
                        'pq-branch'              : 'development/%(branch)s',
                        'spec-file'              : 'auto',
+                       'export-dir'             : 'rpmbuild',
+                       'rpmbuild-builddir'      : 'BUILD',
+                       'rpmbuild-rpmdir'        : 'RPMS',
+                       'rpmbuild-sourcedir'     : 'SOURCES',
+                       'rpmbuild-specdir'       : 'SPECS',
+                       'rpmbuild-srpmdir'       : 'SRPMS',
+                       'rpmbuild-buildrootdir'  : 'BUILDROOT',
+                       'patch-export'           : 'False',
                      } )
 
     help = dict(GbpOptionParser.help)
@@ -551,6 +559,8 @@ class GbpOptionParserRpm(GbpOptionParser):
                         "format string for the patch-queue branch name, default is '%(pq-branch)s'",
                    'spec-file':
                         "Spec file to use, 'auto' makes gbp to guess, other values make the packaging-dir option to be ignored, default is '%(spec-file)s'",
+                   'patch-export':
+                        "Create patches between upstream and export-treeish, default is '%(patch-export)s'",
                  } )
 
 # vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·:
diff --git a/gbp/scripts/buildpackage_rpm.py b/gbp/scripts/buildpackage_rpm.py
new file mode 100755 (executable)
index 0000000..1394160
--- /dev/null
@@ -0,0 +1,516 @@
+# vim: set fileencoding=utf-8 :
+#
+# (C) 2006-2011 Guido Guenther <agx@sigxcpu.org>
+# (C) 2012 Intel Corporation <markus.lehtonen@linux.intel.com>
+#    This program is free software; you can redistribute it and/or modify
+#    it under the terms of the GNU General Public License as published by
+#    the Free Software Foundation; either version 2 of the License, or
+#    (at your option) any later version.
+#
+#    This program is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#    GNU General Public License for more details.
+#
+#    You should have received a copy of the GNU General Public License
+#    along with this program; if not, write to the Free Software
+#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+"""run commands to build an RPM package out of a git repository"""
+
+import ConfigParser
+import errno
+import os, os.path
+import sys
+import tempfile
+import shutil
+import re
+
+import gbp.rpm as rpm
+from gbp.rpm.policy import RpmPkgPolicy
+from gbp.command_wrappers import (Command,
+                                  RunAtCommand, CommandExecFailed,
+                                  RemoveTree)
+from gbp.config import (GbpOptionParserRpm, GbpOptionGroup)
+from gbp.rpm.git import (GitRepositoryError, RpmGitRepository)
+from gbp.errors import GbpError
+import gbp.log
+import gbp.notifications
+from gbp.scripts.common.buildpackage import (index_name, wc_names,
+                                             git_archive_submodules,
+                                             git_archive_single, dump_tree,
+                                             write_wc, drop_index)
+from gbp.pkg import (compressor_opts, compressor_aliases)
+from gbp.scripts.pq_rpm import update_patch_series
+
+
+def git_archive(repo, spec, output_dir, treeish, comp_level, with_submodules):
+    "create a compressed orig tarball in output_dir using git_archive"
+    comp_opts = ''
+    if spec.orig_comp:
+        comp_opts = compressor_opts[spec.orig_comp][0]
+
+    output = os.path.join(output_dir, os.path.basename(spec.orig_file))
+    prefix = spec.orig_base
+
+    try:
+        if repo.has_submodules() and with_submodules:
+            repo.update_submodules()
+            git_archive_submodules(repo, treeish, output, prefix,
+                                   spec.orig_comp, comp_level, comp_opts,
+                                   spec.orig_archive_fmt)
+
+        else:
+            git_archive_single(repo, treeish, output, prefix,
+                               spec.orig_comp, comp_level, comp_opts,
+                               spec.orig_archive_fmt)
+    except (GitRepositoryError, CommandExecFailed):
+        gbp.log.err("Error generating submodules' archives")
+        return False
+    except OSError, err:
+        gbp.log.err("Error creating %s: %s" % (output, err[0]))
+        return False
+    except GbpError:
+        raise
+    except Exception as e:
+        gbp.log.err("Error creating %s: %s" % (output, e))
+        return False
+    return True
+
+
+def prepare_upstream_tarball(repo, spec, options, output_dir):
+    """
+    Make sure we have an upstream tarball. This involves loooking in
+    tarball_dir, symlinking or building it.
+    """
+    # look in tarball_dir first, if found force a symlink to it
+    orig_file = os.path.basename(spec.orig_file)
+    if options.tarball_dir:
+        gbp.log.debug("Looking for orig tarball '%s' at '%s'" % (orig_file, options.tarball_dir))
+        if not RpmPkgPolicy.symlink_orig(orig_file, options.tarball_dir, output_dir, force=True):
+            gbp.log.info("Orig tarball '%s' not found at '%s'" % (orig_file, options.tarball_dir))
+        else:
+            gbp.log.info("Orig tarball '%s' found at '%s'" % (orig_file, options.tarball_dir))
+    # build an orig unless the user forbids it, always build (and overwrite pre-existing) if user forces it
+    if options.force_create or (not options.no_create_orig and not RpmPkgPolicy.has_orig(orig_file, output_dir)):
+        if not pristine_tar_build_orig(repo, orig_file, output_dir, options):
+            upstream_tree = git_archive_build_orig(repo, spec, output_dir, options)
+            if options.pristine_tar_commit:
+                if repo.pristine_tar.has_commit(orig_file):
+                    gbp.log.debug("%s already on pristine tar branch" %
+                                  orig_file)
+                else:
+                    archive = os.path.join(output_dir, orig_file)
+                    gbp.log.debug("Adding %s to pristine-tar branch" %
+                                  archive)
+                    repo.pristine_tar.commit(archive, upstream_tree)
+
+
+def makedir(dir):
+    output_dir = os.path.abspath(dir)
+
+    try:
+        os.mkdir(dir)
+    except OSError, (e, msg):
+        if e != errno.EEXIST:
+            raise GbpError, "Cannot create dir %s" % dir
+    return dir
+
+
+def prepare_export_dir(dir):
+    if not dir:
+        dir = 'rpmbuild'
+    return makedir(dir)
+
+
+def pristine_tar_build_orig(repo, orig_file, output_dir, options):
+    """
+    build orig using pristine-tar
+    @return: True: orig tarball build, False: noop
+    """
+    if options.pristine_tar:
+        if not repo.has_branch(repo.pristine_tar_branch):
+            gbp.log.warn('Pristine-tar branch "%s" not found' %
+                         repo.pristine_tar.branch)
+        try:
+            repo.pristine_tar.checkout(os.path.join(output_dir, orig_file))
+            return True
+        except CommandExecFailed:
+            if options.pristine_tar_commit:
+                gbp.log.debug("pristine-tar checkout failed, "
+                              "will commit tarball due to "
+                              "'--pristine-tar-commit'")
+            elif not options.force_create:
+                raise
+    return False
+
+def get_upstream_tree(repo, spec, options):
+    """Determine the upstream tree from the given options"""
+    if options.upstream_tree.upper() == 'TAG':
+        upstream_tree = repo.version_to_tag(options.upstream_tag, spec.version)
+    elif options.upstream_tree.upper() == 'BRANCH':
+        if not repo.has_branch(options.upstream_branch):
+            raise GbpError("%s is not a valid branch" % options.upstream_branch)
+        upstream_tree = options.upstream_branch
+    else:
+        upstream_tree = options.upstream_tree
+    if not repo.has_treeish(upstream_tree):
+        raise GbpError('Invalid upstream treeish %s' % upstream_tree)
+    return upstream_tree
+
+
+def git_archive_build_orig(repo, spec, output_dir, options):
+    """
+    Build orig tarball using git-archive
+
+    @param repo: our git repository
+    @type repo: L{RpmGitRepository}
+    @param spec: spec file of the package
+    @type spec: L{SpecFile}
+    @param output_dir: where to put the tarball
+    @type output_dir: C{Str}
+    @param options: the parsed options
+    @type options: C{dict} of options
+    @return: the tree we built the tarball from
+    @rtype: C{str}
+    """
+    upstream_tree = get_upstream_tree(repo, spec, options)
+    gbp.log.info("%s does not exist, creating from '%s'" % (spec.orig_file,
+                                                            upstream_tree))
+    if spec.orig_comp:
+        gbp.log.debug("Building upstream source archive with compression '%s -%s'" %
+                      (spec.orig_comp, options.comp_level))
+    if not git_archive(repo, spec, output_dir, upstream_tree,
+                       options.comp_level,
+                       options.with_submodules):
+        raise GbpError("Cannot create upstream tarball at '%s'" % output_dir)
+    return upstream_tree
+
+
+def export_patches(repo, spec, export_treeish, options):
+    """
+    Generate patches and update spec file
+    """
+    upstream_tree = get_upstream_tree(repo, spec, options)
+    update_patch_series(repo, spec, upstream_tree, export_treeish, options)
+
+
+def is_native(repo, options):
+    if repo.has_branch(options.upstream_branch):
+        return False
+    return True
+
+
+def setup_builder(options, builder_args):
+    """setup everything to use git-pbuilder"""
+    if options.builder.startswith('rpmbuild'):
+        if len(builder_args) == 0:
+            builder_args.append('-ba')
+        builder_args.extend(['--define "_topdir %s"' % os.path.abspath(options.export_dir),
+                             '--define "_builddir %%_topdir/%s"' % options.build_dir,
+                             '--define "_rpmdir %%_topdir/%s"' % options.rpm_dir,
+                             '--define "_sourcedir %%_topdir/%s"' % options.source_dir,
+                             '--define "_specdir %%_topdir/%s"' % options.spec_dir,
+                             '--define "_srcrpmdir %%_topdir/%s"' % options.srpm_dir,
+                             '--define "_buildrootdir %%_topdir/%s"' % options.buildroot_dir])
+    elif options.builder.startswith('osc'):
+        builder_args.insert(0, 'build')
+        options.source_dir = ''
+        options.spec_dir = ''
+
+
+def parse_args(argv, prefix):
+    args = [ arg for arg in argv[1:] if arg.find('--%s' % prefix) == 0 ]
+    builder_args = [ arg for arg in argv[1:] if arg.find('--%s' % prefix) == -1 ]
+
+    # We handle these although they don't have a --git- prefix
+    for arg in [ "--help", "-h", "--version" ]:
+        if arg in builder_args:
+            args.append(arg)
+
+    try:
+        parser = GbpOptionParserRpm(command=os.path.basename(argv[0]), prefix=prefix)
+    except ConfigParser.ParsingError, err:
+        gbp.log.err(err)
+        return None, None, None
+
+    tag_group = GbpOptionGroup(parser, "tag options", "options related to git tag creation")
+    branch_group = GbpOptionGroup(parser, "branch options", "branch layout options")
+    cmd_group = GbpOptionGroup(parser, "external command options", "how and when to invoke external commands and hooks")
+    orig_group = GbpOptionGroup(parser, "orig tarball options", "options related to the creation of the orig tarball")
+    export_group = GbpOptionGroup(parser, "export build-tree options", "alternative build tree related options")
+    parser.add_option_group(tag_group)
+    parser.add_option_group(orig_group)
+    parser.add_option_group(branch_group)
+    parser.add_option_group(cmd_group)
+    parser.add_option_group(export_group)
+
+    parser.add_boolean_config_file_option(option_name = "ignore-new", dest="ignore_new")
+    parser.add_option("--git-verbose", action="store_true", dest="verbose", default=False,
+                      help="verbose command execution")
+    parser.add_config_file_option(option_name="color", dest="color", type='tristate')
+    parser.add_config_file_option(option_name="notify", dest="notify", type='tristate')
+    tag_group.add_option("--git-tag", action="store_true", dest="tag", default=False,
+                      help="create a tag after a successful build")
+    tag_group.add_option("--git-tag-only", action="store_true", dest="tag_only", default=False,
+                      help="don't build, only tag and run the posttag hook")
+    tag_group.add_option("--git-retag", action="store_true", dest="retag", default=False,
+                      help="don't fail if the tag already exists")
+    tag_group.add_boolean_config_file_option(option_name="sign-tags", dest="sign_tags")
+    tag_group.add_config_file_option(option_name="keyid", dest="keyid")
+    tag_group.add_config_file_option(option_name="packaging-tag", dest="packaging_tag")
+    tag_group.add_config_file_option(option_name="upstream-tag", dest="upstream_tag")
+    orig_group.add_config_file_option(option_name="upstream-tree", dest="upstream_tree")
+    orig_group.add_boolean_config_file_option(option_name="pristine-tar", dest="pristine_tar")
+    orig_group.add_boolean_config_file_option(option_name="pristine-tar-commit",
+                                              dest="pristine_tar_commit")
+    orig_group.add_config_file_option(option_name="force-create", dest="force_create",
+                      help="force creation of upstream source tarball", action="store_true")
+    orig_group.add_config_file_option(option_name="no-create-orig", dest="no_create_orig",
+                      help="don't create upstream source tarball", action="store_true")
+    orig_group.add_config_file_option(option_name="tarball-dir", dest="tarball_dir", type="path",
+                      help="location to look for external tarballs")
+    orig_group.add_config_file_option(option_name="compression-level", dest="comp_level",
+                      help="Compression level, default is '%(compression-level)s'")
+    branch_group.add_config_file_option(option_name="upstream-branch", dest="upstream_branch")
+    branch_group.add_config_file_option(option_name="packaging-branch", dest="packaging_branch")
+    branch_group.add_boolean_config_file_option(option_name = "ignore-branch", dest="ignore_branch")
+    branch_group.add_boolean_config_file_option(option_name = "submodules", dest="with_submodules")
+    cmd_group.add_config_file_option(option_name="builder", dest="builder",
+                      help="command to build the package, default is '%(builder)s'")
+    cmd_group.add_config_file_option(option_name="cleaner", dest="cleaner",
+                      help="command to clean the working copy, default is '%(cleaner)s'")
+    cmd_group.add_config_file_option(option_name="prebuild", dest="prebuild",
+                      help="command to run before a build, default is '%(prebuild)s'")
+    cmd_group.add_config_file_option(option_name="postexport", dest="postexport",
+                      help="command to run after exporting the source tree, default is '%(postexport)s'")
+    cmd_group.add_config_file_option(option_name="postbuild", dest="postbuild",
+                      help="hook run after a successful build, default is '%(postbuild)s'")
+    cmd_group.add_config_file_option(option_name="posttag", dest="posttag",
+                      help="hook run after a successful tag operation, default is '%(posttag)s'")
+    export_group.add_config_file_option(option_name="export-dir", dest="export_dir", type="path",
+                      help="Build topdir, also export the sources under EXPORT_DIR, default is '%(export-dir)s'")
+    export_group.add_config_file_option(option_name="rpmbuild-builddir", dest="build_dir", type="path",
+                      help="subdir where package is built (under EXPORT_DIR), i.e. rpmbuild builddir, default is '%(rpmbuild-builddir)s'")
+    export_group.add_config_file_option(option_name="rpmbuild-rpmdir", dest="rpm_dir", type="path",
+                      help="subdir where ready binary packages are stored (under EXPORT_DIR), i.e. rpmbuild builddir, default is '%(rpmbuild-rpmdir)s'")
+    export_group.add_config_file_option(option_name="rpmbuild-sourcedir", dest="source_dir", type="path",
+                      help="subdir where package sources are stored (under EXPORT_DIR), i.e. rpmbuild sourcedir, default is '%(rpmbuild-sourcedir)s'")
+    export_group.add_config_file_option(option_name="rpmbuild-specdir", dest="spec_dir", type="path",
+                      help="subdir where package spec file is stored (under EXPORT_DIR), i.e. rpmbuild specdir, default is '%(rpmbuild-specdir)s'")
+    export_group.add_config_file_option(option_name="rpmbuild-srpmdir", dest="srpm_dir", type="path",
+                      help="subdir where ready sources package is stored (under EXPORT_DIR), i.e. rpmbuild srpmdir, default is '%(rpmbuild-srpmdir)s'")
+    export_group.add_config_file_option(option_name="rpmbuild-buildrootdir", dest="buildroot_dir", type="path",
+                      help="subdir for build-time alternative root (under EXPORT_DIR), i.e. rpmbuild buildrootdir, default is '%(rpmbuild-buildrootdir)s'")
+    export_group.add_config_file_option("export", dest="export",
+                      help="export treeish object TREEISH, default is '%(export)s'", metavar="TREEISH")
+    export_group.add_option("--git-purge", action="store_true", dest="purge", default=False,
+                      help="purge exported package build directory")
+    export_group.add_config_file_option(option_name="packaging-dir",
+                      dest="packaging_dir")
+    export_group.add_config_file_option(option_name="spec-file", dest="spec_file")
+    export_group.add_option("--git-export-only", action="store_true", dest="export_only", default=False,
+                      help="only export packaging files, don't build")
+    export_group.add_boolean_config_file_option("patch-export", dest="patch_export")
+    export_group.add_boolean_config_file_option(option_name="patch-numbers", dest="patch_numbers")
+    options, args = parser.parse_args(args)
+
+    gbp.log.setup(options.color, options.verbose)
+    if options.retag:
+        if not options.tag and not options.tag_only:
+            gbp.log.err("'--%sretag' needs either '--%stag' or '--%stag-only'" % (prefix, prefix, prefix))
+            return None, None, None
+
+    return options, args, builder_args
+
+
+def main(argv):
+    retval = 0
+    prefix = "git-"
+    cp = None
+    dump_dir = None
+
+    options, gbp_args, builder_args = parse_args(argv, prefix)
+    if not options:
+        return 1
+
+    try:
+        repo = RpmGitRepository(os.path.curdir)
+    except GitRepositoryError:
+        gbp.log.err("%s is not a git repository" % (os.path.abspath('.')))
+        return 1
+    else:
+        repo_dir = os.path.abspath(os.path.curdir)
+
+    try:
+        branch = repo.get_branch()
+    except GitRepositoryError:
+        branch = None
+
+    try:
+        if not options.export_only:
+            Command(options.cleaner, shell=True)()
+        if not options.ignore_new:
+            (ret, out) = repo.is_clean()
+            if not ret:
+                gbp.log.err("You have uncommitted changes in your source tree:")
+                gbp.log.err(out)
+                raise GbpError, "Use --git-ignore-new to ignore."
+
+        if not options.ignore_new and not options.ignore_branch:
+            if branch != options.packaging_branch:
+                gbp.log.err("You are not on branch '%s' but on '%s'" % (options.packaging_branch, branch))
+                raise GbpError, "Use --git-ignore-branch to ignore or --git-packaging-branch to set the branch name."
+
+        # Determine tree-ish to be exported
+        if options.export == index_name:
+            # Write a tree of the index
+            tree = repo.write_tree()
+        elif options.export in wc_names:
+            # Write a tree of the working copy
+            tree = write_wc(repo,
+                            force=wc_names[options.export]['force'],
+                            untracked=wc_names[options.export]['untracked'])
+        else:
+            tree = options.export
+        if not repo.has_treeish(tree):
+            raise GbpError('Invalid treeish object %s' % tree)
+
+        # Dump from git to a temporary directory:
+        dump_dir = tempfile.mkdtemp(dir=".")
+        gbp.log.debug("Dumping tree '%s' to '%s'" % (options.export, dump_dir))
+        if not dump_tree(repo, dump_dir, tree, options.with_submodules):
+            raise GbpError
+        # Find and parse spec from dump dir to get version etc.
+        if options.spec_file != 'auto':
+            specfile = os.path.join(dump_dir, options.spec_file)
+            options.packaging_dir = os.path.dirname(specfile)
+            if not os.path.exists(specfile):
+                raise rpm.NoSpecError("Failed to export specfile: %s" % options.spec_file)
+        else:
+            specfile = rpm.guess_spec(os.path.join(dump_dir, options.packaging_dir),
+                                      True,
+                                      os.path.basename(repo.path) + '.spec')
+        spec = rpm.SpecFile(specfile)
+        gbp.log.debug("Using spec file '%s'" % specfile)
+
+        if not options.tag_only:
+            # Setup builder opts
+            setup_builder(options, builder_args)
+
+            # Generate patches, if requested
+            if options.patch_export and not is_native(repo, options):
+                export_patches(repo, spec, tree, options)
+
+            # Prepare final export dirs
+            export_dir = prepare_export_dir(options.export_dir)
+            source_dir = makedir(os.path.join(export_dir, options.source_dir))
+            spec_dir = makedir(os.path.join(export_dir, options.spec_dir))
+
+            # Move packaging files
+            gbp.log.debug("Exporting packaging files in '%s' to '%s'" % (spec.specdir, export_dir))
+            pkgfiles = os.listdir(spec.specdir)
+            for f in pkgfiles:
+                src = os.path.join(spec.specdir, f)
+                if f == os.path.basename(spec.specfile):
+                    dst = os.path.join(spec_dir, f)
+                    spec.specfile = os.path.abspath(dst)
+                else:
+                    dst = os.path.join(source_dir, f)
+                try:
+                    if os.path.isdir(src):
+                        # dir is not packaging files, skip it
+                        continue
+                    else:
+                        shutil.copy2(src, dst)
+                except IOError, err:
+                    raise GbpError, "Error exporting files: %s" % err
+            spec.specdir = spec_dir
+
+            # Get/build the orig tarball
+            if is_native(repo, options):
+                if spec.orig_file:
+                    # Just build source archive from the exported tree
+                    gbp.log.info("Creating (native) source archive %s from '%s'" % (spec.orig_file, tree))
+                    if spec.orig_comp:
+                        gbp.log.debug("Building source archive with compression '%s -%s'" % (spec.orig_comp, options.comp_level))
+                    if not git_archive(repo, spec, source_dir, tree,
+                                       options.comp_level, options.with_submodules):
+                        raise GbpError, "Cannot create source tarball at '%s'" % export_dir
+            # Non-native packages: create orig tarball from upstream
+            elif spec.orig_file:
+                 prepare_upstream_tarball(repo, spec, options, source_dir)
+
+            # Run postexport hook
+            if options.postexport:
+                RunAtCommand(options.postexport, shell=True,
+                             extra_env={'GBP_GIT_DIR': repo.git_dir,
+                                        'GBP_TMP_DIR': export_dir})(dir=export_dir)
+            # Do actual build
+            if not options.export_only and not options.tag_only:
+                if options.prebuild:
+                    RunAtCommand(options.prebuild, shell=True,
+                                 extra_env={'GBP_GIT_DIR': repo.git_dir(),
+                                            'GBP_BUILD_DIR': export_dir})(dir=export_dir)
+
+                # Finally build the package:
+                if options.builder.startswith("rpmbuild"):
+                    builder_args.extend([spec.specfile])
+                else:
+                    builder_args.extend([os.path.basename(spec.specfile)])
+                RunAtCommand(options.builder, builder_args, shell=True,
+                             extra_env={'GBP_BUILD_DIR': export_dir})(dir=export_dir)
+                if options.postbuild:
+                    changes = os.path.abspath("%s/%s.changes" % (source_dir, spec.name))
+                    gbp.log.debug("Looking for changes file %s" % changes)
+                    Command(options.postbuild, shell=True,
+                            extra_env={'GBP_CHANGES_FILE': changes,
+                                       'GBP_BUILD_DIR': export_dir})()
+
+        # Tag (note: tags the exported version)
+        if options.tag or options.tag_only:
+            gbp.log.info("Tagging %s" % spec.version)
+            tag = repo.version_to_tag(options.packaging_tag, spec.version)
+            if options.retag and repo.has_tag(tag):
+                repo.delete_tag(tag)
+            repo.create_tag(name=tag, msg="Distribution release %s" % spec.version,
+                            sign=options.sign_tags, keyid=options.keyid, commit=tree)
+            if options.posttag:
+                sha = repo.rev_parse("%s^{}" % tag)
+                Command(options.posttag, shell=True,
+                        extra_env={'GBP_TAG': tag,
+                                   'GBP_BRANCH': branch,
+                                   'GBP_SHA1': sha})()
+    except CommandExecFailed:
+        retval = 1
+    except GitRepositoryError as err:
+        gbp.log.err("Git command failed: %s" % err)
+        ret = 1
+    except GbpError, err:
+        if len(err.__str__()):
+            gbp.log.err(err)
+        retval = 1
+    except rpm.NoSpecError, err:
+        gbp.log.err(err)
+        retval = 1
+    finally:
+        drop_index(repo)
+
+    # Clean temporary dumpdir
+    if dump_dir and retval == 0:
+        shutil.rmtree(dump_dir)
+
+    if not options.tag_only:
+        if options.purge and not retval and not options.export_only:
+            RemoveTree(export_dir)()
+
+        if cp and not gbp.notifications.notify(cp, not retval, options.notify):
+            gbp.log.err("Failed to send notification")
+            retval = 1
+
+    return retval
+
+if __name__ == '__main__':
+    sys.exit(main(sys.argv))
+
+# vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·:
index 3902575d9885c2530cdd30bd70216589467d5a54..2aabf60cbb6bcb7fac0e7dc63e877f00e9403f2e 100644 (file)
--- a/setup.py
+++ b/setup.py
@@ -57,7 +57,8 @@ setup(name = "gbp",
                   'bin/gbp-create-remote-repo',
                   'bin/git-pbuilder',
                   'bin/git-import-srpm',
-                  'bin/gbp-pq-rpm'],
+                  'bin/gbp-pq-rpm',
+                  'bin/git-buildpackage-rpm'],
       packages = find_packages(exclude=['tests', 'tests.*']),
       data_files = [("/etc/git-buildpackage/", ["gbp.conf"]),],
       setup_requires=['nose>=0.11.1', 'coverage>=2.85', 'nosexcover>=1.0.7'] if \
index e8b62646abf12df0dc77a471b5759ea7059f8ed8..13b2c50789f9e863ba0be6ead48a7002d83d1ebb 100644 (file)
@@ -27,7 +27,8 @@ class TestHelp(unittest.TestCase):
     """Test help output of RPM-specific commands"""
     def testHelpRpm(self):
         for script in ['import_srpm',
-                       'pq_rpm']:
+                       'pq_rpm',
+                       'buildpackage_rpm']:
             module = 'gbp.scripts.%s' % script
             m = __import__(module, globals(), locals(), ['main'], -1)
             self.assertRaises(SystemExit,