From 466666d6f3cca2e4ab2bd59039cd632e615b04ea Mon Sep 17 00:00:00 2001 From: sachin235 Date: Wed, 20 May 2020 07:40:54 +0530 Subject: [PATCH] Add Bitbucket Repo provider --- binderhub/app.py | 2 + binderhub/event-schemas/launch.json | 1 + binderhub/main.py | 1 + binderhub/repoproviders.py | 73 +++++++++++++++++++++++++++++ binderhub/static/js/index.js | 9 +++- binderhub/templates/index.html | 1 + 6 files changed, 86 insertions(+), 1 deletion(-) diff --git a/binderhub/app.py b/binderhub/app.py index 0aba78196..2d235ac22 100755 --- a/binderhub/app.py +++ b/binderhub/app.py @@ -33,6 +33,7 @@ from .registry import DockerRegistry from .main import MainHandler, ParameterizedMainHandler, LegacyRedirectHandler from .repoproviders import (GitHubRepoProvider, GitRepoProvider, + BitbucketRepoProvider, GitLabRepoProvider, GistRepoProvider, ZenodoProvider, FigshareProvider, HydroshareProvider, DataverseProvider) @@ -399,6 +400,7 @@ def _add_slash(self, proposal): repo_providers = Dict( { 'gh': GitHubRepoProvider, + 'bb': BitbucketRepoProvider, 'gist': GistRepoProvider, 'git': GitRepoProvider, 'gl': GitLabRepoProvider, diff --git a/binderhub/event-schemas/launch.json b/binderhub/event-schemas/launch.json index 662d03680..31680a061 100755 --- a/binderhub/event-schemas/launch.json +++ b/binderhub/event-schemas/launch.json @@ -8,6 +8,7 @@ "provider": { "enum": [ "GitHub", + "Bitbucket", "Gist", "GitLab", "Git", diff --git a/binderhub/main.py b/binderhub/main.py index 329634238..1f0799d3f 100755 --- a/binderhub/main.py +++ b/binderhub/main.py @@ -12,6 +12,7 @@ SPEC_NAMES = { "gh": "GitHub", + "bb": "Bitbucket", "gist": "Gist", "gl": "GitLab", "git": "Git repo", diff --git a/binderhub/repoproviders.py b/binderhub/repoproviders.py index 6a48a283e..2a7236a83 100755 --- a/binderhub/repoproviders.py +++ b/binderhub/repoproviders.py @@ -899,3 +899,76 @@ async def get_resolved_spec(self): def get_build_slug(self): return self.gist_id + + + +# For Bitbucket + +class BitbucketRepoProvider(RepoProvider): + """Repo provider for Bitbucket sevices. + + Users must provide a spec that matches the following form. + + [https://bitbucket.org/][/] + + / + / + + The ref is optional, valid values are + - a full sha1 of a ref in the history + - master + + If master or no ref is specified the latest revision will be used. + """ + + name = Unicode("Bitbucket") + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.url, unresolved_ref = self.spec.split('/', 1) + self.repo = urllib.parse.unquote(self.url) + self.unresolved_ref = urllib.parse.unquote(unresolved_ref) + if not self.unresolved_ref: + raise ValueError("`unresolved_ref` must be specified as a query parameter for Bitbucket provider") + + @gen.coroutine + def get_resolved_ref(self): + if hasattr(self, 'resolved_ref'): + return self.resolved_ref + + try: + # Check if the reference is a valid SHA hash + self.sha1_validate(self.unresolved_ref) + except ValueError: + # The ref is a head/tag and we resolve it using `git ls-remote` + command = ["git", "ls-remote", self.repo, self.unresolved_ref] + result = subprocess.run(command, universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + if result.returncode: + raise RuntimeError("Unable to run git ls-remote to get the `resolved_ref`: {}".format(result.stderr)) + if not result.stdout: + raise ValueError("The specified branch, tag or commit SHA ('{}') was not found on the remote repository." + .format(self.unresolved_ref)) + resolved_ref = result.stdout.split(None, 1)[0] + self.sha1_validate(resolved_ref) + self.resolved_ref = resolved_ref + else: + # The ref already was a valid SHA hash + self.resolved_ref = self.unresolved_ref + + return self.resolved_ref + + async def get_resolved_spec(self): + if not hasattr(self, 'resolved_ref'): + self.resolved_ref = await self.get_resolved_ref() + return f"{self.url}/{self.resolved_ref}" + + def get_repo_url(self): + return self.repo + + async def get_resolved_ref_url(self): + # not possible to construct ref url + return self.get_repo_url() + + def get_build_slug(self): + return self.repo + diff --git a/binderhub/static/js/index.js b/binderhub/static/js/index.js index 2465a05ef..ea0c28a63 100755 --- a/binderhub/static/js/index.js +++ b/binderhub/static/js/index.js @@ -68,7 +68,14 @@ function updateRepoText() { $("label[for=ref]").prop("disabled", false); if (provider === "gh") { text = "GitHub repository name or URL"; - } else if (provider === "gl") { + } + + else if (provider === "bb") { + text = "Bitbucket repository name or URL"; + tag_text = "Bitbucket branch, tag, or commit SHA"; + } + + else if (provider === "gl") { text = "GitLab.com repository or URL"; } else if (provider === "gist") { diff --git a/binderhub/templates/index.html b/binderhub/templates/index.html index b625f63db..1a63f9f4c 100755 --- a/binderhub/templates/index.html +++ b/binderhub/templates/index.html @@ -50,6 +50,7 @@

Build and launch a repository