From ab9d15b33df3e4c808746352ea73e4d240939712 Mon Sep 17 00:00:00 2001
From: Tomas Kopecek <tkopecek@redhat.com>
Date: Nov 08 2022 11:15:57 +0000
Subject: [PATCH 1/3] Enable fetching any ref from git repo


Related: https://pagure.io/koji/issue/3508

---

diff --git a/koji/daemon.py b/koji/daemon.py
index d487803..535961e 100644
--- a/koji/daemon.py
+++ b/koji/daemon.py
@@ -520,7 +520,7 @@ class SCM(object):
         # TODO: sanity check arguments
         sourcedir = '%s/%s' % (scmdir, self.module)
 
-        update_checkout_cmd = None
+        update_checkout_cmds = None
         update_checkout_dir = None
         env = None
 
@@ -578,7 +578,10 @@ class SCM(object):
             sourcedir = '%s/%s' % (scmdir, checkout_path)
             module_checkout_cmd = ['git', 'clone', '-n', gitrepo, sourcedir]
             common_checkout_cmd = ['git', 'clone', commonrepo, 'common']
-            update_checkout_cmd = ['git', 'reset', '--hard', self.revision]
+            update_checkout_cmds = [
+                ['git', 'fetch', 'origin', self.revision, 'KOJI_FETCH_HEAD'],
+                ['git', 'reset', '--hard', 'KOJI_FETCH_HEAD']
+            ]
             update_checkout_dir = sourcedir
 
             # self.module may be empty, in which case the specfile should be in the top-level
@@ -608,7 +611,10 @@ class SCM(object):
             sourcedir = '%s/%s' % (scmdir, checkout_path)
             module_checkout_cmd = ['git', 'clone', '-n', gitrepo, sourcedir]
             common_checkout_cmd = ['git', 'clone', commonrepo, 'common']
-            update_checkout_cmd = ['git', 'reset', '--hard', self.revision]
+            update_checkout_cmds = [
+                ['git', 'fetch', 'origin', self.revision, 'KOJI_FETCH_HEAD'],
+                ['git', 'reset', '--hard', 'KOJI_FETCH_HEAD']
+            ]
             update_checkout_dir = sourcedir
 
             # self.module may be empty, in which case the specfile should be in the top-level
@@ -643,7 +649,7 @@ class SCM(object):
         # perform checkouts
         _run(module_checkout_cmd, chdir=scmdir, fatal=True)
 
-        if update_checkout_cmd:
+        if update_checkout_cmds:
             # Currently only required for GIT checkouts
             # Run the command in the directory the source was checked out into
             if self.scmtype.startswith('GIT') and globals().get('KOJIKAMID'):
@@ -651,7 +657,8 @@ class SCM(object):
                      chdir=update_checkout_dir, fatal=True)
                 _run(['git', 'config', 'core.safecrlf', 'true'],
                      chdir=update_checkout_dir, fatal=True)
-            _run(update_checkout_cmd, chdir=update_checkout_dir, fatal=True)
+            for cmd in update_checkout_cmds:
+                _run(cmd, chdir=update_checkout_dir, fatal=True)
 
         if self.use_common and not globals().get('KOJIKAMID'):
             _run(common_checkout_cmd, chdir=scmdir, fatal=True)

From 4cf59602f16e71a359a3bd5677aa1d50fac079f0 Mon Sep 17 00:00:00 2001
From: Tomas Kopecek <tkopecek@redhat.com>
Date: Nov 08 2022 11:15:57 +0000
Subject: [PATCH 2/3] exception in case origin/ is part of ref


---

diff --git a/koji/daemon.py b/koji/daemon.py
index 535961e..41ac10c 100644
--- a/koji/daemon.py
+++ b/koji/daemon.py
@@ -575,11 +575,16 @@ class SCM(object):
                 checkout_path = os.path.basename(self.repository[:-4])
                 commonrepo = os.path.dirname(gitrepo[:-4]) + '/common.git'
 
+            # git-reset happily accepted origin/x spec, fetch has it split
+            if self.revision.startswith('origin/'):
+                rev = self.revision[7:]
+            else:
+                rev = self.revision
             sourcedir = '%s/%s' % (scmdir, checkout_path)
             module_checkout_cmd = ['git', 'clone', '-n', gitrepo, sourcedir]
             common_checkout_cmd = ['git', 'clone', commonrepo, 'common']
             update_checkout_cmds = [
-                ['git', 'fetch', 'origin', self.revision, 'KOJI_FETCH_HEAD'],
+                ['git', 'fetch', 'origin', '%s:KOJI_FETCH_HEAD' % rev],
                 ['git', 'reset', '--hard', 'KOJI_FETCH_HEAD']
             ]
             update_checkout_dir = sourcedir
@@ -608,11 +613,16 @@ class SCM(object):
                 checkout_path = os.path.basename(self.repository[:-4])
                 commonrepo = os.path.dirname(gitrepo[:-4]) + '/common.git'
 
