aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGuido Günther <agx@sigxcpu.org>2015-03-17 09:16:03 +0100
committerGuido Günther <agx@sigxcpu.org>2015-03-17 09:16:03 +0100
commit6f51faef5a021488a159c62473c5f17d4bead1ee (patch)
tree02dd28ff140ae846ba7b5cb6abe3d96ef2728b14
parent2271202a44b461a9c61ccd1815822483b64bc4d3 (diff)
parent4c9d692d52fd3fdf72733b07a5c4d5da3a128ca8 (diff)
Merge tag 'debian/0.6.22' into bpo/wheezy
git-buildpackage Debian release 0.6.22
-rw-r--r--.gitignore8
-rw-r--r--.gitmodules3
-rw-r--r--README13
-rw-r--r--bin/git-pbuilder12
-rw-r--r--debian/changelog111
-rw-r--r--debian/control17
-rw-r--r--debian/git-buildpackage-rpm.install2
-rw-r--r--debian/git-buildpackage.bash-completion16
-rw-r--r--debian/git-buildpackage.install31
-rw-r--r--docs/Makefile2
-rw-r--r--docs/manpages/gbp-buildpackage.sgml587
-rw-r--r--docs/manpages/gbp-clone.sgml26
-rw-r--r--docs/manpages/gbp-config.sgml25
-rw-r--r--docs/manpages/gbp-create-remote-repo.sgml34
-rw-r--r--docs/manpages/gbp-dch.sgml387
-rw-r--r--docs/manpages/gbp-import-dsc.sgml147
-rw-r--r--docs/manpages/gbp-import-dscs.sgml25
-rw-r--r--docs/manpages/gbp-import-orig.sgml184
-rw-r--r--docs/manpages/gbp-pq.sgml181
-rw-r--r--docs/manpages/gbp-pull.sgml33
-rw-r--r--docs/manpages/gbp.conf.sgml40
-rw-r--r--docs/manpages/gbp.sgml58
-rw-r--r--docs/manpages/man.common-options.ent65
-rw-r--r--docs/manpages/manpages.ent2
-rw-r--r--gbp.conf3
-rw-r--r--gbp/command_wrappers.py10
-rw-r--r--gbp/config.py50
-rw-r--r--gbp/deb/dscfile.py4
-rw-r--r--gbp/deb/git.py5
-rw-r--r--gbp/deb/upstreamsource.py28
-rw-r--r--gbp/format.py44
-rw-r--r--gbp/git/modifier.py8
-rw-r--r--gbp/git/repository.py2
-rw-r--r--gbp/git/vfs.py2
-rw-r--r--gbp/pkg/__init__.py192
-rw-r--r--gbp/rpm/__init__.py962
-rw-r--r--gbp/rpm/git.py105
-rw-r--r--gbp/rpm/lib_rpm.py47
-rw-r--r--gbp/rpm/linkedlist.py214
-rw-r--r--gbp/rpm/policy.py72
-rwxr-xr-xgbp/scripts/buildpackage.py56
-rwxr-xr-xgbp/scripts/clone.py2
-rw-r--r--gbp/scripts/common/import_orig.py41
-rw-r--r--gbp/scripts/create_remote_repo.py2
-rw-r--r--gbp/scripts/dch.py37
-rw-r--r--gbp/scripts/import_dsc.py6
-rw-r--r--gbp/scripts/import_dscs.py2
-rw-r--r--gbp/scripts/import_orig.py14
-rwxr-xr-xgbp/scripts/import_srpm.py462
-rwxr-xr-xgbp/scripts/pq.py92
-rwxr-xr-xgbp/scripts/pull.py2
-rw-r--r--gbp/scripts/supercommand.py59
-rw-r--r--gbp/tmpfile.py38
-rw-r--r--setup.py15
-rw-r--r--tests/01_test_help.py9
-rw-r--r--tests/13_test_gbp_pq.py23
-rw-r--r--tests/20_test_rpm.py383
-rw-r--r--tests/component/__init__.py2
-rw-r--r--tests/component/rpm/__init__.py30
m---------tests/component/rpm/data0
-rw-r--r--tests/component/rpm/test_import_srpm.py343
-rw-r--r--tests/data/rpm/rpmbuild/SOURCES/bar.tar.gzbin0 -> 177 bytes
-rw-r--r--tests/data/rpm/rpmbuild/SOURCES/foo.txt3
-rw-r--r--tests/data/rpm/rpmbuild/SOURCES/gbp-test-1.0.tar.bz2bin0 -> 383 bytes
-rw-r--r--tests/data/rpm/rpmbuild/SOURCES/gbp-test-native-1.0.zipbin0 -> 656 bytes
-rw-r--r--tests/data/rpm/rpmbuild/SOURCES/gbp-test2-3.0.tar.gzbin0 -> 328 bytes
-rw-r--r--tests/data/rpm/rpmbuild/SOURCES/my.patch9
-rw-r--r--tests/data/rpm/rpmbuild/SOURCES/my2.patch7
-rw-r--r--tests/data/rpm/rpmbuild/SOURCES/my3.patch7
-rw-r--r--tests/data/rpm/rpmbuild/SPECS/gbp-test-native.spec34
-rw-r--r--tests/data/rpm/rpmbuild/SPECS/gbp-test-native2.spec35
-rw-r--r--tests/data/rpm/rpmbuild/SPECS/gbp-test.spec42
-rw-r--r--tests/data/rpm/rpmbuild/SPECS/gbp-test2.spec60
l---------tests/data/rpm/specs/gbp-test-native.spec1
l---------tests/data/rpm/specs/gbp-test-native2.spec1
-rw-r--r--tests/data/rpm/specs/gbp-test-quirks.spec30
-rw-r--r--tests/data/rpm/specs/gbp-test-reference.spec43
-rw-r--r--tests/data/rpm/specs/gbp-test-reference2.spec47
-rw-r--r--tests/data/rpm/specs/gbp-test-tags.spec74
-rw-r--r--tests/data/rpm/specs/gbp-test-updates-reference.spec44
-rw-r--r--tests/data/rpm/specs/gbp-test-updates.spec49
l---------tests/data/rpm/specs/gbp-test.spec1
-rw-r--r--tests/data/rpm/specs/gbp-test2-reference.spec61
-rw-r--r--tests/data/rpm/specs/gbp-test2-reference2.spec68
l---------tests/data/rpm/specs/gbp-test2.spec1
-rw-r--r--tests/test_GitModifier.py2
-rw-r--r--tests/test_GitVfs.py1
87 files changed, 5000 insertions, 995 deletions
diff --git a/.gitignore b/.gitignore
index afc87fff..80960ac9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,10 +18,10 @@ docs/manpage.links
docs/manpage.refs
docs/version.ent
-debian/git-buildpackage.*.debhelper
-debian/git-buildpackage.debhelper.*
+debian/git-buildpackage*.debhelper*
debian/python-module-stampdir/
debian/files
-debian/git-buildpackage.substvars
+debian/git-buildpackage*.substvars
debian/git-buildpackage/
-
+debian/git-buildpackage-rpm/
+debian/tmp/
diff --git a/.gitmodules b/.gitmodules
index 98279cc0..3b52b91f 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +1,6 @@
[submodule "tests/component/deb/data"]
path = tests/component/deb/data
url = git://honk.sigxcpu.org/git/gbp/deb-testdata
+[submodule "tests/component/rpm/data"]
+ path = tests/component/rpm/data
+ url = git://github.com/marquiz/git-buildpackage-rpm-testdata.git
diff --git a/README b/README
index 3301ae61..7a827fb1 100644
--- a/README
+++ b/README
@@ -1,7 +1,14 @@
+Git-buildpackage
+----------------
This is a bunch of scripts to ease the development of Debian packages with git.
-For more documentation see the manual. On Debian systems this can be found in
+For more documentation on howto use these tools see the manual
+online at:
+
+ http://honk.sigxcpu.org/projects/git-buildpackage/manual-html/gbp.html
+
+On Debian systems this can be found in
/usr/share/doc/git-buildpackage/manual-html.
-It can be found online at
+The API documentation of the gbp module can be found at:
- http://honk.sigxcpu.org/projects/git-buildpackage/manual-html/gbp.html
+ http://honk.sigxcpu.org/projects/git-buildpackage/apidocs/
diff --git a/bin/git-pbuilder b/bin/git-pbuilder
index 4024d124..a9104d7a 100644
--- a/bin/git-pbuilder
+++ b/bin/git-pbuilder
@@ -1,5 +1,5 @@
#!/bin/bash
-# $Id: git-pbuilder,v 1.30 2013/11/05 18:17:09 eagle Exp $
+# $Id: git-pbuilder,v 1.33 2014/08/28 21:39:15 eagle Exp $
#
# git-pbuilder -- Wrapper around pbuilder for git-buildpackage
#
@@ -10,6 +10,7 @@
#
# Written by Russ Allbery <eagle@eyrie.org>
# Based on the example in the git-buildpackage documentation
+# Copyright 2014 Russ Allbery <eagle@eyrie.org>
# Copyright 2008, 2009, 2010, 2011, 2012, 2013
# The Board of Trustees of the Leland Stanford Junior University
#
@@ -227,7 +228,8 @@ update|create|login)
sudo "$BUILDER" --"$action" --distribution "$DIST" \
--othermirror "$OTHERMIRROR" "${OPTIONS[@]}" "$@"
else
- sudo "$BUILDER" --"$action" --distribution "$DIST" "${OPTIONS[@]}" "$@"
+ sudo "$BUILDER" --"$action" --distribution "$DIST" \
+ "${OPTIONS[@]}" "$@"
fi
fi
exit $?
@@ -264,7 +266,11 @@ fi
# Add all of the additional arguments we got on the command line, but quote
# them from the shell since they'll undergo another round of shell expansion
# when the pbuilder runs debbuild.
+source_only=false
for arg in "$@" ; do
+ if [ x'-S' = x"$arg" ] ; then
+ source_only=true
+ fi
DEBBUILDOPTS+=" $(shell_quote "$arg")"
done
@@ -278,7 +284,7 @@ else
--debbuildopts "$DEBBUILDOPTS" -- "${OPTIONS[@]}"
fi
status="$?"
-if [ -n "`ls ../*_source.changes`" ] ; then
+if [ -n "`ls ../*_source.changes`" ] && [ true != "$source_only" ] ; then
rm ../*_source.changes
fi
exit "$status"
diff --git a/debian/changelog b/debian/changelog
index 638c09ae..e6eaf494 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,114 @@
+git-buildpackage (0.6.22) unstable; urgency=medium
+
+ * [3d8939d] git.vfs: fix close method. Preventing a infinite recursion
+ which can be triggered by gbp pq export --commit.
+
+ -- Guido Günther <agx@sigxcpu.org> Wed, 29 Oct 2014 07:47:21 +0100
+
+git-buildpackage (0.6.21) unstable; urgency=medium
+
+ * [81dab4b] pq: Don't fail commit if the series file is empty on the source
+ branch
+ * [740e431] man: fix option argument for --git-pbuilder-options
+ * [22a6987] Improve change reporting a bit
+ * [e08d64d] Complete setup.py for pypi
+
+ -- Guido Günther <agx@sigxcpu.org> Fri, 17 Oct 2014 18:41:14 +0200
+
+git-buildpackage (0.6.20) unstable; urgency=medium
+
+ * [ee44479] Allow to always drop pq branch after export (Closes: #761160)
+ * [51ac0a5] pq: document --drop
+ * [90b283f] meta-closes: Move help text to GbpOptionParser.help
+ * [0afcd3d] pq: Add "pq export --commit" option. This commits the changes
+ in the pq right away. This options is currently experimental and subject
+ to change.
+
+ -- Guido Günther <agx@sigxcpu.org> Sun, 12 Oct 2014 11:42:27 +0200
+
+git-buildpackage (0.6.19) unstable; urgency=medium
+
+ * [5d4cb92] Update to git-pbuilder 1.33
+
+ -- Guido Günther <agx@sigxcpu.org> Sun, 07 Sep 2014 09:25:48 +0200
+
+git-buildpackage (0.6.18) unstable; urgency=medium
+
+ * Upload to unstable
+ * [6edd836] Don't delete *_source.changes on source only builds
+ (Closes: #758726)
+ * [a37832e] Mention --no-merge (Closes: #760091)
+
+ -- Guido Günther <agx@sigxcpu.org> Sat, 06 Sep 2014 13:41:05 +0200
+
+git-buildpackage (0.6.17) experimental; urgency=medium
+
+ [ Guido Günther ]
+ * [692e5da] Make sure we fixup the changelog trailer with newer devscripts.
+ We don't change any mainttrailer options already given.
+ Thanks to James McCoy for the detailed explanation (Closes: #740566)
+ * [ae5805e] Improve error messages on formatting errors to
+ make it easier for the user to detect misformated replacement strings in
+ config files and command line options.
+ * [5f82f44] gbp: add --version option (Closes: #758909)
+ * [04aa92f] Allow to list all available gbp subcommands
+ * [68c053f] Unify doc strings a bit since they now show up with --list-cmds
+ * [6d510ce] bash completion: make command list dynamic.
+ Use "gbp --list-cmds" so we don't have to hardcode the available
+ commands and get support for the RPM ones as they show up.
+
+ [ Kamal Mostafa ]
+ * [6823e51] buildpackage: Make debian-tag message configurable via
+ --git-debian-tag-msg.
+
+ -- Guido Günther <agx@sigxcpu.org> Sun, 24 Aug 2014 11:31:28 +0200
+
+git-buildpackage (0.6.16) experimental; urgency=medium
+
+ [ Markus Lehtonen ]
+ * Doc cleanups and reformatting
+ * [736b9d8] Introduce git-import-srpm tool.
+ * [ed228a2] import-srpm: add 'vendor' config option.
+ Intended to represent the distribution vendor (e.g. 'Debian').
+ Currently, this can be used in tag format strings.
+
+ [ Guido Günther ]
+ * [0b1fc0d] buildpackage: Also print tag name when tagging the Debian
+ release. Based on a patch by Kamal Mostafa
+ * [2bf944f] Pass --no-pristine-tar to SRPM compnent tests
+ to avoid pristine-tar showing up in the matched branches
+ * [23090c9] Introduce git-buildpackage-rpm. Currently only including "gbp
+ import-srpm".
+ * Remove newly introducted spurious log outputs from tests
+
+ -- Guido Günther <agx@sigxcpu.org> Mon, 28 Jul 2014 15:57:49 +0200
+
+git-buildpackage (0.6.15) unstable; urgency=medium
+
+ * [5cde49a] Revert "Determine build_dir upfront"
+ This reverts commit b2549fac19f2d666552291a4fcf2020ca0570834.
+ Closes: #749104
+
+ -- Guido Günther <agx@sigxcpu.org> Sat, 24 May 2014 18:40:44 +0200
+
+git-buildpackage (0.6.14) unstable; urgency=medium
+
+ * [949ce84] Slightly improve usage output
+ * [045e607] gbp pq: document --force
+ * [817976e] Handle version format errors more gracefully.
+ * [b0390d1] Fix comitter vs committer typos.
+ Thanks to Sandro Tosi (Closes: #748339)
+ * [dc231f2] Document that the patches must apply without fuzz
+ * [de77df7] pq: Print proper error message if we fail to apply the tree
+ * [54e4542] pq: Try harder to cleanup after a failed patch.
+ Thanks to Marco d'Itri for the repo to debug this
+ * [b2549fa] Determine build_dir upfront
+ * [a050942] Improve error reporting on failed commands.
+ (Closes: #748248)
+ * [030ff96] Improve error reporting on hooks.
+
+ -- Guido Günther <agx@sigxcpu.org> Thu, 22 May 2014 22:47:37 +0200
+
git-buildpackage (0.6.13~bpo70+1) wheezy-backports; urgency=medium
* Rebuild for wheezy-backports.
diff --git a/debian/control b/debian/control
index 712dcd41..7858f233 100644
--- a/debian/control
+++ b/debian/control
@@ -14,10 +14,13 @@ Build-Depends:
python-coverage,
python-dateutil,
python-epydoc,
+ python-mock,
python-nose,
python-nosexcover,
python-pkg-resources,
+ python-rpm,
python-setuptools,
+ rpm,
sgml2x,
# For the testsuite
bzip2,
@@ -54,3 +57,17 @@ Description: Suite to help with Debian packages in Git repositories
* gbp {pull,clone}: clone and pull from remote repos
* gbp pq: manage debian/patches easily
* gbp create-remote-repo: create remote repositories
+
+Package: git-buildpackage-rpm
+Architecture: all
+Depends: ${python:Depends},
+ ${misc:Depends},
+ git-buildpackage (= ${binary:Version}),
+ python-rpm,
+ rpm,
+Recommends: pristine-tar (>= 0.5)
+Suggests: python-notify, unzip
+Description: Suite to help with RPM packages in Git repositories
+ This package contains the following tools:
+ * gbp import-srpm: import existing RPM source packages into a git
+ repository
diff --git a/debian/git-buildpackage-rpm.install b/debian/git-buildpackage-rpm.install
new file mode 100644
index 00000000..67c03097
--- /dev/null
+++ b/debian/git-buildpackage-rpm.install
@@ -0,0 +1,2 @@
+usr/lib/python2.?/dist-packages/gbp/rpm/
+usr/lib/python2.7/dist-packages/gbp/scripts/import_srpm.py
diff --git a/debian/git-buildpackage.bash-completion b/debian/git-buildpackage.bash-completion
index c0127041..053b9332 100644
--- a/debian/git-buildpackage.bash-completion
+++ b/debian/git-buildpackage.bash-completion
@@ -27,6 +27,12 @@ _gbp_options ()
}
+_gbp_commands ()
+{
+ gbp --list-cmds | sed -ne 's/^ \+\([a-z\-]\+\) \-.*/\1/p'
+}
+
+
_gbp_comp ()
{
local cur="${COMP_WORDS[COMP_CWORD]}"
@@ -208,15 +214,7 @@ have gbp &&
_gbp ()
{
local cur="${COMP_WORDS[COMP_CWORD]}"
- local commands="buildpackage \
- clone \
- create-remote-repo \
- dch \
- import-dsc \
- import-dscs \
- import-orig \
- pq \
- pull"
+ local commands=$(_gbp_commands)
local func
command=$(_gbp_find_cmd_on_cmdline "$commands")
diff --git a/debian/git-buildpackage.install b/debian/git-buildpackage.install
new file mode 100644
index 00000000..1a25e1dc
--- /dev/null
+++ b/debian/git-buildpackage.install
@@ -0,0 +1,31 @@
+usr/bin/
+usr/lib/python2.?/dist-packages/gbp-*
+usr/lib/python2.?/dist-packages/gbp/command_wrappers.py
+usr/lib/python2.?/dist-packages/gbp/config.py
+usr/lib/python2.?/dist-packages/gbp/dch.py
+usr/lib/python2.?/dist-packages/gbp/deb/
+usr/lib/python2.?/dist-packages/gbp/errors.py
+usr/lib/python2.?/dist-packages/gbp/format.py
+usr/lib/python2.?/dist-packages/gbp/git/
+usr/lib/python2.?/dist-packages/gbp/__init__.py
+usr/lib/python2.?/dist-packages/gbp/log.py
+usr/lib/python2.?/dist-packages/gbp/notifications.py
+usr/lib/python2.?/dist-packages/gbp/patch_series.py
+usr/lib/python2.?/dist-packages/gbp/pkg/
+usr/lib/python2.?/dist-packages/gbp/scripts/buildpackage.py
+usr/lib/python2.?/dist-packages/gbp/scripts/clone.py
+usr/lib/python2.?/dist-packages/gbp/scripts/common/
+usr/lib/python2.?/dist-packages/gbp/scripts/config.py
+usr/lib/python2.?/dist-packages/gbp/scripts/create_remote_repo.py
+usr/lib/python2.?/dist-packages/gbp/scripts/dch.py
+usr/lib/python2.?/dist-packages/gbp/scripts/import_dsc.py
+usr/lib/python2.?/dist-packages/gbp/scripts/import_dscs.py
+usr/lib/python2.?/dist-packages/gbp/scripts/import_orig.py
+usr/lib/python2.?/dist-packages/gbp/scripts/__init__.py
+usr/lib/python2.?/dist-packages/gbp/scripts/pq.py
+usr/lib/python2.?/dist-packages/gbp/scripts/pull.py
+usr/lib/python2.?/dist-packages/gbp/scripts/supercommand.py
+usr/lib/python2.?/dist-packages/gbp/tmpfile.py
+usr/lib/python2.?/dist-packages/gbp/tristate.py
+usr/lib/python2.?/dist-packages/gbp/version.py
+etc/git-buildpackage/gbp.conf
diff --git a/docs/Makefile b/docs/Makefile
index 594126a6..91c3b0ad 100644
--- a/docs/Makefile
+++ b/docs/Makefile
@@ -22,7 +22,7 @@ POD_MANPAGES=git-pbuilder.1
MANPAGES=$(SGML_MANPAGES) $(POD_MANPAGES)
VERSION_ENT=version.ent
GBP_VERSION=../gbp/version.py
-DEB_VERSION=$(shell sed -ne 's/^gbp_version="\([.a-z0-9~]\+\)"/\1/p' $(GBP_VERSION))
+DEB_VERSION=$(shell sed -ne 's/^gbp_version="\([.a-z0-9~-]\+\)"/\1/p' $(GBP_VERSION))
CHANGELOG=../debian/changelog
all: $(MANUAL) $(MANPAGES)
diff --git a/docs/manpages/gbp-buildpackage.sgml b/docs/manpages/gbp-buildpackage.sgml
index 37d2c313..0e5561ef 100644
--- a/docs/manpages/gbp-buildpackage.sgml
+++ b/docs/manpages/gbp-buildpackage.sgml
@@ -8,8 +8,7 @@
&dhsurname;
</author>
</refentryinfo>
- <refmeta>
- <refentrytitle>gbp-buildpackage</refentrytitle>
+ <refmeta><refentrytitle>gbp-buildpackage</refentrytitle>
&dhsection;
</refmeta>
<refnamediv>
@@ -24,10 +23,12 @@
<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-upstream-branch=</option><replaceable>treeish</replaceable></arg>
- <arg><option>--git-debian-branch=</option><replaceable>branch_name</replaceable></arg>
+ <arg><option>--git-upstream-branch=</option><replaceable>TREEISH</replaceable></arg>
+ <arg><option>--git-debian-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-]pbuilder</option></arg>
@@ -35,24 +36,25 @@
<arg><option>--git-dist=</option><replaceable>DIST</replaceable></arg>
<arg><option>--git-arch=</option><replaceable>ARCH</replaceable></arg>
<arg><option>--git-[no-]pbuilder-autoconf</option></arg>
- <arg><option>--git-pbuilder-options</option></arg>
+ <arg><option>--git-pbuilder-options</option>=<replaceable>PBUILDER_OPTIONS</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-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-]hooks</option></arg>
<arg><option>--git-debian-tag=</option><replaceable>tag-format</replaceable></arg>
<arg><option>--git-upstream-tag=</option><replaceable>tag-format</replaceable></arg>
+ <arg><option>--git-debian-tag-msg=</option><replaceable>tag-msg-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=</option><replaceable>type</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-upstream-tree=</option><replaceable>[TAG|BRANCH|TREEISH]</replaceable></arg>
+ <arg><option>--git-tarball-dir=</option><replaceable>DIRECTORY</replaceable></arg>
+ <arg><option>--git-compression=</option><replaceable>TYPE</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-[no-]pristine-tar</option></arg>
<arg><option>--git-[no-]pristine-tar-commit</option></arg>
<arg><option>--git-[no-]-purge</option></arg>
@@ -64,397 +66,557 @@
<refsect1>
<title>DESCRIPTION</title>
<para>
- &gbp-buildpackage; is used to build Debian source and .deb packages from a &git; repository.
+ &gbp-buildpackage; is used to build Debian source and .deb packages from
+ a &git; repository.
</para>
<para>
- &gbp-buildpackage; will, in order:
- </para>
+ &gbp-buildpackage; 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>
- (Optionally) export the source tree to a separate build area
- </para></listitem>
- <listitem><para>Build an orig tarball if it doesn't exist.</para>
- </listitem>
- <listitem><para>Call <application>debuild</application>(1)
- (or the application specified via <option>--git-builder</option>)
- with arguments instructing it to ignore &git; meta-data in
- the diff.gz, passing along all arguments given to
- &gbp-buildpackage; 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 &lintian;
- </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>
+ <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>
+ (Optionally) export the source tree to a separate build area
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Build an orig tarball if it doesn't exist.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Call <application>debuild</application>(1) (or the application
+ specified via <option>--git-builder</option>) with arguments
+ instructing it to ignore &git; meta-data in the diff.gz, passing along
+ all arguments given to &gbp-buildpackage; 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 &lintian;
+ </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>debian-branch</replaceable>.</para>
+ <para>
+ Don't abort if there are uncommitted changes in the source tree or
+ the current branch doesn't match the
+ <replaceable>DEBIAN-BRANCH</replaceable>.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--git-tag</option>
</term>
<listitem>
- <para>Add a git tag after a successful build.</para>
+ <para>
+ Add a git tag after a successful build.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>--git-builder=<replaceable>BUILD_CMD</replaceable></option></term>
+ <term><option>--git-builder=<replaceable>BUILD_CMD</replaceable></option>
+ </term>
<listitem>
- <para>Use <replaceable>BUILD_CMD</replaceable> instead of <command>debuild -i -I</command></para>
+ <para>
+ Use <replaceable>BUILD_CMD</replaceable> instead of
+ <command>debuild -i -I</command>
+ </para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>--git-cleaner=<replaceable>CLEAN_CMD</replaceable></option></term>
+ <term><option>--git-cleaner=<replaceable>CLEAN_CMD</replaceable></option>
+ </term>
<listitem>
- <para>Use <replaceable>CLEAN_CMD</replaceable> instead of <command>debuild clean</command></para>
+ <para>
+ Use <replaceable>CLEAN_CMD</replaceable> instead of
+ <command>debuild clean</command>
+ </para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>--git-pbuilder</option></term>
+ <term><option>--git-pbuilder</option>
+ </term>
<listitem>
- <para>Build package using <command>git-pbuilder</command>. Note that
- this overwrites any <option>--git-builder</option> and
- <option>--git-cleaner</option> options.</para>
+ <para>
+ Build package using <command>git-pbuilder</command>. Note that this
+ overwrites any <option>--git-builder</option> and
+ <option>--git-cleaner</option> options.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>--git-qemubuilder</option></term>
+ <term><option>--git-qemubuilder</option>
+ </term>
<listitem>
- <para>Build package using <command>git-pbuilder</command> with
- <command>qemubuilder</command>. Note that this overwrites any
- <option>--git-builder</option> and <option>--git-cleaner</option>
- options.</para>
+ <para>
+ Build package using <command>git-pbuilder</command> with
+ <command>qemubuilder</command>. Note that this overwrites any
+ <option>--git-builder</option> and <option>--git-cleaner</option>
+ options.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>--git-dist=<replaceable>DIST</replaceable></option></term>
+ <term><option>--git-dist=<replaceable>DIST</replaceable></option>
+ </term>
<listitem>
- <para>Build for distribution <replaceable>DIST</replaceable> when
- using <command>--git-pbuilder</command>. If unset build for the
- unstable distribution.</para>
+ <para>
+ Build for distribution <replaceable>DIST</replaceable> when using
+ <command>--git-pbuilder</command>. If unset build for the unstable
+ distribution.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>--git-arch=<replaceable>ARCH</replaceable></option></term>
+ <term><option>--git-arch=<replaceable>ARCH</replaceable></option>
+ </term>
<listitem>
- <para>Build for architecture <replaceable>ARCH</replaceable> when
- using <command>--git-pbuilder</command>. If unset no architecture is
- passed to <command>git-pbuilder</command>.</para>
+ <para>
+ Build for architecture <replaceable>ARCH</replaceable> when using
+ <command>--git-pbuilder</command>. If unset no architecture is passed
+ to <command>git-pbuilder</command>.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>--git-pbuilder-autoconf</option></term>
+ <term><option>--git-pbuilder-autoconf</option>
+ </term>
<listitem>
- <para>Whether to try to autoconfigure
- <command>git-pbuilder</command> or to rely on the settings in
- .pbuilderrc. See the <command>git-pbuilder</command>
- manpage for details.</para></listitem>
+ <para>
+ Whether to try to autoconfigure <command>git-pbuilder</command> or to
+ rely on the settings in .pbuilderrc. See the
+ <command>git-pbuilder</command> manpage for details.
+ </para>
+ </listitem>
</varlistentry>
<varlistentry>
- <term><option>--git-pbuilder-options</option></term>
+ <term><option>--git-pbuilder-options</option>
+ </term>
<listitem>
- <para>Options to pass to pbuilder</para>
+ <para>
+ Options to pass to pbuilder
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--git-verbose</option>
</term>
<listitem>
- <para>verbose execution</para>
+ <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>
+ <para>
+ Whether to use colored output.
+ </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>
+ <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><option>--git-color-scheme</option>=<replaceable>COLOR_SCHEME</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>
+ <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-debian-branch</option>=<replaceable>branch_name</replaceable>
+ <term><option>--git-upstream-branch</option>=<replaceable>BRANCH_NAME</replaceable>
</term>
<listitem>
- <para>If you're not on this branch when invoking &gbp-buildpackage;
- 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>
+ <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-debian-branch</option>=<replaceable>BRANCH_NAME</replaceable>
+ </term>
+ <listitem>
+ <para>
+ If you're not on this branch when invoking &gbp-buildpackage; 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>debian-branch</replaceable>.</para>
+ <para>
+ Don't check if the current branch matches
+ <replaceable>DEBIAN-BRANCH</replaceable>.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--git-[no-]sign-tags</option>
</term>
<listitem>
- <para>GPG sign all created tags</para>
+ <para>
+ GPG sign all created tags
+ </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-keyid=</option><replaceable>GPG-KEYID</replaceable>
+ </term>
+ <listitem>
+ <para>
+ use this keyid for gpg signing tags
+ </para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>--git-keyid=</option><replaceable>gpg-keyid</replaceable>
+ <term><option>--git-posttag=</option><replaceable>COMMAND</replaceable>
</term>
<listitem>
- <para>use this keyid for gpg signing tags</para>
+ <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-posttag=</option><replaceable>command</replaceable>
+ <term><option>--git-postbuild=</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>
+ <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-postbuild=</option><replaceable>command</replaceable>
+ <term><option>--git-postexport=</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>
+ <para>
+ execute <replaceable>COMMAND</replaceable> after exporting the source
+ tree - valid only if --git-export-dir has been specified.
+ </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-postexport=</option><replaceable>command</replaceable>
+ <term><option>--git-prebuild=</option><replaceable>COMMAND</replaceable>
</term>
<listitem>
- <para>execute <replaceable>command</replaceable> after exporting the source
- tree - valid only if --git-export-dir has been specified.</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>
+ <para>
+ execute <replaceable>COMMAND</replaceable> from the build directory
+ before calling <application>debuild</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-prebuild=</option><replaceable>command</replaceable>
+ <term><option>--git-[no-]hooks</option>
</term>
<listitem>
- <para>execute <replaceable>command</replaceable> from the build
- directory before calling <application>debuild</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>
+ <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-[no-]hooks</option></term>
+ <term><option>--git-debian-tag=</option><replaceable>TAG-FORMAT</replaceable>
+ </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>
+ <para>
+ use this tag format when tagging Debian versions, default is
+ <replaceable>debian/%(version)s</replaceable>
+ </para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>--git-debian-tag=</option><replaceable>tag-format</replaceable>
+ <term><option>--git-upstream-tag=</option><replaceable>TAG-FORMAT</replaceable>
</term>
<listitem>
- <para>use this tag format when tagging Debian versions,
- default is <replaceable>debian/%(version)s</replaceable></para>
+ <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-upstream-tag=</option><replaceable>tag-format</replaceable>
+ <term><option>--git-debian-tag-msg=</option><replaceable>tag-msg-format</replaceable>
</term>
<listitem>
- <para>use this tag format when looking for tags of upstream versions,
- default is <replaceable>upstream/%(version)s</replaceable>.</para>
+ <para>use this tag message format when signing Debian versions,
+ default is <replaceable>%(pkg)s Debian release %(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>
+ <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>
+ <para>
+ Don't try to create any orig tarball
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--git-overlay</option>
</term>
<listitem>
- <para>Extract orig tarball when using export-dir option (analog to mergeWithUpstream in svn-bp)</para>
+ <para>
+ Extract orig tarball when using export-dir option (analog to
+ mergeWithUpstream in svn-bp)
+ </para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>--git-export-dir=</option><replaceable>directory</replaceable>
+ <term><option>--git-export-dir=</option><replaceable>DIRECTORY</replaceable>
</term>
<listitem>
- <para>Export the current branch head (or the treeish object given via
- <option>--git-export</option> to <replaceable>directory</replaceable>
- before building.</para>
+ <para>
+ Export 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><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 whereas
- the special name <replaceable>WC</replaceable> exports the current working
- copy as is.</para>
+ <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 whereas
+ the special name <replaceable>WC</replaceable> exports the current
+ working copy as is.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>--git-upstream-tree=</option><replaceable>[tag|branch]</replaceable>
+ <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>
+ <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><option>--git-tarball-dir=</option><replaceable>DIRECTORY</replaceable>
</term>
<listitem>
- <para>Search for original tarballs in <replaceable>directory</replaceable> instead of generating them</para>
+ <para>
+ Search for original tarballs in <replaceable>DIRECTORY</replaceable>
+ instead of generating them
+ </para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>--git-compression=</option><replaceable>type</replaceable>
+ <term><option>--git-compression=</option><replaceable>TYPE</replaceable>
</term>
<listitem>
- <para>Specifies the upstream tarball compression type. This will be
- used to locate and build the upstream tarball if necessary. The
- default is <replaceable>auto</replaceable> which derives the
- compression type from the pristine-tar branch if available and falls
- back to gzip otherwise. Other options are
- <replaceable>gzip</replaceable>, <replaceable>bzip2</replaceable>,
- <replaceable>lzma</replaceable> and <replaceable>xz</replaceable>.
- </para>
+ <para>
+ Specifies the upstream tarball compression type. This will be used to
+ locate and build the upstream tarball if necessary. The default is
+ <replaceable>auto</replaceable> which derives the compression type
+ from the pristine-tar branch if available and falls back to gzip
+ otherwise. Other options are <replaceable>gzip</replaceable>,
+ <replaceable>bzip2</replaceable>, <replaceable>lzma</replaceable> and
+ <replaceable>xz</replaceable>.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>--git-compression-level=</option><replaceable>level</replaceable>
+ <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>
+ <para>
+ Specifies the upstream tarball compression level if an upstream
+ tarball needs to be built.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--git[-no]-purge</option>
</term>
<listitem>
- <para>Purge (remove) temporary build directory after build</para>
+ <para>
+ Purge (remove) temporary build directory after build
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--git-dont-purge</option>
</term>
<listitem>
- <para>Deprecated, use --git-no-purge instead.</para>
+ <para>
+ Deprecated, use --git-no-purge instead.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--git-tag-only</option>
</term>
<listitem>
- <para>don't build, only tag and run post-tag hooks</para>
+ <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</para>
+ <para>
+ don't fail tag operations if a tag with the same version already
+ exists
+ </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>
+ <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>
+ <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>Build a Debian package using &git-pbuilder; which in turn invokes &cowbuildercmd;.
- Instruct cowbuilder to build within a Wheezy chroot for i386.</para>
+ <para>
+ Build a Debian package using &git-pbuilder; which in turn invokes
+ &cowbuildercmd;. Instruct cowbuilder to build within a Wheezy chroot for
+ i386.
+ </para>
<screen>
&gbp-buildpackage; --git-pbuilder --git-arch=i386 --git-dist=wheezy
</screen>
<para>
- Note that the above needs a &cowbuildercmd; chroot already. This can be created using:
+ Note that the above needs a &cowbuildercmd; chroot already. This can be
+ created using:
</para>
<screen>
DIST=wheezy ARCH=i386 &git-pbuilder; create
@@ -462,46 +624,33 @@
</refsect1>
<refsect1>
&man.gbp.config-files;
- <para>All options in the config files are specified without the 'git-' prefix.</para>
+ <para>
+ All options in the config files are specified without the 'git-' prefix.
+ </para>
</refsect1>
<refsect1>
<title>SEE ALSO</title>
<para>
- <citerefentry>
- <refentrytitle>gbp-import-dsc</refentrytitle>
- <manvolnum>1</manvolnum>
- </citerefentry>,
- <citerefentry>
- <refentrytitle>gbp-import-dscs</refentrytitle>
- <manvolnum>1</manvolnum>
- </citerefentry>,
- <citerefentry>
- <refentrytitle>gbp-import-orig</refentrytitle>
- <manvolnum>1</manvolnum>
- </citerefentry>,
- <citerefentry>
- <refentrytitle>gbp-dch</refentrytitle>
- <manvolnum>1</manvolnum>
- </citerefentry>,
- <citerefentry>
- <refentrytitle>git-pbuilder</refentrytitle>
- <manvolnum>1</manvolnum>
- </citerefentry>,
- <citerefentry>
- <refentrytitle>cowbuilder</refentrytitle>
- <manvolnum>8</manvolnum>
- </citerefentry>,
- <citerefentry>
- <refentrytitle>gbp.conf</refentrytitle>
- &dhconfsection;
- </citerefentry>
- &man.seealso.common;
+ <xref linkend="man.gbp.import.dsc">,
+ <xref linkend="man.gbp.import.dscs">,
+ <xref linkend="man.gbp.import.orig">,
+ <xref linkend="man.gbp.dch">,
+ <citerefentry>
+ <refentrytitle>git-pbuilder</refentrytitle>
+ <manvolnum>1</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>cowbuilder</refentrytitle>
+ <manvolnum>8</manvolnum>
+ </citerefentry>,
+ <xref linkend="man.gbp.conf">,
+ &man.seealso.common;
</para>
</refsect1>
<refsect1>
<title>AUTHOR</title>
-
- <para>&dhusername; &dhemail;</para>
-
+ <para>
+ &dhusername; &dhemail;
+ </para>
</refsect1>
</refentry>
diff --git a/docs/manpages/gbp-clone.sgml b/docs/manpages/gbp-clone.sgml
index c63db2f5..20e61472 100644
--- a/docs/manpages/gbp-clone.sgml
+++ b/docs/manpages/gbp-clone.sgml
@@ -21,7 +21,7 @@
<cmdsynopsis>
&gbp-clone;
- <arg><option>--verbose</option></arg>
+ &man.common.options.synopsis;
<arg><option>--all</option></arg>
<arg><option>--[no-]pristine-tar</option></arg>
<arg><option>--debian-branch=</option><replaceable>branch_name</replaceable></arg>
@@ -43,6 +43,8 @@
<title>OPTIONS</title>
<variablelist>
+ &man.common.options.description;
+
<varlistentry>
<term><option>--all</option>
</term>
@@ -75,13 +77,6 @@
</listitem>
</varlistentry>
<varlistentry>
- <term><option>--verbose</option></term>
- <term><option>-v</option></term>
- <listitem>
- <para>verbose execution</para>
- </listitem>
- </varlistentry>
- <varlistentry>
<term><option>--pristine-tar</option>
</term>
<listitem>
@@ -96,18 +91,9 @@
<refsect1>
<title>SEE ALSO</title>
<para>
- <citerefentry>
- <refentrytitle>gbp-buildpackage</refentrytitle>
- <manvolnum>1</manvolnum>
- </citerefentry>,
- <citerefentry>
- <refentrytitle>gbp-pull</refentrytitle>
- <manvolnum>1</manvolnum>
- </citerefentry>,
- <citerefentry>
- <refentrytitle>gbp.conf</refentrytitle>
- &dhconfsection;
- </citerefentry>
+ <xref linkend="man.gbp.buildpackage">,
+ <xref linkend="man.gbp.pull">,
+ <xref linkend="man.gbp.conf">
</para>
</refsect1>
<refsect1>
diff --git a/docs/manpages/gbp-config.sgml b/docs/manpages/gbp-config.sgml
index d68ac643..9b3d7edd 100644
--- a/docs/manpages/gbp-config.sgml
+++ b/docs/manpages/gbp-config.sgml
@@ -21,8 +21,7 @@
<cmdsynopsis>
&gbp-config;
- <arg><option>--verbose</option></arg>
- <arg><option>--color=</option><replaceable>[auto|on|off]</replaceable></arg>
+ &man.common.options.synopsis;
<group choice='req'>
<arg choice="plain"><replaceable>command.option</replaceable></arg>
<arg choice="plain"><replaceable>command</replaceable></arg>
@@ -40,26 +39,13 @@
<refsect1>
<title>OPTIONS</title>
<variablelist>
- <varlistentry>
- <term><option>--verbose</option></term>
- <term><option>-v</option></term>
- <listitem>
- <para>verbose execution</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><option>--color=</option><replaceable>[auto|on|off]</replaceable>
- </term>
- <listitem>
- <para>Whether to use colored output.</para>
- </listitem>
- </varlistentry>
+ &man.common.options.description;
</variablelist>
</refsect1>
<refsect1>
<title>EXIT CODES</title>
<para>
- When &gbp-config finishes it indicates success or failure with its exit code:
+ When &gbp-config; finishes it indicates success or failure with its exit code:
</para>
<variablelist>
<varlistentry>
@@ -104,10 +90,7 @@
<refsect1>
<title>SEE ALSO</title>
<para>
- <citerefentry>
- <refentrytitle>gbp.conf</refentrytitle>
- &dhconfsection;
- </citerefentry>
+ <xref linkend="man.gbp.conf">
</para>
</refsect1>
<refsect1>
diff --git a/docs/manpages/gbp-create-remote-repo.sgml b/docs/manpages/gbp-create-remote-repo.sgml
index 08c621a5..e8f6a092 100644
--- a/docs/manpages/gbp-create-remote-repo.sgml
+++ b/docs/manpages/gbp-create-remote-repo.sgml
@@ -20,8 +20,7 @@
<refsynopsisdiv>
<cmdsynopsis>
&gbp-create-remote-repo;
- <arg><option>--verbose</option></arg>
- <arg><option>--color=</option><replaceable>[auto|on|off]</replaceable></arg>
+ &man.common.options.synopsis;
<arg><option>--remote-url-pattern=</option><replaceable>url-pattern</replaceable></arg>
<arg><option>--remote-name=</option><replaceable>name</replaceable></arg>
<arg><option>--template-dir=</option><replaceable>directory</replaceable></arg>
@@ -52,6 +51,8 @@
<refsect1>
<title>OPTIONS</title>
<variablelist>
+ &man.common.options.description;
+
<varlistentry>
<term><option>--remote-url-pattern</option>=<replaceable>pattern</replaceable>
</term>
@@ -112,20 +113,6 @@
</listitem>
</varlistentry>
<varlistentry>
- <term><option>--verbose</option></term>
- <term><option>-v</option></term>
- <listitem>
- <para>verbose execution</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><option>--color=</option><replaceable>[auto|on|off]</replaceable>
- </term>
- <listitem>
- <para>Whether to use colored output.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
<term><option>--[no-]track</option>
</term>
<listitem>
@@ -141,18 +128,9 @@
<refsect1>
<title>SEE ALSO</title>
<para>
- <citerefentry>
- <refentrytitle>gbp-buildpackage</refentrytitle>
- <manvolnum>1</manvolnum>
- </citerefentry>,
- <citerefentry>
- <refentrytitle>gbp-pull</refentrytitle>
- <manvolnum>1</manvolnum>
- </citerefentry>,
- <citerefentry>
- <refentrytitle>gbp.conf</refentrytitle>
- &dhconfsection;
- </citerefentry>
+ <xref linkend="man.gbp.buildpackage">,
+ <xref linkend="man.gbp.pull">,
+ <xref linkend="man.gbp.conf">
</para>
</refsect1>
<refsect1>
diff --git a/docs/manpages/gbp-dch.sgml b/docs/manpages/gbp-dch.sgml
index 177f45dd..8ffdc4f6 100644
--- a/docs/manpages/gbp-dch.sgml
+++ b/docs/manpages/gbp-dch.sgml
@@ -9,7 +9,7 @@
</author>
</refentryinfo>
<refmeta>
- <refentrytitle>gbp-dch</refentrytitle>
+ <refentrytitle>gbp-dch</refentrytitle>
&dhsection;
</refmeta>
<refnamediv>
@@ -20,26 +20,25 @@
<refsynopsisdiv>
<cmdsynopsis>
&gbp-dch;
-
- <arg><option>--verbose</option></arg>
+ &man.common.options.synopsis;
<arg><option>--debian-branch=</option><replaceable>branch_name</replaceable></arg>
<arg><option>--debian-tag=</option><replaceable>tag-format</replaceable></arg>
<arg><option>--upstream-tag=</option><replaceable>tag-format</replaceable></arg>
<arg><option>--ignore-branch</option></arg>
<group>
<arg><option>--snapshot</option></arg>
- <arg><option>--release</option></arg>
+ <arg><option>--release</option></arg>
</group>
<group>
- <arg><option>--auto</option></arg>
- <arg><option>--since=</option><replaceable>commitish</replaceable></arg>
+ <arg><option>--auto</option></arg>
+ <arg><option>--since=</option><replaceable>commitish</replaceable></arg>
</group>
<arg><option>--new-version=</option><replaceable>version</replaceable></arg>
<group>
- <arg><option>--bpo</option></arg>
- <arg><option>--nmu</option></arg>
- <arg><option>--qa</option></arg>
- <arg><option>--team</option></arg>
+ <arg><option>--bpo</option></arg>
+ <arg><option>--nmu</option></arg>
+ <arg><option>--qa</option></arg>
+ <arg><option>--team</option></arg>
</group>
<arg><option>--distribution=</option><replaceable>name</replaceable></arg>
<arg><option>--force-distribution</option></arg>
@@ -56,7 +55,7 @@
<arg><option>--spawn-editor=[always|snapshot|release]</option></arg>
<arg><option>--commit-msg=</option><replaceable>msg-format</replaceable></arg>
<arg><option>--commit</option></arg>
- <arg><option>--customization=</option><replaceable>customization-file</replaceable></arg>
+ <arg><option>--customizations=</option><replaceable>customization-file</replaceable></arg>
<arg choice="plain"><replaceable>[path1 path2]</replaceable></arg>
</cmdsynopsis>
</refsynopsisdiv>
@@ -69,11 +68,14 @@
distribution of the topmost section in
<filename>debian/changelog</filename> is <emphasis>UNRELEASED</emphasis>
the changelog entries will be inserted into this section. Otherwise a new
- section will be created.</para>
- <para>If <option>--auto</option> is given &gbp-dch; tries to guess the
+ section will be created.
+ </para>
+ <para>
+ If <option>--auto</option> is given &gbp-dch; tries to guess the
last &git; commit documented in the changelog - this only works in snapshot
mode. Otherwise <option>--since</option> can be used to tell &gbp-dch;
- at which point it should start in the &git; history.</para>
+ at which point it should start in the &git; history.
+ </para>
<para>
The additional path arguments can be used to restrict the repository paths
&gbp-dch; looks at. Setting <replaceable>path</replaceable> to
@@ -81,106 +83,124 @@
all Debian packaging changes are restricted to the
<replaceable>debian/</replaceable> subdir. In more sophisticated cases
(like backports) you can use <option>--git-log</option> to restrict the
- generated changelog entries further. E.g. by using
- <option>--git-log=</option><replaceable>"--author=Foo Bar"</replaceable>.</para>
+ generated changelog entries further. E.g. by using
+ <option>--git-log=</option><replaceable>"--author=Foo Bar"</replaceable>.
+ </para>
</refsect1>
<refsect1>
<title>OPTIONS</title>
-
<variablelist>
+ &man.common.options.description;
+
<varlistentry>
<term><option>--debian-branch</option>=<replaceable>branch_name</replaceable>
</term>
<listitem>
- <para>The branch in the Git repository the Debian package is being
- developed on, default is <replaceable>master</replaceable>.</para>
+ <para>
+ The branch in the Git repository the Debian package is being
+ developed on, default is <replaceable>master</replaceable>.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--ignore-branch</option>
</term>
<listitem>
- <para>Don't check if the current branch matches
- <replaceable>debian-branch</replaceable>.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><option>--verbose</option></term>
- <term><option>-v</option></term>
- <listitem>
- <para>verbose execution</para>
+ <para>
+ Don't check if the current branch matches
+ <replaceable>debian-branch</replaceable>.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--debian-tag=</option><replaceable>tag-format</replaceable>
</term>
<listitem>
- <para>tag format used, when tagging debian versions,
- default is <replaceable>debian/%(version)s</replaceable></para>
+ <para>
+ tag format used, when tagging debian versions,
+ default is <replaceable>debian/%(version)s</replaceable>
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--since=</option><replaceable>committish</replaceable>
</term>
<listitem>
- <para>Start reading commit messages at <replaceable>committish</replaceable>.</para>
+ <para>
+ Start reading commit messages at
+ <replaceable>committish</replaceable>.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--auto</option>,
- <option>-a</option></term>
+ <option>-a</option></term>
<listitem>
- <para>Guess the last commit documented in the changelog from the
- snapshot banner (or from the last tag if no snapshot banner exists).
- </para>
+ <para>
+ Guess the last commit documented in the changelog from the
+ snapshot banner (or from the last tag if no snapshot banner exists).
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--[no-]meta</option></term>
<listitem>
- <para>Parse meta tags like <option>Closes:</option>,
- <option>Thanks:</option> and <option>Git-Dch:</option>. See META TAGS below.</para>
+ <para>
+ Parse meta tags like <option>Closes:</option>,
+ <option>Thanks:</option> and <option>Git-Dch:</option>. See META TAGS
+ below.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--meta-closes=</option><replaceable>bug-close-tags</replaceable>
</term>
<listitem>
- <para>What meta tags to look for to generate bug-closing changelog
- entries. The default is 'Closes|LP' to support Debian and
- Launchpad.</para>
+ <para>
+ What meta tags to look for to generate bug-closing changelog entries.
+ The default is 'Closes|LP' to support Debian and Launchpad.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>--[no-]full</option></term>
+ <term><option>--[no-]full</option>
+ </term>
<listitem>
- <para>Include the full commit message in the changelog output.</para>
+ <para>
+ Include the full commit message in the changelog output.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--snapshot</option>,
<option>-S</option></term>
<listitem>
- <para>Create a snapshot release entry. This adds a snapshot release
- number and a warning banner to the changelog entry. The release
- version number is being auto incremented with every new snapshot
- release to avoid packages downgrades during snapshot testing.</para>
+ <para>
+ Create a snapshot release entry. This adds a snapshot release
+ number and a warning banner to the changelog entry. The release
+ version number is being auto incremented with every new snapshot
+ release to avoid packages downgrades during snapshot testing.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--snapshot-number=</option><replaceable>expression</replaceable>
</term>
<listitem>
- <para>Python expression that gets eval()ed to the new snapshot number.</para>
+ <para>
+ Python expression that gets eval()ed to the new snapshot number.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--release</option>,
<option>-R</option></term>
<listitem>
- <para>Remove any snapshot release banners and version suffixes, set
- the current distribution to <replaceable>unstable</replaceable> and
- open the changelog for final tweaking.</para>
+ <para>
+ Remove any snapshot release banners and version suffixes, set
+ the current distribution to <replaceable>unstable</replaceable> and
+ open the changelog for final tweaking.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
@@ -188,155 +208,196 @@
<option>-N</option> <replaceable>version</replaceable>
</term>
<listitem>
- <para>Add a new changelog section with version
- <replaceable>newversion</replaceable>. Together with
- <option>--snapshot</option> the snapshot number will be appended to
- <replaceable>newversion</replaceable>.</para>
+ <para>
+ Add a new changelog section with version
+ <replaceable>newversion</replaceable>. Together with
+ <option>--snapshot</option> the snapshot number will be appended to
+ <replaceable>newversion</replaceable>.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>--team</option></term>
+ <term><option>--team</option>
+ </term>
<listitem>
- <para>Create a Team upload changelog entry.</para>
+ <para>
+ Create a Team upload changelog entry.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--bpo</option>
</term>
<listitem>
- <para>Increment the Debian release number for an upload to
- backports, and add a backport upload changelog comment.</para>
+ <para>
+ Increment the Debian release number for an upload to backports, and
+ add a backport upload changelog comment.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--nmu</option>
</term>
<listitem>
- <para>Increment the Debian release number for a non-maintainer upload.</para>
+ <para>
+ Increment the Debian release number for a non-maintainer upload.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--qa</option>
</term>
<listitem>
- <para>Increment the Debian release number for a Debian QA Team
- upload, and add a QA upload changelog comment.</para>
+ <para>
+ Increment the Debian release number for a Debian QA Team upload, and
+ add a QA upload changelog comment.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>--distribution=</option><replaceable>name</replaceable>
- </term>
- <listitem>
- <para>Set the distribution field
- to <replaceable>name</replaceable>.</para>
- </listitem>
+ <term><option>--distribution=</option><replaceable>name</replaceable>
+ </term>
+ <listitem>
+ <para>
+ Set the distribution field to <replaceable>name</replaceable>.
+ </para>
+ </listitem>
</varlistentry>
<varlistentry>
- <term><option>--force-distribution</option>
- </term>
- <listitem>
- <para>Force the distribution specified
- with <option>--distribution</option> to be used, even if it
- doesn't match the list of known distributions.</para>
- </listitem>
+ <term><option>--force-distribution</option>
+ </term>
+ <listitem>
+ <para>
+ Force the distribution specified with <option>--distribution</option>
+ to be used, even if it doesn't match the list of known distributions.
+ </para>
+ </listitem>
</varlistentry>
<varlistentry>
- <term><option>--urgency=</option><replaceable>level</replaceable>
- </term>
- <listitem>
- <para>Set the urgency field
- to <replaceable>level</replaceable>.</para>
- </listitem>
+ <term><option>--urgency=</option><replaceable>level</replaceable>
+ </term>
+ <listitem>
+ <para>
+ Set the urgency field to <replaceable>level</replaceable>.
+ </para>
+ </listitem>
</varlistentry>
<varlistentry>
<term><option>--git-log=</option><replaceable>git-log-options</replaceable>
</term>
<listitem>
- <para>Options passed on verbatim to git-log(1).</para>
+ <para>
+ Options passed on verbatim to git-log(1).
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--id-length=</option><replaceable>N</replaceable>
</term>
<listitem>
- <para>Include <replaceable>N</replaceable> digits of the commit id in
- the changelog entry. Default is to not include any commit ids at
- all.</para>
+ <para>
+ Include <replaceable>N</replaceable> digits of the commit id in the
+ changelog entry. Default is to not include any commit ids at all.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--ignore-regex=</option><replaceable>regex</replaceable>
</term>
<listitem>
- <para>Ignore commit lines matching <replaceable>regex</replaceable>
- when generating the changelog.
- </para>
+ <para>
+ Ignore commit lines matching <replaceable>regex</replaceable>
+ when generating the changelog.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--git-author</option>
</term>
<listitem>
- <para>Use user.name and user.email from <application>git-config</application>(1) for changelog trailer.</para>
+ <para>
+ Use user.name and user.email from
+ <application>git-config</application>(1) for changelog trailer.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--[no-]multimaint-merge</option>
</term>
<listitem>
- <para>Merge commits by maintainer.</para>
+ <para>
+ Merge commits by maintainer.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--spawn-editor=<replaceable>[always|snapshot|release]</replaceable></option>
</term>
<listitem>
- <para>Whether to spawn an editor: always, when doing snapshots or
- when doing a release.</para>
+ <para>
+ Whether to spawn an editor: always, when doing snapshots or when
+ doing a release.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--commit-msg=</option><replaceable>msg-format</replaceable>
</term>
<listitem>
- <para>use this format string for the commit message when
- committing the generated changelog file (when
- <option>--commit</option> is given). Default is
- <replaceable>Update changelog for %(version)s
- release</replaceable></para>
+ <para>
+ use this format string for the commit message when committing the
+ generated changelog file (when <option>--commit</option> is given).
+ Default is
+ <replaceable>Update changelog for %(version)s release</replaceable>
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--commit</option>
</term>
<listitem>
- <para>Commit the generated changelog.</para>
+ <para>
+ Commit the generated changelog.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--customizations=</option><replaceable>customization-file</replaceable>
+ </term>
+ <listitem>
+ <para>
+ Load Python code from <replaceable>customization-file</replaceable>.
+ At the moment, the only useful thing the code can do is define a
+ custom format_changelog_entry() function.
+ </para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
- <title>Snapshot mode</title>
- <para>
- Snapshot mode can be used for quick test and install cycles without
- having to worry about version numbers or changelog entries.
- </para><para>
- When using <option>--snapshot</option> or <option>-S</option> &gbp-dch;
- uses a pseudo header in the Debian changelog to remember the last git
- commit it added a changelog entry for. It also sets a version number
- ending in
- <replaceable>~&lt;snaspshotnumber&gt;.gbp&lt;commitid&gt;</replaceable>.
- It automatically increments the snapshot number on subsequent invocations
- of &gbp-dch; <option>-S</option> so that later snapshots automatically
- have a higher version number. To leave snapshot mode invoke &gbp-dch;
- with the <option>--release</option> option. This removes the pseudo
- header and unmangles the version number so the released version has a
- higher version number than the snapshots.
- </para>
+ <title>Snapshot mode</title>
+ <para>
+ Snapshot mode can be used for quick test and install cycles without
+ having to worry about version numbers or changelog entries.
+ </para>
+ <para>
+ When using <option>--snapshot</option> or <option>-S</option> &gbp-dch;
+ uses a pseudo header in the Debian changelog to remember the last git
+ commit it added a changelog entry for. It also sets a version number
+ ending in
+ <replaceable>~&lt;snaspshotnumber&gt;.gbp&lt;commitid&gt;</replaceable>.
+ It automatically increments the snapshot number on subsequent invocations
+ of &gbp-dch; <option>-S</option> so that later snapshots automatically
+ have a higher version number. To leave snapshot mode invoke &gbp-dch;
+ with the <option>--release</option> option. This removes the pseudo
+ header and unmangles the version number so the released version has a
+ higher version number than the snapshots.
+ </para>
</refsect1>
<refsect1>
<title>META TAGS</title>
- <para>Additional to the above options the formatting of the commit message
+ <para>
+ Additional to the above options the formatting of the commit message
in <filename>debian/changelog</filename> can be modified by special tags
(called Meta Tags)
given in the git commit message. Meta Tag processing can be activated via
@@ -349,40 +410,44 @@
<varlistentry>
<term><option>Git-Dch</option>: <replaceable>action</replaceable>
</term>
- <listitem><para>
- Supported actions are: <replaceable>Ignore</replaceable> which will ignore
- this commit when generating <filename>debian/changelog</filename>,
- <replaceable>Short</replaceable> which will only use the
- description (the first line) of the commit message when
- generating the changelog entry (useful when
- <option>--full</option> is given) and
- <replaceable>Full</replaceable> which will use the full commit
- message when generating the changelog entry (useful when
- <option>--full</option> is not given).
- </para></listitem>
+ <listitem>
+ <para>
+ Supported actions are: <replaceable>Ignore</replaceable> which will
+ ignore this commit when generating
+ <filename>debian/changelog</filename>,
+ <replaceable>Short</replaceable> which will only use the description
+ (the first line) of the commit message when generating the changelog
+ entry (useful when <option>--full</option> is given) and
+ <replaceable>Full</replaceable> which will use the full commit
+ message when generating the changelog entry (useful when
+ <option>--full</option> is not given).
+ </para>
+ </listitem>
</varlistentry>
<varlistentry>
- <term><option>Thanks</option>: <replaceable>msg</replaceable>
- </term>
- <listitem>
- <para>
- Add a thanks message after the commit message.
- </para>
- </listitem>
+ <term><option>Thanks</option>: <replaceable>msg</replaceable>
+ </term>
+ <listitem>
+ <para>
+ Add a thanks message after the commit message.
+ </para>
+ </listitem>
</varlistentry>
<varlistentry>
- <term><option>Closes</option>: <replaceable>bugnumber</replaceable>
- </term>
- <listitem>
- <para>
- Indicate in the <filename>debian/changelog</filename> that the bug was
- closed by this commit. See the <option>--meta-closes</option>
- on how to extend this for other bugtrackers.
- </para>
- </listitem>
+ <term><option>Closes</option>: <replaceable>bugnumber</replaceable>
+ </term>
+ <listitem>
+ <para>
+ Indicate in the <filename>debian/changelog</filename> that the bug
+ was closed by this commit. See the <option>--meta-closes</option> on
+ how to extend this for other bugtrackers.
+ </para>
+ </listitem>
</varlistentry>
</variablelist>
- <para>The following git commit message:</para>
+ <para>
+ The following git commit message:
+ </para>
<screen>
Document meta tags
@@ -393,7 +458,7 @@
Thanks: Raphaël Hertzog for the suggestion
</screen>
<para>
- Results in this <filename>debian/changelog</filename> entry:
+ Results in this <filename>debian/changelog</filename> entry:
</para>
<screen>
* Document meta tags.
@@ -401,32 +466,16 @@
</screen>
</refsect1>
<refsect1>
- &man.gbp.config-files;
+ &man.gbp.config-files;
</refsect1>
<refsect1>
<title>SEE ALSO</title>
-
<para>
- <citerefentry>
- <refentrytitle>gbp-buildpackage</refentrytitle>
- <manvolnum>1</manvolnum>
- </citerefentry>,
- <citerefentry>
- <refentrytitle>gbp-import-dsc</refentrytitle>
- <manvolnum>1</manvolnum>
- </citerefentry>,
- <citerefentry>
- <refentrytitle>gbp-import-dscs</refentrytitle>
- <manvolnum>1</manvolnum>
- </citerefentry>,
- <citerefentry>
- <refentrytitle>gbp-import-orig</refentrytitle>
- <manvolnum>1</manvolnum>
- </citerefentry>,
- <citerefentry>
- <refentrytitle>gbp.conf</refentrytitle>
- &dhconfsection;
- </citerefentry>,
+ <xref linkend="man.gbp.buildpackage">,
+ <xref linkend="man.gbp.import.dsc">,
+ <xref linkend="man.gbp.import.dscs">,
+ <xref linkend="man.gbp.import.orig">,
+ <xref linkend="man.gbp.conf">,
&man.seealso.common;
<ulink url="https://honk.sigxcpu.org/cl2vcs">
<citetitle>Cl2vcs</citetitle></ulink>,
@@ -434,8 +483,8 @@
</refsect1>
<refsect1>
<title>AUTHOR</title>
-
- <para>&dhusername; &dhemail;</para>
-
+ <para>
+ &dhusername; &dhemail;
+ </para>
</refsect1>
</refentry>
diff --git a/docs/manpages/gbp-import-dsc.sgml b/docs/manpages/gbp-import-dsc.sgml
index 98f70e72..e635a3d9 100644
--- a/docs/manpages/gbp-import-dsc.sgml
+++ b/docs/manpages/gbp-import-dsc.sgml
@@ -20,7 +20,7 @@
<refsynopsisdiv>
<cmdsynopsis>
&gbp-import-dsc;
-
+ &man.common.options.synopsis;
<arg><option>--allow-same-versions</option></arg>
<arg><option>--author-date-is-committer-date</option></arg>
<arg><option>--author-is-committer</option></arg>
@@ -35,18 +35,16 @@
<arg><option>--skip-debian-tag=</option></arg>
<arg><option>--upstream-branch=</option><replaceable>branch_name</replaceable></arg>
<arg><option>--upstream-tag=</option><replaceable>tag-format</replaceable></arg>
- <arg><option>--verbose</option></arg>
<arg choice="plain"><replaceable>debian-source.dsc</replaceable></arg>
</cmdsynopsis>
<cmdsynopsis>
&gbp-import-dsc;
-
<arg><option>options</option></arg>
<arg choice="req"><option>--download</option></arg>
<arg><option>--[no-]allow-unauthenticated</option></arg>
<group choice="plain">
- <arg><replaceable>URL</replaceable></arg>
- <arg><replaceable>source-package</replaceable></arg>
+ <arg><replaceable>URL</replaceable></arg>
+ <arg><replaceable>source-package</replaceable></arg>
</group>
</cmdsynopsis>
</refsynopsisdiv>
@@ -61,135 +59,163 @@
</refsect1>
<refsect1>
<title>OPTIONS</title>
-
<variablelist>
+ &man.common.options.description;
+
<varlistentry>
<term><option>--upstream-branch</option>=<replaceable>branch_name</replaceable>
</term>
<listitem>
- <para>The branch in the &git; repository the upstream sources are put
- onto. Default is <replaceable>upstream</replaceable>.</para>
+ <para>
+ The branch in the &git; repository the upstream sources are put
+ onto. Default is <replaceable>upstream</replaceable>.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--debian-branch</option>=<replaceable>branch_name</replaceable>
</term>
<listitem>
- <para>The branch in the &git; repository the debian sources are put
- onto. Default is <replaceable>master</replaceable>.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><option>--verbose</option></term>
- <term><option>-v</option></term>
- <listitem>
- <para>verbose execution</para>
+ <para>
+ The branch in the &git; repository the debian sources are put
+ onto. Default is <replaceable>master</replaceable>.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--[no-]sign-tags</option>
</term>
<listitem>
- <para>GPG sign all created tags</para>
+ <para>
+ GPG sign all created tags
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--keyid=</option><replaceable>gpg-keyid</replaceable>
</term>
<listitem>
- <para>use this keyid for gpg signing tags</para>
+ <para>
+ use this keyid for gpg signing tags
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--debian-tag=</option><replaceable>tag-format</replaceable>
</term>
<listitem>
- <para>use this tag format when tagging Debian versions,
- default is <replaceable>debian/%(version)s</replaceable></para>
+ <para>
+ use this tag format when tagging Debian versions,
+ default is <replaceable>debian/%(version)s</replaceable>
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--upstream-tag=</option><replaceable>tag-format</replaceable>
</term>
<listitem>
- <para>use this tag format when tagging upstream versions,
- default is <replaceable>upstream/%(version)s</replaceable></para>
+ <para>
+ use this tag format when tagging upstream versions,
+ default is <replaceable>upstream/%(version)s</replaceable>
+ </para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>--skip-debian-tag</option></term>
+ <term><option>--skip-debian-tag</option>
+ </term>
<listitem>
- <para>Don't create Debian tag after importing the Debian patch. This can be useful
- if you already created a package but want to further work on it after importing it
- into git.</para>
+ <para>
+ Don't create Debian tag after importing the Debian patch. This can be
+ useful if you already created a package but want to further work on
+ it after importing it into git.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--filter=</option><replaceable>pattern</replaceable>
</term>
<listitem>
- <para>filter out files glob-matching pattern. Can be given multiple times.</para>
+ <para>
+ filter out files glob-matching pattern. Can be given multiple times.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--pristine-tar</option>
</term>
<listitem>
- <para>generate pristine-tar delta file</para>
+ <para>
+ generate pristine-tar delta file
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--download</option>
</term>
<listitem>
- <para>Download the source package instead of looking for it in the local
- file system. The argument can either be a
- <replaceable>source-package</replaceable> name or an
- <replaceable>URL</replaceable>. The former uses &apt-get; to download
- the source while the later uses &dget;.
- </para>
+ <para>
+ Download the source package instead of looking for it in the local
+ file system. The argument can either be a
+ <replaceable>source-package</replaceable> name or an
+ <replaceable>URL</replaceable>. The former uses &apt-get; to download
+ the source while the later uses &dget;.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--allow-unauthenticated</option>
</term>
<listitem>
- <para>Whether to skip signature verification on downloads.</para>
+ <para>
+ Whether to skip signature verification on downloads.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--allow-same-version</option>
</term>
<listitem>
- <para>Allow to import a package with the same debian version.</para>
+ <para>
+ Allow to import a package with the same debian version.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--author-is-committer</option>
</term>
<listitem>
- <para>When importing the Debian patch, use the author identity as
- comitter identity.</para>
+ <para>
+ When importing the Debian patch, use the author identity as
+ committer identity.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--author-date-is-committer-date</option>
</term>
<listitem>
- <para>When importing the Debian patch, use the author date as
- comitter date. <warning><para>Git will subtly misbehave if the
- committer date of a commit is not later than or equal to all
- its parents.</para></warning></para>
+ <para>
+ When importing the Debian patch, use the author date as
+ committer date.
+ <warning>
+ <para>
+ Git will subtly misbehave if the committer date of a commit is not
+ later than or equal to all its parents.
+ </para>
+ </warning>
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--[no-]create-missing-branches</option>
</term>
<listitem>
- <para>Create missing upstream and debian branch if missing.</para>
+ <para>
+ Create missing upstream and debian branch if missing.
+ </para>
</listitem>
</varlistentry>
- </variablelist>
+ </variablelist>
</refsect1>
<refsect1>
&man.gbp.config-files;
@@ -198,22 +224,10 @@
<title>SEE ALSO</title>
<para>
- <citerefentry>
- <refentrytitle>gbp-import-dscs</refentrytitle>
- <manvolnum>1</manvolnum>
- </citerefentry>,
- <citerefentry>
- <refentrytitle>gbp-buildpackage</refentrytitle>
- <manvolnum>1</manvolnum>
- </citerefentry>,
- <citerefentry>
- <refentrytitle>gbp-import-orig</refentrytitle>
- <manvolnum>1</manvolnum>
- </citerefentry>,
- <citerefentry>
- <refentrytitle>gbp-dch</refentrytitle>
- <manvolnum>1</manvolnum>
- </citerefentry>,
+ <xref linkend="man.gbp.import.dscs">,
+ <xref linkend="man.gbp.buildpackage">,
+ <xref linkend="man.gbp.import.orig">,
+ <xref linkend="man.gbp.dch">,
<citerefentry>
<refentrytitle>apt-get</refentrytitle>
<manvolnum>1</manvolnum>
@@ -222,17 +236,14 @@
<refentrytitle>dget</refentrytitle>
<manvolnum>1</manvolnum>
</citerefentry>,
- <citerefentry>
- <refentrytitle>gbp.conf</refentrytitle>
- &dhconfsection;
- </citerefentry>,
+ <xref linkend="man.gbp.conf">,
&man.seealso.common;
</para>
</refsect1>
<refsect1>
<title>AUTHOR</title>
-
- <para>&dhusername; &dhemail;</para>
-
+ <para>
+ &dhusername; &dhemail;
+ </para>
</refsect1>
</refentry>
diff --git a/docs/manpages/gbp-import-dscs.sgml b/docs/manpages/gbp-import-dscs.sgml
index 71ae883a..c288b138 100644
--- a/docs/manpages/gbp-import-dscs.sgml
+++ b/docs/manpages/gbp-import-dscs.sgml
@@ -80,26 +80,11 @@ options shipped in the package source.</para>
<title>SEE ALSO</title>
<para>
- <citerefentry>
- <refentrytitle>gbp-import-dsc</refentrytitle>
- <manvolnum>1</manvolnum>
- </citerefentry>,
- <citerefentry>
- <refentrytitle>gbp-buildpackage</refentrytitle>
- <manvolnum>1</manvolnum>
- </citerefentry>,
- <citerefentry>
- <refentrytitle>gbp-import-orig</refentrytitle>
- <manvolnum>1</manvolnum>
- </citerefentry>,
- <citerefentry>
- <refentrytitle>gbp-dch</refentrytitle>
- <manvolnum>1</manvolnum>
- </citerefentry>,
- <citerefentry>
- <refentrytitle>gbp.conf</refentrytitle>
- &dhconfsection;
- </citerefentry>,
+ <xref linkend="man.gbp.import.dsc">,
+ <xref linkend="man.gbp.buildpackage">,
+ <xref linkend="man.gbp.import.orig">,
+ <xref linkend="man.gbp.dch">,
+ <xref linkend="man.gbp.conf">,
&man.seealso.common;
</para>
</refsect1>
diff --git a/docs/manpages/gbp-import-orig.sgml b/docs/manpages/gbp-import-orig.sgml
index f6df6659..31f433b4 100644
--- a/docs/manpages/gbp-import-orig.sgml
+++ b/docs/manpages/gbp-import-orig.sgml
@@ -9,7 +9,7 @@
</author>
</refentryinfo>
<refmeta>
- <refentrytitle>gbp-import-orig</refentrytitle>
+ <refentrytitle>gbp-import-orig</refentrytitle>
&dhsection;
</refmeta>
<refnamediv>
@@ -21,7 +21,7 @@
<cmdsynopsis>
&gbp-import-orig;
- <arg><option>--verbose</option></arg>
+ &man.common.options.synopsis;
<arg><option>--upstream-version=</option><replaceable>version</replaceable></arg>
<arg><option>--[no-]merge</option></arg>
<arg><option>--upstream-branch=</option><replaceable>branch_name</replaceable></arg>
@@ -37,8 +37,8 @@
<arg><option>--postimport=cmd</option></arg>
<arg><option>--[no-]interactive</option></arg>
<group choice="plain">
- <arg choice="plain"><replaceable>upstream-source</replaceable></arg>
- <arg><option>--uscan</option></arg>
+ <arg choice="plain"><replaceable>upstream-source</replaceable></arg>
+ <arg><option>--uscan</option></arg>
</group>
</cmdsynopsis>
</refsynopsisdiv>
@@ -50,201 +50,215 @@
be a gzip, bzip2, lzma or xz compressed tar archive, a zip archive or an
already unpacked source tree. If it is already of the form
<replaceable>package-name_version.orig.tar.gz</replaceable>, the version
- information is read from the tarball's filename otherwise it can be
- given on the command line via <option>--upstream-version</option>.
- If the source package name or version can't be determined
- &gbp-import-orig; will prompt for it unless <option>--no-interactive</option>
- is given.</para>
-
- <para>The sources are placed on the upstream branch (default:
+ information is read from the tarball's filename otherwise it can be given
+ on the command line via <option>--upstream-version</option>. If the source
+ package name or version can't be determined &gbp-import-orig; will prompt
+ for it unless <option>--no-interactive</option> is given.
+ </para>
+ <para>
+ The sources are placed on the upstream branch (default:
<replaceable>upstream</replaceable>), tagged and merged onto the debian
branch (default: <replaceable>master</replaceable>).
</para>
</refsect1>
<refsect1>
<title>OPTIONS</title>
-
<variablelist>
+ &man.common.options.description;
+
<varlistentry>
<term><option>--upstream-version</option>=<replaceable>version</replaceable></term>
<term><option>-u</option><replaceable>version</replaceable></term>
<listitem>
- <para>The upstream version number</para>
+ <para>
+ The upstream version number
+ </para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>--merge</option></term>
+ <term><option>--[no-]merge</option></term>
<listitem>
- <para>Merge the upstream branch to the debian branch after import</para>
+ <para>
+ Merge the upstream branch to the debian branch after import
+ </para>
</listitem>
</varlistentry>
-
<varlistentry>
<term><option>--upstream-branch</option>=<replaceable>branch_name</replaceable>
</term>
<listitem>
- <para>The branch in the Git repository the upstream sources are put
- onto. Default is <replaceable>upstream</replaceable>.</para>
+ <para>
+ The branch in the Git repository the upstream sources are put
+ onto. Default is <replaceable>upstream</replaceable>.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--debian-branch</option>=<replaceable>branch_name</replaceable>
</term>
<listitem>
- <para>The branch in the Git repository the Debian package is being
- developed on, default is <replaceable>master</replaceable>. After
- importing the new sources on the upstream branch, &gbp-import-orig;
- will try to merge the new version onto this branch.</para>
+ <para>
+ The branch in the Git repository the Debian package is being
+ developed on, default is <replaceable>master</replaceable>. After
+ importing the new sources on the upstream branch, &gbp-import-orig;
+ will try to merge the new version onto this branch.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--upstream-vcs-tag</option>=<replaceable>tag_name</replaceable>
</term>
<listitem>
- <para>
- Add <replaceable>tag_name</replaceable> as additional parent to the commit
- of the upstream tarball. Useful when upstream uses git and you want to
- link to it's revision history.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term><option>--verbose</option></term>
- <term><option>-v</option></term>
- <listitem>
- <para>verbose execution</para>
+ <para>
+ Add <replaceable>tag_name</replaceable> as additional parent to the
+ commit of the upstream tarball. Useful when upstream uses git and you
+ want to link to it's revision history.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--[no-]sign-tags</option>
</term>
<listitem>
- <para>GPG sign all created tags</para>
+ <para>
+ GPG sign all created tags
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--keyid=</option><replaceable>gpg-keyid</replaceable>
</term>
<listitem>
- <para>use this keyid for gpg signing tags</para>
+ <para>
+ use this keyid for gpg signing tags
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--upstream-tag=</option><replaceable>tag-format</replaceable>
</term>
<listitem>
- <para>use this tag format when tagging upstream versions,
- default is <replaceable>upstream/%(version)s</replaceable></para>
+ <para>
+ use this tag format when tagging upstream versions,
+ default is <replaceable>upstream/%(version)s</replaceable>
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--import-msg=</option><replaceable>msg-format</replaceable>
</term>
<listitem>
- <para>use this format string for the commit message when
- importing upstream versions, default is <replaceable>Imported
- Upstream version %(version)s</replaceable></para>
+ <para>
+ use this format string for the commit message when importing upstream
+ versions, default is
+ <replaceable>Imported Upstream version %(version)s</replaceable>
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--filter=</option><replaceable>pattern</replaceable>
</term>
<listitem>
- <para>filter out files glob-matching pattern. Can be given multiple times.</para>
+ <para>
+ filter out files glob-matching pattern. Can be given multiple times.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--[no-]pristine-tar</option>
</term>
<listitem>
- <para>generate <command>pristine-tar</command> delta file</para>
+ <para>
+ generate <command>pristine-tar</command> delta file
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--[no-]filter-pristine-tar</option>
</term>
<listitem>
- <para>if using a filter also filter the files out of the tarball
- passed to <command>pristine-tar</command></para>
+ <para>
+ if using a filter also filter the files out of the tarball
+ passed to <command>pristine-tar</command>
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--[no-]symlink-orig</option></term>
<listitem>
- <para>
- Whether to create and keep a symlink from the upstream tarball
- to a Debian policy conformant upstream tarball name located in
- <filename class='directory'>../</filename>.
- </para>
- <para>
- This is a good idea if not using <command>pristine-tar</command>
- since it avoids creating a new tarball with a different md5sum.
- </para>
+ <para>
+ Whether to create and keep a symlink from the upstream tarball
+ to a Debian policy conformant upstream tarball name located in
+ <filename class="directory">../</filename>.
+ </para>
+ <para>
+ This is a good idea if not using <command>pristine-tar</command>
+ since it avoids creating a new tarball with a different md5sum.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--postimport=<replaceable>cmd</replaceable></option></term>
<listitem>
- <para>run <replaceable>cmd</replaceable> after the import.</para>
+ <para>
+ run <replaceable>cmd</replaceable> after the import.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--uscan</option></term>
<listitem>
- <para>Use uscan to fetch new upstream version.</para>
+ <para>
+ Use uscan to fetch new upstream version.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--[no-]interactive</option></term>
+ <listitem>
+ <para>
+ Run command interactively, i.e. ask package name and version if
+ needed.
+ </para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>EXAMPLES</title>
- <para>Download and import a new upstream version using the informantion from <filename>debian/watch</filename></para>
+ <para>
+ Download and import a new upstream version using the informantion from <filename>debian/watch</filename>
+ </para>
<screen>
&gbp-import-orig; --uscan
</screen>
- <para>After downloading an upstream tarball by hand import it</para>
+ <para>
+ After downloading an upstream tarball by hand import it
+ </para>
<screen>
&gbp-import-orig; ../upstream-tarball-0.1.tar.gz
</screen>
</refsect1>
<refsect1>
- &man.gbp.config-files;
+ &man.gbp.config-files;
</refsect1>
<refsect1>
<title>SEE ALSO</title>
-
<para>
- <citerefentry>
- <refentrytitle>gbp-buildpackage</refentrytitle>
- <manvolnum>1</manvolnum>
- </citerefentry>,
- <citerefentry>
- <refentrytitle>gbp-import-dsc</refentrytitle>
- <manvolnum>1</manvolnum>
- </citerefentry>,
- <citerefentry>
- <refentrytitle>gbp-import-dscs</refentrytitle>
- <manvolnum>1</manvolnum>
- </citerefentry>,
- <citerefentry>
- <refentrytitle>gbp-dch</refentrytitle>
- <manvolnum>1</manvolnum>
- </citerefentry>,
- <citerefentry>
- <refentrytitle>gbp.conf</refentrytitle>
- &dhconfsection;
- </citerefentry>,
+ <xref linkend="man.gbp.buildpackage">,
+ <xref linkend="man.gbp.import.dsc">,
+ <xref linkend="man.gbp.import.dscs">,
+ <xref linkend="man.gbp.dch">,
+ <xref linkend="man.gbp.conf">,
&man.seealso.common;
</para>
-
</refsect1>
<refsect1>
<title>AUTHOR</title>
-
- <para>&dhusername; &dhemail;</para>
-
+ <para>
+ &dhusername; &dhemail;
+ </para>
</refsect1>
</refentry>
-
<!-- LocalWords: xz lzma bzip gzip tarball
-->
diff --git a/docs/manpages/gbp-pq.sgml b/docs/manpages/gbp-pq.sgml
index 83f64123..f1afb04d 100644
--- a/docs/manpages/gbp-pq.sgml
+++ b/docs/manpages/gbp-pq.sgml
@@ -14,39 +14,40 @@
</refmeta>
<refnamediv>
<refname>gbp-pq</refname>
-
<refpurpose>Manage quilt patches on patch queue branches in git</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
&gbp-pq;
- <arg><option>--verbose</option></arg>
- <arg><option>--color=</option><replaceable>[auto|on|off]</replaceable></arg>
+ &man.common.options.synopsis;
<arg><option>--[no-]patch-numbers</option></arg>
<arg><option>--topic=</option><replaceable>topic</replaceable></arg>
<arg><option>--time-machine=</option><replaceable>num</replaceable></arg>
+ <arg><option>--[no-]drop</option></arg>
+ <arg><option>--force</option></arg>
<group choice="plain">
- <arg><option>drop</option></arg>
- <arg><option>export</option></arg>
- <arg><option>import</option></arg>
- <arg><option>rebase</option></arg>
- <arg><option>switch</option></arg>
+ <arg><option>drop</option></arg>
+ <arg><option>export</option></arg>
+ <arg><option>import</option></arg>
+ <arg><option>rebase</option></arg>
+ <arg><option>switch</option></arg>
</group>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>DESCRIPTION</title>
<para>
- &gbp-pq helps one to manage quilt patches in Debian packages that are maintained
- with &gbp;. This is especially useful with packages using the
- 3.0 (quilt) source format. With &gbp-pq; you can maintain the quilt patches
- that should be applied to a package on a separate branch called patch-queue
- branch. So if your Debian package lives on <replaceable>master</replaceable>
- the associated patch-queue branch will be called
- <replaceable>patch-queue/master</replaceable>.
+ &gbp-pq; helps one to manage quilt patches in Debian packages that are
+ maintained with &gbp;. This is especially useful with packages using the
+ 3.0 (quilt) source format. With &gbp-pq; you can maintain the quilt patches
+ that should be applied to a package on a separate branch called patch-queue
+ branch. So if your Debian package lives on
+ <replaceable>master</replaceable> the associated patch-queue branch will be
+ called <replaceable>patch-queue/master</replaceable>.
</para>
<para>
- See <ulink url="https://honk.sigxcpu.org/piki/development/debian_packages_in_git/"></ulink> for example workflows.
+ See <ulink url="https://honk.sigxcpu.org/piki/development/debian_packages_in_git/"></ulink>
+ for example workflows.
</para>
</refsect1>
<refsect1>
@@ -56,64 +57,66 @@
<term><option>import</option>
</term>
<listitem>
- <para>
- Create a patch queue branch from quilt patches in debian/patches/ that
- are listed in debian/patches/series.
- </para>
+ <para>
+ Create a patch queue branch from quilt patches in debian/patches/
+ that are listed in debian/patches/series. The patches must apply
+ without fuzz.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>export</option>
</term>
<listitem>
- <para>
- Export the patches on the patch-queue branch associated to the current
- branch into a quilt patch series in debian/patches/ and update the
- series file.
- </para>
+ <para>
+ Export the patches on the patch-queue branch associated to the
+ current branch into a quilt patch series in debian/patches/ and
+ update the series file.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>rebase</option>
</term>
<listitem>
- <para>
- Switch to the patch-queue branch associated to the current branch and
- rebase it against the current branch.
- </para>
+ <para>
+ Switch to the patch-queue branch associated to the current branch and
+ rebase it against the current branch.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>drop</option>
</term>
<listitem>
- <para>
- Drop (delete) the patch queue associated to the current branch. So if
- you're on branch <replaceable>foo</replaceable> this would drop branch
- <replaceable>patch-queue/foo</replaceable>.
- </para>
+ <para>
+ Drop (delete) the patch queue associated to the current branch. So if
+ you're on branch <replaceable>foo</replaceable> this would drop
+ branch <replaceable>patch-queue/foo</replaceable>.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>apply</option>
</term>
<listitem>
- <para>
- Add a single patch to the patch-queue similar to using
- <command>git-am</command>. Use <option>--topic</option> if you want
- the patch to appear in a separate subdir when exporting the patch queue
- using <option>export</option>. This can be used to separate upstream
- pathes from debian specific patches.</para>
+ <para>
+ Add a single patch to the patch-queue similar to using
+ <command>git-am</command>. Use <option>--topic</option> if you want
+ the patch to appear in a separate subdir when exporting the patch queue
+ using <option>export</option>. This can be used to separate upstream
+ pathes from debian specific patches.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>switch</option>
</term>
<listitem>
- <para>
- Switch to the patch-queue branch if on the base branch and switch
- to base branch if on patch-queue branch.
- </para>
+ <para>
+ Switch to the patch-queue branch if on the base branch and switch
+ to base branch if on patch-queue branch.
+ </para>
</listitem>
</varlistentry>
</variablelist>
@@ -121,44 +124,51 @@
<refsect1>
<title>OPTIONS</title>
<variablelist>
+ &man.common.options.description;
+
<varlistentry>
- <term><option>--verbose</option></term>
- <term><option>-v</option></term>
+ <term><option>--[no-]patch-numbers</option>
+ </term>
<listitem>
- <para>verbose execution</para>
+ <para>
+ Whether the patch files should start with a number or not.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>--color=</option><replaceable>[auto|on|off]</replaceable>
+ <term><option>--topic=</option><replaceable>topic</replaceable>
</term>
<listitem>
- <para>Whether to use colored output.</para>
+ <para>
+ Topic to use when importing a single patch
+ </para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>--[no-]patch-numbers</option>
+ <term><option>--time-machine=</option><replaceable>NUM</replaceable>
</term>
<listitem>
- <para>Whether the patch files should start with a number or not.</para>
+ <para>
+ When importing a patch queue fails, go back commit by commit on the
+ current branch to check if the patch-queue applies there. Do this at
+ most <replaceable>NUM</replaceable> times. This can be useful if the
+ patch-queue doesn't apply to the current branch HEAD anymore, e.g.
+ after importing a new upstream version.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>--topic=</option><replaceable>topic</replaceable>
- </term>
+ <term><option>--[no-]drop</option></term>
<listitem>
- <para>Topic to use when importing a single patch</para>
+ <para>Whether to drop (delete) the patch queue branch after
+ a succesful export</para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>--time-machine=</option><replaceable>NUM</replaceable>
- </term>
+ <term><option>--force</option></term>
<listitem>
- <para>When importing a patch queue fails, go back commit by
- commit on the current branch to check if the patch-queue applies
- there. Do this at most <replaceable>NUM</replaceable> times. This can
- be useful if the patch-queue doesn't apply to the current branch HEAD
- anymore, e.g. after importing a new upstream version.
- </para>
+ <para>In case of import even import if the branch already
+ exists</para>
</listitem>
</varlistentry>
</variablelist>
@@ -172,28 +182,33 @@
</para>
<variablelist>
<varlistentry>
- <term><option>Gbp[-Pq]: Ignore</option></term>
+ <term><option>Gbp[-Pq]: Ignore</option>
+ </term>
<listitem>
- <para>Ignores the commit, no patch is generated out of it.</para>
+ <para>
+ Ignores the commit, no patch is generated out of it.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>Gbp[-Pq]: Topic</option> <replaceable>topic</replaceable></term>
+ <term><option>Gbp[-Pq]: Topic</option> <replaceable>topic</replaceable>
+ </term>
<listitem>
- <para>Moves the patch into a subdir called
- <replaceable>topic</replaceable> when running
- <screen>&gbp-pq; export</screen>
- This allows for some structure below
- <filename>debian/patches</filename>.
- </para>
+ <para>
+ Moves the patch into a subdir called <replaceable>topic</replaceable>
+ when running <screen>&gbp-pq; export</screen> This allows for some
+ structure below <filename>debian/patches</filename>.
+ </para>
</listitem>
</varlistentry>
<varlistentry>
- <term><option>Gbp-Pq-Topic:</option> <replaceable>topic</replaceable></term>
+ <term><option>Gbp-Pq-Topic:</option> <replaceable>topic</replaceable>
+ </term>
<listitem>
- <para>Deprecated: use <option>Gbp[-Pq]: Topic</option>
- <replaceable>topic</replaceable> instead.
- </para>
+ <para>
+ Deprecated: use <option>Gbp[-Pq]: Topic</option>
+ <replaceable>topic</replaceable> instead.
+ </para>
</listitem>
</varlistentry>
</variablelist>
@@ -201,10 +216,7 @@
<refsect1>
<title>SEE ALSO</title>
<para>
- <citerefentry>
- <refentrytitle>gbp-buildpackage</refentrytitle>
- <manvolnum>1</manvolnum>
- </citerefentry>,
+ <xref linkend="man.gbp.buildpackage">,
<citerefentry>
<refentrytitle>dpkg-source</refentrytitle>
<manvolnum>1</manvolnum>
@@ -213,16 +225,13 @@
<refentrytitle>quilt</refentrytitle>
<manvolnum>1</manvolnum>
</citerefentry>,
- <citerefentry>
- <refentrytitle>gbp.conf</refentrytitle>
- &dhconfsection;
- </citerefentry>
+ <xref linkend="man.gbp.conf">
</para>
</refsect1>
<refsect1>
<title>AUTHOR</title>
-
- <para>&dhusername; &dhemail;</para>
-
+ <para>
+ &dhusername; &dhemail;
+ </para>
</refsect1>
</refentry>
diff --git a/docs/manpages/gbp-pull.sgml b/docs/manpages/gbp-pull.sgml
index d223228e..fd658c8d 100644
--- a/docs/manpages/gbp-pull.sgml
+++ b/docs/manpages/gbp-pull.sgml
@@ -21,7 +21,7 @@
<cmdsynopsis>
&gbp-pull;
- <arg><option>--verbose</option></arg>
+ &man.common.options.synopsis;
<arg><option>--force</option></arg>
<arg><option>--redo-pq</option></arg>
<arg><option>--[no-]pristine-tar</option></arg>
@@ -44,6 +44,8 @@
<title>OPTIONS</title>
<variablelist>
+ &man.common.options.description;
+
<varlistentry>
<term><option>--force</option></term>
<listitem>
@@ -90,13 +92,6 @@
</listitem>
</varlistentry>
<varlistentry>
- <term><option>--verbose</option></term>
- <term><option>-v</option></term>
- <listitem>
- <para>verbose execution</para>
- </listitem>
- </varlistentry>
- <varlistentry>
<term><option>--pristine-tar</option>
</term>
<listitem>
@@ -108,7 +103,7 @@
<refsect1>
<title>EXIT CODES</title>
<para>
- When &gbp-pull finishes it indicates success or failure with it's exit code:
+ When &gbp-pull; finishes it indicates success or failure with it's exit code:
</para>
<variablelist>
<varlistentry>
@@ -137,22 +132,10 @@
<refsect1>
<title>SEE ALSO</title>
<para>
- <citerefentry>
- <refentrytitle>gbp-buildpackage</refentrytitle>
- <manvolnum>1</manvolnum>
- </citerefentry>,
- <citerefentry>
- <refentrytitle>gbp-clone</refentrytitle>
- <manvolnum>1</manvolnum>
- </citerefentry>,
- <citerefentry>
- <refentrytitle>gbp-pq</refentrytitle>
- <manvolnum>1</manvolnum>
- </citerefentry>,
- <citerefentry>
- <refentrytitle>gbp.conf</refentrytitle>
- &dhconfsection;
- </citerefentry>
+ <xref linkend="man.gbp.buildpackage">,
+ <xref linkend="man.gbp.clone">,
+ <xref linkend="man.gbp.pq">,
+ <xref linkend="man.gbp.conf">
</para>
</refsect1>
<refsect1>
diff --git a/docs/manpages/gbp.conf.sgml b/docs/manpages/gbp.conf.sgml
index a580220a..a0228759 100644
--- a/docs/manpages/gbp.conf.sgml
+++ b/docs/manpages/gbp.conf.sgml
@@ -215,38 +215,14 @@ the above list of configuration files.</para></listitem>
<refsect1>
<title>SEE ALSO</title>
<para>
- <citerefentry>
- <refentrytitle>gbp-clone</refentrytitle>
- <manvolnum>1</manvolnum>
- </citerefentry>,
- <citerefentry>
- <refentrytitle>gbp-create-remote-repo</refentrytitle>
- <manvolnum>1</manvolnum>
- </citerefentry>,
- <citerefentry>
- <refentrytitle>gbp-pq</refentrytitle>
- <manvolnum>1</manvolnum>
- </citerefentry>
- <citerefentry>
- <refentrytitle>gbp-pull</refentrytitle>
- <manvolnum>1</manvolnum>
- </citerefentry>,
- <citerefentry>
- <refentrytitle>gbp-dch</refentrytitle>
- <manvolnum>1</manvolnum>
- </citerefentry>,
- <citerefentry>
- <refentrytitle>gbp-import-dsc</refentrytitle>
- <manvolnum>1</manvolnum>
- </citerefentry>,
- <citerefentry>
- <refentrytitle>gbp-import-orig</refentrytitle>
- <manvolnum>1</manvolnum>
- </citerefentry>,
- <citerefentry>
- <refentrytitle>gbp-buildpackage</refentrytitle>
- <manvolnum>1</manvolnum>
- </citerefentry>,
+ <xref linkend="man.gbp.clone">,
+ <xref linkend="man.gbp.create.remote.repo">,
+ <xref linkend="man.gbp.pq">,
+ <xref linkend="man.gbp.pull">,
+ <xref linkend="man.gbp.dch">,
+ <xref linkend="man.gbp.import.dsc">,
+ <xref linkend="man.gbp.import.orig">,
+ <xref linkend="man.gbp.buildpackage">,
<ulink url="file:///usr/share/doc/git-buildpackage/manual-html/index.html">
<citetitle>The Git-Buildpackage Manual</citetitle></ulink>
</para>
diff --git a/docs/manpages/gbp.sgml b/docs/manpages/gbp.sgml
index 2b570d4d..c0fdddc7 100644
--- a/docs/manpages/gbp.sgml
+++ b/docs/manpages/gbp.sgml
@@ -21,6 +21,8 @@
&gbp;
<group choice='req'>
<arg><option>--help</option></arg>
+ <arg><option>--version</option></arg>
+ <arg><option>--list-cmds</option></arg>
<arg><option>command</option><arg choice='opt' rep='repeat'><option>args</option></arg></arg>
</group>
</cmdsynopsis>
@@ -41,6 +43,20 @@
<para>Print help</para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><option>--version</option>
+ </term>
+ <listitem>
+ <para>Print the programs version</para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--list-cmds</option>
+ </term>
+ <listitem>
+ <para>List all available commands</para>
+ </listitem>
+ </varlistentry>
</variablelist>
</refsect1>
<refsect1>
@@ -138,42 +154,20 @@
<refsect1>
<title>SEE ALSO</title>
<para>
- <citerefentry>
- <refentrytitle>gbp-import-dsc</refentrytitle>
- <manvolnum>1</manvolnum>
- </citerefentry>,
- <citerefentry>
- <refentrytitle>gbp-import-dscs</refentrytitle>
- <manvolnum>1</manvolnum>
- </citerefentry>,
- <citerefentry>
- <refentrytitle>gbp-import-orig</refentrytitle>
- <manvolnum>1</manvolnum>
- </citerefentry>,
- <citerefentry>
- <refentrytitle>gbp-dch</refentrytitle>
- <manvolnum>1</manvolnum>
- </citerefentry>,
- <citerefentry>
- <refentrytitle>gbp-create-remote-repo</refentrytitle>
- <manvolnum>1</manvolnum>
- </citerefentry>,
- <citerefentry>
- <refentrytitle>gbp-pull</refentrytitle>
- <manvolnum>1</manvolnum>
- </citerefentry>,
- <citerefentry>
- <refentrytitle>gbp-clone</refentrytitle>
- <manvolnum>1</manvolnum>
- </citerefentry>,
+ <xref linkend="man.gbp.buildpackage">,
+ <xref linkend="man.gbp.import.dsc">,
+ <xref linkend="man.gbp.import.dscs">,
+ <xref linkend="man.gbp.import.orig">,
+ <xref linkend="man.gbp.dch">,
+ <xref linkend="man.gbp.pq">,
+ <xref linkend="man.gbp.create.remote.repo">,
+ <xref linkend="man.gbp.pull">,
+ <xref linkend="man.gbp.clone">,
<citerefentry>
<refentrytitle>git-pbuilder</refentrytitle>
<manvolnum>1</manvolnum>
</citerefentry>,
- <citerefentry>
- <refentrytitle>gbp.conf</refentrytitle>
- &dhconfsection;
- </citerefentry>
+ <xref linkend="man.gbp.conf">,
&man.seealso.common;
</para>
</refsect1>
diff --git a/docs/manpages/man.common-options.ent b/docs/manpages/man.common-options.ent
new file mode 100644
index 00000000..74bd9f0d
--- /dev/null
+++ b/docs/manpages/man.common-options.ent
@@ -0,0 +1,65 @@
+<!ENTITY man.common.options.synopsis
+"
+ <arg><option>--version</option></arg>
+ <arg><option>--help</option></arg>
+ <arg><option>--verbose</option></arg>
+ <arg><option>--color=</option><replaceable>[auto|on|off]</replaceable></arg>
+ <arg><option>--color-scheme=</option><replaceable>COLOR_SCHEME</replaceable></arg>
+"
+>
+<!ENTITY man.common.options.description
+"
+ <varlistentry>
+ <term><option>--version</option></term>
+ <listitem>
+ <para>
+ Print version of the program, i.e. version of the git-buildpackage
+ suite
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-v</option></term>
+ <term><option>--verbose</option></term>
+ <listitem>
+ <para>
+ Verbose execution
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>-h</option></term>
+ <term><option>--help</option></term>
+ <listitem>
+ <para>
+ Print help and exit
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--color=</option><replaceable>[auto|on|off]</replaceable>
+ </term>
+ <listitem>
+ <para>
+ Whether to use colored output.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--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>
+"
+>
+
diff --git a/docs/manpages/manpages.ent b/docs/manpages/manpages.ent
index d5882548..6b8ea95f 100644
--- a/docs/manpages/manpages.ent
+++ b/docs/manpages/manpages.ent
@@ -12,3 +12,5 @@
<!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 % COMMON.OPTIONS SYSTEM "man.common-options.ent">
+%COMMON.OPTIONS;
diff --git a/gbp.conf b/gbp.conf
index aa9c35f8..b97036df 100644
--- a/gbp.conf
+++ b/gbp.conf
@@ -12,6 +12,7 @@
# the default tag formats used:
#upstream-tag = upstream/%(version)s
#debian-tag = debian/%(version)s
+#debian-tag-msg = %(pkg)s Debian release %(version)s
# use pristine-tar:
#pristine-tar = True
# don't check if debian-branch == current branch:
@@ -105,6 +106,8 @@
# Options only affecting gbp pq
[pq]
#patch-numbers = False
+# Whether to drop patch queue after export
+#drop = False
# Options only affecting gbp clone
[clone]
diff --git a/gbp/command_wrappers.py b/gbp/command_wrappers.py
index 8a131e11..b8bd21f7 100644
--- a/gbp/command_wrappers.py
+++ b/gbp/command_wrappers.py
@@ -40,8 +40,7 @@ class Command(object):
capture_stderr=False):
self.cmd = cmd
self.args = args
- self.run_error = "Couldn't run '%s'" % (" ".join([self.cmd] +
- self.args))
+ self.run_error = "'%s' failed" % (" ".join([self.cmd] + self.args))
self.shell = shell
self.retcode = 1
self.stderr = ''
@@ -91,12 +90,11 @@ class Command(object):
try:
retcode = self.__call(args)
if retcode < 0:
- err_detail = "%s was terminated by signal %d" % (self.cmd,
- -retcode)
+ err_detail = "it was terminated by signal %d" % -retcode
elif retcode > 0:
- err_detail = "%s returned %d" % (self.cmd, retcode)
+ err_detail = "it exited with %d" % retcode
except OSError as err:
- err_detail = "Execution failed: %s" % err
+ err_detail = "execution failed: %s" % err
retcode = 1
if retcode and not quiet:
log.err("%s: %s" % (self.run_error, err_detail))
diff --git a/gbp/config.py b/gbp/config.py
index fc31076e..174eba42 100644
--- a/gbp/config.py
+++ b/gbp/config.py
@@ -106,6 +106,7 @@ class GbpOptionParser(OptionParser):
'postimport' : '',
'hooks' : 'True',
'debian-tag' : 'debian/%(version)s',
+ 'debian-tag-msg' : '%(pkg)s Debian release %(version)s',
'upstream-tag' : 'upstream/%(version)s',
'import-msg' : 'Imported Upstream version %(version)s',
'commit-msg' : 'Update changelog for %(version)s release',
@@ -154,6 +155,8 @@ class GbpOptionParser(OptionParser):
'allow-unauthenticated': 'False',
'symlink-orig': 'True',
'purge': 'True',
+ 'drop': 'False',
+ 'commit': 'False',
}
help = {
'debian-branch':
@@ -167,6 +170,9 @@ class GbpOptionParser(OptionParser):
'debian-tag':
("Format string for debian tags, "
"default is '%(debian-tag)s'"),
+ 'debian-tag-msg':
+ ("Format string for signed debian-tag messages, "
+ "default is '%(debian-tag-msg)s'"),
'upstream-tag':
("Format string for upstream tags, "
"default is '%(upstream-tag)s'"),
@@ -196,6 +202,8 @@ class GbpOptionParser(OptionParser):
"Include the full commit message instead of only the first line, default is '%(full)s'",
'meta':
"Parse meta tags in commit messages, default is '%(meta)s'",
+ 'meta-closes':
+ "Meta tags for the bts close commands, default is '%(meta-closes)s'",
'ignore-new':
"Build with uncommited changes in the source tree, default is '%(ignore-new)s'",
'ignore-branch':
@@ -249,10 +257,10 @@ class GbpOptionParser(OptionParser):
("Set up tracking for remote branches, "
"default is '%(track)s'"),
'author-is-committer':
- ("Use the authors's name also as the comitter's name, "
+ ("Use the authors's name also as the committer's name, "
"default is '%(author-is-committer)s'"),
'author-date-is-committer-date':
- ("Use the authors's date as the comitter's date, "
+ ("Use the authors's date as the committer's date, "
"default is '%(author-date-is-committer-date)s'"),
'create-missing-branches':
("Create missing branches automatically, "
@@ -290,6 +298,11 @@ class GbpOptionParser(OptionParser):
"'%(symlink-orig)s'"),
'purge':
"Purge exported package build directory. Default is '%(purge)s'",
+ 'drop':
+ ("In case of 'export' drop the patch-queue branch "
+ "after export. Default is '%(drop)s'"),
+ 'commit':
+ "commit changes after export, Default is '%(commit)s'",
}
def_config_files = [ '/etc/git-buildpackage/gbp.conf',
@@ -516,4 +529,37 @@ class GbpOptionParserDebian(GbpOptionParser):
'cleaner' : '/bin/true',
} )
+
+class GbpOptionParserRpm(GbpOptionParser):
+ """
+ Handles commandline options and parsing of config files for rpm tools
+ """
+ defaults = dict(GbpOptionParser.defaults)
+ defaults.update({
+ 'tmp-dir' : '/var/tmp/gbp/',
+ 'vendor' : 'Downstream',
+ 'packaging-branch' : 'master',
+ 'packaging-dir' : '',
+ 'packaging-tag' : 'packaging/%(version)s',
+ })
+
+ help = dict(GbpOptionParser.help)
+ help.update({
+ 'tmp-dir':
+ "Base directory under which temporary directories are "
+ "created, default is '%(tmp-dir)s'",
+ 'vendor':
+ "Distribution vendor name, default is '%(vendor)s'",
+ 'packaging-branch':
+ "Branch the packaging is being maintained on, rpm counterpart "
+ "of the 'debian-branch' option, default is "
+ "'%(packaging-branch)s'",
+ 'packaging-dir':
+ "Subdir for RPM packaging files, default is "
+ "'%(packaging-dir)s'",
+ 'packaging-tag':
+ "Format string for packaging tags, RPM counterpart of the "
+ "'debian-tag' option, default is '%(packaging-tag)s'",
+ })
+
# vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·:
diff --git a/gbp/deb/dscfile.py b/gbp/deb/dscfile.py
index e2492dcc..06713288 100644
--- a/gbp/deb/dscfile.py
+++ b/gbp/deb/dscfile.py
@@ -20,12 +20,12 @@ import os
import re
from gbp.errors import GbpError
-from gbp.pkg import UpstreamSource
+from gbp.deb.upstreamsource import DebianUpstreamSource
from gbp.deb.policy import DebianPkgPolicy
class DscFile(object):
"""Keeps all needed data read from a dscfile"""
- compressions = r"(%s)" % '|'.join(UpstreamSource.known_compressions())
+ compressions = r"(%s)" % '|'.join(DebianUpstreamSource.known_compressions())
pkg_re = re.compile(r'Source:\s+(?P<pkg>.+)\s*')
version_re = re.compile(r'Version:\s((?P<epoch>\d+)\:)?'
'(?P<version>[%s]+)\s*$'
diff --git a/gbp/deb/git.py b/gbp/deb/git.py
index 7a328bed..2a848d4f 100644
--- a/gbp/deb/git.py
+++ b/gbp/deb/git.py
@@ -1,6 +1,6 @@
# vim: set fileencoding=utf-8 :
#
-# (C) 2011 Guido Günther <agx@sigxcpu.org>
+# (C) 2011,2014 Guido Günther <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
@@ -19,6 +19,7 @@
import re
from gbp.git import GitRepository, GitRepositoryError
from gbp.deb.pristinetar import DebianPristineTar
+from gbp.format import format_msg
class DebianGitRepository(GitRepository):
"""A git repository that holds the source of a Debian package"""
@@ -104,7 +105,7 @@ class DebianGitRepository(GitRepository):
>>> DebianGitRepository.version_to_tag("debian/%(version)s", "0:0~0")
'debian/0%0_0'
"""
- return format % dict(version=DebianGitRepository._sanitize_version(version))
+ return format_msg(format, dict(version=DebianGitRepository._sanitize_version(version)))
@staticmethod
def _sanitize_version(version):
diff --git a/gbp/deb/upstreamsource.py b/gbp/deb/upstreamsource.py
new file mode 100644
index 00000000..7eb555ae
--- /dev/null
+++ b/gbp/deb/upstreamsource.py
@@ -0,0 +1,28 @@
+# vim: set fileencoding=utf-8 :
+#
+# (C) 2013 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
+"""Debian-specific upstream sources"""
+
+from gbp.pkg import UpstreamSource
+from gbp.deb.policy import DebianPkgPolicy
+
+
+class DebianUpstreamSource(UpstreamSource):
+ """Upstream source class for Debian"""
+ def __init__(self, name, unpacked=None):
+ super(DebianUpstreamSource, self).__init__(name,
+ unpacked,
+ DebianPkgPolicy)
diff --git a/gbp/format.py b/gbp/format.py
new file mode 100644
index 00000000..2a4af15c
--- /dev/null
+++ b/gbp/format.py
@@ -0,0 +1,44 @@
+# vim: set fileencoding=utf-8 :
+#
+# (C) 2014 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
+# (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
+"""Format a message"""
+
+from gbp.errors import GbpError
+
+def format_msg(msg, args):
+ """
+ Format a strin with the given dict. Be a bit more verbose than
+ default python about the error cause.
+
+ >>> format_msg("%(foo)", {})
+ Traceback (most recent call last):
+ ...
+ GbpError: Failed to format %(foo): Missing value 'foo' in {}
+ >>> format_msg("%(foo)", {'foo': 'bar'})
+ Traceback (most recent call last):
+ ...
+ GbpError: Failed to format %(foo) with {'foo': 'bar'}: incomplete format
+ >>> format_msg("A %(foo)s is a %(bar)s", {'foo': 'dog', 'bar': 'mamal'})
+ 'A dog is a mamal'
+ """
+ try:
+ return msg % args
+ except ValueError as e:
+ raise GbpError("Failed to format %s with %s: %s" % (msg, args, e))
+ except KeyError as e:
+ raise GbpError("Failed to format %s: Missing value %s in %s" % (msg, e, args))
+
+
diff --git a/gbp/git/modifier.py b/gbp/git/modifier.py
index bc986491..2452e0b5 100644
--- a/gbp/git/modifier.py
+++ b/gbp/git/modifier.py
@@ -41,7 +41,7 @@ class GitTz(datetime.tzinfo):
return datetime.timedelta(0)
class GitModifier(object):
- """Stores authorship/comitter information"""
+ """Stores authorship/committer information"""
def __init__(self, name=None, email=None, date=None):
"""
@param name: the modifier's name
@@ -77,10 +77,10 @@ class GitModifier(object):
"datetime object or git raw date" % date)
def _get_env(self, who):
- """Get author or comitter information as env var dictionary"""
+ """Get author or committer information as env var dictionary"""
who = who.upper()
if who not in ['AUTHOR', 'COMMITTER']:
- raise GitModifierError("Neither comitter nor author")
+ raise GitModifierError("Neither committer nor author")
extra_env = {}
if self.name:
@@ -130,7 +130,7 @@ class GitModifier(object):
def get_committer_env(self):
"""
- Get env vars for comitter information
+ Get env vars for committer information
>>> g = GitModifier("foo", "bar")
>>> g.get_committer_env()
diff --git a/gbp/git/repository.py b/gbp/git/repository.py
index 10b90308..23f9482a 100644
--- a/gbp/git/repository.py
+++ b/gbp/git/repository.py
@@ -1408,7 +1408,7 @@ class GitRepository(object):
@param parents: parents of this commit
@param author: authorship information
@type author: C{dict} with keys 'name' and 'email' or L{GitModifier}
- @param committer: comitter information
+ @param committer: committer information
@type committer: C{dict} with keys 'name' and 'email'
"""
extra_env = {}
diff --git a/gbp/git/vfs.py b/gbp/git/vfs.py
index 81649eb9..5d5e1323 100644
--- a/gbp/git/vfs.py
+++ b/gbp/git/vfs.py
@@ -41,7 +41,7 @@ class GitVfs(object):
return self._data.read(size)
def close(self):
- return self.close()
+ return self._data.close()
def __init__(self, repo, committish=None):
"""
diff --git a/gbp/pkg/__init__.py b/gbp/pkg/__init__.py
index e68fc61a..34f81cda 100644
--- a/gbp/pkg/__init__.py
+++ b/gbp/pkg/__init__.py
@@ -34,6 +34,66 @@ compressor_opts = { 'gzip' : [ '-n', 'gz' ],
compressor_aliases = { 'bz2' : 'bzip2',
'gz' : 'gzip', }
+# Supported archive formats
+archive_formats = [ 'tar', 'zip' ]
+
+# Map combined file extensions to archive and compression format
+archive_ext_aliases = { 'tgz' : ('tar', 'gzip'),
+ 'tbz2' : ('tar', 'bzip2'),
+ 'tlz' : ('tar', 'lzma'),
+ 'txz' : ('tar', 'xz')}
+
+def parse_archive_filename(filename):
+ """
+ Given an filename return the basename (i.e. filename without the
+ archive and compression extensions), archive format and compression
+ method used.
+
+ @param filename: the name of the file
+ @type filename: string
+ @return: tuple containing basename, archive format and compression method
+ @rtype: C{tuple} of C{str}
+
+ >>> parse_archive_filename("abc.tar.gz")
+ ('abc', 'tar', 'gzip')
+ >>> parse_archive_filename("abc.tar.bz2")
+ ('abc', 'tar', 'bzip2')
+ >>> parse_archive_filename("abc.def.tbz2")
+ ('abc.def', 'tar', 'bzip2')
+ >>> parse_archive_filename("abc.def.tar.xz")
+ ('abc.def', 'tar', 'xz')
+ >>> parse_archive_filename("abc.zip")
+ ('abc', 'zip', None)
+ >>> parse_archive_filename("abc.lzma")
+ ('abc', None, 'lzma')
+ >>> parse_archive_filename("abc.tar.foo")
+ ('abc.tar.foo', None, None)
+ >>> parse_archive_filename("abc")
+ ('abc', None, None)
+ """
+ (base_name, archive_fmt, compression) = (filename, None, None)
+
+ # Split filename to pieces
+ split = filename.split(".")
+ if len(split) > 1:
+ if split[-1] in archive_ext_aliases:
+ base_name = ".".join(split[:-1])
+ (archive_fmt, compression) = archive_ext_aliases[split[-1]]
+ elif split[-1] in archive_formats:
+ base_name = ".".join(split[:-1])
+ (archive_fmt, compression) = (split[-1], None)
+ else:
+ for (c, o) in compressor_opts.iteritems():
+ if o[1] == split[-1]:
+ base_name = ".".join(split[:-1])
+ compression = c
+ if len(split) > 2 and split[-2] in archive_formats:
+ base_name = ".".join(split[:-2])
+ archive_fmt = split[-2]
+
+ return (base_name, archive_fmt, compression)
+
+
class PkgPolicy(object):
"""
Common helpers for packaging policy.
@@ -72,25 +132,63 @@ class PkgPolicy(object):
return True if cls.upstreamversion_re.match(version) else False
@staticmethod
- def get_compression(orig_file):
+ def guess_upstream_src_version(filename, extra_regex=r''):
"""
- Given an orig file return the compression used
-
- >>> PkgPolicy.get_compression("abc.tar.gz")
- 'gzip'
- >>> PkgPolicy.get_compression("abc.tar.bz2")
- 'bzip2'
- >>> PkgPolicy.get_compression("abc.tar.foo")
- >>> PkgPolicy.get_compression("abc")
+ Guess the package name and version from the filename of an upstream
+ archive.
+
+ @param filename: filename (archive or directory) from which to guess
+ @type filename: C{string}
+ @param extra_regex: additional regex to apply, needs a 'package' and a
+ 'version' group
+ @return: (package name, version) or ('', '')
+ @rtype: tuple
+
+ >>> PkgPolicy.guess_upstream_src_version('foo-bar_0.2.orig.tar.gz')
+ ('foo-bar', '0.2')
+ >>> PkgPolicy.guess_upstream_src_version('foo-Bar_0.2.orig.tar.gz')
+ ('', '')
+ >>> PkgPolicy.guess_upstream_src_version('git-bar-0.2.tar.gz')
+ ('git-bar', '0.2')
+ >>> PkgPolicy.guess_upstream_src_version('git-bar-0.2-rc1.tar.gz')
+ ('git-bar', '0.2-rc1')
+ >>> PkgPolicy.guess_upstream_src_version('git-bar-0.2:~-rc1.tar.gz')
+ ('git-bar', '0.2:~-rc1')
+ >>> PkgPolicy.guess_upstream_src_version('git-Bar-0A2d:rc1.tar.bz2')
+ ('git-Bar', '0A2d:rc1')
+ >>> PkgPolicy.guess_upstream_src_version('git-1.tar.bz2')
+ ('git', '1')
+ >>> PkgPolicy.guess_upstream_src_version('kvm_87+dfsg.orig.tar.gz')
+ ('kvm', '87+dfsg')
+ >>> PkgPolicy.guess_upstream_src_version('foo-Bar-a.b.tar.gz')
+ ('', '')
+ >>> PkgPolicy.guess_upstream_src_version('foo-bar_0.2.orig.tar.xz')
+ ('foo-bar', '0.2')
+ >>> PkgPolicy.guess_upstream_src_version('foo-bar_0.2.orig.tar.lzma')
+ ('foo-bar', '0.2')
+ >>> PkgPolicy.guess_upstream_src_version('foo-bar-0.2.zip')
+ ('foo-bar', '0.2')
+ >>> PkgPolicy.guess_upstream_src_version('foo-bar-0.2.tlz')
+ ('foo-bar', '0.2')
"""
- try:
- ext = orig_file.rsplit('.',1)[1]
- except IndexError:
- return None
- for (c, o) in compressor_opts.iteritems():
- if o[1] == ext:
- return c
- return None
+ version_chars = r'[a-zA-Z\d\.\~\-\:\+]'
+ basename = parse_archive_filename(os.path.basename(filename))[0]
+
+ version_filters = map ( lambda x: x % version_chars,
+ ( # Debian upstream tarball: package_'<version>.orig.tar.gz'
+ r'^(?P<package>[a-z\d\.\+\-]+)_(?P<version>%s+)\.orig',
+ # Upstream 'package-<version>.tar.gz'
+ # or Debian native 'package_<version>.tar.gz'
+ # or directory 'package-<version>':
+ r'^(?P<package>[a-zA-Z\d\.\+\-]+)(-)(?P<version>[0-9]%s*)'))
+ if extra_regex:
+ version_filters = extra_regex + version_filters
+
+ for filter in version_filters:
+ m = re.match(filter, basename)
+ if m:
+ return (m.group('package'), m.group('version'))
+ return ('', '')
@staticmethod
def has_orig(orig_file, dir):
@@ -140,8 +238,9 @@ class UpstreamSource(object):
@cvar _unpacked: path to the unpacked source tree
@type _unpacked: string
"""
- def __init__(self, name, unpacked=None):
+ def __init__(self, name, unpacked=None, pkg_policy=PkgPolicy):
self._orig = False
+ self._pkg_policy = pkg_policy
self._path = name
self.unpacked = unpacked
@@ -278,63 +377,12 @@ class UpstreamSource(object):
except gbpc.CommandExecFailed:
# repackArchive already printed an error
raise GbpError
- return UpstreamSource(newarchive)
+ return type(self)(newarchive)
@staticmethod
def known_compressions():
return [ args[1][-1] for args in compressor_opts.items() ]
def guess_version(self, extra_regex=r''):
- """
- Guess the package name and version from the filename of an upstream
- archive.
-
- @param extra_regex: extra regular expression to check
- @type extra_regex: raw C{string}
-
- >>> UpstreamSource('foo-bar_0.2.orig.tar.gz').guess_version()
- ('foo-bar', '0.2')
- >>> UpstreamSource('foo-Bar_0.2.orig.tar.gz').guess_version()
- >>> UpstreamSource('git-bar-0.2.tar.gz').guess_version()
- ('git-bar', '0.2')
- >>> UpstreamSource('git-bar-0.2-rc1.tar.gz').guess_version()
- ('git-bar', '0.2-rc1')
- >>> UpstreamSource('git-bar-0.2:~-rc1.tar.gz').guess_version()
- ('git-bar', '0.2:~-rc1')
- >>> UpstreamSource('git-Bar-0A2d:rc1.tar.bz2').guess_version()
- ('git-Bar', '0A2d:rc1')
- >>> UpstreamSource('git-1.tar.bz2').guess_version()
- ('git', '1')
- >>> UpstreamSource('kvm_87+dfsg.orig.tar.gz').guess_version()
- ('kvm', '87+dfsg')
- >>> UpstreamSource('foo-Bar_0.2.orig.tar.gz').guess_version()
- >>> UpstreamSource('foo-Bar-a.b.tar.gz').guess_version()
- >>> UpstreamSource('foo-bar_0.2.orig.tar.xz').guess_version()
- ('foo-bar', '0.2')
- >>> UpstreamSource('foo-bar_0.2.orig.tar.lzma').guess_version()
- ('foo-bar', '0.2')
-
- @param extra_regex: additional regex to apply, needs a 'package' and a
- 'version' group
- @return: (package name, version) or None.
- @rtype: tuple
- """
- version_chars = r'[a-zA-Z\d\.\~\-\:\+]'
- if self.is_dir():
- extensions = ''
- else:
- extensions = r'\.tar\.(%s)' % "|".join(self.known_compressions())
-
- version_filters = map ( lambda x: x % (version_chars, extensions),
- ( # Debian upstream tarball: package_'<version>.orig.tar.gz'
- r'^(?P<package>[a-z\d\.\+\-]+)_(?P<version>%s+)\.orig%s',
- # Upstream 'package-<version>.tar.gz'
- # or directory 'package-<version>':
- r'^(?P<package>[a-zA-Z\d\.\+\-]+)-(?P<version>[0-9]%s*)%s'))
- if extra_regex:
- version_filters = extra_regex + version_filters
-
- for filter in version_filters:
- m = re.match(filter, os.path.basename(self.path))
- if m:
- return (m.group('package'), m.group('version'))
+ return self._pkg_policy.guess_upstream_src_version(self.path,
+ extra_regex)
diff --git a/gbp/rpm/__init__.py b/gbp/rpm/__init__.py
new file mode 100644
index 00000000..87f82ffa
--- /dev/null
+++ b/gbp/rpm/__init__.py
@@ -0,0 +1,962 @@
+# vim: set fileencoding=utf-8 :
+#
+# (C) 2006,2007 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
+"""provides some rpm source package related helpers"""
+
+import commands
+import sys
+import os
+import re
+import tempfile
+import glob
+import shutil as shutil
+from optparse import OptionParser
+from collections import defaultdict
+
+import gbp.command_wrappers as gbpc
+from gbp.errors import GbpError
+from gbp.git import GitRepositoryError
+from gbp.patch_series import (PatchSeries, Patch)
+import gbp.log
+from gbp.pkg import (UpstreamSource, compressor_opts, parse_archive_filename)
+from gbp.rpm.policy import RpmPkgPolicy
+from gbp.rpm.linkedlist import LinkedList
+from gbp.rpm.lib_rpm import librpm, get_librpm_log
+
+
+class NoSpecError(Exception):
+ """Spec file parsing error"""
+ pass
+
+class MacroExpandError(Exception):
+ """Macro expansion in spec file failed"""
+ pass
+
+
+class RpmUpstreamSource(UpstreamSource):
+ """Upstream source class for RPM packages"""
+ def __init__(self, name, unpacked=None, **kwargs):
+ super(RpmUpstreamSource, self).__init__(name,
+ unpacked,
+ RpmPkgPolicy,
+ **kwargs)
+
+
+class SrcRpmFile(object):
+ """Keeps all needed data read from a source rpm"""
+ def __init__(self, srpmfile):
+ # Do not required signed packages to be able to import
+ ts_vsflags = (librpm.RPMVSF_NOMD5HEADER | librpm.RPMVSF_NORSAHEADER |
+ librpm.RPMVSF_NOSHA1HEADER | librpm.RPMVSF_NODSAHEADER |
+ librpm.RPMVSF_NOMD5 | librpm.RPMVSF_NORSA |
+ librpm.RPMVSF_NOSHA1 | librpm.RPMVSF_NODSA)
+ srpmfp = open(srpmfile)
+ self.rpmhdr = librpm.ts(vsflags=ts_vsflags).hdrFromFdno(srpmfp.fileno())
+ srpmfp.close()
+ self.srpmfile = os.path.abspath(srpmfile)
+
+ @property
+ def version(self):
+ """Get the (downstream) version of the RPM package"""
+ version = dict(upstreamversion = self.rpmhdr[librpm.RPMTAG_VERSION],
+ release = self.rpmhdr[librpm.RPMTAG_RELEASE])
+ if self.rpmhdr[librpm.RPMTAG_EPOCH] is not None:
+ version['epoch'] = str(self.rpmhdr[librpm.RPMTAG_EPOCH])
+ return version
+
+ @property
+ def name(self):
+ """Get the name of the RPM package"""
+ return self.rpmhdr[librpm.RPMTAG_NAME]
+
+ @property
+ def upstreamversion(self):
+ """Get the upstream version of the RPM package"""
+ return self.rpmhdr[librpm.RPMTAG_VERSION]
+
+ @property
+ def packager(self):
+ """Get the packager of the RPM package"""
+ return self.rpmhdr[librpm.RPMTAG_PACKAGER]
+
+ def unpack(self, dest_dir):
+ """
+ Unpack the source rpm to tmpdir.
+ Leave the cleanup to the caller in case of an error.
+ """
+ gbpc.RunAtCommand('rpm2cpio',
+ [self.srpmfile, '|', 'cpio', '-id'],
+ shell=True)(dir=dest_dir)
+
+
+class SpecFile(object):
+ """Class for parsing/modifying spec files"""
+ tag_re = re.compile(r'^(?P<name>[a-z]+)(?P<num>[0-9]+)?\s*:\s*'
+ '(?P<value>\S(.*\S)?)\s*$', flags=re.I)
+ directive_re = re.compile(r'^%(?P<name>[a-z]+)(?P<num>[0-9]+)?'
+ '(\s+(?P<args>.*))?$', flags=re.I)
+ gbptag_re = re.compile(r'^\s*#\s*gbp-(?P<name>[a-z-]+)'
+ '(\s*:\s*(?P<args>\S.*))?$', flags=re.I)
+ # Here "sections" stand for all scripts, scriptlets and other directives,
+ # but not macros
+ section_identifiers = ('package', 'description', 'prep', 'build', 'install',
+ 'clean', 'check', 'pre', 'preun', 'post', 'postun', 'verifyscript',
+ 'files', 'changelog', 'triggerin', 'triggerpostin', 'triggerun',
+ 'triggerpostun')
+
+ def __init__(self, filename=None, filedata=None):
+
+ self._content = LinkedList()
+
+ # Check args: only filename or filedata can be given, not both
+ if filename is None and filedata is None:
+ raise NoSpecError("No filename or raw data given for parsing!")
+ elif filename and filedata:
+ raise NoSpecError("Both filename and raw data given, don't know "
+ "which one to parse!")
+ elif filename:
+ # Load spec file into our special data structure
+ self.specfile = os.path.basename(filename)
+ self.specdir = os.path.dirname(os.path.abspath(filename))
+ try:
+ with open(filename) as spec_file:
+ for line in spec_file.readlines():
+ self._content.append(line)
+ except IOError as err:
+ raise NoSpecError("Unable to read spec file: %s" % err)
+ else:
+ self.specfile = None
+ self.specdir = None
+ for line in filedata.splitlines():
+ self._content.append(line + '\n')
+
+ # Use rpm-python to parse the spec file content
+ self._filtertags = ("excludearch", "excludeos", "exclusivearch",
+ "exclusiveos","buildarch")
+ self._listtags = self._filtertags + ('source', 'patch',
+ 'requires', 'conflicts', 'recommends',
+ 'suggests', 'supplements', 'enhances',
+ 'provides', 'obsoletes', 'buildrequires',
+ 'buildconflicts', 'buildrecommends',
+ 'buildsuggests', 'buildsupplements',
+ 'buildenhances', 'collections',
+ 'nosource', 'nopatch')
+ self._specinfo = self._parse_filtered_spec(self._filtertags)
+
+ # Other initializations
+ source_header = self._specinfo.packages[0].header
+ self.name = source_header[librpm.RPMTAG_NAME]
+ self.upstreamversion = source_header[librpm.RPMTAG_VERSION]
+ self.release = source_header[librpm.RPMTAG_RELEASE]
+ # rpm-python returns epoch as 'long', convert that to string
+ self.epoch = str(source_header[librpm.RPMTAG_EPOCH]) \
+ if source_header[librpm.RPMTAG_EPOCH] != None else None
+ self.packager = source_header[librpm.RPMTAG_PACKAGER]
+ self._tags = {}
+ self._special_directives = defaultdict(list)
+ self._gbp_tags = defaultdict(list)
+
+ # Parse extra info from spec file
+ self._parse_content()
+
+ # Find 'Packager' tag. Needed to circumvent a bug in python-rpm where
+ # spec.sourceHeader[librpm.RPMTAG_PACKAGER] is not reset when a new spec
+ # file is parsed
+ if 'packager' not in self._tags:
+ self.packager = None
+
+ self.orig_src = self._guess_orig_file()
+
+ def _parse_filtered_spec(self, skip_tags):
+ """Parse a filtered spec file in rpm-python"""
+ skip_tags = [tag.lower() for tag in skip_tags]
+ with tempfile.NamedTemporaryFile(prefix='gbp') as filtered:
+ filtered.writelines(str(line) for line in self._content
+ if str(line).split(":")[0].strip().lower() not in skip_tags)
+ filtered.flush()
+ try:
+ # Parse two times to circumvent a rpm-python problem where
+ # macros are not expanded if used before their definition
+ librpm.spec(filtered.name)
+ return librpm.spec(filtered.name)
+ except ValueError as err:
+ rpmlog = get_librpm_log()
+ gbp.log.debug("librpm log:\n %s" %
+ "\n ".join(rpmlog))
+ raise GbpError("RPM error while parsing %s: %s (%s)" %
+ (self.specfile, err, rpmlog[-1]))
+
+ @property
+ def version(self):
+ """Get the (downstream) version"""
+ version = dict(upstreamversion = self.upstreamversion,
+ release = self.release)
+ if self.epoch != None:
+ version['epoch'] = self.epoch
+ return version
+
+ @property
+ def specpath(self):
+ """Get the dir/filename"""
+ return os.path.join(self.specdir, self.specfile)
+
+ @property
+ def ignorepatches(self):
+ """Get numbers of ignored patches as a sorted list"""
+ if 'ignore-patches' in self._gbp_tags:
+ data = self._gbp_tags['ignore-patches'][-1]['args'].split()
+ return sorted([int(num) for num in data])
+ return []
+
+ def _patches(self):
+ """Get all patch tags as a dict"""
+ if 'patch' not in self._tags:
+ return {}
+ return {patch['num']: patch for patch in self._tags['patch']['lines']}
+
+ def _sources(self):
+ """Get all source tags as a dict"""
+ if 'source' not in self._tags:
+ return {}
+ return {src['num']: src for src in self._tags['source']['lines']}
+
+ def sources(self):
+ """Get all source tags as a dict"""
+ return {src['num']: src['linevalue']
+ for src in self._sources().values()}
+
+ def _macro_replace(self, matchobj):
+ macro_dict = {'name': self.name,
+ 'version': self.upstreamversion,
+ 'release': self.release}
+
+ if matchobj.group(2) in macro_dict:
+ return macro_dict[matchobj.group(2)]
+ raise MacroExpandError("Unknown macro '%s'" % matchobj.group(0))
+
+ def macro_expand(self, text):
+ """
+ Expand the rpm macros (that gbp knows of) in the given text.
+
+ @param text: text to check for macros
+ @type text: C{str}
+ @return: text with macros expanded
+ @rtype: C{str}
+ """
+ # regexp to match '%{macro}' and '%macro'
+ macro_re = re.compile(r'%({)?(?P<macro_name>[a-z_][a-z0-9_]*)(?(1)})', flags=re.I)
+ return macro_re.sub(self._macro_replace, text)
+
+ def write_spec_file(self):
+ """
+ Write, possibly updated, spec to disk
+ """
+ with open(os.path.join(self.specdir, self.specfile), 'w') as spec_file:
+ for line in self._content:
+ spec_file.write(str(line))
+
+ def _parse_tag(self, lineobj):
+ """Parse tag line"""
+
+ line = str(lineobj)
+
+ matchobj = self.tag_re.match(line)
+ if not matchobj:
+ return False
+
+ tagname = matchobj.group('name').lower()
+ tagnum = int(matchobj.group('num')) if matchobj.group('num') else None
+ # 'Source:' tags
+ if tagname == 'source':
+ tagnum = 0 if tagnum is None else tagnum
+ # 'Patch:' tags
+ elif tagname == 'patch':
+ tagnum = -1 if tagnum is None else tagnum
+
+ # Record all tag locations
+ try:
+ header = self._specinfo.packages[0].header
+ tagvalue = header[getattr(librpm, 'RPMTAG_%s' % tagname.upper())]
+ except AttributeError:
+ tagvalue = None
+ # We don't support "multivalue" tags like "Provides:" or "SourceX:"
+ # Rpm python doesn't support many of these, thus the explicit list
+ if type(tagvalue) is int or type(tagvalue) is long:
+ tagvalue = str(tagvalue)
+ elif type(tagvalue) is list or tagname in self._listtags:
+ tagvalue = None
+ elif not tagvalue:
+ # Rpm python doesn't give the following, for reason or another
+ if tagname not in ('buildroot', 'autoprov', 'autoreq',
+ 'autoreqprov') + self._filtertags:
+ gbp.log.warn("BUG: '%s:' tag not found by rpm" % tagname)
+ tagvalue = matchobj.group('value')
+ linerecord = {'line': lineobj,
+ 'num': tagnum,
+ 'linevalue': matchobj.group('value')}
+ if tagname in self._tags:
+ self._tags[tagname]['value'] = tagvalue
+ self._tags[tagname]['lines'].append(linerecord)
+ else:
+ self._tags[tagname] = {'value': tagvalue, 'lines': [linerecord]}
+
+ return tagname
+
+ @staticmethod
+ def _patch_macro_opts(args):
+ """Parse arguments of the '%patch' macro"""
+
+ patchparser = OptionParser()
+ patchparser.add_option("-p", dest="strip")
+ patchparser.add_option("-s", dest="silence")
+ patchparser.add_option("-P", dest="patchnum")
+ patchparser.add_option("-b", dest="backup")
+ patchparser.add_option("-E", dest="removeempty")
+ arglist = args.split()
+ return patchparser.parse_args(arglist)[0]
+
+ @staticmethod
+ def _setup_macro_opts(args):
+ """Parse arguments of the '%setup' macro"""
+
+ setupparser = OptionParser()
+ setupparser.add_option("-n", dest="name")
+ setupparser.add_option("-c", dest="create_dir", action="store_true")
+ setupparser.add_option("-D", dest="no_delete_dir", action="store_true")
+ setupparser.add_option("-T", dest="no_unpack_default",
+ action="store_true")
+ setupparser.add_option("-b", dest="unpack_before")
+ setupparser.add_option("-a", dest="unpack_after")
+ setupparser.add_option("-q", dest="quiet", action="store_true")
+ arglist = args.split()
+ return setupparser.parse_args(arglist)[0]
+
+ def _parse_directive(self, lineobj):
+ """Parse special directive/scriptlet/macro lines"""
+
+ line = str(lineobj)
+ matchobj = self.directive_re.match(line)
+ if not matchobj:
+ return None
+
+ directivename = matchobj.group('name')
+ # '%patch' macros
+ directiveid = None
+ if directivename == 'patch':
+ opts = self._patch_macro_opts(matchobj.group('args'))
+ if matchobj.group('num'):
+ directiveid = int(matchobj.group('num'))
+ elif opts.patchnum:
+ directiveid = int(opts.patchnum)
+ else:
+ directiveid = -1
+
+ # Record special directive/scriptlet/macro locations
+ if directivename in self.section_identifiers + ('setup', 'patch'):
+ linerecord = {'line': lineobj,
+ 'id': directiveid,
+ 'args': matchobj.group('args')}
+ self._special_directives[directivename].append(linerecord)
+ return directivename
+
+ def _parse_gbp_tag(self, linenum, lineobj):
+ """Parse special git-buildpackage tags"""
+
+ line = str(lineobj)
+ matchobj = self.gbptag_re.match(line)
+ if matchobj:
+ gbptagname = matchobj.group('name').lower()
+ if gbptagname not in ('ignore-patches', 'patch-macros'):
+ gbp.log.info("Found unrecognized Gbp tag on line %s: '%s'" %
+ (linenum, line))
+ if matchobj.group('args'):
+ args = matchobj.group('args').strip()
+ else:
+ args = None
+ record = {'line': lineobj, 'args': args}
+ self._gbp_tags[gbptagname].append(record)
+ return gbptagname
+
+ return None
+
+ def _parse_content(self):
+ """
+ Go through spec file content line-by-line and (re-)parse info from it
+ """
+ in_preamble = True
+ for linenum, lineobj in enumerate(self._content):
+ matched = False
+ if in_preamble:
+ if self._parse_tag(lineobj):
+ continue
+ matched = self._parse_directive(lineobj)
+ if matched:
+ if matched in self.section_identifiers:
+ in_preamble = False
+ continue
+ self._parse_gbp_tag(linenum, lineobj)
+
+ # Update sources info (basically possible macros expanded by rpm)
+ # And, double-check that we parsed spec content correctly
+ patches = self._patches()
+ sources = self._sources()
+ for name, num, typ in self._specinfo.sources:
+ # workaround rpm parsing bug
+ if typ == 1 or typ == 9:
+ if num in sources:
+ sources[num]['linevalue'] = name
+ else:
+ gbp.log.err("BUG: failed to parse all 'Source' tags!")
+ elif typ == 2 or typ == 10:
+ # Patch tag without any number defined is treated by RPM as
+ # having number (2^31-1), we use number -1
+ if num >= pow(2,30):
+ num = -1
+ if num in patches:
+ patches[num]['linevalue'] = name
+ else:
+ gbp.log.err("BUG: failed to parse all 'Patch' tags!")
+
+ def _delete_tag(self, tag, num):
+ """Delete a tag"""
+ key = tag.lower()
+ tagname = '%s%s' % (tag, num) if num is not None else tag
+ if key not in self._tags:
+ gbp.log.warn("Trying to delete non-existent tag '%s:'" % tag)
+ return None
+
+ sparedlines = []
+ prev = None
+ for line in self._tags[key]['lines']:
+ if line['num'] == num:
+ gbp.log.debug("Removing '%s:' tag from spec" % tagname)
+ prev = self._content.delete(line['line'])
+ else:
+ sparedlines.append(line)
+ self._tags[key]['lines'] = sparedlines
+ if not self._tags[key]['lines']:
+ self._tags.pop(key)
+ return prev
+
+ def _set_tag(self, tag, num, value, insertafter):
+ """Set a tag value"""
+ key = tag.lower()
+ tagname = '%s%s' % (tag, num) if num is not None else tag
+ value = value.strip()
+ if not value:
+ raise GbpError("Cannot set empty value to '%s:' tag" % tag)
+
+ # Check type of tag, we don't support values for 'multivalue' tags
+ try:
+ header = self._specinfo.packages[0].header
+ tagvalue = header[getattr(librpm, 'RPMTAG_%s' % tagname.upper())]
+ except AttributeError:
+ tagvalue = None
+ tagvalue = None if type(tagvalue) is list else value
+
+ # Try to guess the correct indentation from the previous or next tag
+ indent_re = re.compile(r'^([a-z]+([0-9]+)?\s*:\s*)', flags=re.I)
+ match = indent_re.match(str(insertafter))
+ if not match:
+ match = indent_re.match(str(insertafter.next))
+ indent = 12 if not match else len(match.group(1))
+ text = '%-*s%s\n' % (indent, '%s:' % tagname, value)
+ if key in self._tags:
+ self._tags[key]['value'] = tagvalue
+ for line in reversed(self._tags[key]['lines']):
+ if line['num'] == num:
+ gbp.log.debug("Updating '%s:' tag in spec" % tagname)
+ line['line'].set_data(text)
+ line['linevalue'] = value
+ return line['line']
+
+ gbp.log.debug("Adding '%s:' tag after '%s...' line in spec" %
+ (tagname, str(insertafter)[0:20]))
+ line = self._content.insert_after(insertafter, text)
+ linerec = {'line': line, 'num': num, 'linevalue': value}
+ if key in self._tags:
+ self._tags[key]['lines'].append(linerec)
+ else:
+ self._tags[key] = {'value': tagvalue, 'lines': [linerec]}
+ return line
+
+ def set_tag(self, tag, num, value, insertafter=None):
+ """Update a tag in spec file content"""
+ key = tag.lower()
+ tagname = '%s%s' % (tag, num) if num is not None else tag
+ if key in ('patch', 'vcs'):
+ if key in self._tags:
+ insertafter = key
+ elif not insertafter in self._tags:
+ insertafter = 'name'
+ after_line = self._tags[insertafter]['lines'][-1]['line']
+ if value:
+ self._set_tag(tag, num, value, after_line)
+ elif key in self._tags:
+ self._delete_tag(tag, num)
+ else:
+ raise GbpError("Setting '%s:' tag not supported" % tagname)
+
+ def _delete_special_macro(self, name, identifier):
+ """Delete a special macro line in spec file content"""
+ if name != 'patch':
+ raise GbpError("Deleting '%s:' macro not supported" % name)
+
+ key = name.lower()
+ fullname = '%%%s%s' % (name, identifier)
+ sparedlines = []
+ prev = None
+ for line in self._special_directives[key]:
+ if line['id'] == identifier:
+ gbp.log.debug("Removing '%s' macro from spec" % fullname)
+ prev = self._content.delete(line['line'])
+ else:
+ sparedlines.append(line)
+ self._special_directives[key] = sparedlines
+ if not prev:
+ gbp.log.warn("Tried to delete non-existent macro '%s'" % fullname)
+ return prev
+
+ def _set_special_macro(self, name, identifier, args, insertafter):
+ """Update a special macro line in spec file content"""
+ key = name.lower()
+ fullname = '%%%s%s' % (name, identifier)
+ if key != 'patch':
+ raise GbpError("Setting '%s' macro not supported" % name)
+
+ updated = 0
+ text = "%%%s%d %s\n" % (name, identifier, args)
+ for line in self._special_directives[key]:
+ if line['id'] == identifier:
+ gbp.log.debug("Updating '%s' macro in spec" % fullname)
+ line['args'] = args
+ line['line'].set_data(text)
+ ret = line['line']
+ updated += 1
+ if not updated:
+ gbp.log.debug("Adding '%s' macro after '%s...' line in spec" %
+ (fullname, str(insertafter)[0:20]))
+ ret = self._content.insert_after(insertafter, text)
+ linerec = {'line': ret, 'id': identifier, 'args': args}
+ self._special_directives[key].append(linerec)
+ return ret
+
+ def _set_section(self, name, text):
+ """Update/create a complete section in spec file."""
+ if name not in self.section_identifiers:
+ raise GbpError("Not a valid section directive: '%s'" % name)
+ # Delete section, if it exists
+ if name in self._special_directives:
+ if len(self._special_directives[name]) > 1:
+ raise GbpError("Multiple %%%s sections found, don't know "
+ "which to update" % name)
+ line = self._special_directives[name][0]['line']
+ gbp.log.debug("Removing content of %s section" % name)
+ while line.next:
+ match = self.directive_re.match(str(line.next))
+ if match and match.group('name') in self.section_identifiers:
+ break
+ self._content.delete(line.next)
+ else:
+ gbp.log.debug("Adding %s section to the end of spec file" % name)
+ line = self._content.append('%%%s\n' % name)
+ linerec = {'line': line, 'id': None, 'args': None}
+ self._special_directives[name] = [linerec]
+ # Add new lines
+ gbp.log.debug("Updating content of %s section" % name)
+ for linetext in text.splitlines():
+ line = self._content.insert_after(line, linetext + '\n')
+
+ def set_changelog(self, text):
+ """Update or create the %changelog section"""
+ self._set_section('changelog', text)
+
+ def get_changelog(self):
+ """Get the %changelog section"""
+ text = ''
+ if 'changelog' in self._special_directives:
+ line = self._special_directives['changelog'][0]['line']
+ while line.next:
+ line = line.next
+ match = self.directive_re.match(str(line))
+ if match and match.group('name') in self.section_identifiers:
+ break
+ text += str(line)
+ return text
+
+ def update_patches(self, patches, commands):
+ """Update spec with new patch tags and patch macros"""
+ # Remove non-ignored patches
+ tag_prev = None
+ macro_prev = None
+ ignored = self.ignorepatches
+ # Remove 'Patch:̈́' tags
+ for tag in self._patches().values():
+ if not tag['num'] in ignored:
+ tag_prev = self._delete_tag('patch', tag['num'])
+ # Remove a preceding comment if it seems to originate from GBP
+ if re.match("^\s*#.*patch.*auto-generated",
+ str(tag_prev), flags=re.I):
+ tag_prev = self._content.delete(tag_prev)
+
+ # Remove '%patch:' macros
+ for macro in self._special_directives['patch']:
+ if not macro['id'] in ignored:
+ macro_prev = self._delete_special_macro('patch', macro['id'])
+ # Remove surrounding if-else
+ macro_next = macro_prev.next
+ if (str(macro_prev).startswith('%if') and
+ str(macro_next).startswith('%endif')):
+ self._content.delete(macro_next)
+ macro_prev = self._content.delete(macro_prev)
+
+ # Remove a preceding comment line if it ends with '.patch' or
+ # '.diff' plus an optional compression suffix
+ if re.match("^\s*#.+(patch|diff)(\.(gz|bz2|xz|lzma))?\s*$",
+ str(macro_prev), flags=re.I):
+ macro_prev = self._content.delete(macro_prev)
+
+ if len(patches) == 0:
+ return
+
+ # Determine where to add Patch tag lines
+ if tag_prev:
+ gbp.log.debug("Adding 'Patch' tags in place of the removed tags")
+ tag_line = tag_prev
+ elif 'patch' in self._tags:
+ gbp.log.debug("Adding new 'Patch' tags after the last 'Patch' tag")
+ tag_line = self._tags['patch']['lines'][-1]['line']
+ elif 'source' in self._tags:
+ gbp.log.debug("Didn't find any old 'Patch' tags, adding new "
+ "patches after the last 'Source' tag.")
+ tag_line = self._tags['source']['lines'][-1]['line']
+ else:
+ gbp.log.debug("Didn't find any old 'Patch' or 'Source' tags, "
+ "adding new patches after the last 'Name' tag.")
+ tag_line = self._tags['name']['lines'][-1]['line']
+
+ # Determine where to add %patch macro lines
+ if 'patch-macros' in self._gbp_tags:
+ gbp.log.debug("Adding '%patch' macros after the start marker")
+ macro_line = self._gbp_tags['patch-macros'][-1]['line']
+ elif macro_prev:
+ gbp.log.debug("Adding '%patch' macros in place of the removed "
+ "macros")
+ macro_line = macro_prev
+ elif self._special_directives['patch']:
+ gbp.log.debug("Adding new '%patch' macros after the last existing"
+ "'%patch' macro")
+ macro_line = self._special_directives['patch'][-1]['line']
+ elif self._special_directives['setup']:
+ gbp.log.debug("Didn't find any old '%patch' macros, adding new "
+ "patches after the last '%setup' macro")
+ macro_line = self._special_directives['setup'][-1]['line']
+ elif self._special_directives['prep']:
+ gbp.log.warn("Didn't find any old '%patch' or '%setup' macros, "
+ "adding new patches directly after '%prep' directive")
+ macro_line = self._special_directives['prep'][-1]['line']
+ else:
+ raise GbpError("Couldn't determine where to add '%patch' macros")
+
+ startnum = sorted(ignored)[-1] + 1 if ignored else 0
+ gbp.log.debug("Starting autoupdate patch numbering from %s" % startnum)
+ # Add a comment indicating gbp generated patch tags
+ comment_text = "# Patches auto-generated by git-buildpackage:\n"
+ tag_line = self._content.insert_after(tag_line, comment_text)
+ for ind, patch in enumerate(patches):
+ cmds = commands[patch] if patch in commands else {}
+ patchnum = startnum + ind
+ tag_line = self._set_tag("Patch", patchnum, patch, tag_line)
+ # Add '%patch' macro and a preceding comment line
+ comment_text = "# %s\n" % patch
+ macro_line = self._content.insert_after(macro_line, comment_text)
+ macro_line = self._set_special_macro('patch', patchnum, '-p1',
+ macro_line)
+ for cmd, args in cmds.iteritems():
+ if cmd in ('if', 'ifarch'):
+ self._content.insert_before(macro_line, '%%%s %s\n' %
+ (cmd, args))
+ macro_line = self._content.insert_after(macro_line,
+ '%endif\n')
+ # We only support one command per patch, for now
+ break
+
+ def patchseries(self, unapplied=False, ignored=False):
+ """Return non-ignored patches of the RPM as a gbp patchseries"""
+ series = PatchSeries()
+ if 'patch' in self._tags:
+ tags = self._patches()
+ applied = []
+ for macro in self._special_directives['patch']:
+ if macro['id'] in tags:
+ applied.append((macro['id'], macro['args']))
+ ignored = set() if ignored else set(self.ignorepatches)
+
+ # Put all patches that are applied first in the series
+ for num, args in applied:
+ if num not in ignored:
+ opts = self._patch_macro_opts(args)
+ strip = int(opts.strip) if opts.strip else 0
+ filename = os.path.basename(tags[num]['linevalue'])
+ series.append(Patch(os.path.join(self.specdir, filename),
+ strip=strip))
+ # Finally, append all unapplied patches to the series, if requested
+ if unapplied:
+ applied_nums = set([num for num, _args in applied])
+ unapplied = set(tags.keys()).difference(applied_nums)
+ for num in sorted(unapplied):
+ if num not in ignored:
+ filename = os.path.basename(tags[num]['linevalue'])
+ series.append(Patch(os.path.join(self.specdir,
+ filename), strip=0))
+ return series
+
+ def _guess_orig_prefix(self, orig):
+ """Guess prefix for the orig file"""
+ # Make initial guess about the prefix in the archive
+ filename = orig['filename']
+ name, version = RpmPkgPolicy.guess_upstream_src_version(filename)
+ if name and version:
+ prefix = "%s-%s/" % (name, version)
+ else:
+ prefix = orig['filename_base'] + "/"
+
+ # Refine our guess about the prefix
+ for macro in self._special_directives['setup']:
+ args = macro['args']
+ opts = self._setup_macro_opts(args)
+ srcnum = None
+ if opts.no_unpack_default:
+ if opts.unpack_before:
+ srcnum = int(opts.unpack_before)
+ elif opts.unpack_after:
+ srcnum = int(opts.unpack_after)
+ else:
+ srcnum = 0
+ if srcnum == orig['num']:
+ if opts.create_dir:
+ prefix = ''
+ elif opts.name:
+ try:
+ prefix = self.macro_expand(opts.name) + '/'
+ except MacroExpandError as err:
+ gbp.log.warn("Couldn't determine prefix from %%setup "\
+ "macro (%s). Using filename base as a " \
+ "fallback" % err)
+ prefix = orig['filename_base'] + '/'
+ else:
+ # RPM default
+ prefix = "%s-%s/" % (self.name, self.upstreamversion)
+ break
+ return prefix
+
+ def _guess_orig_file(self):
+ """
+ Try to guess the name of the primary upstream/source archive.
+ Returns a dict with all the relevant information.
+ """
+ orig = None
+ sources = self.sources()
+ for num, filename in sorted(sources.iteritems()):
+ src = {'num': num, 'filename': os.path.basename(filename),
+ 'uri': filename}
+ src['filename_base'], src['archive_fmt'], src['compression'] = \
+ parse_archive_filename(os.path.basename(filename))
+ if (src['filename_base'].startswith(self.name) and
+ src['archive_fmt']):
+ # Take the first archive that starts with pkg name
+ orig = src
+ break
+ # otherwise we take the first archive
+ elif not orig and src['archive_fmt']:
+ orig = src
+ # else don't accept
+ if orig:
+ orig['prefix'] = self._guess_orig_prefix(orig)
+
+ return orig
+
+
+def parse_srpm(srpmfile):
+ """parse srpm by creating a SrcRpmFile object"""
+ try:
+ srcrpm = SrcRpmFile(srpmfile)
+ except IOError, err:
+ raise GbpError, "Error reading src.rpm file: %s" % err
+ except librpm.error, err:
+ raise GbpError, "RPM error while reading src.rpm: %s" % err
+
+ return srcrpm
+
+
+def guess_spec_fn(file_list, preferred_name=None):
+ """Guess spec file from a list of filenames"""
+ specs = []
+ for filepath in file_list:
+ filename = os.path.basename(filepath)
+ # Stop at the first file matching the preferred name
+ if filename == preferred_name:
+ gbp.log.debug("Found a preferred spec file %s" % filepath)
+ specs = [filepath]
+ break
+ if filename.endswith(".spec"):
+ gbp.log.debug("Found spec file %s" % filepath)
+ specs.append(filepath)
+ if len(specs) == 0:
+ raise NoSpecError("No spec file found.")
+ elif len(specs) > 1:
+ raise NoSpecError("Multiple spec files found (%s), don't know which "
+ "to use." % ', '.join(specs))
+ return specs[0]
+
+
+def guess_spec(topdir, recursive=True, preferred_name=None):
+ """Guess a spec file"""
+ file_list = []
+ if not topdir:
+ topdir = '.'
+ for root, dirs, files in os.walk(topdir):
+ file_list.extend([os.path.join(root, fname) for fname in files])
+ if not recursive:
+ del dirs[:]
+ # Skip .git dir in any case
+ if '.git' in dirs:
+ dirs.remove('.git')
+ return SpecFile(os.path.abspath(guess_spec_fn(file_list, preferred_name)))
+
+
+def guess_spec_repo(repo, treeish, topdir='', recursive=True, preferred_name=None):
+ """
+ Try to find/parse the spec file from a given git treeish.
+ """
+ topdir = topdir.rstrip('/') + ('/') if topdir else ''
+ try:
+ file_list = [nam for (mod, typ, sha, nam) in
+ repo.list_tree(treeish, recursive, topdir) if typ == 'blob']
+ except GitRepositoryError as err:
+ raise NoSpecError("Cannot find spec file from treeish %s, Git error: %s"
+ % (treeish, err))
+ spec_path = guess_spec_fn(file_list, preferred_name)
+ return spec_from_repo(repo, treeish, spec_path)
+
+
+def spec_from_repo(repo, treeish, spec_path):
+ """Get and parse a spec file from a give Git treeish"""
+ try:
+ spec = SpecFile(filedata=repo.show('%s:%s' % (treeish, spec_path)))
+ spec.specdir = os.path.dirname(spec_path)
+ spec.specfile = os.path.basename(spec_path)
+ return spec
+ except GitRepositoryError as err:
+ raise NoSpecError("Git error: %s" % err)
+
+
+def string_to_int(val_str):
+ """
+ Convert string of possible unit identifier to int.
+
+ @param val_str: value to be converted
+ @type val_str: C{str}
+ @return: value as integer
+ @rtype: C{int}
+
+ >>> string_to_int("1234")
+ 1234
+ >>> string_to_int("123k")
+ 125952
+ >>> string_to_int("1234K")
+ 1263616
+ >>> string_to_int("1M")
+ 1048576
+ """
+ units = {'k': 1024,
+ 'm': 1024**2,
+ 'g': 1024**3,
+ 't': 1024**4}
+
+ if val_str[-1].lower() in units:
+ return int(val_str[:-1]) * units[val_str[-1].lower()]
+ else:
+ return int(val_str)
+
+
+def split_version_str(version):
+ """
+ Parse full version string and split it into individual "version
+ components", i.e. upstreamversion, epoch and release
+
+ @param version: full version of a package
+ @type version: C{str}
+ @return: individual version components
+ @rtype: C{dict}
+
+ >>> split_version_str("1")
+ {'release': None, 'epoch': None, 'upstreamversion': '1'}
+ >>> split_version_str("1.2.3-5.3")
+ {'release': '5.3', 'epoch': None, 'upstreamversion': '1.2.3'}
+ >>> split_version_str("3:1.2.3")
+ {'release': None, 'epoch': '3', 'upstreamversion': '1.2.3'}
+ >>> split_version_str("3:1-0")
+ {'release': '0', 'epoch': '3', 'upstreamversion': '1'}
+ """
+ ret = {'epoch': None, 'upstreamversion': None, 'release': None}
+
+ e_vr = version.split(":", 1)
+ if len(e_vr) == 1:
+ v_r = e_vr[0].split("-", 1)
+ else:
+ ret['epoch'] = e_vr[0]
+ v_r = e_vr[1].split("-", 1)
+ ret['upstreamversion'] = v_r[0]
+ if len(v_r) > 1:
+ ret['release'] = v_r[1]
+
+ return ret
+
+def compose_version_str(evr):
+ """
+ Compose a full version string from individual "version components",
+ i.e. epoch, version and release
+
+ @param evr: dict of version components
+ @type evr: C{dict} of C{str}
+ @return: full version
+ @rtype: C{str}
+
+ >>> compose_version_str({'epoch': '', 'upstreamversion': '1.0'})
+ '1.0'
+ >>> compose_version_str({'epoch': '2', 'upstreamversion': '1.0', 'release': None})
+ '2:1.0'
+ >>> compose_version_str({'epoch': None, 'upstreamversion': '1', 'release': '0'})
+ '1-0'
+ >>> compose_version_str({'epoch': '2', 'upstreamversion': '1.0', 'release': '2.3'})
+ '2:1.0-2.3'
+ >>> compose_version_str({'epoch': '2', 'upstreamversion': '', 'release': '2.3'})
+ """
+ if 'upstreamversion' in evr and evr['upstreamversion']:
+ version = ""
+ if 'epoch' in evr and evr['epoch']:
+ version += "%s:" % evr['epoch']
+ version += evr['upstreamversion']
+ if 'release' in evr and evr['release']:
+ version += "-%s" % evr['release']
+ if version:
+ return version
+ return None
+
+
+# vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·:
diff --git a/gbp/rpm/git.py b/gbp/rpm/git.py
new file mode 100644
index 00000000..c7cc023b
--- /dev/null
+++ b/gbp/rpm/git.py
@@ -0,0 +1,105 @@
+# vim: set fileencoding=utf-8 :
+#
+# (C) 2011 Guido Günther <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
+import re
+
+from gbp.git import GitRepository, GitRepositoryError
+from gbp.pkg.pristinetar import PristineTar
+from gbp.rpm import compose_version_str
+
+class RpmGitRepository(GitRepository):
+ """A git repository that holds the source of an RPM package"""
+
+ def __init__(self, path):
+ super(RpmGitRepository, self).__init__(path)
+ self.pristine_tar = PristineTar(self)
+
+ def find_version(self, format, str_fields):
+ """
+ Check if a certain version is stored in this repo and return the SHA1
+ of the related commit. That is, an annotated tag is dereferenced to the
+ commit object it points to.
+
+ @param format: tag pattern
+ @type format: C{str}
+ @param str_fields: arguments for format string ('upstreamversion', 'release', 'vendor'...)
+ @type str_fields: C{dict} of C{str}
+ @return: sha1 of the commit the tag references to
+ """
+ try:
+ tag = self.version_to_tag(format, str_fields)
+ except KeyError:
+ return None
+ if self.has_tag(tag): # new tags are injective
+ # dereference to a commit object
+ return self.rev_parse("%s^0" % tag)
+ return None
+
+ @staticmethod
+ def version_to_tag(format, str_fields):
+ """
+ Generate a tag from a given format and a version
+
+ @param format: tag pattern
+ @type format: C{str}
+ @param str_fields: arguments for format string ('upstreamversion', 'release', 'vendor'...)
+ @type str_fields: C{dict} of C{str}
+ @return: version tag
+
+ >>> RpmGitRepository.version_to_tag("packaging/%(version)s", dict(epoch='0', upstreamversion='0~0'))
+ 'packaging/0%0_0'
+ >>> RpmGitRepository.version_to_tag("%(vendor)s/v%(version)s", dict(upstreamversion='1.0', release='2', vendor="myvendor"))
+ 'myvendor/v1.0-2'
+ """
+ version_tag = format % dict(str_fields,
+ version=compose_version_str(str_fields))
+ return RpmGitRepository._sanitize_tag(version_tag)
+
+ @staticmethod
+ def _sanitize_tag(tag):
+ """sanitize a version so git accepts it as a tag
+
+ >>> RpmGitRepository._sanitize_tag("0.0.0")
+ '0.0.0'
+ >>> RpmGitRepository._sanitize_tag("0.0~0")
+ '0.0_0'
+ >>> RpmGitRepository._sanitize_tag("0:0.0")
+ '0%0.0'
+ >>> RpmGitRepository._sanitize_tag("0%0~0")
+ '0%0_0'
+ """
+ return tag.replace('~', '_').replace(':', '%')
+
+ @property
+ def pristine_tar_branch(self):
+ """
+ The name of the pristine-tar branch, whether it already exists or
+ not.
+ """
+ return PristineTar.branch
+
+ def has_pristine_tar_branch(self):
+ """
+ Wheter the repo has a I{pristine-tar} branch.
+
+ @return: C{True} if the repo has pristine-tar commits already, C{False}
+ otherwise
+ @rtype: C{Bool}
+ """
+ return True if self.has_branch(self.pristine_tar_branch) else False
+
+# vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·:
diff --git a/gbp/rpm/lib_rpm.py b/gbp/rpm/lib_rpm.py
new file mode 100644
index 00000000..4bad44e7
--- /dev/null
+++ b/gbp/rpm/lib_rpm.py
@@ -0,0 +1,47 @@
+# vim: set fileencoding=utf-8 :
+#
+# (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
+"""Wrapper module for librpm"""
+
+import tempfile
+
+import gbp.log
+from gbp.rpm.policy import RpmPkgPolicy
+
+try:
+ # Try to load special RPM lib to be used for GBP (only)
+ librpm = __import__(RpmPkgPolicy.python_rpmlib_module_name)
+except ImportError:
+ gbp.log.warn("Failed to import '%s' as rpm python module, using host's "
+ "default rpm library instead" %
+ RpmPkgPolicy.python_rpmlib_module_name)
+ import rpm as librpm
+
+# Module initialization
+_rpmlog = tempfile.NamedTemporaryFile(prefix='gbp_rpmlog')
+_rpmlogfd = _rpmlog.file
+librpm.setVerbosity(librpm.RPMLOG_INFO)
+librpm.setLogFile(_rpmlogfd)
+
+
+def get_librpm_log(truncate=True):
+ """Get rpmlib log output"""
+ _rpmlogfd.seek(0)
+ log = [line.strip() for line in _rpmlogfd.readlines()]
+ if truncate:
+ _rpmlogfd.truncate(0)
+ return log
+
diff --git a/gbp/rpm/linkedlist.py b/gbp/rpm/linkedlist.py
new file mode 100644
index 00000000..74d897bc
--- /dev/null
+++ b/gbp/rpm/linkedlist.py
@@ -0,0 +1,214 @@
+# vim: set fileencoding=utf-8 :
+#
+# (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
+"""Simple implementation of a doubly linked list"""
+
+import collections
+
+import gbp.log
+
+
+class LinkedListNode(object):
+ """Node of the linked list"""
+
+ def __init__(self, data="", prev_node=None, next_node=None):
+ self.prev = prev_node
+ self.next = next_node
+ self._data = data
+
+ def __str__(self):
+ return str(self.data)
+
+ @property
+ def data(self):
+ """Get data stored into node"""
+ if self._data is None:
+ gbp.log.debug("BUG: referencing a deleted node!")
+ return("")
+ return self._data
+
+ def set_data(self, data):
+ """
+ Set data stored into node
+
+ >>> node = LinkedListNode('foo')
+ >>> node.data
+ 'foo'
+ >>> node.set_data('bar')
+ >>> node.data
+ 'bar'
+ >>> node.set_data(None)
+ >>> node.data
+ ''
+ """
+ if data is None:
+ gbp.log.debug("BUG: trying to store 'None', not allowed")
+ data = ""
+ self._data = data
+
+
+ def delete(self):
+ """Delete node"""
+ if self.prev:
+ self.prev.next = self.next
+ if self.next:
+ self.next.prev = self.prev
+ self._data = None
+
+
+class LinkedListIterator(collections.Iterator):
+ """Iterator for the linked list"""
+
+ def __init__(self, obj):
+ self._next = obj.first
+
+ def next(self):
+ ret = self._next
+ if ret:
+ self._next = ret.next
+ else:
+ raise StopIteration
+ return ret
+
+
+class LinkedList(collections.Iterable):
+ """Doubly linked list"""
+
+ def __init__(self):
+ self._first = None
+ self._last = None
+
+ def __iter__(self):
+ return LinkedListIterator(self)
+
+ def __len__(self):
+ for num, data in enumerate(self):
+ pass
+ return num + 1
+
+ @property
+ def first(self):
+ """Get the first node of the list"""
+ return self._first
+
+ def prepend(self, data):
+ """
+ Insert to the beginning of list
+
+ >>> list = LinkedList()
+ >>> [str(data) for data in list]
+ []
+ >>> node = list.prepend("foo")
+ >>> len(list)
+ 1
+ >>> node = list.prepend("bar")
+ >>> [str(data) for data in list]
+ ['bar', 'foo']
+ """
+ if self._first is None:
+ new = self._first = self._last = LinkedListNode(data)
+ else:
+ new = self.insert_before(self._first, data)
+ return new
+
+ def append(self, data):
+ """
+ Insert to the end of list
+
+ >>> list = LinkedList()
+ >>> node = list.append('foo')
+ >>> len(list)
+ 1
+ >>> node = list.append('bar')
+ >>> [str(data) for data in list]
+ ['foo', 'bar']
+ """
+ if self._last is None:
+ return self.prepend(data)
+ else:
+ return self.insert_after(self._last, data)
+
+ def insert_before(self, node, data=""):
+ """
+ Insert before a node
+
+ >>> list = LinkedList()
+ >>> node1 = list.append('foo')
+ >>> node2 = list.insert_before(node1, 'bar')
+ >>> node3 = list.insert_before(node1, 'baz')
+ >>> [str(data) for data in list]
+ ['bar', 'baz', 'foo']
+ """
+ new = LinkedListNode(data, prev_node=node.prev, next_node=node)
+ if node.prev:
+ node.prev.next = new
+ else:
+ self._first = new
+ node.prev = new
+ return new
+
+ def insert_after(self, node, data=""):
+ """
+ Insert after a node
+
+ >>> list = LinkedList()
+ >>> node1 = list.prepend('foo')
+ >>> node2 = list.insert_after(node1, 'bar')
+ >>> node3 = list.insert_after(node1, 'baz')
+ >>> [str(data) for data in list]
+ ['foo', 'baz', 'bar']
+ """
+ new = LinkedListNode(data, prev_node=node, next_node=node.next)
+ if node.next:
+ node.next.prev = new
+ else:
+ self._last = new
+ node.next = new
+ return new
+
+ def delete(self, node):
+ """
+ Delete node
+
+ >>> list = LinkedList()
+ >>> node1 = list.prepend('foo')
+ >>> node2 = list.insert_after(node1, 'bar')
+ >>> node3 = list.insert_before(node2, 'baz')
+ >>> [str(data) for data in list]
+ ['foo', 'baz', 'bar']
+ >>> str(list.delete(node3))
+ 'foo'
+ >>> [str(data) for data in list]
+ ['foo', 'bar']
+ >>> print "%s" % node3
+ <BLANKLINE>
+ >>> str(list.delete(node1))
+ 'bar'
+ >>> [str(data) for data in list]
+ ['bar']
+ >>> list.delete(node2)
+ >>> [str(data) for data in list]
+ []
+ """
+ ret = node.prev
+ if node is self._first:
+ ret = self._first = self._first.next
+ if node is self._last:
+ self._last = self._last.prev
+ node.delete()
+ return ret
+
+# vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·:
diff --git a/gbp/rpm/policy.py b/gbp/rpm/policy.py
new file mode 100644
index 00000000..f8cb8630
--- /dev/null
+++ b/gbp/rpm/policy.py
@@ -0,0 +1,72 @@
+# vim: set fileencoding=utf-8 :
+#
+# (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
+"""Default packaging policy for RPM"""
+
+import re
+from gbp.pkg import PkgPolicy, parse_archive_filename
+
+class RpmPkgPolicy(PkgPolicy):
+ """Packaging policy for RPM"""
+
+ # Special rpmlib python module for GBP (only)
+ python_rpmlib_module_name = "rpm"
+
+ alnum = 'a-zA-Z0-9'
+ # Valid characters for RPM pkg name
+ name_whitelist_chars = '._+%{}\-'
+ # Valid characters for RPM pkg version
+ version_whitelist_chars = '._+%{}~'
+
+ # Regexp for checking the validity of package name
+ packagename_re = re.compile("^[%s][%s%s]+$" %
+ (alnum, alnum, name_whitelist_chars))
+ packagename_msg = ("Package names must be at least two characters long, "
+ "start with an alphanumeric and can only contain "
+ "alphanumerics or characters in %s" %
+ list(name_whitelist_chars))
+
+ # Regexp for checking the validity of package (upstream) version
+ upstreamversion_re = re.compile("^[0-9][%s%s]*$" %
+ (alnum, version_whitelist_chars))
+ upstreamversion_msg = ("Upstream version numbers must start with a digit "
+ "and can only containg alphanumerics or characters "
+ "in %s" % list(version_whitelist_chars))
+
+ @classmethod
+ def is_valid_orig_archive(cls, filename):
+ """
+ Is this a valid orig source archive
+
+ @param filename: upstream source archive filename
+ @type filename: C{str}
+ @return: true if valid upstream source archive filename
+ @rtype: C{bool}
+
+ >>> RpmPkgPolicy.is_valid_orig_archive("foo/bar_baz.tar.gz")
+ True
+ >>> RpmPkgPolicy.is_valid_orig_archive("foo.bar.tar")
+ True
+ >>> RpmPkgPolicy.is_valid_orig_archive("foo.bar")
+ False
+ >>> RpmPkgPolicy.is_valid_orig_archive("foo.gz")
+ False
+ """
+ _base, arch_fmt, _compression = parse_archive_filename(filename)
+ if arch_fmt:
+ return True
+ return False
+
diff --git a/gbp/scripts/buildpackage.py b/gbp/scripts/buildpackage.py
index c077b9e6..e96e8e77 100755
--- a/gbp/scripts/buildpackage.py
+++ b/gbp/scripts/buildpackage.py
@@ -1,6 +1,6 @@
# vim: set fileencoding=utf-8 :
#
-# (C) 2006-2013 Guido Günther <agx@sigxcpu.org>
+# (C) 2006-2014 Guido Günther <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
@@ -15,7 +15,7 @@
# 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 a debian package out of a git repository"""
+"""Build a debian package out of a GIT repository"""
import ConfigParser
import errno
@@ -29,7 +29,9 @@ from gbp.command_wrappers import (Command,
from gbp.config import (GbpOptionParserDebian, GbpOptionGroup)
from gbp.deb.git import (GitRepositoryError, DebianGitRepository)
from gbp.deb.source import DebianSource, DebianSourceError
+from gbp.format import format_msg
from gbp.git.vfs import GitVfs
+from gbp.deb.upstreamsource import DebianUpstreamSource
from gbp.errors import GbpError
import gbp.log
import gbp.notifications
@@ -37,7 +39,7 @@ from gbp.scripts.common.buildpackage import (index_name, wc_name,
git_archive_submodules,
git_archive_single, dump_tree,
write_wc, drop_index)
-from gbp.pkg import (UpstreamSource, compressor_opts, compressor_aliases)
+from gbp.pkg import compressor_opts, compressor_aliases, parse_archive_filename
def git_archive(repo, cp, output_dir, treeish, comp_type, comp_level, with_submodules):
"create a compressed orig tarball in output_dir using git_archive"
@@ -171,7 +173,7 @@ def extract_orig(orig_tarball, dest_dir):
gbp.log.info("Extracting %s to '%s'" % (os.path.basename(orig_tarball), dest_dir))
move_old_export(dest_dir)
- upstream = UpstreamSource(orig_tarball)
+ upstream = DebianUpstreamSource(orig_tarball)
upstream.unpack(dest_dir)
# Check if tarball extracts into a single folder or not:
@@ -241,6 +243,8 @@ def pristine_tar_build_orig(repo, cp, output_dir, options):
def get_upstream_tree(repo, cp, options):
"""Determine the upstream tree from the given options"""
if options.upstream_tree.upper() == 'TAG':
+ if cp['Upstream-Version'] is None:
+ raise GitRepositoryError("Can't determine upstream version from changelog")
upstream_tree = repo.version_to_tag(options.upstream_tag,
cp['Upstream-Version'])
elif options.upstream_tree.upper() == 'BRANCH':
@@ -316,7 +320,7 @@ def guess_comp_type(repo, comp_type, cp, tarball_dir):
else:
commit = repo.pristine_tar_branch
tarball = repo.get_commit_info(commit)['subject']
- comp_type = du.DebianPkgPolicy.get_compression(tarball)
+ (base_name, archive_fmt, comp_type) = parse_archive_filename(tarball)
gbp.log.debug("Determined compression type '%s'" % comp_type)
if not comp_type:
comp_type = 'gzip'
@@ -399,6 +403,7 @@ def build_parser(name, prefix=None):
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="debian-tag", dest="debian_tag")
+ tag_group.add_config_file_option(option_name="debian-tag-msg", dest="debian_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")
@@ -482,6 +487,13 @@ def parse_args(argv, prefix):
return options, args, dpkg_args
+class Hook(RunAtCommand):
+ "A hook run during the build"
+ def __init__(self, name, *args, **kwargs):
+ RunAtCommand.__init__(self, *args, **kwargs)
+ self.run_error = '%s-hook %s' % (name, self.run_error)
+
+
def main(argv):
retval = 0
prefix = "git-"
@@ -547,9 +559,9 @@ def main(argv):
# Run postexport hook
if options.postexport:
- RunAtCommand(options.postexport, shell=True,
- extra_env={'GBP_GIT_DIR': repo.git_dir,
- 'GBP_TMP_DIR': tmp_dir})(dir=tmp_dir)
+ Hook('Postexport', options.postexport, shell=True,
+ extra_env={'GBP_GIT_DIR': repo.git_dir,
+ 'GBP_TMP_DIR': tmp_dir})(dir=tmp_dir)
major = (source.changelog.debian_version if source.is_native()
else source.changelog.upstream_version)
@@ -569,9 +581,9 @@ def main(argv):
build_dir = repo_dir
if options.prebuild:
- RunAtCommand(options.prebuild, shell=True,
- extra_env={'GBP_GIT_DIR': repo.git_dir,
- 'GBP_BUILD_DIR': build_dir})(dir=build_dir)
+ Hook('Prebuild', options.prebuild, shell=True,
+ extra_env={'GBP_GIT_DIR': repo.git_dir,
+ 'GBP_BUILD_DIR': build_dir})(dir=build_dir)
setup_pbuilder(options)
# Finally build the package:
@@ -584,24 +596,26 @@ def main(argv):
source.changelog.noepoch,
changes_file_suffix(dpkg_args)))
gbp.log.debug("Looking for changes file %s" % changes)
- Command(options.postbuild, shell=True,
- extra_env={'GBP_CHANGES_FILE': changes,
- 'GBP_BUILD_DIR': build_dir})()
+ Hook('Postbuild', options.postbuild, shell=True,
+ extra_env={'GBP_CHANGES_FILE': changes,
+ 'GBP_BUILD_DIR': build_dir})()
if options.tag or options.tag_only:
- gbp.log.info("Tagging %s" % source.changelog.version)
tag = repo.version_to_tag(options.debian_tag, source.changelog.version)
+ gbp.log.info("Tagging %s as %s" % (source.changelog.version, tag))
if options.retag and repo.has_tag(tag):
repo.delete_tag(tag)
+ tag_msg = format_msg(options.debian_tag_msg,
+ dict(pkg=source.sourcepkg,
+ version=source.changelog.version))
repo.create_tag(name=tag,
- msg="%s Debian release %s" % (source.sourcepkg,
- source.changelog.version),
+ msg=tag_msg,
sign=options.sign_tags, keyid=options.keyid)
if options.posttag:
sha = repo.rev_parse("%s^{}" % tag)
- Command(options.posttag, shell=True,
- extra_env={'GBP_TAG': tag,
- 'GBP_BRANCH': branch or '(no branch)',
- 'GBP_SHA1': sha})()
+ Hook('Posttag', options.posttag, shell=True,
+ extra_env={'GBP_TAG': tag,
+ 'GBP_BRANCH': branch or '(no branch)',
+ 'GBP_SHA1': sha})()
except CommandExecFailed:
retval = 1
except (GbpError, GitRepositoryError) as err:
diff --git a/gbp/scripts/clone.py b/gbp/scripts/clone.py
index 62d0dcc2..8078854b 100755
--- a/gbp/scripts/clone.py
+++ b/gbp/scripts/clone.py
@@ -17,7 +17,7 @@
#
# inspired by dom-git-checkout
#
-"""clone a repo and set it up for gbp"""
+"""Clone a GIT repository and set it up for gbp"""
import ConfigParser
import sys
diff --git a/gbp/scripts/common/import_orig.py b/gbp/scripts/common/import_orig.py
index c2c53a64..8e18e978 100644
--- a/gbp/scripts/common/import_orig.py
+++ b/gbp/scripts/common/import_orig.py
@@ -32,29 +32,26 @@ except ImportError:
pass
-class OrigUpstreamSource(UpstreamSource):
- """Upstream source that will be imported"""
-
- def needs_repack(self, options):
- """
- Determine if the upstream sources needs to be repacked
-
- We repack if
- 1. we want to filter out files and use pristine tar since we want
- to make a filtered tarball available to pristine-tar
- 2. when we don't have a suitable upstream tarball (e.g. zip archive or unpacked dir)
- and want to use filters
- 3. when we don't have a suitable upstream tarball (e.g. zip archive or unpacked dir)
- and want to use pristine-tar
- """
- if ((options.pristine_tar and options.filter_pristine_tar and len(options.filters) > 0)):
+def orig_needs_repack(upstream_source, options):
+ """
+ Determine if the upstream sources needs to be repacked
+
+ We repack if
+ 1. we want to filter out files and use pristine tar since we want
+ to make a filtered tarball available to pristine-tar
+ 2. when we don't have a suitable upstream tarball (e.g. zip archive or unpacked dir)
+ and want to use filters
+ 3. when we don't have a suitable upstream tarball (e.g. zip archive or unpacked dir)
+ and want to use pristine-tar
+ """
+ if ((options.pristine_tar and options.filter_pristine_tar and len(options.filters) > 0)):
+ return True
+ elif not upstream_source.is_orig():
+ if len(options.filters):
return True
- elif not self.is_orig():
- if len(options.filters):
- return True
- elif options.pristine_tar:
- return True
- return False
+ elif options.pristine_tar:
+ return True
+ return False
def cleanup_tmp_tree(tree):
diff --git a/gbp/scripts/create_remote_repo.py b/gbp/scripts/create_remote_repo.py
index f0e680b4..b8923cd1 100644
--- a/gbp/scripts/create_remote_repo.py
+++ b/gbp/scripts/create_remote_repo.py
@@ -16,7 +16,7 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# Based on the aa-create-git-repo and dom-new-git-repo shell scripts
-"""Create a remote repo based on the current one"""
+"""Create a remote GIT repository based on the current one"""
import ConfigParser
import sys
diff --git a/gbp/scripts/dch.py b/gbp/scripts/dch.py
index f36f2877..ce19c9a6 100644
--- a/gbp/scripts/dch.py
+++ b/gbp/scripts/dch.py
@@ -15,7 +15,7 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
-"""Generate Debian changelog entries from git commit messages"""
+"""Generate Debian changelog entries from GIT commit messages"""
import ConfigParser
import os.path
@@ -64,17 +64,19 @@ def get_author_email(repo, use_git_config):
return author, email
-def fixup_section(repo, git_author, options, dch_options):
+def fixup_section(repo, use_git_author, options, dch_options):
"""
- Fixup the changelog header and trailer's comitter and email address
+ Fixup the changelog header and trailer's committer and email address
It might otherwise point to the last git committer instead of the person
creating the changelog
- This apply --distribution and --urgency options passed to git-dch
+
+ This also applies --distribution and --urgency options passed to gbp dch
"""
- author, email = get_author_email(repo, git_author)
+ author, email = get_author_email(repo, use_git_author)
used_options = ['distribution', 'urgency']
- header_opts = []
+ opts = []
+ mainttrailer_opts = [ '--nomainttrailer', '--mainttrailer', '-t' ]
# This must not be done for snapshots or snapshots changelog entries
# will not be concatenated
@@ -83,11 +85,17 @@ def fixup_section(repo, git_author, options, dch_options):
val = getattr(options, opt)
if val:
gbp.log.debug("Set header option '%s' to '%s'" % (opt, val))
- header_opts.append("--%s=%s" % (opt, val))
+ opts.append("--%s=%s" % (opt, val))
else:
gbp.log.debug("Snapshot enabled: do not fixup options in header")
- ChangeLog.spawn_dch(msg='', author=author, email=email, dch_options=dch_options+header_opts)
+ if use_git_author:
+ for opt in mainttrailer_opts:
+ if opt in dch_options:
+ break
+ else:
+ opts.append(mainttrailer_opts[0])
+ ChangeLog.spawn_dch(msg='', author=author, email=email, dch_options=dch_options+opts)
def snapshot_version(version):
@@ -153,9 +161,9 @@ def mangle_changelog(changelog, cp, snapshot=''):
raise GbpError("Error mangling changelog %s" % e)
-def do_release(changelog, repo, cp, git_author, dch_options):
+def do_release(changelog, repo, cp, use_git_author, dch_options):
"""Remove the snapshot header and set the distribution"""
- author, email = get_author_email(repo, git_author)
+ author, email = get_author_email(repo, use_git_author)
(release, snapshot) = snapshot_version(cp['Version'])
if snapshot:
cp['MangledVersion'] = release
@@ -343,10 +351,9 @@ def build_parser(name):
help="Increment the Debian release number for a Debian Team upload, and add a Team upload changelog comment.")
version_group.add_option("--security", dest="security", action="store_true", default=False,
help="Increment the Debian release number for a security upload and add a security upload changelog comment.")
- version_group.add_boolean_config_file_option(option_name="git-author", dest="git_author")
+ version_group.add_boolean_config_file_option(option_name="git-author", dest="use_git_author")
commit_group.add_boolean_config_file_option(option_name="meta", dest="meta")
- commit_group.add_config_file_option(option_name="meta-closes", dest="meta_closes",
- help="Meta tags for the bts close commands, default is '%(meta-closes)s'")
+ commit_group.add_config_file_option(option_name="meta-closes", dest="meta_closes")
commit_group.add_boolean_config_file_option(option_name="full", dest="full")
commit_group.add_config_file_option(option_name="id-length", dest="idlen",
help="include N digits of the commit id in the changelog entry, default is '%(id-length)s'",
@@ -505,11 +512,11 @@ def main(argv):
version=version_change,
dch_options=dch_options)
- fixup_section(repo, git_author=options.git_author, options=options,
+ fixup_section(repo, use_git_author=options.use_git_author, options=options,
dch_options=dch_options)
if options.release:
- do_release(changelog, repo, cp, git_author=options.git_author,
+ do_release(changelog, repo, cp, use_git_author=options.use_git_author,
dch_options=dch_options)
elif options.snapshot:
(snap, version) = do_snapshot(changelog, repo, options.snapshot_number)
diff --git a/gbp/scripts/import_dsc.py b/gbp/scripts/import_dsc.py
index 600b394d..c0bf6504 100644
--- a/gbp/scripts/import_dsc.py
+++ b/gbp/scripts/import_dsc.py
@@ -14,7 +14,7 @@
# 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
-"""Import a Debian source package into a git repository"""
+"""Import a Debian source package into a GIT repository"""
import ConfigParser
import sys
@@ -26,8 +26,8 @@ import glob
import pipes
import time
import gbp.command_wrappers as gbpc
-from gbp.pkg import UpstreamSource
from gbp.deb.dscfile import DscFile
+from gbp.deb.upstreamsource import DebianUpstreamSource
from gbp.deb.git import (DebianGitRepository, GitRepositoryError)
from gbp.deb.changelog import ChangeLog
from gbp.git import rfc822_date_to_git
@@ -328,7 +328,7 @@ def main(argv):
set_bare_repo_options(options)
dirs['tmp'] = os.path.abspath(tempfile.mkdtemp(dir='..'))
- upstream = UpstreamSource(src.tgz)
+ upstream = DebianUpstreamSource(src.tgz)
upstream.unpack(dirs['tmp'], options.filters)
format = [(options.upstream_tag, "Upstream"), (options.debian_tag, "Debian")][src.native]
diff --git a/gbp/scripts/import_dscs.py b/gbp/scripts/import_dscs.py
index 28413faf..2a71560e 100644
--- a/gbp/scripts/import_dscs.py
+++ b/gbp/scripts/import_dscs.py
@@ -14,7 +14,7 @@
# 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
-"""Import multiple dsc files in one go"""
+"""Import multiple dsc files into GIT in one go"""
import glob
import os
diff --git a/gbp/scripts/import_orig.py b/gbp/scripts/import_orig.py
index 542896ef..6256431c 100644
--- a/gbp/scripts/import_orig.py
+++ b/gbp/scripts/import_orig.py
@@ -15,7 +15,7 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
-"""Import a new upstream version into a git repository"""
+"""Import a new upstream version into a GIT repository"""
import ConfigParser
import os
@@ -23,13 +23,15 @@ import sys
import tempfile
import gbp.command_wrappers as gbpc
from gbp.deb import (DebianPkgPolicy, parse_changelog_repo)
+from gbp.deb.upstreamsource import DebianUpstreamSource
from gbp.deb.uscan import (Uscan, UscanError)
from gbp.deb.changelog import ChangeLog, NoChangeLogError
from gbp.deb.git import (GitRepositoryError, DebianGitRepository)
from gbp.config import GbpOptionParserDebian, GbpOptionGroup, no_upstream_branch_msg
from gbp.errors import GbpError
+from gbp.format import format_msg
import gbp.log
-from gbp.scripts.common.import_orig import (OrigUpstreamSource, cleanup_tmp_tree,
+from gbp.scripts.common.import_orig import (orig_needs_repack, cleanup_tmp_tree,
ask_package_name, ask_package_version,
repack_source, is_link_target)
@@ -80,7 +82,7 @@ def upstream_import_commit_msg(options, version):
def detect_name_and_version(repo, source, options):
# Guess defaults for the package name and version from the
# original tarball.
- (guessed_package, guessed_version) = source.guess_version() or ('', '')
+ guessed_package, guessed_version = source.guess_version()
# Try to find the source package name
try:
@@ -167,7 +169,7 @@ def find_source(use_uscan, args):
elif len(args) == 0:
raise GbpError("No archive to import specified. Try --help.")
else:
- archive = OrigUpstreamSource(args[0])
+ archive = DebianUpstreamSource(args[0])
return archive
@@ -300,7 +302,7 @@ def main(argv):
source.unpack(tmpdir, options.filters)
gbp.log.debug("Unpacked '%s' to '%s'" % (source.path, source.unpacked))
- if source.needs_repack(options):
+ if orig_needs_repack(source, options):
gbp.log.debug("Filter pristine-tar: repacking '%s' from '%s'" % (source.path, source.unpacked))
(source, tmpdir) = repack_source(source, sourcepackage, version, tmpdir, options.filters)
@@ -372,7 +374,7 @@ def main(argv):
epoch = '%s:' % cp.epoch
info = { 'version': "%s%s-1" % (epoch, version) }
env = { 'GBP_BRANCH': options.debian_branch }
- gbpc.Command(options.postimport % info, extra_env=env, shell=True)()
+ gbpc.Command(format_msg(options.postimport, info), extra_env=env, shell=True)()
# Update working copy and index if we've possibly updated the
# checked out branch
current_branch = repo.get_branch()
diff --git a/gbp/scripts/import_srpm.py b/gbp/scripts/import_srpm.py
new file mode 100755
index 00000000..958f5ff7
--- /dev/null
+++ b/gbp/scripts/import_srpm.py
@@ -0,0 +1,462 @@
+# vim: set fileencoding=utf-8 :
+#
+# (C) 2006,2007,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
+"""Import an RPM source package into a GIT repository"""
+
+import ConfigParser
+import sys
+import re
+import os
+import glob
+import time
+import shutil
+import errno
+import urllib2
+
+import gbp.tmpfile as tempfile
+import gbp.command_wrappers as gbpc
+from gbp.rpm import (parse_srpm, guess_spec, SpecFile, NoSpecError,
+ RpmUpstreamSource, compose_version_str)
+from gbp.rpm.git import (RpmGitRepository, GitRepositoryError)
+from gbp.git.modifier import GitModifier
+from gbp.config import (GbpOptionParserRpm, GbpOptionGroup,
+ no_upstream_branch_msg)
+from gbp.errors import GbpError
+import gbp.log
+from gbp.pkg import parse_archive_filename
+
+no_packaging_branch_msg = """
+Repository does not have branch '%s' for packaging/distribution sources.
+You need to reate it or use --packaging-branch to specify it.
+"""
+
+class SkipImport(Exception):
+ """Nothing imported"""
+ pass
+
+
+def download_file(target_dir, url):
+ """Download a remote file"""
+ gbp.log.info("Downloading '%s'..." % url)
+ try:
+ urlobj = urllib2.urlopen(url)
+ local_fn = os.path.join(target_dir, os.path.basename(url))
+ with open(local_fn, "wb") as local_file:
+ local_file.write(urlobj.read())
+ except urllib2.HTTPError as err:
+ raise GbpError("Download failed: %s" % err)
+ except urllib2.URLError as err:
+ raise GbpError("Download failed: %s" % err.reason)
+ return local_fn
+
+def download_source(pkg, dirs):
+ """Download package from a remote location"""
+ if re.match(r'[a-z]{1,5}://', pkg):
+ mode = 'python urllib2'
+ else:
+ mode = 'yumdownloader'
+
+ tmpdir = tempfile.mkdtemp(dir=dirs['tmp_base'], prefix='download_')
+ gbp.log.info("Trying to download '%s' using '%s'..." % (pkg, mode))
+ if mode == 'yumdownloader':
+ gbpc.RunAtCommand('yumdownloader',
+ ['--source', '--destdir=', '.', pkg],
+ shell=False)(dir=tmpdir)
+ else:
+ download_file(tmpdir, pkg)
+ srpm = glob.glob(os.path.join(tmpdir, '*.src.rpm'))[0]
+ return srpm
+
+
+def committer_from_author(author, options):
+ """Get committer info based on options"""
+ committer = GitModifier()
+ if options.author_is_committer:
+ committer.name = author.name
+ committer.email = author.email
+ return committer
+
+
+def move_tag_stamp(repo, tag_format, tag_str_fields):
+ "Move tag out of the way appending the current timestamp"
+ old = repo.version_to_tag(tag_format, tag_str_fields)
+ new = repo.version_to_tag('%s~%d' % (tag_format, int(time.time())),
+ tag_str_fields)
+ repo.move_tag(old, new)
+
+
+def set_bare_repo_options(options):
+ """Modify options for import into a bare repository"""
+ if options.pristine_tar:
+ gbp.log.info("Bare repository: setting %s option '--no-pristine-tar'")
+ options.pristine_tar = False
+
+
+def force_to_branch_head(repo, branch):
+ """Checkout branch and reset --hard"""
+ if repo.get_branch() == branch:
+ # Update HEAD if we modified the checked out branch
+ repo.force_head(branch, hard=True)
+ # Checkout packaging branch
+ repo.set_branch(branch)
+
+
+def parse_args(argv):
+ """Parse commandline arguments"""
+ try:
+ parser = GbpOptionParserRpm(command=os.path.basename(argv[0]),
+ prefix='',
+ usage='%prog [options] /path/to/package'
+ '.src.rpm')
+ except ConfigParser.ParsingError, err:
+ gbp.log.err(err)
+ return None, None
+
+ import_group = GbpOptionGroup(parser, "import options",
+ "pristine-tar and filtering")
+ tag_group = GbpOptionGroup(parser, "tag options",
+ "options related to git tag creation")
+ branch_group = GbpOptionGroup(parser, "version and branch naming options",
+ "version number and branch layout options")
+
+ for group in [import_group, branch_group, tag_group ]:
+ parser.add_option_group(group)
+
+ parser.add_option("-v", "--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="color-scheme",
+ dest="color_scheme")
+ parser.add_config_file_option(option_name="tmp-dir", dest="tmp_dir")
+ parser.add_config_file_option(option_name="vendor", action="store",
+ dest="vendor")
+ parser.add_option("--download", action="store_true", dest="download",
+ default=False, help="download source package")
+ branch_group.add_config_file_option(option_name="packaging-branch",
+ dest="packaging_branch")
+ branch_group.add_config_file_option(option_name="upstream-branch",
+ dest="upstream_branch")
+ branch_group.add_boolean_config_file_option(
+ option_name="create-missing-branches",
+ dest="create_missing_branches")
+ branch_group.add_option("--orphan-packaging", action="store_true",
+ dest="orphan_packaging", default=False,
+ help="The packaging branch doesn't base on upstream")
+ branch_group.add_option("--native", action="store_true",
+ dest="native", default=False,
+ help="This is a dist native package, no separate "
+ "upstream branch")
+
+ 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")
+
+ import_group.add_config_file_option(option_name="filter",
+ dest="filters", action="append")
+ import_group.add_boolean_config_file_option(option_name="pristine-tar",
+ dest="pristine_tar")
+ import_group.add_option("--allow-same-version", action="store_true",
+ dest="allow_same_version", default=False,
+ help="allow to import already imported version")
+ import_group.add_boolean_config_file_option(
+ option_name="author-is-committer",
+ dest="author_is_committer")
+ import_group.add_config_file_option(option_name="packaging-dir",
+ dest="packaging_dir")
+ (options, args) = parser.parse_args(argv[1:])
+ gbp.log.setup(options.color, options.verbose, options.color_scheme)
+ return options, args
+
+
+def main(argv):
+ """Main function of the git-import-srpm script"""
+ dirs = dict(top=os.path.abspath(os.curdir))
+
+ ret = 0
+ skipped = False
+
+ options, args = parse_args(argv)
+
+ if len(args) != 1:
+ gbp.log.err("Need to give exactly one package to import. Try --help.")
+ return 1
+ try:
+ dirs['tmp_base'] = tempfile.mkdtemp(dir=options.tmp_dir,
+ prefix='import-srpm')
+ except GbpError as err:
+ gbp.log.err(err)
+ return 1
+ try:
+ srpm = args[0]
+ if options.download:
+ srpm = download_source(srpm, dirs)
+
+ # Real srpm, we need to unpack, first
+ true_srcrpm = False
+ if not os.path.isdir(srpm) and not srpm.endswith(".spec"):
+ src = parse_srpm(srpm)
+ true_srcrpm = True
+ dirs['pkgextract'] = tempfile.mkdtemp(dir=dirs['tmp_base'],
+ prefix='pkgextract_')
+ gbp.log.info("Extracting src rpm to '%s'" % dirs['pkgextract'])
+ src.unpack(dirs['pkgextract'])
+ preferred_spec = src.name + '.spec'
+ srpm = dirs['pkgextract']
+ elif os.path.isdir(srpm):
+ preferred_spec = os.path.basename(srpm.rstrip('/')) + '.spec'
+ else:
+ preferred_spec = None
+
+ # Find and parse spec file
+ if os.path.isdir(srpm):
+ gbp.log.debug("Trying to import an unpacked srpm from '%s'" % srpm)
+ dirs['src'] = os.path.abspath(srpm)
+ spec = guess_spec(srpm, True, preferred_spec)
+ else:
+ gbp.log.debug("Trying to import an srpm from '%s' with spec "\
+ "file '%s'" % (os.path.dirname(srpm), srpm))
+ dirs['src'] = os.path.abspath(os.path.dirname(srpm))
+ spec = SpecFile(srpm)
+
+ # Check the repository state
+ try:
+ repo = RpmGitRepository('.')
+ is_empty = repo.is_empty()
+
+ (clean, out) = repo.is_clean()
+ if not clean and not is_empty:
+ gbp.log.err("Repository has uncommitted changes, commit "
+ "these first: ")
+ raise GbpError, out
+
+ except GitRepositoryError:
+ gbp.log.info("No git repository found, creating one.")
+ is_empty = True
+ repo = RpmGitRepository.create(spec.name)
+ os.chdir(repo.path)
+
+ if repo.bare:
+ set_bare_repo_options(options)
+
+ # Create more tempdirs
+ dirs['origsrc'] = tempfile.mkdtemp(dir=dirs['tmp_base'],
+ prefix='origsrc_')
+ dirs['packaging_base'] = tempfile.mkdtemp(dir=dirs['tmp_base'],
+ prefix='packaging_')
+ dirs['packaging'] = os.path.join(dirs['packaging_base'],
+ options.packaging_dir)
+ try:
+ os.mkdir(dirs['packaging'])
+ except OSError as err:
+ if err.errno != errno.EEXIST:
+ raise
+
+ if true_srcrpm:
+ # For true src.rpm we just take everything
+ files = os.listdir(dirs['src'])
+ else:
+ # Need to copy files to the packaging directory given by caller
+ files = [os.path.basename(patch.path) \
+ for patch in spec.patchseries(unapplied=True, ignored=True)]
+ for filename in spec.sources().values():
+ files.append(os.path.basename(filename))
+ files.append(os.path.join(spec.specdir, spec.specfile))
+ # Don't copy orig source archive, though
+ if spec.orig_src and spec.orig_src['filename'] in files:
+ files.remove(spec.orig_src['filename'])
+
+ for fname in files:
+ fpath = os.path.join(dirs['src'], fname)
+ if os.path.exists(fpath):
+ shutil.copy2(fpath, dirs['packaging'])
+ else:
+ gbp.log.err("File '%s' listed in spec not found" % fname)
+ raise GbpError
+
+ # Unpack orig source archive
+ if spec.orig_src:
+ orig_tarball = os.path.join(dirs['src'], spec.orig_src['filename'])
+ sources = RpmUpstreamSource(orig_tarball)
+ sources.unpack(dirs['origsrc'], options.filters)
+ else:
+ sources = None
+
+ src_tag_format = options.packaging_tag if options.native \
+ else options.upstream_tag
+ tag_str_fields = dict(spec.version, vendor=options.vendor.lower())
+ src_tag = repo.version_to_tag(src_tag_format, tag_str_fields)
+ ver_str = compose_version_str(spec.version)
+
+ if repo.find_version(options.packaging_tag, tag_str_fields):
+ gbp.log.warn("Version %s already imported." % ver_str)
+ if options.allow_same_version:
+ gbp.log.info("Moving tag of version '%s' since import forced" %
+ ver_str)
+ move_tag_stamp(repo, options.packaging_tag, tag_str_fields)
+ else:
+ raise SkipImport
+
+ if is_empty:
+ options.create_missing_branches = True
+
+ # Determine author and committer info, currently same info is used
+ # for both sources and packaging files
+ author = None
+ if spec.packager:
+ match = re.match(r'(?P<name>.*[^ ])\s*<(?P<email>\S*)>',
+ spec.packager.strip())
+ if match:
+ author = GitModifier(match.group('name'), match.group('email'))
+ if not author:
+ author = GitModifier()
+ gbp.log.debug("Couldn't determine packager info")
+ committer = committer_from_author(author, options)
+
+ # Import sources
+ if sources:
+ src_commit = repo.find_version(src_tag_format, tag_str_fields)
+ if not src_commit:
+ gbp.log.info("Tag %s not found, importing sources" % src_tag)
+
+ branch = [options.upstream_branch,
+ options.packaging_branch][options.native]
+ if not repo.has_branch(branch):
+ if options.create_missing_branches:
+ gbp.log.info("Will create missing branch '%s'" %
+ branch)
+ else:
+ gbp.log.err(no_upstream_branch_msg % branch + "\n"
+ "Also check the --create-missing-branches option.")
+ raise GbpError
+ src_vendor = "Native" if options.native else "Upstream"
+ msg = "%s version %s" % (src_vendor, spec.upstreamversion)
+ src_commit = repo.commit_dir(sources.unpacked,
+ "Imported %s" % msg,
+ branch,
+ author=author,
+ committer=committer,
+ create_missing_branch=options.create_missing_branches)
+ repo.create_tag(name=src_tag,
+ msg=msg,
+ commit=src_commit,
+ sign=options.sign_tags,
+ keyid=options.keyid)
+
+ if not options.native:
+ if options.pristine_tar:
+ archive_fmt = parse_archive_filename(orig_tarball)[1]
+ if archive_fmt == 'tar':
+ repo.pristine_tar.commit(orig_tarball,
+ 'refs/heads/%s' %
+ options.upstream_branch)
+ else:
+ gbp.log.warn('Ignoring pristine-tar, %s archives '
+ 'not supported' % archive_fmt)
+ else:
+ gbp.log.info("No orig source archive imported")
+
+ # Import packaging files. For native packages we assume that also
+ # packaging files are found in the source tarball
+ if not options.native or not sources:
+ gbp.log.info("Importing packaging files")
+ branch = options.packaging_branch
+ if not repo.has_branch(branch):
+ if options.create_missing_branches:
+ gbp.log.info("Will create missing branch '%s'" % branch)
+ else:
+ gbp.log.err(no_packaging_branch_msg % branch + "\n"
+ "Also check the --create-missing-branches "
+ "option.")
+ raise GbpError
+
+ tag = repo.version_to_tag(options.packaging_tag, tag_str_fields)
+ msg = "%s release %s" % (options.vendor, ver_str)
+
+ if options.orphan_packaging or not sources:
+ commit = repo.commit_dir(dirs['packaging_base'],
+ "Imported %s" % msg,
+ branch,
+ author=author,
+ committer=committer,
+ create_missing_branch=options.create_missing_branches)
+ else:
+ # Copy packaging files to the unpacked sources dir
+ try:
+ pkgsubdir = os.path.join(sources.unpacked,
+ options.packaging_dir)
+ os.mkdir(pkgsubdir)
+ except OSError as err:
+ if err.errno != errno.EEXIST:
+ raise
+ for fname in os.listdir(dirs['packaging']):
+ shutil.copy2(os.path.join(dirs['packaging'], fname),
+ pkgsubdir)
+ commit = repo.commit_dir(sources.unpacked,
+ "Imported %s" % msg,
+ branch,
+ other_parents=[src_commit],
+ author=author,
+ committer=committer,
+ create_missing_branch=options.create_missing_branches)
+ # Import patches on top of the source tree
+ # (only for non-native packages with non-orphan packaging)
+ force_to_branch_head(repo, options.packaging_branch)
+
+ # Create packaging tag
+ repo.create_tag(name=tag,
+ msg=msg,
+ commit=commit,
+ sign=options.sign_tags,
+ keyid=options.keyid)
+
+ force_to_branch_head(repo, options.packaging_branch)
+
+ except KeyboardInterrupt:
+ ret = 1
+ gbp.log.err("Interrupted. Aborting.")
+ except gbpc.CommandExecFailed:
+ ret = 1
+ except GitRepositoryError as err:
+ gbp.log.err("Git command failed: %s" % err)
+ ret = 1
+ except GbpError as err:
+ if len(err.__str__()):
+ gbp.log.err(err)
+ ret = 1
+ except NoSpecError as err:
+ gbp.log.err("Failed determine spec file: %s" % err)
+ ret = 1
+ except SkipImport:
+ skipped = True
+ finally:
+ os.chdir(dirs['top'])
+ gbpc.RemoveTree(dirs['tmp_base'])()
+
+ if not ret and not skipped:
+ gbp.log.info("Version '%s' imported under '%s'" % (ver_str, spec.name))
+ return ret
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv))
+
+# vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·:
diff --git a/gbp/scripts/pq.py b/gbp/scripts/pq.py
index fc205bf2..194145e8 100755
--- a/gbp/scripts/pq.py
+++ b/gbp/scripts/pq.py
@@ -1,6 +1,6 @@
# vim: set fileencoding=utf-8 :
#
-# (C) 2011 Guido Günther <agx@sigxcpu.org>
+# (C) 2011,2014 Guido Günther <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
@@ -15,7 +15,7 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
-"""manage patches in a patch queue"""
+"""Manage Debian patches on a patch queue branch"""
import ConfigParser
import errno
@@ -35,6 +35,7 @@ from gbp.scripts.common.pq import (is_pq_branch, pq_branch_name, pq_branch_base,
switch_to_pq_branch, apply_single_patch,
apply_and_commit_patch,
drop_pq, get_maintainer_from_control)
+from gbp.dch import extract_bts_cmds
PATCH_DIR = "debian/patches/"
SERIES_FILE = os.path.join(PATCH_DIR,"series")
@@ -67,6 +68,71 @@ def generate_patches(repo, start, end, outdir, options):
return patches
+def compare_series(old, new):
+ """
+ Compare new pathes to lists of patches already exported
+
+ >>> compare_series(['a', 'b'], ['b', 'c'])
+ (['c'], ['a'])
+ >>> compare_series([], [])
+ ([], [])
+ """
+ added = set(new).difference(old)
+ removed = set(old).difference(new)
+ return (list(added), list(removed))
+
+
+def format_series_diff(added, removed, options):
+ """
+ Format the patch differences into a suitable commit message
+
+ >>> format_series_diff(['a'], ['b'], None)
+ 'Rediff patches\\n\\nAdded a: <REASON>\\nDropped b: <REASON>\\n'
+ """
+ if len(added) == 1 and not removed:
+ # Single patch added, create a more thorough commit message
+ patch = Patch(os.path.join('debian', 'patches', added[0]))
+ msg = patch.subject
+ bugs, dummy = extract_bts_cmds(patch.long_desc.split('\n'), options)
+ if bugs:
+ msg += '\n'
+ for k, v in bugs.items():
+ msg += '\n%s: %s' % (k, ', '.join(v))
+ else:
+ msg = "Rediff patches\n\n"
+ for p in added:
+ msg += 'Added %s: <REASON>\n' % p
+ for p in removed:
+ msg += 'Dropped %s: <REASON>\n' % p
+ return msg
+
+
+def commit_patches(repo, branch, patches, options):
+ """
+ Commit chanages exported from patch queue
+ """
+ clean, dummy = repo.is_clean()
+ if clean:
+ return ([], [])
+
+ vfs = gbp.git.vfs.GitVfs(repo, branch)
+ try:
+ oldseries = vfs.open('debian/patches/series')
+ oldpatches = [ p.strip() for p in oldseries.readlines() ]
+ oldseries.close()
+ except IOError:
+ # No series file yet
+ oldpatches = []
+ newpatches = [ p[len(PATCH_DIR):] for p in patches ]
+
+ # FIXME: handle case were only the contents of the patches changed
+ added, removed = compare_series(oldpatches, newpatches)
+ msg = format_series_diff(added, removed, options)
+ repo.add_files(PATCH_DIR)
+ repo.commit_staged(msg=msg)
+ return added, removed
+
+
def export_patches(repo, branch, options):
"""Export patches from the pq branch into a patch series"""
if is_pq_branch(branch):
@@ -90,10 +156,22 @@ def export_patches(repo, branch, options):
with open(SERIES_FILE, 'w') as seriesfd:
for patch in patches:
seriesfd.write(os.path.relpath(patch, PATCH_DIR) + '\n')
- GitCommand('status')(['--', PATCH_DIR])
+ if options.commit:
+ added, removed = commit_patches(repo, branch, patches, options)
+ if added:
+ what = 'patches' if len(added) > 1 else 'patch'
+ gbp.log.info("Added %s %s to patch series" % (what, ', '.join(added)))
+ if removed:
+ what = 'patches' if len(removed) > 1 else 'patch'
+ gbp.log.info("Removed %s %s from patch series" % (what, ', '.join(removed)))
+ else:
+ GitCommand('status')(['--', PATCH_DIR])
else:
gbp.log.info("No patches on '%s' - nothing to do." % pq_branch)
+ if options.drop:
+ drop_pq(repo, branch)
+
def safe_patches(series):
"""
@@ -174,8 +252,9 @@ def import_quilt_patches(repo, branch, series, tries, force):
gbp.log.debug("Applying %s" % patch.path)
try:
apply_and_commit_patch(repo, patch, maintainer, patch.topic)
- except (GbpError, GitRepositoryError):
- gbp.log.err("Failed to apply '%s'" % patch.path)
+ except (GbpError, GitRepositoryError) as e:
+ gbp.log.err("Failed to apply '%s': %s" % (patch.path, e))
+ repo.force_head('HEAD', hard=True)
repo.set_branch(branch)
repo.delete_branch(pq_branch)
break
@@ -233,11 +312,14 @@ def build_parser(name):
help="verbose command execution")
parser.add_option("--topic", dest="topic", help="in case of 'apply' topic (subdir) to put patch into")
parser.add_config_file_option(option_name="time-machine", dest="time_machine", type="int")
+ parser.add_boolean_config_file_option("drop", dest='drop')
+ parser.add_boolean_config_file_option(option_name="commit", dest="commit")
parser.add_option("--force", dest="force", action="store_true", default=False,
help="in case of import even import if the branch already exists")
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="meta-closes", dest="meta_closes")
return parser
diff --git a/gbp/scripts/pull.py b/gbp/scripts/pull.py
index fb0d8271..65e3e492 100755
--- a/gbp/scripts/pull.py
+++ b/gbp/scripts/pull.py
@@ -17,7 +17,7 @@
#
# heavily inspired by dom-safe-pull which is © 2009 Stéphane Glondu <steph@glondu.net>
#
-"""fast forward debian, upstream and pristine-tar branch"""
+"""Pull remote changes and fast forward debian, upstream and pristine-tar branch"""
import ConfigParser
import sys
diff --git a/gbp/scripts/supercommand.py b/gbp/scripts/supercommand.py
index 2eb64de2..83c8446b 100644
--- a/gbp/scripts/supercommand.py
+++ b/gbp/scripts/supercommand.py
@@ -17,6 +17,8 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
"""Supercommand for all gbp commands"""
+import glob
+import os
import re
import sys
@@ -42,8 +44,18 @@ The most commonly used commands are:
import-orig - import a new upstream tarball
import-dsc - import a single Debian source package
import-dscs - import multiple Debian source packages
+
+Use '--list-cmds' to list all available commands.
"""
+def version(prog):
+ try:
+ from gbp.version import gbp_version
+ except ImportError:
+ gbp_version = '[Unknown version]'
+ print("%s %s" % (os.path.basename(prog), gbp_version))
+
+
def import_command(cmd):
"""
Import the module that implements the given command
@@ -56,6 +68,40 @@ def import_command(cmd):
return __import__('gbp.scripts.%s' % modulename, fromlist='main', level=0)
+def pymod_to_cmd(mod):
+ """
+ >>> pymod_to_cmd('/x/y/z/a_cmd.py')
+ 'a-cmd'
+ """
+ return os.path.basename(mod.rsplit('.', 1)[0]).replace('_','-')
+
+
+def get_available_commands(path):
+ cmds = []
+ for f in glob.glob(os.path.join(path, '*.py')):
+ if os.path.basename(f) in ['__init__.py', 'supercommand.py']:
+ continue
+ cmds.append((pymod_to_cmd(f), f))
+ return cmds
+
+
+def list_available_commands():
+ mod = __import__('gbp.scripts', fromlist='main', level=0)
+ path = os.path.dirname(mod.__file__)
+ maxlen = 0
+
+ print("Available commands in %s\n" % path)
+ cmds = sorted(get_available_commands(path))
+ for cmd in cmds:
+ if len(cmd[0]) > maxlen:
+ maxlen = len(cmd[0])
+ for cmd in cmds:
+ mod = import_command(cmd[0])
+ doc = mod.__doc__
+ print(" %s - %s" % (cmd[0].rjust(maxlen), doc))
+ print('')
+
+
def supercommand(argv=None):
argv = argv or sys.argv
@@ -63,12 +109,18 @@ def supercommand(argv=None):
usage()
return 1
- cmd = argv[1]
+ prg, cmd = argv[0:2]
args = argv[1:]
- if cmd in ['--help', '-h']:
+ if cmd in ['--help', '-h', 'help' ]:
usage()
return 0
+ elif cmd in [ '--version', 'version' ]:
+ version(argv[0])
+ return 0
+ elif cmd in [ '--list-cmds', 'list-cmds' ]:
+ list_available_commands()
+ return 0
try:
module = import_command(cmd)
@@ -81,4 +133,7 @@ def supercommand(argv=None):
return module.main(args)
+if __name__ == '__main__':
+ sys.exit(supercommand())
+
# vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·:
diff --git a/gbp/tmpfile.py b/gbp/tmpfile.py
new file mode 100644
index 00000000..e1ad3084
--- /dev/null
+++ b/gbp/tmpfile.py
@@ -0,0 +1,38 @@
+# vim: set fileencoding=utf-8 :
+#
+# (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
+"""Temporary directory handling"""
+
+import os
+import tempfile
+
+from gbp.errors import GbpError
+
+def mkdtemp(dir, **kwargs):
+ """Create temporary directory"""
+ try:
+ if not os.path.exists(dir):
+ os.makedirs(dir)
+ except OSError as (dummy_e, msg):
+ raise GbpError, "Unable to create dir %s (%s)" % (dir, msg)
+
+ try:
+ return os.path.abspath(tempfile.mkdtemp(dir=dir, **kwargs))
+ except OSError as (dummy_e, msg):
+ raise GbpError, "Unable to create tmpdir under %s (%s)" % (dir, msg)
+
+# vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·:
+
diff --git a/setup.py b/setup.py
index fb6f6245..3337c21a 100644
--- a/setup.py
+++ b/setup.py
@@ -42,10 +42,25 @@ def fetch_version():
return version
+
+def readme():
+ with open('README') as file:
+ return file.read()
+
setup(name = "gbp",
version = fetch_version(),
author = u'Guido Günther',
author_email = 'agx@sigxcpu.org',
+ url = 'https://honk.sigxcpu.org/piki/projects/git-buildpackage/',
+ description = 'Suite to help with Debian packages in Git repositories',
+ license = 'GPLv2+',
+ long_description = readme(),
+ classifiers = [
+ 'Environment :: Console',
+ 'Programming Language :: Python :: 2',
+ 'Topic :: Software Development :: Version Control :: Git',
+ 'Operating System :: POSIX :: Linux',
+ ],
scripts = [ 'bin/git-buildpackage',
'bin/git-import-dsc',
'bin/git-import-orig',
diff --git a/tests/01_test_help.py b/tests/01_test_help.py
index 673d8708..331d7cc6 100644
--- a/tests/01_test_help.py
+++ b/tests/01_test_help.py
@@ -25,4 +25,13 @@ class TestHelp(unittest.TestCase):
m.main,
['doesnotmatter', '--help'])
+ """Test help output of RPM-specific commands"""
+ def testHelpRpm(self):
+ for script in ['import_srpm']:
+ module = 'gbp.scripts.%s' % script
+ m = __import__(module, globals(), locals(), ['main'], -1)
+ self.assertRaises(SystemExit,
+ m.main,
+ ['doesnotmatter', '--help'])
+
# vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·:
diff --git a/tests/13_test_gbp_pq.py b/tests/13_test_gbp_pq.py
index 753143d3..910ce206 100644
--- a/tests/13_test_gbp_pq.py
+++ b/tests/13_test_gbp_pq.py
@@ -21,7 +21,7 @@ import os
import logging
import unittest
-from gbp.scripts.pq import generate_patches
+from gbp.scripts.pq import generate_patches, switch_pq, export_patches
import gbp.scripts.common.pq as pq
import gbp.patch_series
import tests.testutils as testutils
@@ -132,5 +132,26 @@ class TestWritePatch(testutils.DebianGitTestRepo):
# Branches must be identical afterwards
self.assertEqual('', diff)
+class TestExport(testutils.DebianGitTestRepo):
+ class Options(object):
+ drop = True
+ patch_numbers = False
+
+ def setUp(self):
+ testutils.DebianGitTestRepo.setUp(self)
+ self.add_file('bar', 'bar')
+
+ def test_drop(self):
+ """Test if we drop the patch-queue branch with --drop"""
+ repo = self.repo
+ start = repo.get_branch()
+ pq = os.path.join('patch-queue', start)
+ switch_pq(repo, start)
+ self.assertEqual(repo.get_branch(), pq)
+ export_patches(repo, pq, TestExport.Options)
+ self.assertEqual(repo.get_branch(), start)
+ self.assertFalse(repo.has_branch(pq))
+
+
def _patch_path(name):
return os.path.join(context.projectdir, 'tests/data', name)
diff --git a/tests/20_test_rpm.py b/tests/20_test_rpm.py
new file mode 100644
index 00000000..227a1c68
--- /dev/null
+++ b/tests/20_test_rpm.py
@@ -0,0 +1,383 @@
+# vim: set fileencoding=utf-8 :
+#
+# (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
+"""Test the classes under L{gbp.rpm}"""
+
+import filecmp
+import os
+import shutil
+import tempfile
+from nose.tools import assert_raises, eq_ # pylint: disable=E0611
+
+from gbp.errors import GbpError
+from gbp.rpm import (SrcRpmFile, SpecFile, parse_srpm, NoSpecError, guess_spec,
+ guess_spec_repo, spec_from_repo)
+from gbp.git.repository import GitRepository
+
+# Disable "Method could be a function"
+# pylint: disable=R0201
+
+
+DATA_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'data',
+ 'rpm')
+SRPM_DIR = os.path.join(DATA_DIR, 'srpms')
+SPEC_DIR = os.path.join(DATA_DIR, 'specs')
+
+
+class SpecFileTester(SpecFile):
+ """Helper class for testing"""
+
+ def protected(self, name):
+ """Get a protected member"""
+ return super(SpecFileTester, self).__getattribute__(name)
+
+
+class RpmTestBase(object):
+ """Test base class"""
+ def __init__(self):
+ self.tmpdir = None
+
+ def setup(self):
+ """Test case setup"""
+ self.tmpdir = tempfile.mkdtemp(prefix='gbp_%s_' % __name__, dir='.')
+
+ def teardown(self):
+ """Test case teardown"""
+ shutil.rmtree(self.tmpdir)
+
+class TestSpecFile(RpmTestBase):
+ """Test L{gbp.rpm.SpecFile}"""
+
+ def test_spec(self):
+ """Test parsing of a valid spec file"""
+ spec_filepath = os.path.join(SPEC_DIR, 'gbp-test.spec')
+ spec = SpecFileTester(spec_filepath)
+
+ # Test basic properties
+ assert spec.specfile == os.path.basename(spec_filepath)
+ assert spec.specdir == os.path.dirname(spec_filepath)
+ assert spec.specpath == spec_filepath
+
+ assert spec.name == 'gbp-test'
+ assert spec.packager is None
+
+ assert spec.upstreamversion == '1.0'
+ assert spec.release == '1'
+ assert spec.epoch is None
+ assert spec.version == {'release': '1', 'upstreamversion': '1.0'}
+
+ orig = spec.orig_src
+ assert orig['filename'] == 'gbp-test-1.0.tar.bz2'
+ assert orig['uri'] == 'gbp-test-1.0.tar.bz2'
+ assert orig['filename_base'] == 'gbp-test-1.0'
+ assert orig['archive_fmt'] == 'tar'
+ assert orig['compression'] == 'bzip2'
+ assert orig['prefix'] == 'gbp-test/'
+
+ def test_spec_2(self):
+ """Test parsing of another valid spec file"""
+ spec_filepath = os.path.join(SPEC_DIR, 'gbp-test2.spec')
+ spec = SpecFile(spec_filepath)
+
+ # Test basic properties
+ assert spec.name == 'gbp-test2'
+ assert spec.packager == 'Markus Lehtonen ' \
+ '<markus.lehtonen@linux.intel.com>'
+
+ assert spec.epoch == '2'
+ assert spec.version == {'release': '0', 'upstreamversion': '3.0',
+ 'epoch': '2'}
+
+ orig = spec.orig_src
+ assert orig['filename'] == 'gbp-test2-3.0.tar.gz'
+ assert orig['uri'] == 'ftp://ftp.host.com/gbp-test2-3.0.tar.gz'
+ assert orig['archive_fmt'] == 'tar'
+ assert orig['compression'] == 'gzip'
+ assert orig['prefix'] == ''
+
+ def test_spec_3(self):
+ """Test parsing of yet another valid spec file"""
+ spec_filepath = os.path.join(SPEC_DIR, 'gbp-test-native.spec')
+ spec = SpecFile(spec_filepath)
+
+ # Test basic properties
+ assert spec.name == 'gbp-test-native'
+ orig = spec.orig_src
+ assert orig['filename'] == 'gbp-test-native-1.0.zip'
+ assert orig['archive_fmt'] == 'zip'
+ assert orig['compression'] == None
+ assert orig['prefix'] == 'gbp-test-native-1.0/'
+
+ def test_spec_4(self):
+ """Test parsing of spec without orig tarball"""
+ spec_filepath = os.path.join(SPEC_DIR, 'gbp-test-native2.spec')
+ spec = SpecFile(spec_filepath)
+
+ # Test basic properties
+ assert spec.name == 'gbp-test-native2'
+ assert spec.orig_src is None
+
+ def test_parse_raw(self):
+ """Test parsing of a valid spec file"""
+ with assert_raises(NoSpecError):
+ SpecFile(None, None)
+ with assert_raises(NoSpecError):
+ SpecFile('filename', 'filedata')
+
+ spec_filepath = os.path.join(SPEC_DIR, 'gbp-test.spec')
+ with open(spec_filepath, 'r') as spec_fd:
+ spec_data = spec_fd.read()
+ spec = SpecFile(filedata=spec_data)
+
+ # Test basic properties
+ assert spec.specfile == None
+ assert spec.specdir == None
+ assert spec.name == 'gbp-test'
+
+ def test_update_spec(self):
+ """Test spec autoupdate functionality"""
+ # Create temporary spec file
+ tmp_spec = os.path.join(self.tmpdir, 'gbp-test.spec')
+ shutil.copy2(os.path.join(SPEC_DIR, 'gbp-test.spec'), tmp_spec)
+
+ reference_spec = os.path.join(SPEC_DIR, 'gbp-test-reference.spec')
+ spec = SpecFile(tmp_spec)
+ spec.update_patches(['new.patch'], {})
+ spec.write_spec_file()
+ assert filecmp.cmp(tmp_spec, reference_spec) is True
+
+ # Test adding the VCS tag and adding changelog
+ reference_spec = os.path.join(SPEC_DIR, 'gbp-test-reference2.spec')
+ spec.set_tag('VCS', None, 'myvcstag')
+ spec.set_changelog("* Wed Feb 05 2014 Name <email> 1\n- New entry\n")
+ spec.write_spec_file()
+ assert filecmp.cmp(tmp_spec, reference_spec) is True
+
+ def test_update_spec2(self):
+ """Another test for spec autoupdate functionality"""
+ tmp_spec = os.path.join(self.tmpdir, 'gbp-test2.spec')
+ shutil.copy2(os.path.join(SPEC_DIR, 'gbp-test2.spec'), tmp_spec)
+
+ reference_spec = os.path.join(SPEC_DIR, 'gbp-test2-reference2.spec')
+ spec = SpecFile(tmp_spec)
+ spec.update_patches(['1.patch', '2.patch'],
+ {'1.patch': {'if': 'true'},
+ '2.patch': {'ifarch': '%ix86'}})
+ spec.set_tag('VCS', None, 'myvcstag')
+ spec.write_spec_file()
+ assert filecmp.cmp(tmp_spec, reference_spec) is True
+
+ # Test updating patches again, removing the VCS tag and re-writing
+ # changelog
+ reference_spec = os.path.join(SPEC_DIR, 'gbp-test2-reference.spec')
+ spec.update_patches(['new.patch'], {'new.patch': {'if': '1'}})
+ spec.set_tag('VCS', None, '')
+ spec.set_changelog("* Wed Feb 05 2014 Name <email> 2\n- New entry\n\n")
+ spec.write_spec_file()
+ assert filecmp.cmp(tmp_spec, reference_spec) is True
+
+ def test_modifying(self):
+ """Test updating/deleting of tags and macros"""
+ tmp_spec = os.path.join(self.tmpdir, 'gbp-test.spec')
+ shutil.copy2(os.path.join(SPEC_DIR, 'gbp-test-updates.spec'), tmp_spec)
+ reference_spec = os.path.join(SPEC_DIR,
+ 'gbp-test-updates-reference.spec')
+ spec = SpecFileTester(tmp_spec)
+
+ # Mangle tags
+ prev = spec.protected('_delete_tag')('Vendor', None)
+ spec.protected('_set_tag')('License', None, 'new license', prev)
+ spec.protected('_delete_tag')('source', 0)
+ assert spec.sources() == {}
+ spec.protected('_delete_tag')('patch', 0)
+ spec.protected('_delete_tag')('patch', -1)
+ assert spec.protected('_patches')() == {}
+ prev = spec.protected('_delete_tag')('invalidtag', None)
+
+ with assert_raises(GbpError):
+ # Check that setting empty value fails
+ spec.protected('_set_tag')('Version', None, '', prev)
+ with assert_raises(GbpError):
+ # Check that setting invalid tag with public method fails
+ spec.set_tag('invalidtag', None, 'value')
+
+ # Mangle macros
+ prev = spec.protected('_delete_special_macro')('patch', -1)
+ spec.protected('_delete_special_macro')('patch', 123)
+ spec.protected('_set_special_macro')('patch', 0, 'my new args', prev)
+ with assert_raises(GbpError):
+ spec.protected('_delete_special_macro')('invalidmacro', 0)
+ with assert_raises(GbpError):
+ spec.protected('_set_special_macro')('invalidmacro', 0, 'args',
+ prev)
+
+ # Check resulting spec file
+ spec.write_spec_file()
+ assert filecmp.cmp(tmp_spec, reference_spec) is True
+
+ def test_modifying_err(self):
+ """Test error conditions of modification methods"""
+ spec_filepath = os.path.join(SPEC_DIR, 'gbp-test2.spec')
+ spec = SpecFileTester(spec_filepath)
+
+ # Unknown/invalid section name
+ with assert_raises(GbpError):
+ spec.protected('_set_section')('patch', 'new content\n')
+
+ # Multiple sections with the same name
+ with assert_raises(GbpError):
+ spec.protected('_set_section')('files', '%{_sysconfdir}/foo\n')
+
+ def test_changelog(self):
+ """Test changelog methods"""
+ spec_filepath = os.path.join(SPEC_DIR, 'gbp-test2.spec')
+ spec = SpecFile(spec_filepath)
+
+ # Read changelog
+ eq_(spec.get_changelog(),
+ "* Tue Feb 04 2014 Name <email> 1\n- My change\n\n\n")
+
+ # Set changelog and check again
+ new_text = "* Wed Feb 05 2014 Name <email> 2\n- New entry\n\n\n"
+ spec.set_changelog(new_text)
+ eq_(spec.get_changelog(), new_text)
+
+ def test_quirks(self):
+ """Test spec that is broken/has anomalities"""
+ spec_filepath = os.path.join(SPEC_DIR, 'gbp-test-quirks.spec')
+ spec = SpecFile(spec_filepath)
+
+ # Check that we quess orig source and prefix correctly
+ assert spec.orig_src['prefix'] == 'foobar/'
+
+ def test_tags(self):
+ """Test parsing of all the different tags of spec file"""
+ spec_filepath = os.path.join(SPEC_DIR, 'gbp-test-tags.spec')
+ spec = SpecFileTester(spec_filepath)
+
+ # Check all the tags
+ for name, val in spec.protected('_tags').iteritems():
+ rval = None
+ if name in ('version', 'release', 'epoch'):
+ rval = '0'
+ elif name in ('autoreq', 'autoprov', 'autoreqprov'):
+ rval = 'No'
+ elif name not in spec.protected('_listtags'):
+ rval = 'my_%s' % name
+ if rval:
+ assert val['value'] == rval, ("'%s:' is '%s', expecting '%s'" %
+ (name, val['value'], rval))
+ assert spec.ignorepatches == []
+ # Check patch numbers and patch filenames
+ patches = {}
+ for patch in spec.protected('_tags')['patch']['lines']:
+ patches[patch['num']] = patch['linevalue']
+
+ assert patches == {0: 'my_patch0', -1: 'my_patch'}
+
+ def test_patch_series(self):
+ """Test the getting the patches as a patchseries"""
+ spec_filepath = os.path.join(SPEC_DIR, 'gbp-test-native.spec')
+ spec = SpecFileTester(spec_filepath)
+
+ assert len(spec.patchseries()) == 0
+ spec.update_patches(['1.patch', '2.patch', '3.patch'], {})
+ assert len(spec.patchseries()) == 3
+ spec.protected('_gbp_tags')['ignore-patches'].append({'args': "0"})
+ spec.update_patches(['4.patch'], {})
+ assert len(spec.patchseries()) == 1
+ assert len(spec.patchseries(ignored=True)) == 2
+ spec.protected('_delete_special_macro')('patch', 0)
+ assert len(spec.patchseries(ignored=True)) == 1
+ series = spec.patchseries(unapplied=True, ignored=True)
+ assert len(series) == 2
+ assert os.path.basename(series[-1].path) == '1.patch'
+
+ def test_patch_series_quirks(self):
+ """Patches are applied in order different from the patch numbering"""
+ spec_filepath = os.path.join(SPEC_DIR, 'gbp-test-quirks.spec')
+ spec = SpecFileTester(spec_filepath)
+
+ # Check series is returned in the order the patches are applied
+ files = [os.path.basename(patch.path) for patch in spec.patchseries()]
+ assert files == ['05.patch', '01.patch']
+ # Also ignored patches are returned in the correct order
+ files = [os.path.basename(patch.path) for patch in
+ spec.patchseries(ignored=True)]
+ assert files == ['05.patch', '02.patch', '01.patch']
+ # Unapplied patches are added to the end of the series
+ files = [os.path.basename(patch.path) for patch in
+ spec.patchseries(unapplied=True)]
+ assert files == ['05.patch', '01.patch', '03.patch']
+ # Return all patches (for which tag is found)
+ files = [os.path.basename(patch.path) for patch in
+ spec.patchseries(unapplied=True, ignored=True)]
+ assert files == ['05.patch', '02.patch', '01.patch', '03.patch',
+ '04.patch']
+
+
+class TestUtilityFunctions(RpmTestBase):
+ """Test utility functions of L{gbp.rpm}"""
+
+ def test_guess_spec(self):
+ """Test guess_spec() function"""
+ # Spec not found
+ with assert_raises(NoSpecError):
+ guess_spec(DATA_DIR, recursive=False)
+ # Multiple spec files
+ with assert_raises(NoSpecError):
+ guess_spec(DATA_DIR, recursive=True)
+ with assert_raises(NoSpecError):
+ guess_spec(SPEC_DIR, recursive=False)
+ # Spec found
+ spec = guess_spec(SPEC_DIR, recursive=False,
+ preferred_name = 'gbp-test2.spec')
+ assert spec.specfile == 'gbp-test2.spec'
+ assert spec.specdir == SPEC_DIR
+
+ def test_guess_spec_repo(self):
+ """Test guess_spec_repo() and spec_from_repo() functions"""
+ # Create dummy repository with some commits
+ repo = GitRepository.create(self.tmpdir)
+ with open(os.path.join(repo.path, 'foo.txt'), 'w') as fobj:
+ fobj.write('bar\n')
+ repo.add_files('foo.txt')
+ repo.commit_all('Add dummy file')
+ os.mkdir(os.path.join(repo.path, 'packaging'))
+ shutil.copy(os.path.join(SPEC_DIR, 'gbp-test.spec'),
+ os.path.join(repo.path, 'packaging'))
+ repo.add_files('packaging/gbp-test.spec')
+ repo.commit_all('Add spec file')
+
+ # Spec not found
+ with assert_raises(NoSpecError):
+ guess_spec_repo(repo, 'HEAD~1', recursive=True)
+ with assert_raises(NoSpecError):
+ guess_spec_repo(repo, 'HEAD', recursive=False)
+ # Spec found
+ spec = guess_spec_repo(repo, 'HEAD', 'packaging', recursive=False)
+ spec = guess_spec_repo(repo, 'HEAD', recursive=True)
+ assert spec.specfile == 'gbp-test.spec'
+ assert spec.specdir == 'packaging'
+ assert spec.specpath == 'packaging/gbp-test.spec'
+
+ # Test spec_from_repo()
+ with assert_raises(NoSpecError):
+ spec_from_repo(repo, 'HEAD~1', 'packaging/gbp-test.spec')
+ spec = spec_from_repo(repo, 'HEAD', 'packaging/gbp-test.spec')
+ assert spec.specfile == 'gbp-test.spec'
+
+# vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·:
diff --git a/tests/component/__init__.py b/tests/component/__init__.py
index 4ef22563..7abb16d1 100644
--- a/tests/component/__init__.py
+++ b/tests/component/__init__.py
@@ -153,6 +153,8 @@ class ComponentTestBase(object):
self._loghandler = gbp.log.GbpStreamHandler(self._log, False)
self._loghandler.addFilter(gbp.log.GbpFilter([gbp.log.WARNING,
gbp.log.ERROR]))
+ for hdl in gbp.log.LOGGER.handlers:
+ gbp.log.LOGGER.removeHandler(hdl)
gbp.log.LOGGER.addHandler(self._loghandler)
elif self._log is not None:
gbp.log.LOGGER.removeHandler(self._loghandler)
diff --git a/tests/component/rpm/__init__.py b/tests/component/rpm/__init__.py
new file mode 100644
index 00000000..e84fca94
--- /dev/null
+++ b/tests/component/rpm/__init__.py
@@ -0,0 +1,30 @@
+# vim: set fileencoding=utf-8 :
+#
+# (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
+"""Test module for RPM command line tools of the git-buildpackage suite"""
+
+import os
+
+from tests.component import ComponentTestGitRepository
+
+RPM_TEST_DATA_SUBMODULE = os.path.join('tests', 'component', 'rpm', 'data')
+RPM_TEST_DATA_DIR = os.path.abspath(RPM_TEST_DATA_SUBMODULE)
+
+def setup():
+ """Test Module setup"""
+ ComponentTestGitRepository.check_testdata(RPM_TEST_DATA_SUBMODULE)
+
+# vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·:
diff --git a/tests/component/rpm/data b/tests/component/rpm/data
new file mode 160000
+Subproject 90bf36d7981fdd1677cf7e734d9e1056a5fced1
diff --git a/tests/component/rpm/test_import_srpm.py b/tests/component/rpm/test_import_srpm.py
new file mode 100644
index 00000000..d0e71701
--- /dev/null
+++ b/tests/component/rpm/test_import_srpm.py
@@ -0,0 +1,343 @@
+# vim: set fileencoding=utf-8 :
+#
+# (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
+"""Basic tests for the git-import-srpm tool"""
+
+import os
+import shutil
+import urllib2
+from nose.plugins.skip import SkipTest
+from nose.tools import assert_raises, eq_, ok_ # pylint: disable=E0611
+from mock import Mock
+
+from gbp.scripts.import_srpm import main as import_srpm
+from gbp.git import GitRepository
+from gbp.rpm import SrcRpmFile
+
+from tests.component import ComponentTestBase
+from tests.component.rpm import RPM_TEST_DATA_DIR as DATA_DIR
+
+# Disable "Method could be a function warning"
+# pylint: disable=R0201
+
+def mock_import(args):
+ """Wrapper for import-srpm"""
+ # Call import-orig-rpm with added arg0
+ return import_srpm(['arg0'] + args)
+
+
+class TestImportPacked(ComponentTestBase):
+ """Test importing of src.rpm files"""
+
+ def test_invalid_args(self):
+ """See that import-srpm fails gracefully if called with invalid args"""
+ eq_(mock_import([]), 1)
+ with assert_raises(SystemExit):
+ mock_import(['--invalid-arg=123'])
+
+ def test_basic_import(self):
+ """Test importing of non-native src.rpm"""
+ srpm = os.path.join(DATA_DIR, 'gbp-test-1.0-1.src.rpm')
+ eq_(mock_import(['--no-pristine-tar', srpm]), 0)
+ # Check repository state
+ repo = GitRepository('gbp-test')
+ files = {'Makefile', 'README', 'bar.tar.gz', 'dummy.sh', 'foo.txt',
+ 'gbp-test.spec', 'my.patch', 'my2.patch', 'my3.patch'}
+ self._check_repo_state(repo, 'master', ['master', 'upstream'], files)
+ # Two commits: upstream and packaging files
+ eq_(len(repo.get_commits()), 2)
+
+ def test_basic_import2(self):
+ """Import package with multiple spec files and full url patch"""
+ srpm = os.path.join(DATA_DIR, 'gbp-test2-2.0-0.src.rpm')
+ eq_(mock_import(['--no-pristine-tar', srpm]), 0)
+ # Check repository state
+ repo = GitRepository('gbp-test2')
+ files = {'Makefile', 'README', 'bar.tar.gz', 'dummy.sh', 'foo.txt',
+ 'gbp-test2.spec', 'gbp-test2-alt.spec', 'my.patch',
+ 'my2.patch', 'my3.patch'}
+ self._check_repo_state(repo, 'master', ['master', 'upstream'], files)
+
+ # Two commits: upstream and packaging files
+ eq_(len(repo.get_commits()), 2)
+
+ def test_basic_import_orphan(self):
+ """
+ Test importing of non-native src.rpm to separate packaging and
+ development branches
+ """
+ srpm = os.path.join(DATA_DIR, 'gbp-test2-2.0-0.src.rpm')
+ eq_(mock_import(['--no-pristine-tar', '--orphan-packaging', srpm]), 0)
+ # Check repository state
+ repo = GitRepository('gbp-test2')
+ files = {'bar.tar.gz', 'foo.txt', 'gbp-test2.spec',
+ 'gbp-test2-alt.spec', 'my.patch', 'my2.patch', 'my3.patch'}
+ self._check_repo_state(repo, 'master', ['master', 'upstream'], files)
+ # Only one commit: the packaging files
+ eq_(len(repo.get_commits()), 1)
+
+ def test_basic_native_import(self):
+ """Test importing of native src.rpm"""
+ srpm = os.path.join(DATA_DIR, 'gbp-test-native-1.0-1.src.rpm')
+ eq_(mock_import(['--native', srpm]), 0)
+ # Check repository state
+ files = {'.gbp.conf', 'Makefile', 'README', 'dummy.sh', 'packaging/',
+ 'packaging/gbp-test-native.spec'}
+ repo = GitRepository('gbp-test-native')
+ self._check_repo_state(repo, 'master', ['master'], files)
+ # Only one commit: the imported source tarball
+ eq_(len(repo.get_commits()), 1)
+
+ def test_import_no_orig_src(self):
+ """Test importing of (native) srpm without orig tarball"""
+ srpm = os.path.join(DATA_DIR, 'gbp-test-native2-2.0-0.src.rpm')
+ eq_(mock_import([srpm]), 0)
+ # Check repository state
+ repo = GitRepository('gbp-test-native2')
+ self._check_repo_state(repo, 'master', ['master'])
+ # Only one commit: packaging files
+ eq_(len(repo.get_commits()), 1)
+
+ def test_multiple_versions(self):
+ """Test importing of multiple versions"""
+ srpms = [ os.path.join(DATA_DIR, 'gbp-test-1.0-1.src.rpm'),
+ os.path.join(DATA_DIR, 'gbp-test-1.0-1.other.src.rpm'),
+ os.path.join(DATA_DIR, 'gbp-test-1.1-1.src.rpm') ]
+ eq_(mock_import(['--no-pristine-tar', srpms[0]]), 0)
+ repo = GitRepository('gbp-test')
+ self._check_repo_state(repo, 'master', ['master', 'upstream'])
+ eq_(len(repo.get_commits()), 2)
+ # Try to import same version again
+ eq_(mock_import([srpms[1]]), 0)
+ eq_(len(repo.get_commits()), 2)
+ eq_(len(repo.get_commits(until='upstream')), 1)
+ eq_(mock_import(['--no-pristine-tar', '--allow-same-version', srpms[1]]), 0)
+ # Added new version of packaging
+ eq_(len(repo.get_commits()), 3)
+ eq_(len(repo.get_commits(until='upstream')), 1)
+ # Import new version
+ eq_(mock_import(['--no-pristine-tar', srpms[2]]), 0)
+ files = {'Makefile', 'README', 'bar.tar.gz', 'dummy.sh', 'foo.txt',
+ 'gbp-test.spec', 'my.patch', 'my2.patch', 'my3.patch'}
+ self._check_repo_state(repo, 'master', ['master', 'upstream'], files)
+ eq_(len(repo.get_commits()), 5)
+ eq_(len(repo.get_commits(until='upstream')), 2)
+ # Check number of tags
+ eq_(len(repo.get_tags('upstream/*')), 2)
+ eq_(len(repo.get_tags('packaging/*')), 3)
+
+ def test_import_to_existing(self):
+ """Test importing to an existing repo"""
+ srpm = os.path.join(DATA_DIR, 'gbp-test-1.0-1.src.rpm')
+
+ # Create new repo
+ repo = GitRepository.create('myrepo')
+ os.chdir('myrepo')
+ shutil.copy2('.git/HEAD', 'foobar')
+ repo.add_files('.')
+ repo.commit_all('First commit')
+
+ # Test importing to non-clean repo
+ shutil.copy2('.git/HEAD', 'foobaz')
+ eq_(mock_import(['--create-missing', srpm]), 1)
+ self._check_log(0, 'gbp:error: Repository has uncommitted changes')
+ self._clear_log()
+ os.unlink('foobaz')
+
+ # The first import should fail because upstream branch is missing
+ eq_(mock_import([srpm]), 1)
+ self._check_log(-1, 'Also check the --create-missing-branches')
+ eq_(mock_import(['--no-pristine-tar', '--create-missing', srpm]), 0)
+ self._check_repo_state(repo, 'master', ['master', 'upstream'])
+ # Four commits: our initial, upstream and packaging files
+ eq_(len(repo.get_commits()), 3)
+
+ # The import should fail because missing packaging-branch
+ srpm = os.path.join(DATA_DIR, 'gbp-test-1.1-1.src.rpm')
+ eq_(mock_import(['--packaging-branch=foo', srpm]), 1)
+ self._check_log(-1, 'Also check the --create-missing-branches')
+
+
+ def test_filter(self):
+ """Test filter option"""
+ srpm = os.path.join(DATA_DIR, 'gbp-test-1.0-1.src.rpm')
+ eq_(mock_import(['--no-pristine-tar', '--filter=README', '--filter=mydir', srpm]), 0)
+ # Check repository state
+ repo = GitRepository('gbp-test')
+ files = set(['Makefile', 'dummy.sh', 'bar.tar.gz', 'foo.txt',
+ 'gbp-test.spec', 'my.patch', 'my2.patch', 'my3.patch'])
+ self._check_repo_state(repo, 'master', ['master', 'upstream'], files)
+
+ def test_misc_options(self):
+ """Test various options of git-import-srpm"""
+ srpm = os.path.join(DATA_DIR, 'gbp-test2-2.0-0.src.rpm')
+
+ eq_(mock_import(['--no-pristine-tar',
+ '--packaging-branch=pack',
+ '--upstream-branch=orig',
+ '--packaging-dir=packaging',
+ '--packaging-tag=ver_%(upstreamversion)s-rel_%(release)s',
+ '--upstream-tag=orig/%(upstreamversion)s',
+ '--author-is-committer',
+ srpm]), 0)
+ # Check repository state
+ repo = GitRepository('gbp-test2')
+ files = {'Makefile', 'README', 'dummy.sh', 'packaging/',
+ 'packaging/bar.tar.gz', 'packaging/foo.txt',
+ 'packaging/gbp-test2.spec', 'packaging/gbp-test2-alt.spec',
+ 'packaging/my.patch', 'packaging/my2.patch',
+ 'packaging/my3.patch'}
+ self._check_repo_state(repo, 'pack', ['pack', 'orig'], files)
+ eq_(len(repo.get_commits()), 2)
+ # Check packaging dir
+ eq_(len(repo.get_commits(paths='packaging')), 1)
+ # Check tags
+ tags = repo.get_tags()
+ eq_(set(tags), set(['orig/2.0', 'ver_2.0-rel_0']))
+ # Check git committer/author
+ info = repo.get_commit_info('pack')
+ eq_(info['author'].name, 'Markus Lehtonen')
+ eq_(info['author'].email, 'markus.lehtonen@linux.intel.com')
+ eq_(info['author'].name, info['committer'].name)
+ eq_(info['author'].email, info['committer'].email)
+
+
+class TestImportUnPacked(ComponentTestBase):
+ """Test importing of unpacked source rpms"""
+
+ def setup(self):
+ super(TestImportUnPacked, self).setup()
+ # Unpack some source rpms
+ os.mkdir('multi-unpack')
+ for pkg in ['gbp-test-1.0-1.src.rpm', 'gbp-test2-2.0-0.src.rpm']:
+ unpack_dir = pkg.replace('.src.rpm', '-unpack')
+ os.mkdir(unpack_dir)
+ pkg_path = os.path.join(DATA_DIR, pkg)
+ SrcRpmFile(pkg_path).unpack(unpack_dir)
+ SrcRpmFile(pkg_path).unpack('multi-unpack')
+
+ def test_import_dir(self):
+ """Test importing of directories"""
+ eq_(mock_import(['--no-pristine-tar', 'gbp-test-1.0-1-unpack']), 0)
+ # Check repository state
+ repo = GitRepository('gbp-test')
+ self._check_repo_state(repo, 'master', ['master', 'upstream'])
+
+ # Check that importing dir with multiple spec files fails
+ eq_(mock_import(['multi-unpack']), 1)
+ self._check_log(-1, 'gbp:error: Failed determine spec file: '
+ 'Multiple spec files found')
+
+ def test_import_spec(self):
+ """Test importing of spec file"""
+ specfile = 'gbp-test2-2.0-0-unpack/gbp-test2.spec'
+ eq_(mock_import([specfile]), 0)
+ # Check repository state
+ ok_(GitRepository('gbp-test2').is_clean())
+
+ def test_missing_files(self):
+ """Test importing of directory with missing packaging files"""
+ specfile = 'gbp-test2-2.0-0-unpack/gbp-test2.spec'
+ os.unlink('gbp-test2-2.0-0-unpack/my.patch')
+ eq_(mock_import([specfile]), 1)
+ self._check_log(-1, "gbp:error: File 'my.patch' listed in spec "
+ "not found")
+
+
+class TestDownloadImport(ComponentTestBase):
+ """Test download functionality"""
+
+ def test_urldownload(self):
+ """Test downloading and importing src.rpm from remote url"""
+ srpm = 'http://raw.github.com/marquiz/git-buildpackage-rpm-testdata/'\
+ 'master/gbp-test-1.0-1.src.rpm'
+ # Mock to use local files instead of really downloading
+ local_fn = os.path.join(DATA_DIR, os.path.basename(srpm))
+ urllib2.urlopen = Mock()
+ urllib2.urlopen.return_value = open(local_fn, 'r')
+
+ eq_(mock_import(['--no-pristine-tar', '--download', srpm]), 0)
+ # Check repository state
+ repo = GitRepository('gbp-test')
+ self._check_repo_state(repo, 'master', ['master', 'upstream'])
+
+ def test_nonexistent_url(self):
+ """Test graceful failure when trying download from nonexistent url"""
+ srpm = 'http://url.does.not.exist.com/foo.src.rpm'
+ # Do not connect to remote, mock failure
+ urllib2.urlopen = Mock()
+ urllib2.urlopen.side_effect = urllib2.HTTPError(srpm, 404, "Not found",
+ None, None)
+
+ eq_(mock_import(['--download', srpm]), 1)
+ self._check_log(-1, "gbp:error: Download failed: HTTP Error 404")
+ self._clear_log()
+
+ def test_invalid_url(self):
+ """Test graceful failure when trying download from invalid url"""
+ srpm = 'foob://url.does.not.exist.com/foo.src.rpm'
+ eq_(mock_import(['--download', srpm]), 1)
+ self._check_log(-1, "gbp:error: Download failed: unknown url type:")
+ self._clear_log()
+
+
+class TestPristineTar(ComponentTestBase):
+ """Test importing with pristine-tar"""
+
+ @classmethod
+ def setup_class(cls):
+ if not os.path.exists('/usr/bin/pristine-tar'):
+ raise SkipTest('Skipping %s:%s as pristine-tar tool is not '
+ 'available' % (__name__, cls.__name__))
+ super(TestPristineTar, cls).setup_class()
+
+ def test_basic_import_pristine_tar(self):
+ """Test importing of non-native src.rpm, with pristine-tar"""
+ srpm = os.path.join(DATA_DIR, 'gbp-test-1.0-1.src.rpm')
+ eq_(mock_import(['--pristine-tar', srpm]), 0)
+ # Check repository state
+ repo = GitRepository('gbp-test')
+ self._check_repo_state(repo, 'master', ['master', 'upstream',
+ 'pristine-tar'])
+ # Two commits: upstream and packaging files
+ eq_(len(repo.get_commits()), 2)
+
+ def test_unsupported_archive(self):
+ """Test importing of src.rpm with a zip source archive"""
+ srpm = os.path.join(DATA_DIR, 'gbp-test-native-1.0-1.src.rpm')
+ eq_(mock_import(['--pristine-tar', srpm]), 0)
+ # Check repository state
+ repo = GitRepository('gbp-test-native')
+ self._check_repo_state(repo, 'master', ['master', 'upstream'])
+ # Check that a warning is printed
+ self._check_log(-1, "gbp:warning: Ignoring pristine-tar")
+
+
+class TestBareRepo(ComponentTestBase):
+ """Test importing to a bare repository"""
+
+ def test_basic_import_to_bare_repo(self):
+ """Test importing of srpm to a bare git repository"""
+ srpm = os.path.join(DATA_DIR, 'gbp-test-1.0-1.src.rpm')
+ # Create new repo
+ repo = GitRepository.create('myrepo', bare=True)
+ os.chdir('myrepo')
+ eq_(mock_import([srpm]), 0)
+ self._check_repo_state(repo, 'master', ['master', 'upstream'])
+ # Patch import to bare repos not supported -> only 2 commits
+ eq_(len(repo.get_commits(until='master')), 2)
+
+# vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·:
diff --git a/tests/data/rpm/rpmbuild/SOURCES/bar.tar.gz b/tests/data/rpm/rpmbuild/SOURCES/bar.tar.gz
new file mode 100644
index 00000000..f5dae803
--- /dev/null
+++ b/tests/data/rpm/rpmbuild/SOURCES/bar.tar.gz
Binary files differ
diff --git a/tests/data/rpm/rpmbuild/SOURCES/foo.txt b/tests/data/rpm/rpmbuild/SOURCES/foo.txt
new file mode 100644
index 00000000..25ed442f
--- /dev/null
+++ b/tests/data/rpm/rpmbuild/SOURCES/foo.txt
@@ -0,0 +1,3 @@
+FOO:
+
+file for testing rpm support of git-buildpackage.
diff --git a/tests/data/rpm/rpmbuild/SOURCES/gbp-test-1.0.tar.bz2 b/tests/data/rpm/rpmbuild/SOURCES/gbp-test-1.0.tar.bz2
new file mode 100644
index 00000000..7d0759fe
--- /dev/null
+++ b/tests/data/rpm/rpmbuild/SOURCES/gbp-test-1.0.tar.bz2
Binary files differ
diff --git a/tests/data/rpm/rpmbuild/SOURCES/gbp-test-native-1.0.zip b/tests/data/rpm/rpmbuild/SOURCES/gbp-test-native-1.0.zip
new file mode 100644
index 00000000..22a273d1
--- /dev/null
+++ b/tests/data/rpm/rpmbuild/SOURCES/gbp-test-native-1.0.zip
Binary files differ
diff --git a/tests/data/rpm/rpmbuild/SOURCES/gbp-test2-3.0.tar.gz b/tests/data/rpm/rpmbuild/SOURCES/gbp-test2-3.0.tar.gz
new file mode 100644
index 00000000..7b3eaf3c
--- /dev/null
+++ b/tests/data/rpm/rpmbuild/SOURCES/gbp-test2-3.0.tar.gz
Binary files differ
diff --git a/tests/data/rpm/rpmbuild/SOURCES/my.patch b/tests/data/rpm/rpmbuild/SOURCES/my.patch
new file mode 100644
index 00000000..50870df2
--- /dev/null
+++ b/tests/data/rpm/rpmbuild/SOURCES/my.patch
@@ -0,0 +1,9 @@
+diff --git a/dummy.sh b/dummy.sh
+index 8c33db6..6f04268 100755
+--- dummy.sh
++++ dummy.sh
+@@ -1,3 +1,3 @@
+ #!/bin/sh
+
+-echo "Hello world"
++echo "Hello GBP"
diff --git a/tests/data/rpm/rpmbuild/SOURCES/my2.patch b/tests/data/rpm/rpmbuild/SOURCES/my2.patch
new file mode 100644
index 00000000..ad5ca2d2
--- /dev/null
+++ b/tests/data/rpm/rpmbuild/SOURCES/my2.patch
@@ -0,0 +1,7 @@
+diff --git a/mydir/myfile.txt b/mydir/myfile.txt
+new file mode 100644
+index 0000000..2cdad29
+--- /dev/null
++++ b/mydir/myfile.txt
+@@ -0,0 +1 @@
++Dummy
diff --git a/tests/data/rpm/rpmbuild/SOURCES/my3.patch b/tests/data/rpm/rpmbuild/SOURCES/my3.patch
new file mode 100644
index 00000000..9fee859d
--- /dev/null
+++ b/tests/data/rpm/rpmbuild/SOURCES/my3.patch
@@ -0,0 +1,7 @@
+diff --git a/README b/README
+index a1311cb..a59f1b9 100644
+--- a/README
++++ b/README
+@@ -1 +1 @@
+-Just for testing git-buildpackage.
++Just for testing GBP.
diff --git a/tests/data/rpm/rpmbuild/SPECS/gbp-test-native.spec b/tests/data/rpm/rpmbuild/SPECS/gbp-test-native.spec
new file mode 100644
index 00000000..38b07e48
--- /dev/null
+++ b/tests/data/rpm/rpmbuild/SPECS/gbp-test-native.spec
@@ -0,0 +1,34 @@
+Name: gbp-test-native
+Summary: Test package for git-buildpackage
+Version: 1.0
+Release: 1
+Group: Development/Libraries
+License: GPLv2
+Source1: %{name}-%{version}.zip
+BuildRequires: unzip
+
+%description
+Package for testing the RPM functionality of git-buildpackage.
+Mimics a "native" package
+
+
+%prep
+unzip %{SOURCE1}
+%setup -T -D
+
+
+%build
+make
+
+
+%install
+rm -rf %{buildroot}
+mkdir -p %{buildroot}/%{_datadir}/%{name}
+cp -R * %{buildroot}/%{_datadir}/%{name}
+
+
+
+%files
+%defattr(-,root,root,-)
+%dir %{_datadir}/%{name}
+%{_datadir}/%{name}
diff --git a/tests/data/rpm/rpmbuild/SPECS/gbp-test-native2.spec b/tests/data/rpm/rpmbuild/SPECS/gbp-test-native2.spec
new file mode 100644
index 00000000..34fd33dc
--- /dev/null
+++ b/tests/data/rpm/rpmbuild/SPECS/gbp-test-native2.spec
@@ -0,0 +1,35 @@
+Name: gbp-test-native2
+Summary: Test package for git-buildpackage
+Version: 2.0
+Release: 0
+Group: Development/Libraries
+License: GPLv2
+Source: foo.txt
+BuildRequires: unzip
+
+%description
+Package for testing the RPM functionality of git-buildpackage.
+Mimics a "native" package that doesn't have any source tarball.
+
+
+%prep
+# Just create build dir
+%setup -T -c
+cp %{SOURCE0} .
+
+
+%build
+# Nothing to do
+
+
+%install
+rm -rf %{buildroot}
+mkdir -p %{buildroot}/%{_datadir}/%{name}
+cp -R * %{buildroot}/%{_datadir}/%{name}
+
+
+
+%files
+%defattr(-,root,root,-)
+%dir %{_datadir}/%{name}
+%{_datadir}/%{name}
diff --git a/tests/data/rpm/rpmbuild/SPECS/gbp-test.spec b/tests/data/rpm/rpmbuild/SPECS/gbp-test.spec
new file mode 100644
index 00000000..c46a734e
--- /dev/null
+++ b/tests/data/rpm/rpmbuild/SPECS/gbp-test.spec
@@ -0,0 +1,42 @@
+Name: gbp-test
+Summary: Test package for git-buildpackage
+Version: 1.0
+Release: 1
+Group: Development/Libraries
+License: GPLv2
+Source: %{name}-%{version}.tar.bz2
+Source1: foo.txt
+Source20: bar.tar.gz
+# Gbp-Ignore-Patches: 0
+Patch0: my.patch
+Patch10: my2.patch
+Patch20: my3.patch
+
+
+%description
+Package for testing the RPM functionality of git-buildpackage.
+
+
+%prep
+%setup -n %{name} -a 20
+
+%patch0
+%patch10 -p1
+
+
+%build
+make
+
+
+%install
+rm -rf %{buildroot}
+mkdir -p %{buildroot}/%{_datadir}/%{name}
+cp -R * %{buildroot}/%{_datadir}/%{name}
+install %{SOURCE0} %{buildroot}/%{_datadir}/%{name}
+
+
+
+%files
+%defattr(-,root,root,-)
+%dir %{_datadir}/%{name}
+%{_datadir}/%{name}
diff --git a/tests/data/rpm/rpmbuild/SPECS/gbp-test2.spec b/tests/data/rpm/rpmbuild/SPECS/gbp-test2.spec
new file mode 100644
index 00000000..8a92725d
--- /dev/null
+++ b/tests/data/rpm/rpmbuild/SPECS/gbp-test2.spec
@@ -0,0 +1,60 @@
+Name: gbp-test2
+Summary: Test package 2 for git-buildpackage
+Epoch: 2
+Version: 3.0
+Release: 0
+Group: Development/Libraries
+License: GPLv2
+Source10: ftp://ftp.host.com/%{name}-%{version}.tar.gz
+Source: foo.txt
+Source20: bar.tar.gz
+# Gbp-Ignore-Patches: -1
+Patch: my.patch
+Patch10: my2.patch
+Patch20: my3.patch
+Packager: Markus Lehtonen <markus.lehtonen@linux.intel.com>
+VCS: myoldvcstag
+
+%description
+Package for testing the RPM functionality of git-buildpackage.
+
+%package empty
+Summary: Empty subpackage
+
+%description empty
+Empty subpackage for the %{name} test package.
+
+
+%prep
+%setup -T -n %{name}-%{version} -c -a 10
+
+%patch
+%patch -P 10 -p1
+
+echo "Do things"
+
+# Gbp-Patch-Macros
+
+%build
+make
+
+
+%install
+rm -rf %{buildroot}
+mkdir -p %{buildroot}/%{_datadir}/%{name}
+cp -R * %{buildroot}/%{_datadir}/%{name}
+install %{SOURCE0} %{buildroot}/%{_datadir}/%{name}
+
+
+%changelog
+* Tue Feb 04 2014 Name <email> 1
+- My change
+
+
+%files
+%defattr(-,root,root,-)
+%dir %{_datadir}/%{name}
+%{_datadir}/%{name}
+
+%files empty
+%defattr(-,root,root,-)
diff --git a/tests/data/rpm/specs/gbp-test-native.spec b/tests/data/rpm/specs/gbp-test-native.spec
new file mode 120000
index 00000000..60de36f2
--- /dev/null
+++ b/tests/data/rpm/specs/gbp-test-native.spec
@@ -0,0 +1 @@
+../rpmbuild/SPECS/gbp-test-native.spec \ No newline at end of file
diff --git a/tests/data/rpm/specs/gbp-test-native2.spec b/tests/data/rpm/specs/gbp-test-native2.spec
new file mode 120000
index 00000000..ad13ad6a
--- /dev/null
+++ b/tests/data/rpm/specs/gbp-test-native2.spec
@@ -0,0 +1 @@
+../rpmbuild/SPECS/gbp-test-native2.spec \ No newline at end of file
diff --git a/tests/data/rpm/specs/gbp-test-quirks.spec b/tests/data/rpm/specs/gbp-test-quirks.spec
new file mode 100644
index 00000000..bb56b008
--- /dev/null
+++ b/tests/data/rpm/specs/gbp-test-quirks.spec
@@ -0,0 +1,30 @@
+#
+# Spec for testing some quirks of spec parsing
+#
+
+Name: pkg_name
+Summary: Spec for testing some quirks of spec parsing
+Version: 0.1
+Release: 1.2
+License: GPLv2
+Source1: foobar.tar.gz
+# Gbp-Ignore-Patches: 2 4 888
+Patch1: 01.patch
+Patch2: 02.patch
+Patch3: 03.patch
+Patch4: 04.patch
+Patch5: 05.patch
+
+%description
+Spec for testing some quirks of spec parsing. No intended for building an RPM.
+
+%prep
+# We don't have Source0 so rpmbuild would fail, but gbp shouldn't crash
+%setup -q
+
+# Patches are applied out-of-order wrt. numbering
+%patch5
+%patch2
+%patch1
+# Patch 999 does not exist, rpmbuild would fail but GBP should not
+%patch999
diff --git a/tests/data/rpm/specs/gbp-test-reference.spec b/tests/data/rpm/specs/gbp-test-reference.spec
new file mode 100644
index 00000000..050d1398
--- /dev/null
+++ b/tests/data/rpm/specs/gbp-test-reference.spec
@@ -0,0 +1,43 @@
+Name: gbp-test
+Summary: Test package for git-buildpackage
+Version: 1.0
+Release: 1
+Group: Development/Libraries
+License: GPLv2
+Source: %{name}-%{version}.tar.bz2
+Source1: foo.txt
+Source20: bar.tar.gz
+# Gbp-Ignore-Patches: 0
+Patch0: my.patch
+# Patches auto-generated by git-buildpackage:
+Patch1: new.patch
+
+
+%description
+Package for testing the RPM functionality of git-buildpackage.
+
+
+%prep
+%setup -n %{name} -a 20
+
+%patch0
+# new.patch
+%patch1 -p1
+
+
+%build
+make
+
+
+%install
+rm -rf %{buildroot}
+mkdir -p %{buildroot}/%{_datadir}/%{name}
+cp -R * %{buildroot}/%{_datadir}/%{name}
+install %{SOURCE0} %{buildroot}/%{_datadir}/%{name}
+
+
+
+%files
+%defattr(-,root,root,-)
+%dir %{_datadir}/%{name}
+%{_datadir}/%{name}
diff --git a/tests/data/rpm/specs/gbp-test-reference2.spec b/tests/data/rpm/specs/gbp-test-reference2.spec
new file mode 100644
index 00000000..0fbe0260
--- /dev/null
+++ b/tests/data/rpm/specs/gbp-test-reference2.spec
@@ -0,0 +1,47 @@
+Name: gbp-test
+VCS: myvcstag
+Summary: Test package for git-buildpackage
+Version: 1.0
+Release: 1
+Group: Development/Libraries
+License: GPLv2
+Source: %{name}-%{version}.tar.bz2
+Source1: foo.txt
+Source20: bar.tar.gz
+# Gbp-Ignore-Patches: 0
+Patch0: my.patch
+# Patches auto-generated by git-buildpackage:
+Patch1: new.patch
+
+
+%description
+Package for testing the RPM functionality of git-buildpackage.
+
+
+%prep
+%setup -n %{name} -a 20
+
+%patch0
+# new.patch
+%patch1 -p1
+
+
+%build
+make
+
+
+%install
+rm -rf %{buildroot}
+mkdir -p %{buildroot}/%{_datadir}/%{name}
+cp -R * %{buildroot}/%{_datadir}/%{name}
+install %{SOURCE0} %{buildroot}/%{_datadir}/%{name}
+
+
+
+%files
+%defattr(-,root,root,-)
+%dir %{_datadir}/%{name}
+%{_datadir}/%{name}
+%changelog
+* Wed Feb 05 2014 Name <email> 1
+- New entry
diff --git a/tests/data/rpm/specs/gbp-test-tags.spec b/tests/data/rpm/specs/gbp-test-tags.spec
new file mode 100644
index 00000000..ee4c2b94
--- /dev/null
+++ b/tests/data/rpm/specs/gbp-test-tags.spec
@@ -0,0 +1,74 @@
+#
+# Spec file for testing all RPM tags (that we know of
+#
+
+%define suse_release %(test -e /etc/SuSE-release && head -n1 /etc/SuSE-release | cut -d ' ' -f2 | cut --output-delimiter=0 -d. -f1,2 || echo 0)
+%if "%{suse_release}" >= "1201"
+%define test_weak_dep_tags 1
+%endif
+
+%define test_arch_os_tags %(test -n "$GBP_SKIP_ARCH_OS_TAGS" && echo 0 || echo 1)
+
+%define source_fn_base source
+%define patch_fn_base patch
+
+# Gbp-Undefined-Tag: foobar
+
+# Test that we accept different cases
+NAME: my_name
+version: 0
+ReLeasE: 0
+
+# Rest of the tags
+Epoch: 0
+Summary: my_summary
+License: my_license
+Distribution: my_distribution
+Vendor: my_vendor
+Group: my_group
+Packager: my_packager
+Url: my_url
+Vcs: my_vcs
+Source: my_source
+Patch: my_%patch_fn_base
+Patch0: my_%{patch_fn_base}0
+Nosource: 0
+Nopatch: 0
+#Icon: my_icon
+BuildRoot: my_buildroot
+Provides: my_provides
+Requires: my_requires
+Conflicts: my_conflicts
+Obsoletes: my_obsoletes
+BuildConflicts: my_buildconflicts
+BuildRequires: my_buildrequires
+AutoReqProv: No
+AutoReq: No
+AutoProv: No
+DistTag: my_disttag
+BugUrl: my_bugurl
+Collections: my_collections
+
+%if 0%{?test_weak_dep_tags}
+Recommends: my_recommends
+Suggests: my_suggests
+Supplements: my_supplements
+Enhances: my_enhances
+BuildRecommends:my_buildrecommends
+BuildSuggests: my_buildsuggests
+BuildSupplements:my_buildsupplements
+BuildEnhances: my_buildenhances
+%endif
+
+# These should be filtered out by GBP
+%if "%{test_arch_os_tags}" != "0"
+BuildArch: my_buildarch
+ExcludeArch: my_excludearch
+ExclusiveArch: my_exclusivearch
+ExcludeOs: my_excludeos
+ExclusiveOs: my_exclusiveos
+%endif
+
+%description
+Package for testing GBP.
+
diff --git a/tests/data/rpm/specs/gbp-test-updates-reference.spec b/tests/data/rpm/specs/gbp-test-updates-reference.spec
new file mode 100644
index 00000000..ff56f589
--- /dev/null
+++ b/tests/data/rpm/specs/gbp-test-updates-reference.spec
@@ -0,0 +1,44 @@
+#
+# Spec file for testing deleting/adding/updating tags and macros
+#
+
+# Gbp-Undefined-Tag: foobar
+
+# Test that we accept different cases
+Name: my_name
+Version: 0
+Release: 1
+Summary: my_summary
+License: new license
+Distribution: my_distribution
+Group: my_group
+Packager: my_packager
+Url: my_url
+Vcs: my_vcs
+Nosource: 0
+Nopatch: 0
+BuildRoot: my_buildroot
+Provides: my_provides
+Requires: my_requires
+Conflicts: my_conflicts
+Obsoletes: my_obsoletes
+BuildConflicts: my_buildconflicts
+BuildRequires: my_buildrequires
+AutoReqProv: No
+AutoReq: No
+AutoProv: No
+DistTag: my_disttag
+BugUrl: my_bugurl
+Collections: my_collections
+
+%description
+Package for testing GBP.
+
+%prep
+%setup -n my_prefix
+
+%patch0 my new args
+
+%build
+
+%install
diff --git a/tests/data/rpm/specs/gbp-test-updates.spec b/tests/data/rpm/specs/gbp-test-updates.spec
new file mode 100644
index 00000000..dc8ffbf9
--- /dev/null
+++ b/tests/data/rpm/specs/gbp-test-updates.spec
@@ -0,0 +1,49 @@
+#
+# Spec file for testing deleting/adding/updating tags and macros
+#
+
+# Gbp-Undefined-Tag: foobar
+
+# Test that we accept different cases
+Name: my_name
+Version: 0
+Release: 1
+Summary: my_summary
+License: my_license
+Distribution: my_distribution
+Vendor: my_vendor
+Group: my_group
+Packager: my_packager
+Url: my_url
+Vcs: my_vcs
+Source: my_source
+Patch: my_%patch_fn_base
+Patch0: my_%{patch_fn_base}0
+Nosource: 0
+Nopatch: 0
+BuildRoot: my_buildroot
+Provides: my_provides
+Requires: my_requires
+Conflicts: my_conflicts
+Obsoletes: my_obsoletes
+BuildConflicts: my_buildconflicts
+BuildRequires: my_buildrequires
+AutoReqProv: No
+AutoReq: No
+AutoProv: No
+DistTag: my_disttag
+BugUrl: my_bugurl
+Collections: my_collections
+
+%description
+Package for testing GBP.
+
+%prep
+%setup -n my_prefix
+
+%patch -b my_patch
+%patch -P0 -b my_patch0
+
+%build
+
+%install
diff --git a/tests/data/rpm/specs/gbp-test.spec b/tests/data/rpm/specs/gbp-test.spec
new file mode 120000
index 00000000..30ae2845
--- /dev/null
+++ b/tests/data/rpm/specs/gbp-test.spec
@@ -0,0 +1 @@
+../rpmbuild/SPECS/gbp-test.spec \ No newline at end of file
diff --git a/tests/data/rpm/specs/gbp-test2-reference.spec b/tests/data/rpm/specs/gbp-test2-reference.spec
new file mode 100644
index 00000000..1882131f
--- /dev/null
+++ b/tests/data/rpm/specs/gbp-test2-reference.spec
@@ -0,0 +1,61 @@
+Name: gbp-test2
+Summary: Test package 2 for git-buildpackage
+Epoch: 2
+Version: 3.0
+Release: 0
+Group: Development/Libraries
+License: GPLv2
+Source10: ftp://ftp.host.com/%{name}-%{version}.tar.gz
+Source: foo.txt
+Source20: bar.tar.gz
+# Gbp-Ignore-Patches: -1
+Patch: my.patch
+# Patches auto-generated by git-buildpackage:
+Patch0: new.patch
+Packager: Markus Lehtonen <markus.lehtonen@linux.intel.com>
+
+%description
+Package for testing the RPM functionality of git-buildpackage.
+
+%package empty
+Summary: Empty subpackage
+
+%description empty
+Empty subpackage for the %{name} test package.
+
+
+%prep
+%setup -T -n %{name}-%{version} -c -a 10
+
+%patch
+
+echo "Do things"
+
+# Gbp-Patch-Macros
+# new.patch
+%if 1
+%patch0 -p1
+%endif
+
+%build
+make
+
+
+%install
+rm -rf %{buildroot}
+mkdir -p %{buildroot}/%{_datadir}/%{name}
+cp -R * %{buildroot}/%{_datadir}/%{name}
+install %{SOURCE0} %{buildroot}/%{_datadir}/%{name}
+
+
+%changelog
+* Wed Feb 05 2014 Name <email> 2
+- New entry
+
+%files
+%defattr(-,root,root,-)
+%dir %{_datadir}/%{name}
+%{_datadir}/%{name}
+
+%files empty
+%defattr(-,root,root,-)
diff --git a/tests/data/rpm/specs/gbp-test2-reference2.spec b/tests/data/rpm/specs/gbp-test2-reference2.spec
new file mode 100644
index 00000000..d41f4503
--- /dev/null
+++ b/tests/data/rpm/specs/gbp-test2-reference2.spec
@@ -0,0 +1,68 @@
+Name: gbp-test2
+Summary: Test package 2 for git-buildpackage
+Epoch: 2
+Version: 3.0
+Release: 0
+Group: Development/Libraries
+License: GPLv2
+Source10: ftp://ftp.host.com/%{name}-%{version}.tar.gz
+Source: foo.txt
+Source20: bar.tar.gz
+# Gbp-Ignore-Patches: -1
+Patch: my.patch
+# Patches auto-generated by git-buildpackage:
+Patch0: 1.patch
+Patch1: 2.patch
+Packager: Markus Lehtonen <markus.lehtonen@linux.intel.com>
+VCS: myvcstag
+
+%description
+Package for testing the RPM functionality of git-buildpackage.
+
+%package empty
+Summary: Empty subpackage
+
+%description empty
+Empty subpackage for the %{name} test package.
+
+
+%prep
+%setup -T -n %{name}-%{version} -c -a 10
+
+%patch
+
+echo "Do things"
+
+# Gbp-Patch-Macros
+# 1.patch
+%if true
+%patch0 -p1
+%endif
+# 2.patch
+%ifarch %ix86
+%patch1 -p1
+%endif
+
+%build
+make
+
+
+%install
+rm -rf %{buildroot}
+mkdir -p %{buildroot}/%{_datadir}/%{name}
+cp -R * %{buildroot}/%{_datadir}/%{name}
+install %{SOURCE0} %{buildroot}/%{_datadir}/%{name}
+
+
+%changelog
+* Tue Feb 04 2014 Name <email> 1
+- My change
+
+
+%files
+%defattr(-,root,root,-)
+%dir %{_datadir}/%{name}
+%{_datadir}/%{name}
+
+%files empty
+%defattr(-,root,root,-)
diff --git a/tests/data/rpm/specs/gbp-test2.spec b/tests/data/rpm/specs/gbp-test2.spec
new file mode 120000
index 00000000..af4080cb
--- /dev/null
+++ b/tests/data/rpm/specs/gbp-test2.spec
@@ -0,0 +1 @@
+../rpmbuild/SPECS/gbp-test2.spec \ No newline at end of file
diff --git a/tests/test_GitModifier.py b/tests/test_GitModifier.py
index 1a28c0a8..0a05d4b8 100644
--- a/tests/test_GitModifier.py
+++ b/tests/test_GitModifier.py
@@ -26,7 +26,7 @@ def test_author():
>>> modifier._get_env('foo')
Traceback (most recent call last):
...
- GitModifierError: Neither comitter nor author
+ GitModifierError: Neither committer nor author
>>> modifier['name']
'foo'
>>> modifier['email']
diff --git a/tests/test_GitVfs.py b/tests/test_GitVfs.py
index 7004db1f..8e049545 100644
--- a/tests/test_GitVfs.py
+++ b/tests/test_GitVfs.py
@@ -46,6 +46,7 @@ def test_read():
''
>>> gf.readline()
''
+ >>> gf.close()
>>> gbp.git.vfs.GitVfs(repo, 'HEAD').open('foo.txt').read() == content
True
>>> gf = vfs.open('doesnotexist')