-
Notifications
You must be signed in to change notification settings - Fork 51
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add JShell-based basic installation support
- Loading branch information
Showing
6 changed files
with
239 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
/* | ||
* Copyright (c) 2024 Christian Stein | ||
* Licensed under the Universal Permissive License v 1.0 -> https://opensource.org/license/upl | ||
*/ | ||
|
||
System.out.printf( | ||
""" | ||
___ ___ ___ ___ | ||
/\\ \\ /\\ \\ /\\ \\ /\\__\\ | ||
/::\\ \\ /::\\ \\ /::\\ \\ /:/__/_ | ||
/::\\:\\__\\/::\\:\\__\\/:/\\:\\__\\/::\\/\\__\\ | ||
\\:\\::/ /\\/\\::/ /\\:\\ \\/__/\\/\\::/ / Java %s | ||
\\::/ / /:/ / \\:\\__\\ /:/ / %s | ||
\\/__/ \\/__/ \\/__/ \\/__/ %s | ||
""", | ||
Runtime.version(), | ||
System.getProperty("os.name"), | ||
Path.of("").toUri() | ||
) | ||
|
||
System.out.println("| Source Bach's installer from " + Path.of("src/bach.run/BachInstaller.java").toUri()) | ||
|
||
/open src/bach.run/BachInstaller.java | ||
|
||
int code = 0 | ||
try { | ||
// BachInstaller.installDefaultVersionIntoDefaultDirectory(); | ||
new BachInstaller("main", Path.of(".bach/var/tmp/installed")).install(); | ||
} | ||
catch(Throwable throwable) { | ||
System.err.println(throwable); | ||
code = 1; | ||
} | ||
|
||
System.out.println("| Installation of Bach finished with exit code " + code) | ||
|
||
/exit code |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# Bach's Modular Sources | ||
|
||
For the time being, this folder only contains a subdirectory named `bach.run`. | ||
The `bach.run` subdirectory contains helper files used by https://bach.run path forwarding rules. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
/* | ||
* Copyright (c) 2024 Christian Stein | ||
* Licensed under the Universal Permissive License v 1.0 -> https://opensource.org/license/upl | ||
*/ | ||
|
||
import java.net.*; | ||
import java.nio.file.*; | ||
import java.util.*; | ||
|
||
record BachInstaller(String version, Path home) { | ||
static String DEFAULT_VERSION = System.getProperty("-Default.version".substring(2), "main"); | ||
static Path DEFAULT_HOME = Path.of(System.getProperty("-Default.home".substring(2), ".bach")); | ||
|
||
@SuppressWarnings("unused") | ||
static void installDefaultVersionIntoDefaultDirectory() throws Exception { | ||
var installer = new BachInstaller(DEFAULT_VERSION); | ||
installer.install(); | ||
} | ||
|
||
@SuppressWarnings("unused") | ||
static void listInstallableVersions() { | ||
System.out.println("- Default version: " + DEFAULT_VERSION); | ||
System.out.println("- Released versions: https://github.com/sormuras/run.bach/releases"); | ||
System.out.println("- Head revisions: https://github.com/sormuras/run.bach/branches"); | ||
} | ||
|
||
BachInstaller(String version) { | ||
this(version, DEFAULT_HOME); | ||
} | ||
|
||
void install() throws Exception { | ||
var uris = | ||
List.of( | ||
"https://github.com/sormuras/run.bach/archive/refs/tags/" + version + ".zip", | ||
"https://github.com/sormuras/run.bach/archive/refs/heads/" + version + ".zip"); | ||
for (var uri : uris) { | ||
if (Internal.head(uri)) { | ||
install(uri); | ||
return; | ||
} | ||
} | ||
} | ||
|
||
void install(String uri) throws Exception { | ||
System.out.println("Install Bach " + version + " to " + home.toUri() + "..."); | ||
var tmp = Files.createTempDirectory("run.bach-" + version + "-"); | ||
var dir = Files.createDirectories(home.resolve("src/run.bach/run/bach")); | ||
var zip = tmp.resolve("run.bach-" + version + ".zip"); | ||
// download and unzip | ||
Internal.copy(uri, zip, StandardCopyOption.REPLACE_EXISTING); | ||
Internal.unzip(zip, dir, 1); | ||
|
||
// clean up | ||
Internal.delete(tmp); | ||
} | ||
|
||
private interface Internal { | ||
boolean DEBUG = Boolean.getBoolean("-Debug".substring(2)); | ||
|
||
static void debug(String message) { | ||
if (DEBUG) System.out.println(message); | ||
} | ||
|
||
static boolean head(String source) throws Exception { | ||
var url = URI.create(source).toURL(); | ||
var con = (HttpURLConnection) url.openConnection(); | ||
try { | ||
con.setRequestMethod("HEAD"); | ||
var status = con.getResponseCode(); | ||
debug("%d <- HEAD %s".formatted(status, source)); | ||
if (status < 299) return true; | ||
} finally { | ||
con.disconnect(); | ||
} | ||
return false; | ||
} | ||
|
||
static void copy(String source, Path target, CopyOption... options) throws Exception { | ||
debug("<< %s".formatted(source)); | ||
Files.createDirectories(target.getParent()); | ||
try (var stream = | ||
source.startsWith("http") | ||
? URI.create(source).toURL().openStream() | ||
: Files.newInputStream(Path.of(source))) { | ||
var size = Files.copy(stream, target, options); | ||
debug(">> %,7d %s".formatted(size, target.getFileName())); | ||
} | ||
} | ||
|
||
static void delete(Path path) throws Exception { | ||
var start = path.normalize().toAbsolutePath(); | ||
if (Files.notExists(start)) return; | ||
for (var root : start.getFileSystem().getRootDirectories()) { | ||
if (start.equals(root)) { | ||
debug("deletion of root directory?! " + path); | ||
return; | ||
} | ||
} | ||
debug("delete directory tree " + start); | ||
try (var stream = Files.walk(start)) { | ||
var files = stream.sorted((p, q) -> -p.compareTo(q)); | ||
for (var file : files.toArray(Path[]::new)) Files.deleteIfExists(file); | ||
} | ||
} | ||
|
||
static void unzip(Path zip, Path dir, int sub) throws Exception { | ||
debug("<< %s".formatted(zip.toUri())); | ||
debug(">> %s".formatted(dir.toUri())); | ||
var files = new ArrayList<Path>(); | ||
try (var fs = FileSystems.newFileSystem(zip)) { | ||
for (var root : fs.getRootDirectories()) { | ||
try (var stream = Files.walk(root)) { | ||
var list = stream.filter(Files::isRegularFile).toList(); | ||
for (var file : list) { | ||
var relative = root.relativize(file); | ||
var source = sub == 0 ? relative : relative.subpath(sub, relative.getNameCount()); | ||
var target = dir.resolve(source.toString()); | ||
debug(">> - " + target.toUri()); | ||
Files.createDirectories(target.getParent()); | ||
Files.copy(file, target, StandardCopyOption.REPLACE_EXISTING); | ||
files.add(target); | ||
} | ||
} | ||
} | ||
} | ||
debug(">> %d files unzipped".formatted(files.size())); | ||
} | ||
} | ||
|
||
public static void main(String... args) throws Exception { | ||
installDefaultVersionIntoDefaultDirectory(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
# Bach's `src/bach.run` folder | ||
|
||
This folder contains Java source files (`.java`) and Java Shell scripts (`.jshell`) helping to install Bach. | ||
|
||
## Install default version of Bach | ||
|
||
```shell | ||
mkdir example && cd example | ||
jshell | ||
/open https://install.bach.run | ||
``` | ||
|
||
- https://install.bach.run forwards to the _"install default version of Bach into `.bach` directory of the current working directory"_ [Java Shell](install.jshell) script. | ||
|
||
Above's script is a shortcut for the following Java Shell commands and snippets. | ||
|
||
```shell | ||
/open https://src.bach.run/BachInstaller.java | ||
BachInstaller.installDefaultVersionIntoDefaultDirectory() | ||
/exit | ||
``` | ||
|
||
## Path forwarding | ||
|
||
- https://src.bach.run forwards to https://raw.githubusercontent.com/sormuras/bach/main/src/bach.run - resulting in `404: Not Found` | ||
- https://src.bach.run/install.jshell forwards to https://raw.githubusercontent.com/sormuras/bach/main/src/bach.run/install.jshell | ||
- https://src.bach.run/BachInstaller.java forwards to https://raw.githubusercontent.com/sormuras/bach/main/src/bach.run/BachInstaller.java | ||
- https://src.bach.run/Hello.java forwards to https://raw.githubusercontent.com/sormuras/bach/main/src/bach.run/Hello.java |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
/* | ||
* Copyright (c) 2024 Christian Stein | ||
* Licensed under the Universal Permissive License v 1.0 -> https://opensource.org/license/upl | ||
*/ | ||
|
||
System.out.printf( | ||
""" | ||
___ ___ ___ ___ | ||
/\\ \\ /\\ \\ /\\ \\ /\\__\\ | ||
/::\\ \\ /::\\ \\ /::\\ \\ /:/__/_ | ||
/::\\:\\__\\/::\\:\\__\\/:/\\:\\__\\/::\\/\\__\\ | ||
\\:\\::/ /\\/\\::/ /\\:\\ \\/__/\\/\\::/ / Java %s | ||
\\::/ / /:/ / \\:\\__\\ /:/ / %s | ||
\\/__/ \\/__/ \\/__/ \\/__/ %s | ||
""", | ||
Runtime.version(), | ||
System.getProperty("os.name"), | ||
Path.of("").toUri() | ||
) | ||
|
||
System.out.println("| Source Bach's installer from https://src.bach.run/BachInstaller.java ...") | ||
|
||
/open https://src.bach.run/BachInstaller.java | ||
|
||
int code = 0 | ||
try { | ||
BachInstaller.installDefaultVersionIntoDefaultDirectory(); | ||
} | ||
catch(Throwable throwable) { | ||
System.err.println(throwable); | ||
code = 1; | ||
} | ||
|
||
System.out.println("| Installation of Bach finished with exit code " + code) | ||
|
||
/exit code |