Skip to content

Commit

Permalink
feat: enable jbang [email protected] and jbang tree@https:/jbang.dev
Browse files Browse the repository at this point in the history
  • Loading branch information
maxandersen committed Mar 9, 2022
1 parent 238ef90 commit 9d2ce04
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 16 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ dependencies {
//implementation 'com.google.guava:guava:28.2-jre'


testCompile "com.github.tomakehurst:wiremock-jre8:2.27.2"
testCompile "com.github.tomakehurst:wiremock-jre8:2.32.0"

testImplementation "org.junit.jupiter:junit-jupiter:5.7.1"
testRuntimeOnly('org.junit.jupiter:junit-jupiter-engine:5.7.1')
Expand Down
15 changes: 13 additions & 2 deletions docs/modules/ROOT/pages/alias_catalogs.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,29 @@ The aliases you create are stored locally (see <<Local Alias Catalogs>>), but JB
You can access those catalogs explicitly (see <<Catalogs>>) but it is much easier to use what we call "implicit catalogs", which
are aliases that have a special format and JBang is smart enough to know where to find their definition.

There are two kinds, one that resolves to a Git backed service (github,gitlab and bitbucket) and one that resolves to
https sites.

Examples:

`jbang [email protected]` will (because of the dot in the name) will lookup a catalog first at https://jbang.dev/jbang-catalog.json.

`jbang hello@jbangdev` will run the alias `hello` as defined in `jbang-catalog.json` found in https://github.com/jbangdev/jbang-catalog.

This allows anyone to provide a set of jbang scripts defined in their github, gitlab or bitbucket repositories.
This allows anyone to provide a set of jbang scripts defined in their website or in a github, gitlab or bitbucket repositories.

The full format is `<alias>@<user/org>(/repository)(/branch)(~path)` allowing you to do things like:
The full format is `<alias>@<user/org>(/repository)(/branch)(~path)` or `<alias>@<hostname>(/path/to/catalog)` allowing you to do things like:

.Implicit Catalog Examples:
|====
|Command | Description

|`jbang [email protected]`
|`hello` alias found in `https://acme.corp/jbang-catalog.json` if available or the default branch searched on github, gitlab and bitbucket in that order.

|`jbang [email protected]/a/path/to/jbang-catalog.json`
|`hello` alias found in `https://acme.corp/a/path/to/jbang-catalog.json` if available.

|`jbang hello@acme`
|`hello` alias found in `acme/jbang-catalog/jbang-catalog.json` of the default branch searched on github, gitlab and bitbucket in that order.

Expand Down
40 changes: 27 additions & 13 deletions src/main/java/dev/jbang/catalog/ImplicitCatalogRef.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
package dev.jbang.catalog;

import static dev.jbang.cli.BaseCommand.EXIT_INVALID_INPUT;

import java.util.Arrays;
import java.util.Optional;
import java.util.function.Supplier;
import java.util.stream.Stream;

import dev.jbang.cli.ExitException;
import dev.jbang.util.Util;

public class ImplicitCatalogRef {
Expand All @@ -34,6 +31,12 @@ public String url(String host, String infix) {
return host + org + "/" + repo + infix + ref + "/" + path + Catalog.JBANG_CATALOG_JSON;
}

/**
* Return ImplicitCatalogRef if can be parsed into a git accessible structure.
*
* @param name
* @return null if cannot parse it
*/
public static ImplicitCatalogRef parse(String name) {
String[] parts = name.split("~", 2);
String path;
Expand All @@ -44,7 +47,9 @@ public static ImplicitCatalogRef parse(String name) {
}
String[] names = parts[0].split("/");
if (names.length > 3) {
throw new ExitException(EXIT_INVALID_INPUT, "Invalid catalog name '" + name + "'");
// throw new ExitException(EXIT_INVALID_INPUT, "Invalid catalog name '" + name +
// "'");
return null;
}
String org = names[0];
String repo;
Expand All @@ -62,16 +67,25 @@ public static ImplicitCatalogRef parse(String name) {
return new ImplicitCatalogRef(org, repo, ref, path);
}

static Optional<String> getImplicitCatalogUrl(String catalogName) {
ImplicitCatalogRef icr = parse(catalogName);
public static Optional<String> getImplicitCatalogUrl(String catalogName) {

Optional<ImplicitCatalogRef> icr = Optional.ofNullable(parse(catalogName));
Optional<String> url = chain(
() -> tryDownload(icr.url(GITHUB_URL, "/blob/")),
() -> icr.isPossibleCommit() ? tryDownload(icr.url(GITHUB_URL, "/blob/")) : Optional.empty(),
() -> tryDownload(icr.url(GITLAB_URL, "/-/blob/")),
() -> icr.isPossibleCommit() ? tryDownload(icr.url(GITLAB_URL, "/-/blob/")) : Optional.empty(),
() -> tryDownload(icr.url(BITBUCKET_URL, "/src/")),
() -> icr.isPossibleCommit() ? tryDownload(icr.url(BITBUCKET_URL, "/src/")) : Optional.empty())
.findFirst();
() -> catalogName.startsWith("https://") || catalogName.startsWith("http://")
|| catalogName.startsWith("file://") ? tryDownload(catalogName) : Optional.empty(),
() -> catalogName.contains(".") ? tryDownload("https://" + catalogName) : Optional.empty(),
() -> icr.isPresent() ? tryDownload(icr.get().url(GITHUB_URL, "/blob/")) : Optional.empty(),
() -> icr.isPresent() && icr.get().isPossibleCommit() ? tryDownload(icr.get().url(GITHUB_URL, "/blob/"))
: Optional.empty(),
() -> icr.isPresent() ? tryDownload(icr.get().url(GITLAB_URL, "/-/blob/")) : Optional.empty(),
() -> icr.isPresent() && icr.get().isPossibleCommit()
? tryDownload(icr.get().url(GITLAB_URL, "/-/blob/"))
: Optional.empty(),
() -> icr.isPresent() ? tryDownload(icr.get().url(BITBUCKET_URL, "/src/")) : Optional.empty(),
() -> icr.isPresent() && icr.get().isPossibleCommit()
? tryDownload(icr.get().url(BITBUCKET_URL, "/src/"))
: Optional.empty())
.findFirst();
return url;
}

Expand Down
63 changes: 63 additions & 0 deletions src/test/java/dev/jbang/TestImplicitAlias.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package dev.jbang;

import static org.hamcrest.MatcherAssert.assertThat;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;

import org.hamcrest.Matchers;
import org.junit.jupiter.api.Test;

import dev.jbang.catalog.Alias;
import dev.jbang.catalog.ImplicitCatalogRef;

/**
* TODO: use mock to handle https lookups instead of jbang.dev
*/
public class TestImplicitAlias extends BaseTest {

@Test
public void testGitImplicitCatalog() {
assertThat(ImplicitCatalogRef.getImplicitCatalogUrl("jbangdev").get(),
Matchers.equalTo("https://github.com/jbangdev/jbang-catalog/blob/HEAD/jbang-catalog.json"));
assertThat(ImplicitCatalogRef.getImplicitCatalogUrl("jbangdev/jbang-examples").get(),
Matchers.equalTo("https://github.com/jbangdev/jbang-examples/blob/HEAD/jbang-catalog.json"));
}

@Test
public void testImplictURLAlias() {

Alias url = Alias.get("[email protected]");
assertThat(url.scriptRef, Matchers.equalTo("tree/main.java"));

}

@Test
public void testImplictExplicitURLAlias() {

Alias url = Alias.get("tree@https://xam.dk");
assertThat(url.scriptRef, Matchers.equalTo("tree/main.java"));

}

// @Test needs fixing to not generate absolute paths but instead relative paths.
public void testFileURLAlias() throws IOException {

assertThat(jbangTempDir.resolve("inner").toFile().mkdirs(), Matchers.is(true));

Files.copy(examplesTestFolder.resolve("helloworld.java"), jbangTempDir.resolve("inner/helloworld.java"));
String src = jbangTempDir.resolve("inner/helloworld.java").toString();
Path path = jbangTempDir.resolve("jbang-catalog.json");

checkedRun(null, "alias", "add", "-f", path.toString(), "--name=apptest", src);

String url = "apptest@" + path.toUri();
assertThat(url, Matchers.stringContainsInOrder("file://"));

Alias alias = Alias.get(url);

assertThat(alias.scriptRef, Matchers.equalTo("helloworld.java"));

}
}

0 comments on commit 9d2ce04

Please sign in to comment.