aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGuido Günther <agx@sigxcpu.org>2015-07-01 21:44:27 +0200
committerGuido Günther <agx@sigxcpu.org>2015-08-19 17:32:59 +0200
commit422ae854873adf2f5309ee79996cd96dcbabfaca (patch)
tree066bd59e546c4cb8d07a9e30aa85a22fed12212d
parent7ce69de2d7faacce58c1d01168a29d77aee6b5c5 (diff)
Add gbp buildpackage-rpm
This adds a minimal gbp buildpackage-rpm based on Markus Lehtonens work.
-rw-r--r--debian/git-buildpackage-rpm.install1
-rw-r--r--docs/Makefile1
-rw-r--r--docs/common.ent12
-rw-r--r--docs/man.gbp-buildpackage-rpm.sgml12
-rw-r--r--docs/manpages/gbp-buildpackage-rpm.sgml544
-rw-r--r--docs/manpages/manpages.ent1
-rw-r--r--gbp/config.py20
-rw-r--r--gbp/scripts/buildpackage_rpm.py631
-rw-r--r--gbp/tmpfile.py4
-rw-r--r--packaging/git-buildpackage.spec1
m---------tests/component/rpm/data0
-rw-r--r--tests/component/rpm/test_buildpackage_rpm.py138
12 files changed, 1361 insertions, 4 deletions
diff --git a/debian/git-buildpackage-rpm.install b/debian/git-buildpackage-rpm.install
index 2568b4c9..5178cb37 100644
--- a/debian/git-buildpackage-rpm.install
+++ b/debian/git-buildpackage-rpm.install
@@ -1,3 +1,4 @@
usr/lib/python2.?/dist-packages/gbp/rpm/
usr/lib/python2.7/dist-packages/gbp/scripts/import_srpm.py
usr/lib/python2.7/dist-packages/gbp/scripts/pq_rpm.py
+usr/lib/python2.7/dist-packages/gbp/scripts/buildpackage_rpm.py
diff --git a/docs/Makefile b/docs/Makefile
index 91c3b0ad..055028bd 100644
--- a/docs/Makefile
+++ b/docs/Makefile
@@ -12,6 +12,7 @@ MAN1S = \
gbp-import-orig \
gbp-pq \
gbp-pull \
+ gbp-buildpackage-rpm \
$(NULL)
MAN5S = gbp.conf
diff --git a/docs/common.ent b/docs/common.ent
index 005d6746..51752d90 100644
--- a/docs/common.ent
+++ b/docs/common.ent
@@ -4,6 +4,7 @@
<!ENTITY dhconfsection "<manvolnum>5</manvolnum>">
<!ENTITY dhemail "<email>agx@sigxcpu.org</email>">
<!ENTITY dhusername "Guido Guenther">
+
<!ENTITY gbp-buildpackage "<command>gbp buildpackage</command>">
<!ENTITY gbp-import-orig "<command>gbp import-orig</command>">
<!ENTITY gbp-import-dsc "<command>gbp import-dsc</command>">
@@ -24,6 +25,17 @@
<!ENTITY debuildcmd "<command>debuild</command>">
<!ENTITY gbp.conf "<filename>gbp.conf</filename>">
+ <!ENTITY rpm-firstname "<firstname>Markus</firstname>">
+ <!ENTITY rpm-surname "<surname>Lehtonen</surname>">
+ <!ENTITY rpm-email "<email>markus.lehtonen@linux.intel.com</email>">
+ <!ENTITY rpm-username "Markus Lehtonen">
+ <!ENTITY rpm-mansection "<manvolnum>1</manvolnum>">
+ <!ENTITY gbp-buildpackage-rpm "<command>gbp buildpackage-rpm</command>">
+ <!ENTITY gbp-import-srpm "<command>gbp import-srpm</command>">
+ <!ENTITY gbp-pq-rpm "<command>gbp pq-rpm</command>">
+ <!ENTITY rpmbuild "<command>rpmbuild</command>">
+ <!ENTITY wget "<command>wget</command>">
+
<!ENTITY debian "<productname>Debian</productname>">
<!ENTITY git "<productname>Git</productname>">
<!ENTITY dch "<productname>dch</productname>">
diff --git a/docs/man.gbp-buildpackage-rpm.sgml b/docs/man.gbp-buildpackage-rpm.sgml
new file mode 100644
index 00000000..8e7bac73
--- /dev/null
+++ b/docs/man.gbp-buildpackage-rpm.sgml
@@ -0,0 +1,12 @@
+<!DOCTYPE reference PUBLIC "-//OASIS//DTD DocBook V4.1//EN"
+[
+ <!ENTITY % COMMON SYSTEM "common.ent">
+ %COMMON;
+ <!ENTITY % MANPAGES SYSTEM "manpages/manpages.ent">
+ %MANPAGES;
+]>
+
+<reference>
+<title>git-buildpackage Manual</title>
+&man.gbp.buildpackage.rpm;
+</reference>
diff --git a/docs/manpages/gbp-buildpackage-rpm.sgml b/docs/manpages/gbp-buildpackage-rpm.sgml
new file mode 100644
index 00000000..4b75113f
--- /dev/null
+++ b/docs/manpages/gbp-buildpackage-rpm.sgml
@@ -0,0 +1,544 @@
+<refentry id="man.gbp.buildpackage.rpm">
+ <refentryinfo>
+ <address>
+ &rpm-email;
+ </address>
+ <author>
+ &rpm-firstname;
+ &rpm-surname;
+ </author>
+ </refentryinfo>
+ <refmeta><refentrytitle>gbp-buildpackage-rpm</refentrytitle>
+ &dhsection;
+ </refmeta>
+ <refnamediv>
+ <refname>gbp-buildpackage-rpm</refname>
+ <refpurpose>Build RPM packages from a Git repository</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ &gbp-buildpackage-rpm;
+ <arg><option>--git-[no-]ignore-new</option></arg>
+ <arg><option>--git-tag</option></arg>
+ <arg><option>--git-verbose</option></arg>
+ <arg><option>--git-color=</option><replaceable>[auto|on|off]</replaceable></arg>
+ <arg><option>--git-color-scheme=</option><replaceable>COLOR_SCHEME</replaceable></arg>
+ <arg><option>--git-notify=</option><replaceable>[auto|on|off]</replaceable></arg>
+ <arg><option>--git-tmp-dir</option>=<replaceable>DIRECTORY</replaceable></arg>
+ <arg><option>--git-upstream-branch=</option><replaceable>TREEISH</replaceable></arg>
+ <arg><option>--git-packaging-branch=</option><replaceable>BRANCH_NAME</replaceable></arg>
+ <arg><option>--git-ignore-branch</option></arg>
+ <arg><option>--git-[no-]submodules</option></arg>
+ <arg><option>--git-builder=</option><replaceable>BUILD_CMD</replaceable></arg>
+ <arg><option>--git-cleaner=</option><replaceable>CLEAN_CMD</replaceable></arg>
+ <arg><option>--git-[no-]sign-tags</option></arg>
+ <arg><option>--git-keyid=</option><replaceable>GPG-KEYID</replaceable></arg>
+ <arg><option>--git-posttag=</option><replaceable>COMMAND</replaceable></arg>
+ <arg><option>--git-postbuild=</option><replaceable>COMMAND</replaceable></arg>
+ <arg><option>--git-postexport=</option><replaceable>COMMAND</replaceable></arg>
+ <arg><option>--git-prebuild=</option><replaceable>COMMAND</replaceable></arg>
+ <arg><option>--git-[no-]build</option></arg>
+ <arg><option>--git-[no-]hooks</option></arg>
+ <arg><option>--git-packaging-tag=</option><replaceable>TAG-FORMAT</replaceable></arg>
+ <arg><option>--git-upstream-tag=</option><replaceable>TAG-FORMAT</replaceable></arg>
+ <arg><option>--git-force-create</option></arg>
+ <arg><option>--git-no-create-orig</option></arg>
+ <arg><option>--git-upstream-tree=</option><replaceable>[TAG|BRANCH|TREEISH]</replaceable></arg>
+ <arg><option>--git-tarball-dir=</option><replaceable>DIRECTORY</replaceable></arg>
+ <arg><option>--git-compression-level=</option><replaceable>LEVEL</replaceable></arg>
+ <arg><option>--git-export-dir=</option><replaceable>DIRECTORY</replaceable></arg>
+ <arg><option>--git-export=</option><replaceable>TREEISH</replaceable></arg>
+ <arg><option>--git-export-only</option></arg>
+ <arg><option>--git-packaging-dir=</option><replaceable>DIRECTORY</replaceable></arg>
+ <arg><option>--git-[no-]pristine-tar</option></arg>
+ <arg><option>--git-[no-]pristine-tar-commit</option></arg>
+ <arg><option>--git-tag-only</option></arg>
+ <arg><option>--git-retag</option></arg>
+ <arg><option>--git-[no-]patch-export</option></arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+ <refsect1>
+ <title>DESCRIPTION</title>
+ <para>
+ &gbp-buildpackage-rpm; is used to build RPM packages from a &git;
+ repository. It is an RPM counterpart for the &gbp-buildpackage; tool that
+ is designed for building Debian packages.
+ </para>
+ <para>
+ &gbp-buildpackage-rpm; will, in order:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ Verify that it is being executed from the proper location.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Verify that the repository doesn't contain any uncommitted source
+ changes.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Verify that it is being executed from the correct branch.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Export packaging files to a separate build area.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Create an orig source tarball if it doesn't exist.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Call <application>rpmbuild</application>(1) (or the application
+ specified via <option>--git-builder</option>), passing along all
+ command line arguments that don't start with --git-.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ (Optionally) tag the tree after a successful build.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ (Optionally) call a post build hook - e.g. to run
+ <productname>rpmlint</productname>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ (Optionally) call a post tag hook - e.g. to push the results to a
+ remote repository after creating the tag.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </refsect1>
+ <refsect1>
+ <title>OPTIONS</title>
+ <variablelist>
+ <varlistentry>
+ <term><option>--git-[no-]ignore-new</option>
+ </term>
+ <listitem>
+ <para>
+ Don't abort if there are uncommitted changes in the source tree or
+ the current branch doesn't match the
+ <replaceable>PACKAGING-BRANCH</replaceable>.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--git-tag</option>
+ </term>
+ <listitem>
+ <para>
+ Add a git tag after a successful build.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--git-builder=<replaceable>BUILD_CMD</replaceable></option>
+ </term>
+ <listitem>
+ <para>
+ Use <replaceable>BUILD_CMD</replaceable> instead of
+ <command>rpmbuild -ba</command>.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--git-cleaner=<replaceable>CLEAN_CMD</replaceable></option>
+ </term>
+ <listitem>
+ <para>
+ Use <replaceable>CLEAN_CMD</replaceable>.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--git-verbose</option>
+ </term>
+ <listitem>
+ <para>
+ Verbose execution
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--git-color=</option><replaceable>[auto|on|off]</replaceable>
+ </term>
+ <listitem>
+ <para>
+ Whether to use colored output.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--git-color-scheme=</option><replaceable>COLOR_SCHEME</replaceable>
+ </term>
+ <listitem>
+ <para>
+ Colors to use in output (when color is enabled). The format for
+ COLOR_SCHEME is
+ '&lt;debug&gt;:&lt;info&gt;:&lt;warning&gt;:&lt;error&gt;'.
+ Numerical values and color names are accepted, empty fields imply
+ the default color. For example --git-color-scheme='cyan:34::' would
+ show debug messages in cyan, info messages in blue and other messages
+ in default (i.e. warning and error messages in red).
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--git-notify=</option><replaceable>[auto|on|off]</replaceable>
+ </term>
+ <listitem>
+ <para>
+ Whether to send a desktop notification after the build.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--git-upstream-branch</option>=<replaceable>BRANCH_NAME</replaceable>
+ </term>
+ <listitem>
+ <para>
+ Branch to build the orig tarball from if
+ <option>--git-upstream-tree</option> is set to
+ <replaceable>BRANCH</replaceable>. Default is
+ <replaceable>upstream</replaceable>.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--git-packaging-branch</option>=<replaceable>BRANCH_NAME</replaceable>
+ </term>
+ <listitem>
+ <para>
+ If you're not on this branch when invoking &gbp-buildpackage-rpm; it
+ will fail. Default is <replaceable>master</replaceable>. This is done
+ to make sure you don't accidentally release from a topic branch. Not
+ being on this branch will be ignored when using
+ <option>--git-ignore-new</option>.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--git-ignore-branch</option>
+ </term>
+ <listitem>
+ <para>
+ Don't check if the current branch matches
+ <replaceable>PACKAGING-BRANCH</replaceable>.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--git-[no-]submodules</option>
+ </term>
+ <listitem>
+ <para>
+ Include git submodules in the orig tarball.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--git-[no-]sign-tags</option>
+ </term>
+ <listitem>
+ <para>
+ GPG sign all created tags.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--git-keyid=</option><replaceable>GPG-KEYID</replaceable>
+ </term>
+ <listitem>
+ <para>
+ Use this keyid for gpg signing tags.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--git-posttag=</option><replaceable>COMMAND</replaceable>
+ </term>
+ <listitem>
+ <para>
+ Excecute <replaceable>COMMAND</replaceable> after tagging a new
+ version.
+ </para>
+ <para>
+ Exported environment variables are: <envar>GBP_TAG</envar> (the name
+ of the generated tag), <envar>GBP_BRANCH</envar> (the branch the
+ package was build from) and <envar>GBP_SHA1</envar> (the sha1 of the
+ commit the tag was created at).
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--git-postbuild=</option><replaceable>COMMAND</replaceable>
+ </term>
+ <listitem>
+ <para>
+ Execute <replaceable>COMMAND</replaceable> after successful
+ build.
+ </para>
+ <para>
+ Exported environment variables are: <envar>GBP_CHANGES_FILE</envar>
+ (the name of the generated changes file),
+ <envar>GBP_BUILD_DIR</envar> (the build dir).
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--git-postexport=</option><replaceable>COMMAND</replaceable>
+ </term>
+ <listitem>
+ <para>
+ Execute <replaceable>COMMAND</replaceable> after exporting the source
+ tree.
+ </para>
+ <para>
+ Exported environment variables are: <envar>GBP_GIT_DIR</envar> (the
+ repository the package is being built from),
+ <envar>GBP_TMP_DIR</envar> (the temporary directory where the sources
+ have been initially exported).
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--git-prebuild=</option><replaceable>COMMAND</replaceable>
+ </term>
+ <listitem>
+ <para>
+ Execute <replaceable>COMMAND</replaceable> from the build directory
+ before calling <application>rpmbuild</application> or the application
+ specified via <option>--git-builder</option>.
+ </para>
+ <para>
+ Exported environment variables are: <envar>GBP_GIT_DIR</envar> (the
+ repository the package is being built from),
+ <envar>GBP_BUILD_DIR</envar> (the build dir).
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--git-[no-]build</option>
+ </term>
+ <listitem>
+ <para>
+ Enable builder. Note: <option>--git-no-build</option> causes the
+ postbuild hook to be disabled, too.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--git-[no-]hooks</option>
+ </term>
+ <listitem>
+ <para>
+ Enable running all (cleaner, postexport, prebuild, postbuild, and
+ posttag) hooks. Note: the <option>--git-builder</option> command is
+ not affected by this option.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--git-packaging-tag=</option><replaceable>TAG-FORMAT</replaceable>
+ </term>
+ <listitem>
+ <para>
+ Use this tag format when tagging released versions of the package.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--git-upstream-tag=</option><replaceable>TAG-FORMAT</replaceable>
+ </term>
+ <listitem>
+ <para>
+ Use this tag format when looking for tags of upstream versions,
+ default is <replaceable>upstream/%(version)s</replaceable>.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--git-force-create</option>
+ </term>
+ <listitem>
+ <para>
+ Force creation of an orig tarball (overwriting a pre-existing one if
+ present).
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--git-no-create-orig</option>
+ </term>
+ <listitem>
+ <para>
+ Don't try to create any orig tarball.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--git-export-dir=</option><replaceable>DIRECTORY</replaceable>
+ </term>
+ <listitem>
+ <para>
+ Export the packaging files from the current branch head (or the
+ treeish object given via <option>--git-export</option> to
+ <replaceable>DIRECTORY</replaceable> before building.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--git-export=</option><replaceable>TREEISH</replaceable>
+ </term>
+ <listitem>
+ <para>
+ Instead of exporting the current branch head, export the treeish
+ object <replaceable>TREEISH</replaceable>. The special name
+ <replaceable>INDEX</replaceable> exports the current index,
+ <replaceable>WC</replaceable>) exports all files in the
+ current working directory.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--git-packaging-dir=</option><replaceable>DIRECTORY</replaceable>
+ </term>
+ <listitem>
+ <para>
+ Subdirectory that contains the RPM packaging files.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--git-upstream-tree=</option><replaceable>[TAG|BRANCH|TREEISH]</replaceable>
+ </term>
+ <listitem>
+ <para>
+ How to find the upstream sources used to generate the tarball.
+ <replaceable>TAG</replaceable> looks at a tag corresponding to the
+ version in the changelog. <replaceable>BRANCH</replaceable> looks at
+ the upstream branch given via the
+ <option>--git-upstream-branch</option> option. Other values are
+ interpreted as treeishs.
+ </para>
+ <para>
+ This doesn't have any effect if <option>--git-pristine-tar</option>
+ is being used.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--git-tarball-dir=</option><replaceable>DIRECTORY</replaceable>
+ </term>
+ <listitem>
+ <para>
+ Search for original tarballs in <replaceable>DIRECTORY</replaceable>
+ instead of generating them.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--git-compression-level=</option><replaceable>LEVEL</replaceable>
+ </term>
+ <listitem>
+ <para>
+ Specifies the upstream tarball compression level if an upstream
+ tarball needs to be built.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--git-tag-only</option>
+ </term>
+ <listitem>
+ <para>
+ Don't build, only tag and run post-tag hooks.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--git-retag</option>
+ </term>
+ <listitem>
+ <para>
+ Don't fail tag operations if a tag with the same version already
+ exists, but, overwrite the existing tag, instead.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--git-pristine-tar</option>
+ </term>
+ <listitem>
+ <para>
+ Use pristine-tar when generating the upstream tarball if it doesn't
+ exist.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--git-pristine-tar-commit</option>
+ </term>
+ <listitem>
+ <para>
+ Commit the pristine-tar delta to the pristine-tar branch if a new
+ tarball was generated and the pristine-tar data isn't already there.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+ <refsect1>
+ <title>EXAMPLES</title>
+ <para>
+ Only build a source RPM with &rpmbuild;
+ </para>
+ <screen>
+ &gbp-buildpackage-rpm; -bs
+ </screen>
+ <para>
+ Build an RPM package with &rpmbuild; on a custom branch with the uncommitted
+ changes included.
+ </para>
+ <screen>
+ &gbp-buildpackage-rpm; --git-ignore-branch --git-export=WC
+ </screen>
+ </refsect1>
+ <refsect1>
+ &man.gbp.config-files;
+ <para>
+ All options in the config files are specified without the 'git-' prefix.
+ </para>
+ </refsect1>
+ <refsect1>
+ <title>SEE ALSO</title>
+ <para>
+ <xref linkend="man.gbp.import.srpm">,
+ <xref linkend="man.gbp.pq.rpm">,
+ <citerefentry>
+ <refentrytitle>rpmbuild</refentrytitle>
+ <manvolnum>8</manvolnum>
+ </citerefentry>,
+ <xref linkend="man.gbp.conf">,
+ &man.seealso.common;
+ </para>
+ </refsect1>
+ <refsect1>
+ <title>AUTHOR</title>
+ <para>
+ &rpm-username; &rpm-email;
+ </para>
+ </refsect1>
+</refentry>
diff --git a/docs/manpages/manpages.ent b/docs/manpages/manpages.ent
index 6b8ea95f..d0a6f4c3 100644
--- a/docs/manpages/manpages.ent
+++ b/docs/manpages/manpages.ent
@@ -12,5 +12,6 @@
<!ENTITY man.gbp.conf SYSTEM "gbp.conf.sgml">
<!ENTITY man.gbp.config-files SYSTEM "man.conffiles.sgml">
<!ENTITY man.seealso.common SYSTEM "man.seealso.sgml">
+<!ENTITY man.gbp.buildpackage.rpm SYSTEM "gbp-buildpackage-rpm.sgml">
<!ENTITY % COMMON.OPTIONS SYSTEM "man.common-options.ent">
%COMMON.OPTIONS;
diff --git a/gbp/config.py b/gbp/config.py
index de8a25ea..3b483c0b 100644
--- a/gbp/config.py
+++ b/gbp/config.py
@@ -1,6 +1,6 @@
# vim: set fileencoding=utf-8 :
#
-# (C) 2006,2007,2010-2012 Guido Guenther <agx@sigxcpu.org>
+# (C) 2006,2007,2010-2012,2015 Guido Guenther <agx@sigxcpu.org>
# 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
@@ -101,6 +101,7 @@ class GbpOptionParser(OptionParser):
'sign-tags' : 'False',
'force-create' : 'False',
'no-create-orig' : 'False',
+ 'cleaner' : '/bin/true',
'keyid' : '',
'posttag' : '',
'postbuild' : '',
@@ -577,7 +578,6 @@ class GbpOptionParserDebian(GbpOptionParser):
defaults = dict(GbpOptionParser.defaults)
defaults.update( {
'builder' : 'debuild -i -I',
- 'cleaner' : '/bin/true',
} )
@@ -591,7 +591,13 @@ class GbpOptionParserRpm(GbpOptionParser):
'vendor' : 'Downstream',
'packaging-branch' : 'master',
'packaging-dir' : '',
+ 'packaging-tag-msg' : ('%(pkg)s (vendor)s release '
+ '%(version)s'),
'packaging-tag' : 'packaging/%(version)s',
+ 'export-sourcedir' : 'SOURCES',
+ 'export-specdir' : 'SPECS',
+ 'export-dir' : '../rpmbuild',
+ 'builder' : 'rpmbuild',
'spec-file' : '',
})
@@ -612,9 +618,19 @@ class GbpOptionParserRpm(GbpOptionParser):
'packaging-tag':
"Format string for packaging tags, RPM counterpart of the "
"'debian-tag' option, default is '%(packaging-tag)s'",
+ 'packaging-tag-msg':
+ ("Format string for packaging tag messages, "
+ "default is '%(packaging-tag-msg)s'"),
'spec-file':
"Spec file to use, causes the packaging-dir option to be "
"ignored, default is '%(spec-file)s'",
+ 'export-sourcedir':
+ "Subdir (under EXPORT_DIR) where packaging sources (other than "
+ "the spec file) are exported, default is "
+ "'%(export-sourcedir)s'",
+ 'export-specdir':
+ "Subdir (under EXPORT_DIR) where package spec file is "
+ "exported default is '%(export-specdir)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 100644
index 00000000..d613e91e
--- /dev/null
+++ b/gbp/scripts/buildpackage_rpm.py
@@ -0,0 +1,631 @@
+# vim: set fileencoding=utf-8 :
+#
+# (C) 2006-2011,2015 Guido Guenther <agx@sigxcpu.org>
+# (C) 2012-2015 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
+#
+"""Build an RPM package out of a Git repository"""
+
+import ConfigParser
+import os
+import re
+import shutil
+import sys
+from datetime import datetime
+
+import gbp.log
+import gbp.notifications
+import gbp.rpm as rpm
+from gbp.command_wrappers import Command, RunAtCommand, CommandExecFailed
+from gbp.config import GbpOptionParserRpm, GbpOptionGroup
+from gbp.errors import GbpError
+from gbp.format import format_str
+from gbp.pkg import compressor_opts
+from gbp.rpm.git import GitRepositoryError, RpmGitRepository
+from gbp.rpm.policy import RpmPkgPolicy
+from gbp.tmpfile import init_tmpdir, del_tmpdir, tempfile
+from gbp.scripts.common.buildpackage import (index_name,
+ git_archive_submodules,
+ git_archive_single, dump_tree,
+ write_wc, drop_index)
+from gbp.scripts.pq_rpm import parse_spec
+
+
+class GbpAutoGenerateError(GbpError):
+ pass
+
+
+def makedir(path):
+ """Create directory"""
+ try:
+ if not os.path.exists(path):
+ os.makedirs(path)
+ except OSError as err:
+ raise GbpError("Cannot create dir %s: %s" % (path, err))
+ return path
+
+
+def git_archive(repo, spec, output_dir, treeish, prefix, comp_level,
+ with_submodules):
+ "Create a compressed orig tarball in output_dir using git_archive"
+ comp_opts = ''
+ if spec.orig_src['compression']:
+ comp_opts = compressor_opts[spec.orig_src['compression']][0]
+
+ output = os.path.join(output_dir, spec.orig_src['filename'])
+
+ # Remove extra slashes from prefix, will be added by git_archive_x funcs
+ prefix = prefix.strip('/')
+ try:
+ if repo.has_submodules(treeish) and with_submodules:
+ repo.update_submodules()
+ git_archive_submodules(repo, treeish, output, prefix,
+ spec.orig_src['compression'],
+ comp_level, comp_opts,
+ spec.orig_src['archive_fmt'])
+
+ else:
+ git_archive_single(treeish, output, prefix,
+ spec.orig_src['compression'], comp_level,
+ comp_opts)
+ except (GitRepositoryError, CommandExecFailed):
+ gbp.log.err("Error generating submodules' archives")
+ return False
+ return True
+
+
+def prepare_upstream_tarball(repo, spec, options, output_dir):
+ """Make sure we have an upstream tarball"""
+ # look in tarball_dir first, if found force a symlink to it
+ orig_file = spec.orig_src['filename']
+ 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 pristine_tar_build_orig(repo, orig_file, output_dir, options):
+ """Build orig using pristine-tar"""
+ 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, version, options):
+ """Determine the upstream tree from the given options"""
+ if options.upstream_tree.upper() == 'TAG':
+ tag_str_fields = {'upstreamversion': version,
+ 'version': version}
+ upstream_tree = repo.version_to_tag(options.upstream_tag,
+ tag_str_fields)
+ 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 = get_tree(repo, options.upstream_tree)
+ if not repo.has_treeish(upstream_tree):
+ raise GbpError('Invalid upstream treeish %s' % upstream_tree)
+ return upstream_tree
+
+
+def get_tree(repo, tree_name):
+ """
+ Get/create a tree-ish to be used for exporting and diffing. Accepts
+ special keywords for git index and working copies.
+ """
+ try:
+ if tree_name == index_name:
+ # Write a tree of the index
+ tree = repo.write_tree()
+ elif tree_name == 'WC':
+ # Write a tree of the working copy
+ tree = write_wc(repo)
+ else:
+ tree = tree_name
+ except GitRepositoryError as err:
+ raise GbpError(err)
+ if not repo.has_treeish(tree):
+ raise GbpError('Invalid treeish object %s' % tree)
+
+ return tree
+
+
+def get_current_branch(repo):
+ """Get the currently checked-out branch"""
+ try:
+ branch = repo.get_branch()
+ except GitRepositoryError:
+ branch = None
+ return branch
+
+
+def get_vcs_info(repo, treeish):
+ """Get the info for spec vcs tag"""
+ info = {}
+ try:
+ info['tagname'] = repo.describe(treeish, longfmt=True, always=True,
+ abbrev=40)
+ info['commit'] = repo.rev_parse('%s^0' % treeish)
+ info['commitish'] = repo.rev_parse('%s' % treeish)
+ except GitRepositoryError:
+ # If tree is not commit-ish, expect it to be from current HEAD
+ info['tagname'] = repo.describe('HEAD', longfmt=True, always=True,
+ abbrev=40) + '-dirty'
+ info['commit'] = repo.rev_parse('HEAD') + '-dirty'
+ info['commitish'] = info['commit']
+ return info
+
+
+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}
+ """
+ try:
+ orig_prefix = spec.orig_src['prefix']
+ upstream_tree = get_upstream_tree(repo, spec.upstreamversion, options)
+ gbp.log.info("%s does not exist, creating from '%s'" %
+ (spec.orig_src['filename'], upstream_tree))
+ if spec.orig_src['compression']:
+ gbp.log.debug("Building upstream source archive with compression "
+ "'%s -%s'" % (spec.orig_src['compression'],
+ options.comp_level))
+ if not git_archive(repo, spec, output_dir, upstream_tree,
+ orig_prefix, options.comp_level,
+ options.with_submodules):
+ raise GbpError("Cannot create upstream tarball at '%s'" %
+ output_dir)
+ except (GitRepositoryError, GbpError) as err:
+ raise GbpAutoGenerateError(str(err))
+ return upstream_tree
+
+
+def is_native(repo, options):
+ """Determine whether a package is native or non-native"""
+ if repo.has_branch(options.upstream_branch):
+ return False
+ # Check remotes, too
+ for remote_branch in repo.get_remote_branches():
+ remote, branch = remote_branch.split('/', 1)
+ if branch == options.upstream_branch:
+ gbp.log.debug("Found upstream branch '%s' from remote '%s'" %
+ (remote, branch))
+ return False
+ return True
+
+
+def setup_builder(options, builder_args):
+ """Setup args and options for builder script"""
+ if options.builder == 'rpmbuild':
+ if len(builder_args) == 0:
+ builder_args.append('-ba')
+ builder_args.extend([
+ '--define "_topdir %s"' % os.path.abspath(options.export_dir),
+ '--define "_specdir %%_topdir/%s"' % options.export_specdir,
+ '--define "_sourcedir %%_topdir/%s"' % options.export_sourcedir])
+
+
+def packaging_tag_data(repo, commit, name, version, options):
+ """Compose packaging tag name and msg"""
+ version_dict = dict(version, version=rpm.compose_version_str(version))
+
+ # Compose tag name and message
+ tag_name_fields = dict(version_dict, vendor=options.vendor.lower())
+ tag_name = repo.version_to_tag(options.packaging_tag, tag_name_fields)
+
+ tag_msg = format_str(options.packaging_tag_msg,
+ dict(version_dict, pkg=name,
+ vendor=options.vendor))
+ return (tag_name, tag_msg)
+
+
+def create_packaging_tag(repo, commit, name, version, options):
+ """Create a packaging/release Git tag"""
+ tag_name, tag_msg = packaging_tag_data(repo, commit, name, version, options)
+
+ if options.retag and repo.has_tag(tag_name):
+ repo.delete_tag(tag_name)
+ repo.create_tag(name=tag_name, msg=tag_msg, sign=options.sign_tags,
+ keyid=options.keyid, commit=commit)
+ return tag_name
+
+
+def disable_hooks(options):
+ """Disable all hooks (except for builder)"""
+ for hook in ['cleaner', 'postexport', 'prebuild', 'postbuild', 'posttag']:
+ if getattr(options, hook):
+ gbp.log.info("Disabling '%s' hook" % hook)
+ setattr(options, hook, '')
+
+
+def build_parser(name, prefix=None, git_treeish=None):
+ """Construct config/option parser"""
+ try:
+ parser = GbpOptionParserRpm(command=os.path.basename(name),
+ prefix=prefix)
+ except ConfigParser.ParsingError as err:
+ gbp.log.err(err)
+ return 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="tmp-dir", dest="tmp_dir")
+ parser.add_config_file_option(option_name="color", dest="color",
+ type='tristate')
+ parser.add_config_file_option(option_name="color-scheme",
+ dest="color_scheme")
+ parser.add_config_file_option(option_name="notify", dest="notify",
+ type='tristate')
+ parser.add_config_file_option(option_name="vendor", action="store",
+ dest="vendor")
+ 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="packaging-tag-msg",
+ dest="packaging_tag_msg")
+ 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", action="store_true",
+ help="force creation of upstream source tarball")
+ orig_group.add_config_file_option(option_name="no-create-orig",
+ dest="no_create_orig", action="store_true",
+ help="don't create upstream source tarball")
+ 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'")
+ cmd_group.add_boolean_config_file_option(option_name="hooks", dest="hooks")
+ export_group.add_option("--git-no-build", action="store_true",
+ dest="no_build",
+ help="Don't run builder or the associated hooks")
+ 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="export-specdir",
+ dest="export_specdir", type="path")
+ export_group.add_config_file_option(option_name="export-sourcedir",
+ dest="export_sourcedir", type="path")
+ export_group.add_config_file_option("export", dest="export",
+ metavar="TREEISH",
+ help="export treeish object TREEISH, default is "
+ "'%(export)s'")
+ 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")
+ return parser
+
+
+def parse_args(argv, prefix, git_treeish=None):
+ """Parse config and command line arguments"""
+ 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)
+
+ parser = build_parser(argv[0], prefix=prefix, git_treeish=git_treeish)
+ if not parser:
+ return None, None, None
+ options, args = parser.parse_args(args)
+
+ gbp.log.setup(options.color, options.verbose, options.color_scheme)
+ if not options.hooks:
+ disable_hooks(options)
+ 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):
+ """Entry point for gbp-buildpackage-rpm"""
+ retval = 0
+ prefix = "git-"
+ spec = 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
+
+ # Determine tree-ish to be exported
+ try:
+ tree = get_tree(repo, options.export)
+ except GbpError as err:
+ gbp.log.err('Failed to determine export treeish: %s' % err)
+ return 1
+ # Re-parse config options with using the per-tree config file(s) from the
+ # exported tree-ish
+ options, gbp_args, builder_args = parse_args(argv, prefix, tree)
+
+ branch = get_current_branch(repo)
+
+ try:
+ init_tmpdir(options.tmp_dir, prefix='buildpackage-rpm_')
+
+ tree = get_tree(repo, options.export)
+ spec = parse_spec(options, repo, treeish=tree)
+
+ 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.")
+
+ # Dump from git to a temporary directory:
+ packaging_tree = '%s:%s' % (tree, options.packaging_dir)
+ dump_dir = tempfile.mkdtemp(prefix='packaging_')
+ gbp.log.debug("Dumping packaging files to '%s'" % dump_dir)
+ if not dump_tree(repo, dump_dir, packaging_tree, False, False):
+ raise GbpError
+ # Re-parse spec from dump dir to get version etc.
+ spec = rpm.SpecFile(os.path.join(dump_dir, spec.specfile))
+
+ if not options.tag_only:
+ # Setup builder opts
+ setup_builder(options, builder_args)
+
+ # Prepare final export dirs
+ export_dir = makedir(options.export_dir)
+ source_dir = makedir(os.path.join(export_dir,
+ options.export_sourcedir))
+ spec_dir = makedir(os.path.join(export_dir, options.export_specdir))
+
+ # Move packaging files to final export dir
+ gbp.log.debug("Exporting packaging files from '%s' to '%s'" %
+ (dump_dir, export_dir))
+ for fname in os.listdir(dump_dir):
+ src = os.path.join(dump_dir, fname)
+ if fname == spec.specfile:
+ dst = os.path.join(spec_dir, fname)
+ else:
+ dst = os.path.join(source_dir, fname)
+ try:
+ shutil.copy2(src, dst)
+ except IOError as err:
+ raise GbpError("Error exporting packaging files: %s" % err)
+ spec.specdir = os.path.abspath(spec_dir)
+
+ orig_prefix = spec.orig_src['prefix']
+ # Get/build the orig tarball
+ if is_native(repo, options):
+ if spec.orig_src and not options.no_create_orig:
+ # Just build source archive from the exported tree
+ gbp.log.info("Creating (native) source archive %s from '%s'"
+ % (spec.orig_src['filename'], tree))
+ if spec.orig_src['compression']:
+ gbp.log.debug("Building source archive with "
+ "compression '%s -%s'" %
+ (spec.orig_src['compression'],
+ options.comp_level))
+ if not git_archive(repo, spec, source_dir, tree,
+ orig_prefix, options.comp_level,
+ options.with_submodules):
+ raise GbpError("Cannot create source tarball at '%s'" %
+ source_dir)
+ # Non-native packages: create orig tarball from upstream
+ elif spec.orig_src:
+ 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.no_build 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.append(os.path.join(spec.specdir,
+ spec.specfile))
+ else:
+ builder_args.append(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" % rpm.compose_version_str(spec.version))
+ tag = create_packaging_tag(repo, tree, spec.name, spec.version,
+ options)
+ vcs_info = get_vcs_info(repo, tag)
+ 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})()
+ else:
+ vcs_info = get_vcs_info(repo, tree)
+
+ except CommandExecFailed:
+ retval = 1
+ except GitRepositoryError as err:
+ gbp.log.err("Git command failed: %s" % err)
+ retval = 1
+ except GbpAutoGenerateError as err:
+ if len(err.__str__()):
+ gbp.log.err(err)
+ retval = 2
+ except GbpError as err:
+ if len(err.__str__()):
+ gbp.log.err(err)
+ retval = 1
+ finally:
+ drop_index()
+ #del_tmpdir()
+
+ if not options.tag_only:
+ if spec and options.notify:
+ summary = "Gbp-rpm %s" % ["failed", "successful"][not retval]
+ message = ("Build of %s %s %s" % (spec.name,
+ rpm.compose_version_str(spec.version),
+ ["failed", "succeeded"][not retval]))
+ if not gbp.notifications.notify(summary, message, options.notify):
+ gbp.log.err("Failed to send notification")
+ retval = 1
+
+ return retval
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv))
diff --git a/gbp/tmpfile.py b/gbp/tmpfile.py
index 0e0e7338..b90527fd 100644
--- a/gbp/tmpfile.py
+++ b/gbp/tmpfile.py
@@ -12,8 +12,8 @@
# 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, please see
-# <http://www.gnu.org/licenses/>
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
"""Temporary directory handling"""
import os
diff --git a/packaging/git-buildpackage.spec b/packaging/git-buildpackage.spec
index 2fe27cb6..434c2ba0 100644
--- a/packaging/git-buildpackage.spec
+++ b/packaging/git-buildpackage.spec
@@ -247,6 +247,7 @@ done
%{python_sitelib}/gbp/scripts/*rpm*.py*
%{python_sitelib}/gbp/rpm/*py*
%if %{with docs}
+%{_mandir}/man1/gbp-buildpackage-rpm.1*
%endif
diff --git a/tests/component/rpm/data b/tests/component/rpm/data
-Subproject bae44ddc98ae0ed15ae078cb7c2fc597dee48da
+Subproject bea3aa372447b2fca611f187c2daa55edd8cdb3
diff --git a/tests/component/rpm/test_buildpackage_rpm.py b/tests/component/rpm/test_buildpackage_rpm.py
new file mode 100644
index 00000000..10c5faea
--- /dev/null
+++ b/tests/component/rpm/test_buildpackage_rpm.py
@@ -0,0 +1,138 @@
+# vim: set fileencoding=utf-8 :
+#
+# (C) 2013-2015 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
+"""Unit tests for the gbp-buildpackage-rpm tool"""
+
+import glob
+import mock
+import os
+import re
+import shutil
+import stat
+import subprocess
+
+from nose.tools import assert_raises, eq_, ok_ # pylint: disable=E0611
+
+from gbp.git import GitRepository
+from gbp.scripts.buildpackage_rpm import main as gbp_rpm
+from tests.component.rpm import RpmRepoTestBase, RPM_TEST_DATA_DIR
+from tests.testutils import ls_dir, ls_tar
+
+# Disable "Method could be a function warning"
+# pylint: disable=R0201
+# Disable "Too many public methods"
+# pylint: disable=R0904
+
+
+DATA_DIR = os.path.join(RPM_TEST_DATA_DIR, 'rpm')
+ORIG_DATA_DIR = os.path.join(RPM_TEST_DATA_DIR, 'orig')
+
+MOCK_NOTIFICATIONS = []
+
+
+def mock_gbp(args):
+ """Wrapper for gbp-buildpackage-rpm"""
+ return gbp_rpm(['arg0', '--git-notify=off','--git-ignore-branch']
+ + args
+ + ['-ba', '--clean', '--target=noarch', '--nodeps'])
+
+def mock_notify(summary, message, notify_opt):
+ """Mock notification system"""
+ # Auto will succeed
+ if notify_opt.is_auto():
+ MOCK_NOTIFICATIONS.append((summary, message))
+ return True
+ # Otherwise fail
+ return False
+
+
+class TestGbpRpm(RpmRepoTestBase):
+ """Basic tests for gbp buildpackage-rpm"""
+
+ @staticmethod
+ def ls_rpm(rpm):
+ """List the contents of an rpm package"""
+ args = ['rpm', '-q', '--qf',
+ '[%{FILEDIGESTS %{FILEMODES} %{FILENAMES}\n]', '-p']
+ popen = subprocess.Popen(args + [rpm], stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ stdout, stderr = popen.communicate()
+ if popen.returncode:
+ raise Exception("Failed to get file metadata for %s: %s" %
+ (rpm, stderr))
+ return sorted([(nam, mod, dig) for dig, mod, nam in
+ [lin.split(None, 2) for lin in stdout.splitlines()]])
+
+ @staticmethod
+ def check_rpms(directory):
+ """Check build results"""
+ # Only check files, at least for now
+ files = glob.glob(directory + '/*rpm')
+ assert files, "No rpms (%s)found in %s" % (files, directory)
+ for path in files:
+ ref_file = os.path.join(DATA_DIR, os.path.basename(path))
+ eq_(TestGbpRpm.ls_rpm(path), TestGbpRpm.ls_rpm(ref_file))
+
+ @staticmethod
+ def check_and_rm_file(filepath, content):
+ """Check file content and remove it"""
+ with open(filepath) as fobj:
+ eq_(fobj.read(), content)
+ os.unlink(filepath)
+
+ @classmethod
+ def setup_class(cls, **kwargs):
+ """Setup unit tests"""
+ super(TestGbpRpm, cls).setup_class(**kwargs)
+
+ def test_outside_repo(self):
+ """Run outside a git repository"""
+ eq_(mock_gbp([]), 1)
+ self._check_log(0, 'gbp:error: %s is not a git repository' %
+ os.path.abspath('.'))
+
+ def test_invalid_config_file(self):
+ """Test invalid config file"""
+ # Create and commit dummy invalid config file
+ repo = GitRepository.create('.')
+ with open('.gbp.conf', 'w') as conffd:
+ conffd.write('foobar\n')
+ repo.add_files('.gbp.conf')
+ repo.commit_all('Add conf')
+ eq_(mock_gbp([]), 1)
+ self._check_log(0, 'gbp:error: File contains no section headers.')
+
+ def test_native_build(self):
+ """Basic test of native pkg"""
+ self.init_test_repo('gbp-test-native')
+ eq_(mock_gbp([]), 0)
+ c = os.path.abspath(os.path.curdir)
+ self.check_rpms('../rpmbuild/RPMS/*')
+ shutil.rmtree('../rpmbuild')
+
+ """Test --git-cleaner option"""
+ self.init_test_repo('gbp-test-native')
+
+ # Make repo dirty
+ with open('untracked-file', 'w') as fobj:
+ fobj.write('this file is not tracked\n')
+
+ # Build on dirty repo should fail
+ eq_(mock_gbp([]), 1)
+
+ # Build should succeed with cleaner
+ eq_(mock_gbp(['--git-cleaner=rm untracked-file']), 0)
+