mirror of
https://github.com/nix-community/nix-on-droid-app.git
synced 2025-11-08 19:46:10 +01:00
installer: use offline bootstraps
This commit is contained in:
parent
bd45837d93
commit
d3d8aebd1c
2 changed files with 68 additions and 38 deletions
|
|
@ -35,3 +35,10 @@ android {
|
||||||
dependencies {
|
dependencies {
|
||||||
testImplementation 'junit:junit:4.12'
|
testImplementation 'junit:junit:4.12'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
preBuild.doFirst {
|
||||||
|
assert file("./src/main/assets/bootstrap-aarch64").exists()
|
||||||
|
assert file("./src/main/assets/bootstrap-arm").exists()
|
||||||
|
assert file("./src/main/assets/bootstrap-i686").exists()
|
||||||
|
assert file("./src/main/assets/bootstrap-x86_64").exists()
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import android.app.Activity;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.app.ProgressDialog;
|
import android.app.ProgressDialog;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.res.AssetManager;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
import android.os.UserManager;
|
import android.os.UserManager;
|
||||||
|
|
@ -79,52 +80,74 @@ final class TermuxInstaller {
|
||||||
deleteFolder(STAGING_PREFIX_FILE);
|
deleteFolder(STAGING_PREFIX_FILE);
|
||||||
}
|
}
|
||||||
|
|
||||||
final byte[] buffer = new byte[8096];
|
final byte[] buffer = new byte[16384];
|
||||||
final List<Pair<String, String>> symlinks = new ArrayList<>(50);
|
final List<Pair<String, String>> symlinks = new ArrayList<>(128);
|
||||||
|
final List<String> executables = new ArrayList<>(128);
|
||||||
|
|
||||||
final URL zipUrl = determineZipUrl();
|
final String bootstrapArchiveName = determineZipName();
|
||||||
try (ZipInputStream zipInput = new ZipInputStream(zipUrl.openStream())) {
|
AssetManager assetManager = activity.getAssets();
|
||||||
|
|
||||||
|
try (ZipInputStream zipInput = new ZipInputStream(assetManager.open(bootstrapArchiveName))) {
|
||||||
ZipEntry zipEntry;
|
ZipEntry zipEntry;
|
||||||
while ((zipEntry = zipInput.getNextEntry()) != null) {
|
while ((zipEntry = zipInput.getNextEntry()) != null) {
|
||||||
if (zipEntry.getName().equals("SYMLINKS.txt")) {
|
switch (zipEntry.getName()) {
|
||||||
BufferedReader symlinksReader = new BufferedReader(new InputStreamReader(zipInput));
|
case "EXECUTABLES.txt": {
|
||||||
String line;
|
BufferedReader executablesReader = new BufferedReader(new InputStreamReader(zipInput));
|
||||||
while ((line = symlinksReader.readLine()) != null) {
|
String line;
|
||||||
String[] parts = line.split("←");
|
while ((line = executablesReader.readLine()) != null) {
|
||||||
if (parts.length != 2)
|
executables.add(line);
|
||||||
throw new RuntimeException("Malformed symlink line: " + line);
|
}
|
||||||
String oldPath = parts[0];
|
break;
|
||||||
String newPath = STAGING_PREFIX_PATH + "/" + parts[1];
|
|
||||||
symlinks.add(Pair.create(oldPath, newPath));
|
|
||||||
|
|
||||||
ensureDirectoryExists(new File(newPath).getParentFile());
|
|
||||||
}
|
}
|
||||||
} else {
|
case "SYMLINKS.txt": {
|
||||||
String zipEntryName = zipEntry.getName();
|
BufferedReader symlinksReader = new BufferedReader(new InputStreamReader(zipInput));
|
||||||
File targetFile = new File(STAGING_PREFIX_PATH, zipEntryName);
|
String line;
|
||||||
boolean isDirectory = zipEntry.isDirectory();
|
while ((line = symlinksReader.readLine()) != null) {
|
||||||
|
String[] parts = line.split("←");
|
||||||
ensureDirectoryExists(isDirectory ? targetFile : targetFile.getParentFile());
|
if (parts.length != 2)
|
||||||
|
throw new RuntimeException("Malformed symlink line: " + line);
|
||||||
if (!isDirectory) {
|
String oldPath = parts[0];
|
||||||
try (FileOutputStream outStream = new FileOutputStream(targetFile)) {
|
String newPath = STAGING_PREFIX_PATH + "/" + parts[1];
|
||||||
int readBytes;
|
symlinks.add(Pair.create(oldPath, newPath));
|
||||||
while ((readBytes = zipInput.read(buffer)) != -1)
|
ensureDirectoryExists(new File(newPath).getParentFile());
|
||||||
outStream.write(buffer, 0, readBytes);
|
|
||||||
}
|
}
|
||||||
if (zipEntryName.startsWith("bin/") || zipEntryName.startsWith("libexec") || zipEntryName.startsWith("lib/apt/methods")) {
|
break;
|
||||||
//noinspection OctalInteger
|
}
|
||||||
Os.chmod(targetFile.getAbsolutePath(), 0700);
|
default: {
|
||||||
|
String zipEntryName = zipEntry.getName();
|
||||||
|
File targetFile = new File(STAGING_PREFIX_PATH, zipEntryName);
|
||||||
|
boolean isDirectory = zipEntry.isDirectory();
|
||||||
|
|
||||||
|
ensureDirectoryExists(isDirectory ? targetFile : targetFile.getParentFile());
|
||||||
|
|
||||||
|
if (!isDirectory) {
|
||||||
|
try (FileOutputStream outStream = new FileOutputStream(targetFile)) {
|
||||||
|
int readBytes;
|
||||||
|
while ((readBytes = zipInput.read(buffer)) != -1)
|
||||||
|
outStream.write(buffer, 0, readBytes);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (symlinks.isEmpty())
|
if (!executables.isEmpty()) {
|
||||||
throw new RuntimeException("No SYMLINKS.txt encountered");
|
for (String executable : executables) {
|
||||||
for (Pair<String, String> symlink : symlinks) {
|
//noinspection OctalInteger
|
||||||
Os.symlink(symlink.first, symlink.second);
|
Os.chmod(STAGING_PREFIX_PATH + "/" + executable, 0700);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("Installer: no EXECUTABLES.txt found while extracting environment archive.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!symlinks.isEmpty()) {
|
||||||
|
for (Pair<String, String> symlink : symlinks) {
|
||||||
|
Os.symlink(symlink.first, symlink.second);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("Installer: no SYMLINKS.txt found while extracting environment archive.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!STAGING_PREFIX_FILE.renameTo(PREFIX_FILE)) {
|
if (!STAGING_PREFIX_FILE.renameTo(PREFIX_FILE)) {
|
||||||
|
|
@ -167,10 +190,10 @@ final class TermuxInstaller {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Get bootstrap zip url for this systems cpu architecture. */
|
/** Get bootstrap zip file name for this systems cpu architecture. */
|
||||||
private static URL determineZipUrl() throws MalformedURLException {
|
private static String determineZipName() {
|
||||||
String archName = determineTermuxArchName();
|
String archName = determineTermuxArchName();
|
||||||
return new URL("https://termux.net/bootstrap/bootstrap-" + archName + ".zip");
|
return "bootstrap-" + archName;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String determineTermuxArchName() {
|
private static String determineTermuxArchName() {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue