Commit db5c6700 authored by Guido Günther's avatar Guido Günther

Add tag command

by splitting out the code from buildpackage

This is shorter than running

     gbp buildpackage --git-tag-only

Closes: #797086
parent 23b334c5
......@@ -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/
......
......@@ -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
......@@ -15,6 +15,7 @@ MAN1S = \
gbp-pristine-tar \
gbp-pull \
gbp-push \
gbp-tag \
gbp-buildpackage-rpm \
gbp-import-srpm \
gbp-pq-rpm \
......
......@@ -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>">
......
<!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>
<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>
......@@ -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>
......
<!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;
......@@ -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">
......
......@@ -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.")
......
#!/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\:·:
......@@ -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
......
# 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^{}'))
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment