diff --git a/.gitignore b/.gitignore index 3737ffc..e527d36 100644 --- a/.gitignore +++ b/.gitignore @@ -56,4 +56,5 @@ dev/docker/test_env # A possible symlink for the testsuite /repospanner +/repobridge /repohookrunner diff --git a/doc/configuration.rst b/doc/configuration.rst index f910324..e9fb409 100644 --- a/doc/configuration.rst +++ b/doc/configuration.rst @@ -1521,6 +1521,15 @@ Support for this integration has been included in Pagure version 5.0 and higher. Here below are the different options one can/should use to integrate pagure with repoSpanner. +REPOBRIDGE_BINARY +~~~~~~~~~~~~~~~~~ + +This should contain the path to the repoBridge binary, which is used for pushing +and pulling to/from repoSpanner. + +Defaults to: ``/usr/libexec/repobridge``. + + REPOSPANNER_NEW_REPO ~~~~~~~~~~~~~~~~~~~~ diff --git a/pagure/default_config.py b/pagure/default_config.py index 45569d8..acb4f8e 100644 --- a/pagure/default_config.py +++ b/pagure/default_config.py @@ -492,6 +492,8 @@ ALLOW_HTTP_PUSH = False HTTP_REPO_ACCESS_GITOLITE = "/usr/share/gitolite3/gitolite-shell" # repoSpanner integration settings +# Path the the repoBridge binary +REPOBRIDGE_BINARY = "/usr/libexec/repobridge" # Whether to create new repositories on repoSpanner by default. # Either None or a region name. REPOSPANNER_NEW_REPO = None diff --git a/pagure/lib/git.py b/pagure/lib/git.py index a7819b6..c5dcbef 100644 --- a/pagure/lib/git.py +++ b/pagure/lib/git.py @@ -907,18 +907,32 @@ class TemporaryClone(object): command = [ "git", "-c", - "http.sslcainfo=%s" % regioninfo["ca"], - "-c", - "http.sslcert=%s" % regioninfo["push_cert"]["cert"], - "-c", - "http.sslkey=%s" % regioninfo["push_cert"]["key"], + "protocol.ext.allow=always", "clone", - repourl, + "ext::%s %s" + % ( + pagure_config["REPOBRIDGE_BINARY"], + self._project._repospanner_repo_name(self._repotype), + ), self.repopath, ] + environ = os.environ.copy() + environ.update( + { + "USER": "pagure", + "REPOBRIDGE_CONFIG": ":environment:", + "REPOBRIDGE_BASEURL": regioninfo["url"], + "REPOBRIDGE_CA": regioninfo["ca"], + "REPOBRIDGE_CERT": regioninfo["push_cert"]["cert"], + "REPOBRIDGE_KEY": regioninfo["push_cert"]["key"], + } + ) with open(os.devnull, "w") as devnull: subprocess.check_call( - command, stdout=devnull, stderr=subprocess.STDOUT + command, + stdout=devnull, + stderr=subprocess.STDOUT, + env=environ, ) self.repo = pygit2.Repository(self.repopath) @@ -953,7 +967,6 @@ class TemporaryClone(object): extra["pull_request_uid"] = extra["pull_request"].uid del extra["pull_request"] - opts = [] if self._project.is_on_repospanner: regioninfo = pagure_config["REPOSPANNER_REGIONS"][ self._project.repospanner_region @@ -970,32 +983,47 @@ class TemporaryClone(object): "project_namespace": self._project.namespace or "", } ) - opts = [ - "-c", - "http.sslcainfo=%s" % regioninfo["ca"], - "-c", - "http.sslcert=%s" % regioninfo["push_cert"]["cert"], + args = [] + for opt in extra: + args.extend(["--extra", opt, extra[opt]]) + command = [ + "git", "-c", - "http.sslkey=%s" % regioninfo["push_cert"]["key"], + "protocol.ext.allow=always", + "push", + "ext::%s %s %s" + % ( + pagure_config["REPOBRIDGE_BINARY"], + " ".join(args), + self._project._repospanner_repo_name(self._repotype), + ), + "--repo", + self.repopath, ] - for extrakey in extra: - val = extra[extrakey] - opts.extend( - ["-c", "http.extraHeader=X-Extra-%s: %s" % (extrakey, val)] - ) + environ = { + "USER": "pagure", + "REPOBRIDGE_CONFIG": ":environment:", + "REPOBRIDGE_BASEURL": regioninfo["url"], + "REPOBRIDGE_CA": regioninfo["ca"], + "REPOBRIDGE_CERT": regioninfo["push_cert"]["cert"], + "REPOBRIDGE_KEY": regioninfo["push_cert"]["key"], + } + else: + command = ["git", "push", "origin"] + environ = {} try: _log.debug( "Running a git push of %s to %s" % (pushref, self._project.fullname) ) - _log.debug("Opts: %s", opts) env = os.environ.copy() env["GL_USER"] = username env["GL_BYPASS_ACCESS_CHECKS"] = "1" + env.update(environ) env.update(extra) out = subprocess.check_output( - ["git"] + opts + ["push", "origin", pushref], + command + [pushref], cwd=self.repopath, stderr=subprocess.STDOUT, env=env, diff --git a/pagure/lib/model.py b/pagure/lib/model.py index e284a26..2725665 100644 --- a/pagure/lib/model.py +++ b/pagure/lib/model.py @@ -522,7 +522,7 @@ class Project(BASE): ) return url, regioninfo - def _repospanner_repo_name(self, repotype, region): + def _repospanner_repo_name(self, repotype, region=None): """ Returns the name of a repo as named in repoSpanner. Args: @@ -530,6 +530,8 @@ class Project(BASE): region (string): repoSpanner region name Return type: (string) """ + if region is None: + region = self.repospanner_region return os.path.join( pagure_config["REPOSPANNER_REGIONS"][region].get( "repo_prefix", "" diff --git a/tests/__init__.py b/tests/__init__.py index 762c76f..b8022e3 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -100,6 +100,7 @@ CELERY_CONFIG = { } GIT_AUTH_BACKEND = '%(authbackend)s' TEST_AUTH_STATUS = '%(path)s/testauth_status.json' +REPOBRIDGE_BINARY = '%(repobridge_binary)s' REPOSPANNER_NEW_REPO = %(repospanner_new_repo)s REPOSPANNER_NEW_REPO_ADMIN_OVERRIDE = %(repospanner_admin_override)s REPOSPANNER_NEW_FORK = %(repospanner_new_fork)s @@ -386,6 +387,7 @@ class SimplePagureTest(unittest.TestCase): 'global_path': tests_state["path"], 'authbackend': 'gitolite3', + 'repobridge_binary': '/usr/libexec/repobridge', 'repospanner_gitport': str(8443 + sys.version_info.major), 'repospanner_new_repo': 'None', 'repospanner_admin_override': 'False', diff --git a/tests/test_pagure_repospanner.py b/tests/test_pagure_repospanner.py index 8ab2058..3ec33c5 100644 --- a/tests/test_pagure_repospanner.py +++ b/tests/test_pagure_repospanner.py @@ -138,6 +138,12 @@ class PagureRepoSpannerTests(tests.Modeltests): 'repohookrunner') if not os.path.exists(hookrunbin): raise Exception('repoSpanner found, but repohookrunner not') + repobridgebin = os.path.join(os.path.dirname(self.repospanner_binary), + 'repobridge') + if not os.path.exists(repobridgebin): + raise Exception('repoSpanner found, but repobridge not') + + self.config_values['repobridge_binary'] = repobridgebin codepath = os.path.normpath( os.path.join(