diff options
author | Guido Günther <agx@sigxcpu.org> | 2017-04-25 20:22:34 +0200 |
---|---|---|
committer | Guido Günther <agx@sigxcpu.org> | 2017-04-25 22:57:35 +0200 |
commit | 1113c9590ca2847f586441e857e3f17698a35020 (patch) | |
tree | 4032fb266da48c8a4d2c92c07f43e0c9b5c66ea1 | |
parent | 000f92479367d6245be3bda9a662758009f87d14 (diff) |
clone: Add support for pseudo protocols like vcsgit: and github:
to make cloning simpler
Closes: #861206
-rw-r--r-- | docs/manpages/gbp-clone.sgml | 13 | ||||
-rwxr-xr-x | gbp/scripts/clone.py | 70 | ||||
-rw-r--r-- | tests/29_test_gbp_clone.py | 33 | ||||
-rw-r--r-- | tests/component/deb/test_clone.py | 23 |
4 files changed, 135 insertions, 4 deletions
diff --git a/docs/manpages/gbp-clone.sgml b/docs/manpages/gbp-clone.sgml index 4eba91cc..11a93434 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 0afa54c4..a06307d5 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 00000000..17e958e1 --- /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 d1b70f51..8bc05bfb 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']) |