aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuido Günther <agx@sigxcpu.org>2017-04-25 20:22:34 +0200
committerGuido Günther <agx@sigxcpu.org>2017-04-25 22:57:35 +0200
commit1113c9590ca2847f586441e857e3f17698a35020 (patch)
tree4032fb266da48c8a4d2c92c07f43e0c9b5c66ea1
parent000f92479367d6245be3bda9a662758009f87d14 (diff)
clone: Add support for pseudo protocols like vcsgit: and github:
to make cloning simpler Closes: #861206
-rw-r--r--docs/manpages/gbp-clone.sgml13
-rwxr-xr-xgbp/scripts/clone.py70
-rw-r--r--tests/29_test_gbp_clone.py33
-rw-r--r--tests/component/deb/test_clone.py23
4 files changed, 135 insertions, 4 deletions
diff --git a/docs/manpages/gbp-clone.sgml b/docs/manpages/gbp-clone.sgml
index 4eba91c..11a9343 100644
--- a/docs/manpages/gbp-clone.sgml
+++ b/docs/manpages/gbp-clone.sgml
@@ -148,7 +148,8 @@
<term><replaceable>repository</replaceable></term>
<listitem>
<para>
- The (possibly remote) repository to clone from.
+ The (possibly remote) repository to clone from. This is
+ usually a &git; URL but some shortcuts are supported (see below).
</para>
</listitem>
</varlistentry>
@@ -170,6 +171,16 @@
</para>
<screen>
&gbp-clone; --pristine-tar git://honk.sigxcpu.org/git/git-buildpackage.git</screen>
+ <para>
+ Clone from the <emphasis>Git-Vcs</emphasis> URL of a package:
+ </para>
+ <screen>
+ &gbp-clone; vcsgit:libvirt</screen>
+ <para>
+ Clone from a github repository:
+ </para>
+ <screen>
+ &gbp-clone; github:agx/git-buildpackage</screen>
</refsect1>
<refsect1>
&man.gbp.config-files;
diff --git a/gbp/scripts/clone.py b/gbp/scripts/clone.py
index 0afa54c..a06307d 100755
--- a/gbp/scripts/clone.py
+++ b/gbp/scripts/clone.py
@@ -1,6 +1,6 @@
# vim: set fileencoding=utf-8 :
#
-# (C) 2009, 2010, 2015 Guido Guenther <agx@sigxcpu.org>
+# (C) 2009, 2010, 2015, 2017 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
@@ -19,6 +19,7 @@
#
"""Clone a Git repository and set it up for gbp"""
+import re
import sys
import os
from gbp.config import (GbpOptionParser, GbpOptionGroup)
@@ -28,8 +29,73 @@ from gbp.errors import GbpError
from gbp.scripts.common import ExitCodes
from gbp.scripts.common import repo_setup
from gbp.scripts.common.hook import Hook
+from gbp.command_wrappers import Command, CommandExecFailed
+from gbp.deb import DpkgCompareVersions
import gbp.log
+from functools import cmp_to_key
+
+
+def apt_showsrc(pkg):
+ try:
+ aptsrc = Command("apt-cache", ["showsrc", pkg], capture_stdout=True)
+ aptsrc(quiet=True)
+ return aptsrc.stdout
+ except CommandExecFailed:
+ gbp.log.err("Can't find source package for '%s'" % pkg)
+
+
+def vcs_git_url(pkg):
+ repos = {}
+
+ out = apt_showsrc(pkg)
+ vcs_re = re.compile(r'(x-)?vcs-git:\s*(?P<repo>[^ ]+)$', re.I)
+ version_re = re.compile(r'Version:\s*(?P<version>.*)$', re.I)
+ end_re = re.compile(r'\s*$')
+
+ version = repo = None
+ for line in out.split('\n'):
+ m = vcs_re.match(line)
+ if m:
+ repo = m.group('repo')
+ continue
+ m = version_re.match(line)
+ if m:
+ version = m.group('version')
+ continue
+ m = end_re.match(line)
+ if m:
+ if version and repo:
+ repos[version] = repo
+ version = repo = None
+
+ if not repos:
+ raise GbpError("Can't find a source package for '%s'" % pkg)
+
+ s = sorted(repos, key=cmp_to_key(DpkgCompareVersions()))
+ return repos[s[-1]]
+
+
+def repo_to_url(repo):
+ """
+ >>> repo_to_url("https://foo.example.com")
+ 'https://foo.example.com'
+ >>> repo_to_url("github:agx/git-buildpackage")
+ 'https://github.com/agx/git-buildpackage.git'
+ """
+ parts = repo.split(":", 1)
+ if len(parts) != 2:
+ return repo
+ else:
+ proto, path = parts
+
+ if proto == 'github':
+ return 'https://github.com/%s.git' % path
+ elif proto in ['vcsgit', 'vcs-git']:
+ return vcs_git_url(path)
+ else:
+ return repo
+
def build_parser(name):
try:
@@ -91,7 +157,7 @@ def main(argv):
gbp.log.err("Need a repository to clone.")
return 1
else:
- source = args[1]
+ source = repo_to_url(args[1])
clone_to, auto_name = (os.path.curdir, True) if len(args) < 3 else (args[2], False)
try:
diff --git a/tests/29_test_gbp_clone.py b/tests/29_test_gbp_clone.py
new file mode 100644
index 0000000..17e958e
--- /dev/null
+++ b/tests/29_test_gbp_clone.py
@@ -0,0 +1,33 @@
+# vim: set fileencoding=utf-8 :
+from gbp.scripts.clone import vcs_git_url
+
+import os
+import unittest
+from mock import patch
+
+
+class TestGbpClone(unittest.TestCase):
+ show_src = """
+Version: 0.6.22
+Standards-Version: 3.9.4
+Vcs-Git: git://honk.sigxcpu.org/git/git-buildpackage.git
+
+Version: 0.8.14
+Standards-Version: 3.9.8
+Vcs-Git: https://git.sigxcpu.org/cgit/git-buildpackage/ -b foo
+
+Version: 0.8.12.2
+Standards-Version: 3.9.8
+Vcs-Git: https://git.sigxcpu.org/cgit/git-buildpackage/
+
+Version: 0.6.0~git20120601
+Standards-Version: 3.9.3
+Vcs-Git: git://honk.sigxcpu.org/git/git-buildpackage.git
+
+"""
+
+ @unittest.skipIf(not os.path.exists('/usr/bin/dpkg'), 'Dpkg not found')
+ @patch('gbp.scripts.clone.apt_showsrc', return_value=show_src)
+ def test_vcs_git_url(self, patch):
+ self.assertEqual(vcs_git_url('git-buildpackage'),
+ 'https://git.sigxcpu.org/cgit/git-buildpackage/')
diff --git a/tests/component/deb/test_clone.py b/tests/component/deb/test_clone.py
index d1b70f5..8bc05bf 100644
--- a/tests/component/deb/test_clone.py
+++ b/tests/component/deb/test_clone.py
@@ -19,7 +19,8 @@
import os
from tests.component import (ComponentTestBase,
- ComponentTestGitRepository)
+ ComponentTestGitRepository,
+ skipUnless)
from tests.component.deb.fixtures import RepoFixtures
from nose.tools import ok_
@@ -68,3 +69,23 @@ class TestClone(ComponentTestBase):
got = repo.get_config("user.name")
want = os.environ['DEBFULLNAME']
ok_(got == want, "unexpected git config user.name: got %s, want %s" % (got, want))
+
+ @skipUnless(os.getenv("GBP_NETWORK_TESTS"), "network tests disabled")
+ def test_clone_vcsgit(self):
+ """Test that cloning from vcs-git urls works"""
+ dest = os.path.join(self._tmpdir,
+ 'cloned_repo')
+ ret = clone(['arg0', "vcsgit:libvirt-glib", dest])
+ self.assertEquals(ret, 0)
+ cloned = ComponentTestGitRepository(dest)
+ self._check_repo_state(cloned, 'debian/sid', ['debian/sid', 'upstream/latest'])
+
+ @skipUnless(os.getenv("GBP_NETWORK_TESTS"), "network tests disabled")
+ def test_clone_github(self):
+ """Test that cloning from github urls works"""
+ dest = os.path.join(self._tmpdir,
+ 'cloned_repo')
+ ret = clone(['arg0', "github:agx/git-buildpackage", dest])
+ self.assertEquals(ret, 0)
+ cloned = ComponentTestGitRepository(dest)
+ self._check_repo_state(cloned, 'master', ['master'])