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

Reply via email to