Package: git-buildpackage Version: 0.9.30 Followup-For: Bug #1010751 Hello. A new version is attached, with several unrelated new suggestions. All tests pass.
>From da00146823882a5cf80494f173389ca2559f63ed Mon Sep 17 00:00:00 2001 From: Nicolas Boulenguez <nico...@debian.org> Date: Sat, 30 Nov 2024 14:35:39 +0100 Subject: [PATCH 1/6] Clean unwanted artifacts currently in git-buildpackage.dsc
--- debian/clean | 2 ++ 1 file changed, 2 insertions(+) diff --git a/debian/clean b/debian/clean index bf1eec6f..0b760706 100644 --- a/debian/clean +++ b/debian/clean @@ -1,3 +1,5 @@ build/ gbp.egg-info/ gbp/version.py +coverage.xml +.mypy_cache/ -- 2.39.5
>From 488a1c55ff0b724b7707989b78c491a0cd6f1389 Mon Sep 17 00:00:00 2001 From: Nicolas Boulenguez <nico...@debian.org> Date: Sat, 30 Nov 2024 13:29:13 +0100 Subject: [PATCH 2/6] clone: replace the retval variable with readable ExitCodes --- gbp/scripts/clone.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/gbp/scripts/clone.py b/gbp/scripts/clone.py index 7e02f0e2..835887f0 100755 --- a/gbp/scripts/clone.py +++ b/gbp/scripts/clone.py @@ -178,7 +178,6 @@ def parse_args(argv): def main(argv): - retval = 0 (options, args) = parse_args(argv) if not options: @@ -186,18 +185,18 @@ def main(argv): if len(args) < 2: gbp.log.err("Need a repository to clone.") - return 1 + return ExitCodes.failed else: remote_repo = args[1] source = repo_to_url(remote_repo) if options.aliases else remote_repo if not source: - return 1 + return ExitCodes.failed clone_to, auto_name = (os.path.curdir, True) if len(args) < 3 else (args[2], False) try: GitRepository(clone_to) gbp.log.err("Can't run inside a git repository.") - return 1 + return ExitCodes.failed except GitRepositoryError: pass @@ -248,17 +247,17 @@ def main(argv): )() except KeyboardInterrupt: - retval = 1 gbp.log.err("Interrupted. Aborting.") + return ExitCodes.failed except GitRepositoryError as err: gbp.log.err("Git command failed: %s" % err) - retval = 1 + return ExitCodes.failed except GbpError as err: if str(err): gbp.log.err(err) - retval = 1 + return ExitCodes.failed - return retval + return ExitCodes.ok if __name__ == '__main__': -- 2.39.5
>From 925dd049845b686b1b6e5ec0a17cd379998f8070 Mon Sep 17 00:00:00 2001 From: Nicolas Boulenguez <nico...@debian.org> Date: Sat, 30 Nov 2024 16:47:21 +0100 Subject: [PATCH 3/6] clone: raise MissingVCSGitField instead of returning None several times --- gbp/scripts/clone.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/gbp/scripts/clone.py b/gbp/scripts/clone.py index 835887f0..ffedf5c1 100755 --- a/gbp/scripts/clone.py +++ b/gbp/scripts/clone.py @@ -46,6 +46,10 @@ def apt_showsrc(pkg): return '' +class MissingVCSGitField(Exception): + """When the VCS-Git field is requested but missing.""" + + def vcs_git_url(pkg): repos = {} @@ -72,7 +76,7 @@ def vcs_git_url(pkg): if not repos: gbp.log.err("Can't find any vcs-git URL for '%s'" % pkg) - return None + raise MissingVCSGitField() s = sorted(repos, key=cmp_to_key(DpkgCompareVersions())) return repos[s[-1]] @@ -188,9 +192,14 @@ def main(argv): return ExitCodes.failed else: remote_repo = args[1] - source = repo_to_url(remote_repo) if options.aliases else remote_repo - if not source: + + if options.aliases: + try: + source = repo_to_url(remote_repo) + except MissingVCSGitField: return ExitCodes.failed + else: + source = remote_repo clone_to, auto_name = (os.path.curdir, True) if len(args) < 3 else (args[2], False) try: -- 2.39.5
>From 3475c2f3ffa3ccaf3277df56f38639ffd573b3ff Mon Sep 17 00:00:00 2001 From: Nicolas Boulenguez <nico...@debian.org> Date: Sat, 30 Nov 2024 13:38:26 +0100 Subject: [PATCH 4/6] clone: extend tests and improve consistency Test all repo_to_url cases, vcs_git_url is an implementation detail. Remove the confusing case with '-b foo' from the version selection test. --- tests/29_test_gbp_clone.py | 51 ++++++++++++++++++++++++++++---------- 1 file changed, 38 insertions(+), 13 deletions(-) diff --git a/tests/29_test_gbp_clone.py b/tests/29_test_gbp_clone.py index 96bd905e..3c5e2bbb 100644 --- a/tests/29_test_gbp_clone.py +++ b/tests/29_test_gbp_clone.py @@ -1,5 +1,5 @@ # vim: set fileencoding=utf-8 : -from gbp.scripts.clone import vcs_git_url +from gbp.scripts.clone import repo_to_url import unittest from unittest.mock import patch @@ -8,15 +8,42 @@ from . testutils import skip_without_cmd class TestGbpClone(unittest.TestCase): - show_src = """ + + def test_repo_to_url(self): + arg = "https://foo.example.com" + exp = arg + self.assertEqual(repo_to_url(arg), exp) + + def test_repo_to_url_salsa(self): + arg = "salsa:agx/git-buildpackage" + exp = 'https://salsa.debian.org/agx/git-buildpackage.git' + self.assertEqual(repo_to_url(arg), exp) + + def test_repo_to_url_github(self): + arg = "github:agx/git-buildpackage" + exp = "https://github.com/agx/git-buildpackage.git" + self.assertEqual(repo_to_url(arg), exp) + + @skip_without_cmd('dpkg') + @patch('gbp.scripts.clone.apt_showsrc', return_value="VCS-Git: https://a") + def test_repo_to_url_vcs_git(self, patch): + arg = "vcs-git:pkg" + exp = "https://a" + self.assertEqual(repo_to_url(arg), exp) + + @skip_without_cmd('dpkg') + @patch('gbp.scripts.clone.apt_showsrc', return_value="VCS-Git: https://a") + def test_repo_to_url_vcs_git_alias(self, patch): + arg = "vcsgit:pkg" + exp = "https://a" + self.assertEqual(repo_to_url(arg), exp) + + @skip_without_cmd('dpkg') + @patch('gbp.scripts.clone.apt_showsrc', return_value=""" 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/ @@ -25,10 +52,8 @@ Version: 0.6.0~git20120601 Standards-Version: 3.9.3 Vcs-Git: git://honk.sigxcpu.org/git/git-buildpackage.git -""" - - @skip_without_cmd('dpkg') - @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/') +""") + def test_repo_to_url_vcs_git_version(self, patch): + arg = 'vcs-git:git-buildpackage' + exp = 'https://git.sigxcpu.org/cgit/git-buildpackage/' + self.assertEqual(repo_to_url(arg), exp) -- 2.39.5
>From 738062982eb8d290303303da9795a7de5f1800a5 Mon Sep 17 00:00:00 2001 From: Nicolas Boulenguez <nico...@debian.org> Date: Sat, 30 Nov 2024 14:03:59 +0100 Subject: [PATCH 5/6] clone: replace some if statements with match statements --- gbp/scripts/clone.py | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/gbp/scripts/clone.py b/gbp/scripts/clone.py index ffedf5c1..15a16ed1 100755 --- a/gbp/scripts/clone.py +++ b/gbp/scripts/clone.py @@ -91,20 +91,15 @@ def repo_to_url(repo): >>> 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 == 'salsa': - return 'https://salsa.debian.org/%s.git' % path - if proto == 'github': - return 'https://github.com/%s.git' % path - elif proto in ['vcsgit', 'vcs-git']: - return vcs_git_url(path) - else: - return repo + match repo.split(":", 1): + case 'salsa', path: + return 'https://salsa.debian.org/%s.git' % path + case 'github', path: + return 'https://github.com/%s.git' % path + case 'vcsgit' | 'vcs-git', path: + return vcs_git_url(path) + case _: + return repo def add_upstream_vcs(repo): @@ -187,11 +182,18 @@ def main(argv): if not options: return ExitCodes.parse_error - if len(args) < 2: - gbp.log.err("Need a repository to clone.") - return ExitCodes.failed - else: - remote_repo = args[1] + match args: + case _, : + gbp.log.err("Need a repository to clone.") + return ExitCodes.failed + case _, remote_repo: + clone_to = os.path.curdir + auto_name = True + case _, remote_repo, clone_to: + auto_name = False + case _: + gbp.log.err("Too many arguments on the command line.") + return ExitCodes.failed if options.aliases: try: @@ -201,7 +203,6 @@ def main(argv): else: source = remote_repo - clone_to, auto_name = (os.path.curdir, True) if len(args) < 3 else (args[2], False) try: GitRepository(clone_to) gbp.log.err("Can't run inside a git repository.") -- 2.39.5
>From 8f7c0484078a035b78db806e64d6ab09076ecfb2 Mon Sep 17 00:00:00 2001 From: Nicolas Boulenguez <nico...@debian.org> Date: Sat, 30 Nov 2024 14:25:06 +0100 Subject: [PATCH 6/6] clone: handle -b optional branch specification in VCS-Git --- gbp/scripts/clone.py | 34 ++++++++++++++++++++++------------ tests/29_test_gbp_clone.py | 19 +++++++++++++------ 2 files changed, 35 insertions(+), 18 deletions(-) diff --git a/gbp/scripts/clone.py b/gbp/scripts/clone.py index 15a16ed1..0d348a30 100755 --- a/gbp/scripts/clone.py +++ b/gbp/scripts/clone.py @@ -50,11 +50,14 @@ class MissingVCSGitField(Exception): """When the VCS-Git field is requested but missing.""" -def vcs_git_url(pkg): +def vcs_git_url(pkg: str) -> tuple[str, str | None]: + """URL and optional branch from the VCS-Git field.""" repos = {} out = apt_showsrc(pkg) - vcs_re = re.compile(r'(x-)?vcs-git:\s*(?P<repo>[^ ]+)$', re.I) + vcs_re = re.compile( + r'(?:x-)?vcs-git:\s*([^ ]+)(?:\s+-b\s+([^ ]+))?$', re.I + ) version_re = re.compile(r'Version:\s*(?P<version>.*)$', re.I) end_re = re.compile(r'\s*$') @@ -62,7 +65,7 @@ def vcs_git_url(pkg): for line in out.split('\n'): m = vcs_re.match(line) if m: - repo = m.group('repo') + repo = m.groups() continue m = version_re.match(line) if m: @@ -82,24 +85,24 @@ def vcs_git_url(pkg): return repos[s[-1]] -def repo_to_url(repo): +def repo_to_url(repo: str) -> tuple[str, str | None]: """ >>> repo_to_url("https://foo.example.com") - 'https://foo.example.com' + ('https://foo.example.com', None) >>> repo_to_url("salsa:agx/git-buildpackage") - 'https://salsa.debian.org/agx/git-buildpackage.git' + ('https://salsa.debian.org/agx/git-buildpackage.git', None) >>> repo_to_url("github:agx/git-buildpackage") - 'https://github.com/agx/git-buildpackage.git' + ('https://github.com/agx/git-buildpackage.git', None) """ match repo.split(":", 1): case 'salsa', path: - return 'https://salsa.debian.org/%s.git' % path + return 'https://salsa.debian.org/%s.git' % path, None case 'github', path: - return 'https://github.com/%s.git' % path + return 'https://github.com/%s.git' % path, None case 'vcsgit' | 'vcs-git', path: return vcs_git_url(path) case _: - return repo + return repo, None def add_upstream_vcs(repo): @@ -197,11 +200,11 @@ def main(argv): if options.aliases: try: - source = repo_to_url(remote_repo) + source, vcs_git_branch = repo_to_url(remote_repo) except MissingVCSGitField: return ExitCodes.failed else: - source = remote_repo + source, vcs_git_branch = remote_repo, None try: GitRepository(clone_to) @@ -221,6 +224,13 @@ def main(argv): postclone = options.postclone (options, args) = parse_args(argv) + if vcs_git_branch not in (None, options.debian_branch): + gbp.log.warn( + 'VCS-Git: -b ' + vcs_git_branch + + ' overrides --debian-branch=' + options.debian_branch + ) + options.debian_branch = vcs_git_branch + # Track all branches: if options.all: remotes = repo.get_remote_branches() diff --git a/tests/29_test_gbp_clone.py b/tests/29_test_gbp_clone.py index 3c5e2bbb..a48b664c 100644 --- a/tests/29_test_gbp_clone.py +++ b/tests/29_test_gbp_clone.py @@ -11,31 +11,31 @@ class TestGbpClone(unittest.TestCase): def test_repo_to_url(self): arg = "https://foo.example.com" - exp = arg + exp = arg, None self.assertEqual(repo_to_url(arg), exp) def test_repo_to_url_salsa(self): arg = "salsa:agx/git-buildpackage" - exp = 'https://salsa.debian.org/agx/git-buildpackage.git' + exp = 'https://salsa.debian.org/agx/git-buildpackage.git', None self.assertEqual(repo_to_url(arg), exp) def test_repo_to_url_github(self): arg = "github:agx/git-buildpackage" - exp = "https://github.com/agx/git-buildpackage.git" + exp = "https://github.com/agx/git-buildpackage.git", None self.assertEqual(repo_to_url(arg), exp) @skip_without_cmd('dpkg') @patch('gbp.scripts.clone.apt_showsrc', return_value="VCS-Git: https://a") def test_repo_to_url_vcs_git(self, patch): arg = "vcs-git:pkg" - exp = "https://a" + exp = "https://a", None self.assertEqual(repo_to_url(arg), exp) @skip_without_cmd('dpkg') @patch('gbp.scripts.clone.apt_showsrc', return_value="VCS-Git: https://a") def test_repo_to_url_vcs_git_alias(self, patch): arg = "vcsgit:pkg" - exp = "https://a" + exp = "https://a", None self.assertEqual(repo_to_url(arg), exp) @skip_without_cmd('dpkg') @@ -55,5 +55,12 @@ Vcs-Git: git://honk.sigxcpu.org/git/git-buildpackage.git """) def test_repo_to_url_vcs_git_version(self, patch): arg = 'vcs-git:git-buildpackage' - exp = 'https://git.sigxcpu.org/cgit/git-buildpackage/' + exp = 'https://git.sigxcpu.org/cgit/git-buildpackage/', None + self.assertEqual(repo_to_url(arg), exp) + + @skip_without_cmd('dpkg') + @patch('gbp.scripts.clone.apt_showsrc', return_value='VCS-Git: h://a -b d') + def test_repo_to_url_vcs_git_branch(self, patch): + arg = 'vcs-git:pkg' + exp = 'h://a', 'd' self.assertEqual(repo_to_url(arg), exp) -- 2.39.5