aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGuido Günther <agx@sigxcpu.org>2017-09-14 14:35:39 +0200
committerGuido Günther <agx@sigxcpu.org>2017-09-14 18:32:12 +0200
commitdb5c6700943706aa5f68e67769144b3a1efca8c5 (patch)
tree0bd3e8003718bcf192e09e1dd4d13b184f0f7aaa
parent23b334c511e80a7f9dc30e1b54993a62966fe138 (diff)
Add tag command
by splitting out the code from buildpackage This is shorter than running gbp buildpackage --git-tag-only Closes: #797086
-rw-r--r--debian/git-buildpackage.install1
-rw-r--r--debian/git-buildpackage.manpages1
-rw-r--r--docs/Makefile1
-rw-r--r--docs/common.ent1
-rw-r--r--docs/man.gbp-tag.sgml11
-rw-r--r--docs/manpages/gbp-tag.sgml197
-rw-r--r--docs/manpages/gbp.sgml9
-rw-r--r--docs/manpages/manpages.ent28
-rw-r--r--docs/manual.sgml15
-rwxr-xr-xgbp/scripts/buildpackage.py42
-rwxr-xr-xgbp/scripts/tag.py161
-rw-r--r--packaging/git-buildpackage.spec2
-rw-r--r--tests/component/deb/test_tag.py77
13 files changed, 483 insertions, 63 deletions
diff --git a/debian/git-buildpackage.install b/debian/git-buildpackage.install
index 0989806c..4ed4cc74 100644
--- a/debian/git-buildpackage.install
+++ b/debian/git-buildpackage.install
@@ -30,6 +30,7 @@ usr/lib/python3.?/dist-packages/gbp/scripts/pristine_tar.py usr/lib/python3/dist
usr/lib/python3.?/dist-packages/gbp/scripts/pull.py usr/lib/python3/dist-packages/gbp/scripts/
usr/lib/python3.?/dist-packages/gbp/scripts/push.py usr/lib/python3/dist-packages/gbp/scripts/
usr/lib/python3.?/dist-packages/gbp/scripts/supercommand.py usr/lib/python3/dist-packages/gbp/scripts/
+usr/lib/python3.?/dist-packages/gbp/scripts/tag.py usr/lib/python3/dist-packages/gbp/scripts/
usr/lib/python3.?/dist-packages/gbp/tmpfile.py usr/lib/python3/dist-packages/gbp/
usr/lib/python3.?/dist-packages/gbp/tristate.py usr/lib/python3/dist-packages/gbp/
usr/lib/python3.?/dist-packages/gbp/version.py usr/lib/python3/dist-packages/gbp/
diff --git a/debian/git-buildpackage.manpages b/debian/git-buildpackage.manpages
index 73ea6b1f..60f37624 100644
--- a/debian/git-buildpackage.manpages
+++ b/debian/git-buildpackage.manpages
@@ -13,4 +13,5 @@ docs/gbp-pq.1
docs/gbp-pristine-tar.1
docs/gbp-pull.1
docs/gbp-push.1
+docs/gbp-tag.1
docs/git-pbuilder.1
diff --git a/docs/Makefile b/docs/Makefile
index 6ad326a3..4fdbecee 100644
--- a/docs/Makefile
+++ b/docs/Makefile
@@ -15,6 +15,7 @@ MAN1S = \
gbp-pristine-tar \
gbp-pull \
gbp-push \
+ gbp-tag \
gbp-buildpackage-rpm \
gbp-import-srpm \
gbp-pq-rpm \
diff --git a/docs/common.ent b/docs/common.ent
index fd9f68cb..2e3d09b6 100644
--- a/docs/common.ent
+++ b/docs/common.ent
@@ -35,6 +35,7 @@
<!ENTITY gbp-pull "<command>gbp&nbsp;pull</command>">
<!ENTITY gbp-push "<command>gbp&nbsp;push</command>">
<!ENTITY gbp-rpm-ch "<command>gbp rpm-ch</command>">
+ <!ENTITY gbp-tag "<command>gbp tag</command>">
<!ENTITY gbp.conf "<filename>gbp.conf</filename>">
<!ENTITY git-pbuilder "<command>git-pbuilder</command>">
<!ENTITY git-qemubuilder "<command>git-pbuilder</command>">
diff --git a/docs/man.gbp-tag.sgml b/docs/man.gbp-tag.sgml
new file mode 100644
index 00000000..e4c8dafd
--- /dev/null
+++ b/docs/man.gbp-tag.sgml
@@ -0,0 +1,11 @@
+<!DOCTYPE reference PUBLIC "-//OASIS//DTD DocBook V4.1//EN" [
+ <!ENTITY % COMMON SYSTEM "common.ent">
+ %COMMON;
+ <!ENTITY % MANPAGES SYSTEM "manpages/manpages.ent">
+ %MANPAGES;
+]>
+
+<reference>
+<title>git-buildpackage Manual</title>
+&man.gbp.tag;
+</reference>
diff --git a/docs/manpages/gbp-tag.sgml b/docs/manpages/gbp-tag.sgml
new file mode 100644
index 00000000..48504e2a
--- /dev/null
+++ b/docs/manpages/gbp-tag.sgml
@@ -0,0 +1,197 @@
+<refentry id="man.gbp.tag">
+ <refentryinfo>
+ <address>
+ &dhemail;
+ </address>
+ <author>
+ &dhfirstname;
+ &dhsurname;
+ </author>
+ </refentryinfo>
+ <refmeta><refentrytitle>gbp-tag</refentrytitle>
+ &dhsection;
+ </refmeta>
+ <refnamediv>
+ <refname>gbp-tag</refname>
+ <refpurpose>Tag a &debian; packages in a &git; repository</refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ &gbp-tag;
+
+ &man.common.options.synopsis;
+ <arg><option>--ignore-branch</option></arg>
+ <arg><option>--[no-]ignore-new</option></arg>
+ <arg><option>--[no-]sign-tags</option></arg>
+ <arg><option>--keyid=</option><replaceable>GPG-KEYID</replaceable></arg>
+ <arg><option>--debian-branch=</option><replaceable>BRANCH_NAME</replaceable></arg>
+ <arg><option>--debian-tag=</option><replaceable>tag-format</replaceable></arg>
+ <arg><option>--debian-tag-msg=</option><replaceable>tag-msg-format</replaceable></arg>
+ <arg><option>--posttag=</option><replaceable>COMMAND</replaceable></arg>
+ <arg><option>--retag</option></arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+ <refsect1>
+ <title>DESCRIPTION</title>
+ <para>
+ &gbp-tag; tags the current head commit appropriately. It will in order:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ Verify that it is being executed from the Debian branch.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Verify that the repository doesn't contain any uncommitted source
+ changes.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Create a git tag using the information from <filename>debian/changelog</filename>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ (Optionally) call a post tag hook.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </refsect1>
+ <refsect1>
+ <title>OPTIONS</title>
+ <variablelist>
+ &man.common.options.description;
+ <varlistentry>
+ <term><option>--posttag=</option><replaceable>COMMAND</replaceable>
+ </term>
+ <listitem>
+ <para>
+ Execute <replaceable>COMMAND</replaceable> after creating the tag.
+ </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>--[no-]sign-tags</option>
+ </term>
+ <listitem>
+ <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>
+ </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>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--debian-tag-msg=</option><replaceable>tag-msg-format</replaceable>
+ </term>
+ <listitem>
+ <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>--retag</option>
+ </term>
+ <listitem>
+ <para>
+ Don't fail tag operations if a tag with the same version
+ already exists. This is a command line only option that
+ cannot be specified via &gbp.conf;.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--debian-branch</option>=<replaceable>BRANCH_NAME</replaceable>
+ </term>
+ <listitem>
+ <para>
+ If you're not on this branch when invoking &gbp-tag; it will
+ fail. Default is <replaceable>master</replaceable>. This is done to
+ make sure you don't accidentally tag on the wrong branch. Not
+ being on this branch will be ignored when using
+ <option>--ignore-branch</option>.
+ </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>--[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>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect1>
+ <refsect1>
+ <title>EXAMPLES</title>
+ <para>
+ Create a tag with the current defaults
+ </para>
+ <screen>
+ &gbp-tag;
+ </screen>
+ <para>
+ Create using a more upstreamish tag format:
+ </para>
+ <screen>
+ &gbp-tag; --debian-tag='v%(version)s'
+ </screen>
+ </refsect1>
+ <refsect1>
+ &man.gbp.config-files;
+ </refsect1>
+ <refsect1>
+ <title>SEE ALSO</title>
+ <para>
+ <xref linkend="man.gbp.buildpackage"/,
+ <xref linkend="man.gbp.push"/,
+ <xref linkend="man.gbp.conf"/,
+ </para>
+ </refsect1>
+ <refsect1>
+ <title>AUTHOR</title>
+ <para>
+ &dhusername; &dhemail;
+ </para>
+ </refsect1>
+</refentry>
diff --git a/docs/manpages/gbp.sgml b/docs/manpages/gbp.sgml
index eff89f25..1a3c8e93 100644
--- a/docs/manpages/gbp.sgml
+++ b/docs/manpages/gbp.sgml
@@ -155,17 +155,18 @@
<title>SEE ALSO</title>
<para>
<xref linkend="man.gbp.buildpackage"/,
+ <xref linkend="man.gbp.clone"/,
+ <xref linkend="man.gbp.create.remote.repo"/,
+ <xref linkend="man.gbp.dch"/,
+ <xref linkend="man.gbp.export.orig"/,
<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.pristine.tar"/,
- <xref linkend="man.gbp.export.orig"/,
- <xref linkend="man.gbp.create.remote.repo"/,
<xref linkend="man.gbp.pull"/,
<xref linkend="man.gbp.push"/,
- <xref linkend="man.gbp.clone"/,
+ <xref linkend="man.gbp.tag"/,
<citerefentry>
<refentrytitle>git-pbuilder</refentrytitle>
<manvolnum>1</manvolnum>
diff --git a/docs/manpages/manpages.ent b/docs/manpages/manpages.ent
index 9415946a..29289684 100644
--- a/docs/manpages/manpages.ent
+++ b/docs/manpages/manpages.ent
@@ -1,23 +1,25 @@
-<!ENTITY man.gbp.importorig SYSTEM "gbp-import-orig.sgml">
-<!ENTITY man.gbp.importdsc SYSTEM "gbp-import-dsc.sgml">
-<!ENTITY man.gbp.importdscs SYSTEM "gbp-import-dscs.sgml">
+<!ENTITY man.gbp SYSTEM "gbp.sgml">
<!ENTITY man.gbp.buildpackage SYSTEM "gbp-buildpackage.sgml">
+<!ENTITY man.gbp.buildpackage.rpm SYSTEM "gbp-buildpackage-rpm.sgml">
+<!ENTITY man.gbp.clone SYSTEM "gbp-clone.sgml">
+<!ENTITY man.gbp.conf SYSTEM "gbp.conf.sgml">
<!ENTITY man.gbp.config SYSTEM "gbp-config.sgml">
+<!ENTITY man.gbp.config-files SYSTEM "man.conffiles.sgml">
+<!ENTITY man.gbp.create.remote.repo SYSTEM "gbp-create-remote-repo.sgml">
<!ENTITY man.gbp.dch SYSTEM "gbp-dch.sgml">
<!ENTITY man.gbp.exportorig SYSTEM "gbp-export-orig.sgml">
-<!ENTITY man.gbp SYSTEM "gbp.sgml">
+<!ENTITY man.gbp.import.srpm SYSTEM "gbp-import-srpm.sgml">
+<!ENTITY man.gbp.importdsc SYSTEM "gbp-import-dsc.sgml">
+<!ENTITY man.gbp.importdscs SYSTEM "gbp-import-dscs.sgml">
+<!ENTITY man.gbp.importorig SYSTEM "gbp-import-orig.sgml">
+<!ENTITY man.gbp.pq SYSTEM "gbp-pq.sgml">
+<!ENTITY man.gbp.pq.rpm SYSTEM "gbp-pq-rpm.sgml">
<!ENTITY man.gbp.pristine.tar SYSTEM "gbp-pristine-tar.sgml">
<!ENTITY man.gbp.pull SYSTEM "gbp-pull.sgml">
<!ENTITY man.gbp.push SYSTEM "gbp-push.sgml">
-<!ENTITY man.gbp.clone SYSTEM "gbp-clone.sgml">
-<!ENTITY man.gbp.pq SYSTEM "gbp-pq.sgml">
-<!ENTITY man.gbp.create.remote.repo SYSTEM "gbp-create-remote-repo.sgml">
-<!ENTITY man.gbp.conf SYSTEM "gbp.conf.sgml">
-<!ENTITY man.gbp.config-files SYSTEM "man.conffiles.sgml">
-<!ENTITY man.seealso.common SYSTEM "man.seealso.sgml">
-<!ENTITY man.gbp.buildpackage.rpm SYSTEM "gbp-buildpackage-rpm.sgml">
-<!ENTITY man.gbp.import.srpm SYSTEM "gbp-import-srpm.sgml">
-<!ENTITY man.gbp.pq.rpm SYSTEM "gbp-pq-rpm.sgml">
<!ENTITY man.gbp.rpm.ch SYSTEM "gbp-rpm-ch.sgml">
+<!ENTITY man.gbp.tag SYSTEM "gbp-tag.sgml">
+<!ENTITY man.seealso.common SYSTEM "man.seealso.sgml">
+
<!ENTITY % COMMON.OPTIONS SYSTEM "man.common-options.ent">
%COMMON.OPTIONS;
diff --git a/docs/manual.sgml b/docs/manual.sgml
index 35809ada..234e55dc 100644
--- a/docs/manual.sgml
+++ b/docs/manual.sgml
@@ -30,18 +30,19 @@
<title>Command Reference</title>
&man.gbp;
&man.gbp.buildpackage;
+ &man.gbp.clone;
+ &man.gbp.config;
+ &man.gbp.create.remote.repo;
+ &man.gbp.dch;
+ &man.gbp.exportorig;
&man.gbp.importdsc;
&man.gbp.importdscs;
&man.gbp.importorig;
- &man.gbp.dch;
- &man.gbp.clone;
- &man.gbp.config;
+ &man.gbp.pq;
+ &man.gbp.pristine.tar;
&man.gbp.pull;
&man.gbp.push;
- &man.gbp.pristine.tar;
- &man.gbp.exportorig;
- &man.gbp.pq;
- &man.gbp.create.remote.repo;
+ &man.gbp.tag;
&man.gbp.conf;
</appendix>
<appendix id="gbp.copyleft">
diff --git a/gbp/scripts/buildpackage.py b/gbp/scripts/buildpackage.py
index 356fcccf..7ffb5e95 100755
--- a/gbp/scripts/buildpackage.py
+++ b/gbp/scripts/buildpackage.py
@@ -31,11 +31,9 @@ from gbp.config import (GbpOptionParserDebian, GbpOptionGroup)
from gbp.deb.git import (GitRepositoryError, DebianGitRepository)
from gbp.deb.source import DebianSource, DebianSourceError, FileVfs
from gbp.deb.format import DebianSourceFormat
-from gbp.format import format_str
from gbp.git.vfs import GitVfs
from gbp.deb.upstreamsource import DebianUpstreamSource
from gbp.errors import GbpError
-from gbp.scripts.common.pq import is_pq_branch, pq_branch_base
import gbp.log
import gbp.notifications
from gbp.scripts.common.buildpackage import (index_name, wc_name,
@@ -45,6 +43,7 @@ from gbp.scripts.common import ExitCodes
from gbp.scripts.common.hook import Hook
from gbp.scripts.export_orig import prepare_upstream_tarballs
+from gbp.scripts.tag import perform_tagging
def pristine_tar_commit(repo, source, options, output_dir, orig_file, upstream_tree):
@@ -196,27 +195,6 @@ def check_tag(options, repo, source):
raise GbpError("Tag '%s' already exists" % tag)
-def create_debian_tag(repo, source, commit, options):
- """
- Create the debian tag
-
- returns: the created tag
- """
- tag = repo.version_to_tag(options.debian_tag, source.version)
- gbp.log.info("Tagging %s as %s" % (source.version, tag))
- if options.retag and repo.has_tag(tag):
- repo.delete_tag(tag)
- tag_msg = format_str(options.debian_tag_msg,
- dict(pkg=source.sourcepkg,
- version=source.version))
- repo.create_tag(name=tag,
- msg=tag_msg,
- sign=options.sign_tags,
- commit=commit,
- keyid=options.keyid)
- return tag
-
-
def get_pbuilder_dist(options, repo, native=False):
"""
Determin the dist to build for with pbuilder/cowbuilder
@@ -487,7 +465,6 @@ def main(argv):
retval = 0
prefix = "git-"
source = None
- branch = None
hook_env = {}
options, gbp_args, dpkg_args = parse_args(argv, prefix)
@@ -503,8 +480,7 @@ def main(argv):
try:
clean_working_tree(options, repo)
- branch = check_branch(repo, options)
- head = repo.head
+ check_branch(repo, options)
tree = maybe_write_tree(repo, options)
source = source_vfs(repo, options, tree)
@@ -575,20 +551,8 @@ def main(argv):
'GBP_BUILD_DIR': build_dir})
)()
if options.tag or options.tag_only:
- if branch and is_pq_branch(branch):
- commit = repo.get_merge_base(branch, pq_branch_base(branch))
- else:
- commit = head
+ perform_tagging(repo, source, options, hook_env)
- tag = create_debian_tag(repo, source, commit, options)
- if options.posttag:
- sha = repo.rev_parse("%s^{}" % tag)
- Hook('Posttag', options.posttag,
- extra_env=Hook.md(hook_env,
- {'GBP_TAG': tag,
- 'GBP_BRANCH': branch or '(no branch)',
- 'GBP_SHA1': sha})
- )()
except KeyboardInterrupt:
retval = 1
gbp.log.err("Interrupted. Aborting.")
diff --git a/gbp/scripts/tag.py b/gbp/scripts/tag.py
new file mode 100755
index 00000000..7cc93dab
--- /dev/null
+++ b/gbp/scripts/tag.py
@@ -0,0 +1,161 @@
+#!/usr/bin/python3
+# vim: set fileencoding=utf-8 :
+#
+# (C) 2017 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
+# (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, please see
+# <http://www.gnu.org/licenses/>
+"""Create a Debian tag"""
+
+import os
+import sys
+
+import gbp.log
+from gbp.format import format_str
+from gbp.config import GbpOptionParserDebian
+from gbp.deb.git import DebianGitRepository, GitRepositoryError
+from gbp.deb.source import DebianSourceError
+from gbp.deb.source import DebianSource
+from gbp.errors import GbpError
+
+from gbp.scripts.common import ExitCodes
+from gbp.scripts.common.hook import Hook
+
+from gbp.scripts.common.pq import is_pq_branch, pq_branch_base
+
+
+def create_debian_tag(repo, source, commit, options):
+ """
+ Create the debian tag
+
+ returns: the created tag
+ """
+ tag = repo.version_to_tag(options.debian_tag, source.version)
+ gbp.log.info("Tagging %s as %s" % (source.version, tag))
+ if options.retag and repo.has_tag(tag):
+ repo.delete_tag(tag)
+ tag_msg = format_str(options.debian_tag_msg,
+ dict(pkg=source.sourcepkg,
+ version=source.version))
+ repo.create_tag(name=tag,
+ msg=tag_msg,
+ sign=options.sign_tags,
+ commit=commit,
+ keyid=options.keyid)
+ return tag
+
+
+def perform_tagging(repo, source, options, hook_env=None):
+ """
+ Perform the tagging
+
+ Select brach to tag, create tag and run hooks
+ """
+ branch = repo.branch
+ if branch and is_pq_branch(branch):
+ commit = repo.get_merge_base(branch, pq_branch_base(branch))
+ else:
+ commit = repo.head
+
+ tag = create_debian_tag(repo, source, commit, options)
+ if options.posttag:
+ sha = repo.rev_parse("%s^{}" % tag)
+ Hook('Posttag', options.posttag,
+ extra_env=Hook.md(hook_env or {},
+ {'GBP_TAG': tag,
+ 'GBP_BRANCH': branch or '(no branch)',
+ 'GBP_SHA1': sha})
+ )()
+
+
+def build_parser(name):
+ try:
+ parser = GbpOptionParserDebian(command=os.path.basename(name),
+ usage='%prog [options]')
+ except GbpError as err:
+ gbp.log.err(err)
+ return None
+
+ parser.add_option("--retag", action="store_true", dest="retag", default=False,
+ help="don't fail if the tag already exists")
+ parser.add_config_file_option(option_name="debian-branch",
+ dest="debian_branch")
+ parser.add_config_file_option(option_name="debian-tag",
+ dest="debian_tag")
+ parser.add_config_file_option(option_name="debian-tag-msg", dest="debian_tag_msg")
+ parser.add_boolean_config_file_option(option_name="sign-tags", dest="sign_tags")
+ parser.add_config_file_option(option_name="keyid", dest="keyid")
+ parser.add_config_file_option(option_name="posttag", dest="posttag",
+ help="hook run after a successful tag operation, "
+ "default is '%(posttag)s'")
+ parser.add_boolean_config_file_option(option_name="ignore-branch", dest="ignore_branch")
+ parser.add_boolean_config_file_option(option_name="ignore-new", dest="ignore_new")
+ 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_option("--verbose", action="store_true", dest="verbose",
+ default=False, help="verbose command execution")
+ return parser
+
+
+def parse_args(argv):
+ parser = build_parser(argv[0])
+ if not parser:
+ return None, None
+ return parser.parse_args(argv)
+
+
+def main(argv):
+ retval = 1
+
+ (options, args) = parse_args(argv)
+ if not options:
+ return ExitCodes.parse_error
+
+ gbp.log.setup(options.color, options.verbose, options.color_scheme)
+ try:
+ repo = DebianGitRepository(os.path.curdir, toplevel=False)
+ except GitRepositoryError:
+ gbp.log.err("%s is not inside a git repository" % (os.path.abspath('.')))
+ return 1
+
+ try:
+ source = DebianSource(repo.path)
+ if not (options.ignore_branch or options.ignore_new):
+ if repo.branch != options.debian_branch:
+ gbp.log.err("You are not on branch '%s' but on '%s'"
+ % (options.debian_branch,
+ repo.branch or 'no branch'))
+ raise GbpError("Use --ignore-branch to ignore or "
+ "--debian-branch to set the branch name.")
+
+ if not options.ignore_new:
+ (ret, out) = repo.is_clean()
+ if not ret:
+ gbp.log.err("You have uncommitted changes in your source tree:")
+ gbp.log.err(out)
+ raise GbpError("Use --ignore-new to ignore.")
+
+ perform_tagging(repo, source, options)
+ retval = 0
+ except (GbpError, GitRepositoryError, DebianSourceError) as err:
+ if str(err):
+ gbp.log.err(err)
+
+ return retval
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv))
+
+# vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·:
diff --git a/packaging/git-buildpackage.spec b/packaging/git-buildpackage.spec
index 045688c5..f9f36824 100644
--- a/packaging/git-buildpackage.spec
+++ b/packaging/git-buildpackage.spec
@@ -227,6 +227,7 @@ done
%{python_sitelib}/gbp/scripts/pull.py*
%{python_sitelib}/gbp/scripts/push.py*
%{python_sitelib}/gbp/scripts/supercommand.py*
+%{python_sitelib}/gbp/scripts/tag.py*
%{python_sitelib}/gbp/scripts/common/*.py*
%{python_sitelib}/gbp/git/*.py*
%{python_sitelib}/gbp/pkg/*.py*
@@ -238,6 +239,7 @@ done
%{_mandir}/man1/gbp-pristine-tar.1*
%{_mandir}/man1/gbp-pull.1*
%{_mandir}/man1/gbp-push.1*
+%{_mandir}/man1/gbp-tag.1*
%{_mandir}/man5/*.5*
%endif
diff --git a/tests/component/deb/test_tag.py b/tests/component/deb/test_tag.py
new file mode 100644
index 00000000..f56dabb3
--- /dev/null
+++ b/tests/component/deb/test_tag.py
@@ -0,0 +1,77 @@
+# vim: set fileencoding=utf-8 :
+#
+# (C) 2015-2017 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
+# (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, please see
+# <http://www.gnu.org/licenses/>
+
+import os
+
+from tests.component import ComponentTestBase
+from tests.component.deb import DEB_TEST_DATA_DIR
+from tests.component.deb.fixtures import RepoFixtures
+
+from nose.tools import ok_, eq_
+
+from gbp.scripts.tag import main as tag
+from gbp.scripts.pq import main as pq
+
+
+class TestTag(ComponentTestBase):
+ """Test tagging a debian package"""
+
+ @staticmethod
+ def _dsc_name(pkg, version, dir):
+ return os.path.join(DEB_TEST_DATA_DIR,
+ dir,
+ '%s_%s.dsc' % (pkg, version))
+
+ @RepoFixtures.native()
+ def test_tag(self, repo):
+ """Test that tagging a native debian package works"""
+ repo.delete_tag('debian/0.4.14') # make sure we can tag again
+ eq_(repo.has_tag('debian/0.4.14'), False)
+ ret = tag(['arg0',
+ '--posttag=printenv > posttag.out'])
+ ok_(ret == 0, "Tagging the package failed")
+ eq_(os.path.exists('posttag.out'), True)
+ self.check_hook_vars('posttag', [("GBP_TAG", "debian/0.4.14"),
+ ("GBP_BRANCH", "master"),
+ "GBP_SHA1"])
+ eq_(repo.head, repo.rev_parse('debian/0.4.14^{}'))
+
+ @RepoFixtures.quilt30()
+ def test_tag_pq_branch(self, repo):
+ ret = pq(['argv0', 'import'])
+ eq_(repo.rev_parse('master'), repo.rev_parse('debian/2.8-1^{}'))
+ eq_(ret, 0)
+ eq_(repo.branch, 'patch-queue/master')
+ self.add_file(repo, 'foo.txt')
+ ret = tag(['argv0', '--retag', '--ignore-branch'])
+ eq_(ret, 0)
+ eq_(repo.branch, 'patch-queue/master')
+ eq_(repo.rev_parse('patch-queue/master^{}^'), repo.rev_parse('debian/2.8-1^{}'))
+
+ @RepoFixtures.quilt30()
+ def test_tag_detached_head(self, repo):
+ """
+ Test that tagging works with an detached head (#863167)
+ """
+ eq_(repo.rev_parse('master^{}'), repo.rev_parse('debian/2.8-1^{}'))
+ self.add_file(repo, 'debian/foo.txt')
+ repo.checkout("HEAD~")
+ ret = tag(['argv0', '--retag', '--ignore-branch'])
+ eq_(ret, 0)
+ repo.checkout("master")
+ eq_(repo.rev_parse('master~^{}'), repo.rev_parse('debian/2.8-1^{}'))