+            # git-reset happily accepted origin/x spec, fetch has it split
+            if self.revision.startswith('origin/'):
+                rev = self.revision[7:]
+            else:
+                rev = self.revision
             sourcedir = '%s/%s' % (scmdir, checkout_path)
             module_checkout_cmd = ['git', 'clone', '-n', gitrepo, sourcedir]
             common_checkout_cmd = ['git', 'clone', commonrepo, 'common']
             update_checkout_cmds = [
-                ['git', 'fetch', 'origin', self.revision, 'KOJI_FETCH_HEAD'],
+                ['git', 'fetch', 'origin', '%s:KOJI_FETCH_HEAD' % rev],
                 ['git', 'reset', '--hard', 'KOJI_FETCH_HEAD']
             ]
             update_checkout_dir = sourcedir

From 58fb7c7ee65d28a1b4fc00555e8054b3ab8cfea7 Mon Sep 17 00:00:00 2001
From: Tomas Kopecek <tkopecek@redhat.com>
Date: Nov 08 2022 11:25:10 +0000
Subject: [PATCH 3/3] fix tests


---

diff --git a/tests/test_scm.py b/tests/test_scm.py
index a75f259..3e95ace 100644
--- a/tests/test_scm.py
+++ b/tests/test_scm.py
@@ -466,10 +466,13 @@ class TestSCMCheckouts(unittest.TestCase):
         cmd = ['git', 'clone', '-n', 'git://nocommon/koji.git', self.tempdir + '/koji']
         call1 = mock.call(self.session, cmd[0], cmd, self.logfile, self.uploadpath,
                           cwd=self.tempdir, logerror=1, append=False, env=None)
-        cmd = ['git', 'reset', '--hard', 'asdasd']
+        cmd = ['git', 'fetch', 'origin', 'asdasd:KOJI_FETCH_HEAD']
         call2 = mock.call(self.session, cmd[0], cmd, self.logfile, self.uploadpath,
                           cwd=self.tempdir + '/koji', logerror=1, append=True, env=None)
-        self.log_output.assert_has_calls([call1, call2])
+        cmd = ['git', 'reset', '--hard', 'KOJI_FETCH_HEAD']
+        call3 = mock.call(self.session, cmd[0], cmd, self.logfile, self.uploadpath,
+                          cwd=self.tempdir + '/koji', logerror=1, append=True, env=None)
+        self.log_output.assert_has_calls([call1, call2, call3])
 
     def test_checkout_gitssh_nocommon(self):
 
@@ -484,10 +487,13 @@ class TestSCMCheckouts(unittest.TestCase):
         cmd = ['git', 'clone', '-n', 'git+ssh://user@nocommon/koji.git', self.tempdir + '/koji']
         call1 = mock.call(self.session, cmd[0], cmd, self.logfile, self.uploadpath,
                           cwd=self.tempdir, logerror=1, append=False, env=None)
-        cmd = ['git', 'reset', '--hard', 'asdasd']
+        cmd = ['git', 'fetch', 'origin', 'asdasd:KOJI_FETCH_HEAD']
         call2 = mock.call(self.session, cmd[0], cmd, self.logfile, self.uploadpath,
                           cwd=self.tempdir + '/koji', logerror=1, append=True, env=None)
-        self.log_output.assert_has_calls([call1, call2])
+        cmd = ['git', 'reset', '--hard', 'KOJI_FETCH_HEAD']
+        call3 = mock.call(self.session, cmd[0], cmd, self.logfile, self.uploadpath,
+                          cwd=self.tempdir + '/koji', logerror=1, append=True, env=None)
+        self.log_output.assert_has_calls([call1, call2, call3])
 
     def test_checkout_git_common(self):
 
@@ -502,13 +508,16 @@ class TestSCMCheckouts(unittest.TestCase):
         cmd = ['git', 'clone', '-n', 'git://default/koji.git', self.tempdir + '/koji']
         call1 = mock.call(self.session, cmd[0], cmd, self.logfile, self.uploadpath,
                           cwd=self.tempdir, logerror=1, append=False, env=None)
-        cmd = ['git', 'reset', '--hard', 'asdasd']
+        cmd = ['git', 'fetch', 'origin', 'asdasd:KOJI_FETCH_HEAD']
         call2 = mock.call(self.session, cmd[0], cmd, self.logfile, self.uploadpath,
                           cwd=self.tempdir + '/koji', logerror=1, append=True, env=None)
-        cmd = ['git', 'clone', 'git://default/common.git', 'common']
+        cmd = ['git', 'reset', '--hard', 'KOJI_FETCH_HEAD']
         call3 = mock.call(self.session, cmd[0], cmd, self.logfile, self.uploadpath,
+                          cwd=self.tempdir + '/koji', logerror=1, append=True, env=None)
+        cmd = ['git', 'clone', 'git://default/common.git', 'common']
+        call4 = mock.call(self.session, cmd[0], cmd, self.logfile, self.uploadpath,
                           cwd=self.tempdir, logerror=1, append=True, env=None)
-        self.log_output.assert_has_calls([call1, call2, call3])
+        self.log_output.assert_has_calls([call1, call2, call3, call4])
 
     def test_checkout_error_in_command(self):
 

