diff --git a/binderhub/app.py b/binderhub/app.py index 85872210c5..1cbe68af7c 100755 --- a/binderhub/app.py +++ b/binderhub/app.py @@ -36,7 +36,7 @@ from .repoproviders import (GitHubRepoProvider, GitRepoProvider, GitLabRepoProvider, GistRepoProvider, ZenodoProvider, FigshareProvider, HydroshareProvider, - DataverseProvider) + DataverseProvider, SWHIDProvider) from .metrics import MetricsHandler from .utils import ByteSpecification, url_path_join @@ -436,6 +436,7 @@ def _add_slash(self, proposal): 'figshare': FigshareProvider, 'hydroshare': HydroshareProvider, 'dataverse': DataverseProvider, + 'swh': SWHIDProvider, }, config=True, help=""" diff --git a/binderhub/event-schemas/launch.json b/binderhub/event-schemas/launch.json index 7e8a22a1f6..17f45eca94 100755 --- a/binderhub/event-schemas/launch.json +++ b/binderhub/event-schemas/launch.json @@ -14,7 +14,8 @@ "Zenodo", "Figshare", "Hydroshare", - "Dataverse" + "Dataverse", + "Software Heritage" ], "description": "Provider for the repository being launched" }, diff --git a/binderhub/main.py b/binderhub/main.py index 3296342382..5ee853d3ce 100755 --- a/binderhub/main.py +++ b/binderhub/main.py @@ -19,6 +19,7 @@ "figshare": "Figshare", "hydroshare": "Hydroshare", "dataverse": "Dataverse", + "swh": "Software Heritage", } diff --git a/binderhub/repoproviders.py b/binderhub/repoproviders.py index 5e92b22353..1cf3d462bb 100755 --- a/binderhub/repoproviders.py +++ b/binderhub/repoproviders.py @@ -886,3 +886,40 @@ async def get_resolved_spec(self): def get_build_slug(self): return self.gist_id + + +class SWHIDProvider(RepoProvider): + """Provide contents of a SWHID record + + Users must provide a spec consisting of the SWHID of a directory or revision. + """ + name = Unicode("SWHID") + + async def get_resolved_ref(self): + client = AsyncHTTPClient() + req = HTTPRequest("https://archive.softwareheritage.org/api/1/known/", + headers={'content-type': 'application/json'}, + body=json.dumps([self.spec]), + user_agent="BinderHub") + r = await client.fetch(req) + r.rethrow() + + response = json.loads(r.body) + if response[self.spec]["known"]: + return self.spec + raise RuntimeError(f"Unknown SWHID {self.spec}") + + + async def get_resolved_spec(self): + return self.spec + + def get_repo_url(self): + # While called repo URL, the return value of this function is passed + # as argument to repo2docker, hence we return the spec as is. + return self.spec + + async def get_resolved_ref_url(self): + return self.spec + + def get_build_slug(self): + return "swh-{}".format(self.spec) diff --git a/binderhub/static/js/index.js b/binderhub/static/js/index.js index 0f9f1628bd..d3df19791d 100755 --- a/binderhub/static/js/index.js +++ b/binderhub/static/js/index.js @@ -99,6 +99,11 @@ function updateRepoText() { $("#ref").prop("disabled", true); $("label[for=ref]").prop("disabled", true); } + else if (provider === "swh") { + text = "Software Heritage SWHID (swh:1:rev:c30614ec4587418fb264efb466cba58991029f16)"; + $("#ref").prop("disabled", true); + $("label[for=ref]").prop("disabled", true); + } $("#repository").attr('placeholder', text); $("label[for=repository]").text(text); $("#ref").attr('placeholder', placeholder); @@ -123,7 +128,7 @@ function getBuildFormValues() { var ref = $('#ref').val().trim() || $("#ref").attr("placeholder"); if (providerPrefix === 'zenodo' || providerPrefix === 'figshare' || providerPrefix === 'dataverse' || - providerPrefix === 'hydroshare') { + providerPrefix === 'hydroshare' || providerPrefix === 'swh') { ref = ""; } var path = $('#filepath').val().trim(); diff --git a/binderhub/templates/index.html b/binderhub/templates/index.html index 75f49d47a4..4cde2f7c3e 100755 --- a/binderhub/templates/index.html +++ b/binderhub/templates/index.html @@ -60,6 +60,7 @@