From 21f2d3407d29cdf8f9825c89f594488ae5811834 Mon Sep 17 00:00:00 2001 From: Matyrobbrt <65940752+Matyrobbrt@users.noreply.github.com> Date: Wed, 3 Jan 2024 14:25:35 +0200 Subject: [PATCH] Add progress reporters (#1) --- .gitignore | 2 +- build.gradle | 16 ++- cli-utils/build.gradle | 18 +++ .../cliutils/progress/ProgressActionType.java | 31 +++++ .../progress/ProgressInterceptor.java | 67 ++++++++++ .../cliutils/progress/ProgressManager.java | 32 +++++ .../cliutils/progress/ProgressReporter.java | 114 ++++++++++++++++++ .../cliutils/test/TestProgressManager.java | 107 ++++++++++++++++ jarsplitter/build.gradle | 3 + .../neoforged/jarsplitter/ConsoleTool.java | 50 ++++++-- settings.gradle | 1 + .../installertools/BundlerExtract.java | 16 ++- .../installertools/DownloadMojmaps.java | 4 +- .../installertools/ExtractFiles.java | 40 ++---- .../installertools/ExtractInheritance.java | 14 ++- .../net/neoforged/installertools/Task.java | 4 + 16 files changed, 469 insertions(+), 50 deletions(-) create mode 100644 cli-utils/build.gradle create mode 100644 cli-utils/src/main/java/net/neoforged/cliutils/progress/ProgressActionType.java create mode 100644 cli-utils/src/main/java/net/neoforged/cliutils/progress/ProgressInterceptor.java create mode 100644 cli-utils/src/main/java/net/neoforged/cliutils/progress/ProgressManager.java create mode 100644 cli-utils/src/main/java/net/neoforged/cliutils/progress/ProgressReporter.java create mode 100644 cli-utils/src/test/java/net/neoforged/cliutils/test/TestProgressManager.java diff --git a/.gitignore b/.gitignore index a562d73..cfed60d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ /.gradle/ /.idea/ -/build/ +build/ /repo/ /.settings/ /bin/ diff --git a/build.gradle b/build.gradle index 28d5041..9629977 100644 --- a/build.gradle +++ b/build.gradle @@ -11,7 +11,9 @@ allprojects { apply plugin: 'maven-publish' apply plugin: 'java-library' apply plugin: 'net.neoforged.gradleutils' - apply plugin: 'com.github.johnrengelman.shadow' + if (project.name != 'cli-utils') { + apply plugin: 'com.github.johnrengelman.shadow' + } group = 'net.neoforged.installertools' java { @@ -34,10 +36,15 @@ allprojects { tasks.named('jar', Jar).configure { manifest.attributes('Implementation-Version': project.version) - manifest.attributes('Main-Class': application.mainClass.get()) + if (application.mainClass.getOrNull()) { + manifest.attributes('Main-Class': application.mainClass.get()) + } } - tasks.named('shadowJar', ShadowJar).configure { - archiveClassifier = 'fatjar' + + if (project.name != 'cli-utils') { + tasks.named('shadowJar', ShadowJar).configure { + archiveClassifier = 'fatjar' + } } } @@ -61,6 +68,7 @@ dependencies { implementation 'de.siegmar:fastcsv:2.0.0' implementation 'net.neoforged:srgutils:1.0.0' implementation 'org.ow2.asm:asm-commons:9.3' + implementation project(':cli-utils') } publishing { diff --git a/cli-utils/build.gradle b/cli-utils/build.gradle new file mode 100644 index 0000000..35108a9 --- /dev/null +++ b/cli-utils/build.gradle @@ -0,0 +1,18 @@ +dependencies { + testImplementation('org.junit.jupiter:junit-jupiter-api:5.8.2') + testImplementation('org.junit.jupiter:junit-jupiter-engine:5.8.2') +} + +test { + useJUnitPlatform() +} + +publishing { + publications.register('mavenJava', MavenPublication) { + from components.java + pom { + name = 'CLI Utils' + description = "CLI Utilities for NeoForge's projects" + } + } +} diff --git a/cli-utils/src/main/java/net/neoforged/cliutils/progress/ProgressActionType.java b/cli-utils/src/main/java/net/neoforged/cliutils/progress/ProgressActionType.java new file mode 100644 index 0000000..461c53d --- /dev/null +++ b/cli-utils/src/main/java/net/neoforged/cliutils/progress/ProgressActionType.java @@ -0,0 +1,31 @@ +package net.neoforged.cliutils.progress; + +import java.util.Arrays; +import java.util.Map; +import java.util.function.BiConsumer; +import java.util.function.Function; +import java.util.stream.Collectors; + +public enum ProgressActionType { + STEP('s', ProgressManager::setStep), + PROGRESS('p', (progressManager, value) -> { + if (value.endsWith("%")) { + progressManager.setPercentageProgress(Double.parseDouble(value.substring(0, value.length() - 1))); + } else { + progressManager.setProgress(Integer.parseInt(value)); + } + }), + MAX_PROGRESS('m', (progressManager, value) -> progressManager.setMaxProgress(Integer.parseInt(value))), + INDETERMINATE('i', (progressManager, value) -> progressManager.setIndeterminate(Boolean.parseBoolean(value))); + + public static final Map TYPES = Arrays.stream(values()) + .collect(Collectors.toMap(val -> val.identifier, Function.identity())); + + public final char identifier; + public final BiConsumer acceptor; + + ProgressActionType(char identifier, BiConsumer acceptor) { + this.identifier = identifier; + this.acceptor = acceptor; + } +} diff --git a/cli-utils/src/main/java/net/neoforged/cliutils/progress/ProgressInterceptor.java b/cli-utils/src/main/java/net/neoforged/cliutils/progress/ProgressInterceptor.java new file mode 100644 index 0000000..cdd7b7d --- /dev/null +++ b/cli-utils/src/main/java/net/neoforged/cliutils/progress/ProgressInterceptor.java @@ -0,0 +1,67 @@ +package net.neoforged.cliutils.progress; + +import java.io.FilterOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; + +/** + * Intercepts {@link ProgressActionType} progress manager actions and redirects them to the {@code manager}. + */ +public class ProgressInterceptor extends FilterOutputStream { + public static final String FULL_MODIFIER = "\033[" + ProgressReporter.MODIFIER_KEY + ";"; + + protected final ProgressManager manager; + public ProgressInterceptor(OutputStream out, ProgressManager manager) { + super(out); + this.manager = manager; + } + + private StringBuffer current; + + @Override + public void write(int b) throws IOException { + if (current != null) { + if (b == '\n') { + processCurrent(); + } else if (b != '\r') // Ignore CR because Windows is bad + current.append((char)b); + } else { + if (b == '\033') { + current = new StringBuffer() + .append((char)b); + } else { + out.write(b); + } + } + } + + private void processCurrent() throws IOException { + final String cur = current.toString(); + if (cur.startsWith(FULL_MODIFIER)) { + final String[] values = cur.substring(FULL_MODIFIER.length()).split(" ", 2); + // If not 2, the value's empty, which isn't supported, so ignore + if (values.length == 2) { + final String first = values[0]; + if (first.length() != 1) { + System.err.println("Invalid progress modifier: " + values[0]); + return; + } + + final ProgressActionType action = ProgressActionType.TYPES.get(first.charAt(0)); + if (action == null) { + System.err.println("Unknown progress modifier: " + first.charAt(0)); + return; + } + + action.acceptor.accept(manager, values[1]); + } + } else { + out.write(cur.getBytes(StandardCharsets.UTF_8)); + out.write(System.lineSeparator().getBytes(StandardCharsets.UTF_8)); + } + + current = null; + } +} diff --git a/cli-utils/src/main/java/net/neoforged/cliutils/progress/ProgressManager.java b/cli-utils/src/main/java/net/neoforged/cliutils/progress/ProgressManager.java new file mode 100644 index 0000000..7433b27 --- /dev/null +++ b/cli-utils/src/main/java/net/neoforged/cliutils/progress/ProgressManager.java @@ -0,0 +1,32 @@ +package net.neoforged.cliutils.progress; + +/** + * A manager that changes the progress of a progress bar, to indicate the current progress to users. + */ +public interface ProgressManager { + /** + * Sets the max progress of the manager. + */ + void setMaxProgress(int maxProgress); + + /** + * Sets the current progress of the manager. + */ + void setProgress(int progress); + + /** + * Sets progress of the manager, based on a fractional value.
+ * Note: this also sets the {@link #setMaxProgress(int)} to {@literal 100}. + */ + void setPercentageProgress(double progress); + + /** + * Sets the current step to be shown to the user. + */ + void setStep(String name); + + /** + * Sets whether the max progress is known or not. If not, the loading bar will load 'forever'. + */ + void setIndeterminate(boolean indeterminate); +} diff --git a/cli-utils/src/main/java/net/neoforged/cliutils/progress/ProgressReporter.java b/cli-utils/src/main/java/net/neoforged/cliutils/progress/ProgressReporter.java new file mode 100644 index 0000000..339cc9d --- /dev/null +++ b/cli-utils/src/main/java/net/neoforged/cliutils/progress/ProgressReporter.java @@ -0,0 +1,114 @@ +package net.neoforged.cliutils.progress; + +import java.io.FilterInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintStream; +import java.net.URLConnection; +import java.text.DecimalFormat; + +/** + * A {@link ProgressManager} that forwards all changes to a {@link ProgressReporter#output print stream} + * that writes the changes with an ANSI modifier {@value #MODIFIER_KEY}.
+ * The ANSI modifier takes the form "\033[{@literal progressmanager};action value".

+ * The {@link #getDefault() default reporter} will only be enabled if the {@value #ENABLED_PROPERTY} system property is set to {@code true}, + * and will output to {@link System#err}. + * @see ProgressActionType for the actions + */ +public class ProgressReporter implements ProgressManager { + public static final String MODIFIER_KEY = "progressmanager"; + public static final String ENABLED_PROPERTY = "net.neoforged.progressmanager.enabled"; + private static final DecimalFormat TWO_DECIMALS = new DecimalFormat("#.00"); + + protected final boolean enabled; + protected final PrintStream output; + + public ProgressReporter(boolean enabled, PrintStream output) { + this.enabled = enabled; + this.output = output; + } + + public static ProgressReporter getDefault() { + return new ProgressReporter(Boolean.getBoolean(ENABLED_PROPERTY), System.err); + } + + @Override + public void setMaxProgress(int maxProgress) { + write(ProgressActionType.MAX_PROGRESS, String.valueOf(maxProgress)); + } + + @Override + public void setProgress(int progress) { + write(ProgressActionType.PROGRESS, String.valueOf(progress)); + } + + @Override + public void setPercentageProgress(double progress) { + write(ProgressActionType.PROGRESS, TWO_DECIMALS.format(progress) + "%"); + } + + @Override + public void setStep(String name) { + write(ProgressActionType.STEP, name); + } + + @Override + public void setIndeterminate(boolean indeterminate) { + write(ProgressActionType.INDETERMINATE, String.valueOf(indeterminate)); + } + + protected void write(ProgressActionType type, String value) { + if (!enabled) return; + + try { + //noinspection RedundantStringFormatCall + output.println(String.format("\033[%s;%s %s", MODIFIER_KEY, type.identifier, value)); + } catch (Exception exception) { + exception.printStackTrace(System.err); + System.err.println("Failed to write progress: " + exception); + } + } + + public InputStream wrapDownload(URLConnection connection) throws IOException { + connection.connect(); + setMaxProgress(connection.getContentLength()); + return wrapDownload(connection.getInputStream()); + } + + public InputStream wrapDownload(InputStream in) { + return new FilterInputStream(in) { + private int nread = 0; + + @Override + public int read() throws IOException { + int c = in.read(); + if (c >= 0) setProgress(++nread); + return c; + } + + + @Override + public int read(byte[] b) throws IOException { + int nr = in.read(b); + if (nr > 0) setProgress(nread += nr); + return nr; + } + + + @Override + public int read(byte[] b, int off, int len) throws IOException { + int nr = in.read(b, off, len); + if (nr > 0) setProgress(nread += nr); + return nr; + } + + + @Override + public long skip(long n) throws IOException { + long nr = in.skip(n); + if (nr > 0) setProgress(nread += nr); + return nr; + } + }; + } +} diff --git a/cli-utils/src/test/java/net/neoforged/cliutils/test/TestProgressManager.java b/cli-utils/src/test/java/net/neoforged/cliutils/test/TestProgressManager.java new file mode 100644 index 0000000..a683d97 --- /dev/null +++ b/cli-utils/src/test/java/net/neoforged/cliutils/test/TestProgressManager.java @@ -0,0 +1,107 @@ +package net.neoforged.cliutils.test; + +import net.neoforged.cliutils.progress.ProgressInterceptor; +import net.neoforged.cliutils.progress.ProgressManager; +import net.neoforged.cliutils.progress.ProgressReporter; +import org.junit.jupiter.api.Test; + +import java.io.OutputStream; +import java.io.PrintStream; +import java.io.StringWriter; + +public class TestProgressManager { + + @Test + void testStep() { + final TestSuite suite = new TestSuite(); + suite.in.setStep("Doing stuff"); + assert suite.out.step.equals("Doing stuff"); + assert suite.allowedOut.toString().isEmpty(); + } + + @Test + void testMaxProgress() { + final TestSuite suite = new TestSuite(); + suite.in.setMaxProgress(10); + assert suite.out.maxProgress == 10; + } + + @Test + void testPercentageProgress() { + final TestSuite suite = new TestSuite(); + suite.in.setPercentageProgress(0.11); + assert suite.out.maxProgress == 100; + assert suite.out.progress == 11; + } + + @Test + void testProgress() { + final TestSuite suite = new TestSuite(); + suite.in.setProgress(145); + assert suite.out.progress == 145; + } + + @Test + void testIndeterminate() { + final TestSuite suite = new TestSuite(); + suite.in.setIndeterminate(true); + assert suite.out.indeterminate; + } + + @Test + void testWriteIsForwarded() { + final TestSuite suite = new TestSuite(); + + suite.in.setProgress(10); + assert suite.allowedOut.toString().isEmpty(); + + suite.stream.println("abcd"); + assert suite.allowedOut.toString().equals("abcd" + System.lineSeparator()); + + suite.stream.println("\033jkas"); + assert suite.allowedOut.toString().equals("abcd" + System.lineSeparator() + "\033jkas" + System.lineSeparator()); + } + + private static class TestSuite { + public final ProgressManagerImpl out = new ProgressManagerImpl(); + public final StringWriter allowedOut = new StringWriter(); + private final PrintStream stream = new PrintStream(new ProgressInterceptor(new OutputStream() { + @Override + public void write(int b) { + allowedOut.write(b); + } + }, out)); + public final ProgressManager in = new ProgressReporter(true, stream); + } + + private static class ProgressManagerImpl implements ProgressManager { + public int maxProgress = 0, progress = 0; + public boolean indeterminate = false; + public String step; + @Override + public void setMaxProgress(int maxProgress) { + this.maxProgress = maxProgress; + } + + @Override + public void setProgress(int progress) { + this.progress = progress; + } + + @Override + public void setPercentageProgress(double progress) { + if (maxProgress != 100) setMaxProgress(100); + setProgress((int) (progress * 100)); + } + + @Override + public void setStep(String name) { + this.step = name; + } + + @Override + public void setIndeterminate(boolean indeterminate) { + this.indeterminate = indeterminate; + } + } +} diff --git a/jarsplitter/build.gradle b/jarsplitter/build.gradle index 3e025e4..041b953 100644 --- a/jarsplitter/build.gradle +++ b/jarsplitter/build.gradle @@ -1,6 +1,9 @@ +evaluationDependsOn(':cli-utils') + dependencies { implementation 'net.sf.jopt-simple:jopt-simple:5.0.4' implementation 'net.neoforged:srgutils:1.0.0' + implementation project(':cli-utils') } application { diff --git a/jarsplitter/src/main/java/net/neoforged/jarsplitter/ConsoleTool.java b/jarsplitter/src/main/java/net/neoforged/jarsplitter/ConsoleTool.java index 33f4d56..1489aa7 100644 --- a/jarsplitter/src/main/java/net/neoforged/jarsplitter/ConsoleTool.java +++ b/jarsplitter/src/main/java/net/neoforged/jarsplitter/ConsoleTool.java @@ -11,13 +11,17 @@ import java.io.InputStream; import java.io.OutputStream; import java.math.BigInteger; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; import java.nio.file.Files; +import java.nio.file.Path; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Arrays; import java.util.HashSet; import java.util.Set; import java.util.TimeZone; +import java.util.stream.Stream; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import java.util.zip.ZipOutputStream; @@ -26,12 +30,16 @@ import joptsimple.OptionParser; import joptsimple.OptionSet; import joptsimple.OptionSpec; +import net.neoforged.cliutils.progress.ProgressManager; +import net.neoforged.cliutils.progress.ProgressReporter; import net.neoforged.srgutils.IMappingFile; public class ConsoleTool { private static final OutputStream NULL_OUTPUT = new OutputStream() { - @Override public void write(int b) throws IOException {} + @Override public void write(int b) {} }; + private static final boolean DEBUG = Boolean.getBoolean("net.neoforged.jarsplitter.debug"); + private static final ProgressManager PROGRESS = ProgressReporter.getDefault(); public static void main(String[] args) throws IOException { TimeZone.setDefault(TimeZone.getTimeZone("GMT")); //Fix Java stupidity that causes timestamps in zips to depend on user's timezone! @@ -89,8 +97,12 @@ public static void main(String[] args) throws IOException { return; } - log("Splitting: "); - try (ZipInputStream zinput = new ZipInputStream(new FileInputStream(input)); + final int fileAmount = getCountInZip(input); + PROGRESS.setMaxProgress(fileAmount); + log("Splitting " + fileAmount + " files:"); + + int amount = 0; + try (ZipInputStream zinput = new ZipInputStream(Files.newInputStream(input.toPath())); ZipOutputStream zslim = new ZipOutputStream(slim == null ? NULL_OUTPUT : new FileOutputStream(slim)); ZipOutputStream zdata = new ZipOutputStream(data == null ? NULL_OUTPUT : new FileOutputStream(data)); ZipOutputStream zextra = new ZipOutputStream(extra == null ? NULL_OUTPUT : new FileOutputStream(extra))) { @@ -101,18 +113,25 @@ public static void main(String[] args) throws IOException { String key = entry.getName().substring(0, entry.getName().length() - 6); //String .class if (whitelist.isEmpty() || whitelist.contains(key)) { - log(" Slim " + entry.getName()); + debug(" Slim " + entry.getName()); copy(entry, zinput, zslim); } else { - log(" Extra " + entry.getName()); + debug(" Extra " + entry.getName()); copy(entry, zinput, zextra); } } else { - log(" Data " + entry.getName()); + debug(" Data " + entry.getName()); copy(entry, zinput, merge ? zextra : zdata); } + + // To avoid spam, only change the progress every 10 files processed + if ((++amount) % 10 == 0) { + PROGRESS.setProgress(amount); + } } } + PROGRESS.setProgress(fileAmount); + writeCache(slim, inputSha, srgSha); writeCache(data, inputSha, srgSha); writeCache(extra, inputSha, srgSha); @@ -177,7 +196,13 @@ public static void log(String message) { System.out.println(message); } - private static String sha1(Set data) throws IOException { + public static void debug(String message) { + if (DEBUG) { + log(message); + } + } + + private static String sha1(Set data) { if (data.isEmpty()) return "empty"; @@ -201,8 +226,8 @@ private static String sha1(File path, boolean allowCache) throws IOException { try { MessageDigest digest = MessageDigest.getInstance("SHA-1"); - try(InputStream input = new FileInputStream(path)) { - int read = -1; + try (InputStream input = Files.newInputStream(path.toPath())) { + int read; while ((read = input.read(BUFFER)) != -1) digest.update(BUFFER, 0, read); return new BigInteger(1, digest.digest()).toString(16); @@ -211,4 +236,11 @@ private static String sha1(File path, boolean allowCache) throws IOException { throw new RuntimeException(e); } } + + private static int getCountInZip(File path) throws IOException { + try (FileSystem fs = FileSystems.newFileSystem(path.toPath(), null); final Stream count = Files.find(fs.getPath("."), Integer.MAX_VALUE, (p, basicFileAttributes) -> Files.isRegularFile(p))) { + final long c = count.count(); + return c > (long) Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) c; + } + } } diff --git a/settings.gradle b/settings.gradle index f57b959..af163b7 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1,2 @@ +include(':cli-utils') include(':jarsplitter') diff --git a/src/main/java/net/neoforged/installertools/BundlerExtract.java b/src/main/java/net/neoforged/installertools/BundlerExtract.java index 16e0bc6..2c5340a 100644 --- a/src/main/java/net/neoforged/installertools/BundlerExtract.java +++ b/src/main/java/net/neoforged/installertools/BundlerExtract.java @@ -89,6 +89,8 @@ public void process(String[] args) throws IOException { FileList libraries = FileList.read(fs.getPath("META-INF", "libraries.list")); FileList versions = FileList.read(fs.getPath("META-INF", "versions.list")); + int amount = 0; + if (jarOnly) { FileList.Entry entry = null; for (FileList.Entry e : versions.entries) { @@ -106,16 +108,24 @@ public void process(String[] args) throws IOException { if (output.exists() && output.isFile()) error("Can not extract to " + output + " as it is a file, not a directory"); - for (FileList.Entry entry : libraries.entries) + PROGRESS.setMaxProgress(libraries.entries.size()); + for (FileList.Entry entry : libraries.entries) { extractFile("libraries", fs, entry, new File(output, entry.path)); + PROGRESS.setProgress(++amount); + } } else if (all) { if (output.exists() && output.isFile()) error("Can not extract to " + output + " as it is a file, not a directory"); - for (FileList.Entry entry : libraries.entries) + PROGRESS.setMaxProgress(libraries.entries.size() + versions.entries.size()); + for (FileList.Entry entry : libraries.entries) { extractFile("libraries", fs, entry, new File(output, "libraries/" + entry.path)); - for (FileList.Entry entry : versions.entries) + PROGRESS.setProgress(++amount); + } + for (FileList.Entry entry : versions.entries) { extractFile("versions", fs, entry, new File(output, "versions/" + entry.path)); + PROGRESS.setProgress(++amount); + } } else { error("Must specify either --jar only, or --all"); } diff --git a/src/main/java/net/neoforged/installertools/DownloadMojmaps.java b/src/main/java/net/neoforged/installertools/DownloadMojmaps.java index b14c68e..35d4988 100644 --- a/src/main/java/net/neoforged/installertools/DownloadMojmaps.java +++ b/src/main/java/net/neoforged/installertools/DownloadMojmaps.java @@ -32,6 +32,7 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.net.URL; +import java.net.URLConnection; import java.nio.file.Files; public class DownloadMojmaps extends Task { @@ -76,7 +77,8 @@ public void process(String[] args) throws IOException { if (download == null || download.url == null) error("Missing download info for " + side + " mappings"); - Files.copy(download.url.openStream(), output.toPath()); + final URLConnection connection = download.url.openConnection(); + Files.copy(PROGRESS.wrapDownload(connection), output.toPath()); log("Downloaded Mojang mappings for " + mcversion); } } diff --git a/src/main/java/net/neoforged/installertools/ExtractFiles.java b/src/main/java/net/neoforged/installertools/ExtractFiles.java index 25d962d..b86d5e4 100644 --- a/src/main/java/net/neoforged/installertools/ExtractFiles.java +++ b/src/main/java/net/neoforged/installertools/ExtractFiles.java @@ -57,31 +57,21 @@ public void process(String[] args) throws IOException { List execs = options.valuesOf(execsO); List optional = options.valuesOf(optionalO).stream().map(File::getAbsolutePath).collect(Collectors.toList()); - /* - Map tokens = new HashMap<>(); - String prev = null; - for (String s : options.valuesOf(tokensO)) { - if (prev == null) { - prev = s; - } else { - tokens.put(prev, s); - prev = null; - } - } - */ - log("Archive: " + archive); for (int x = 0; x < from.size(); x++) { - log("Extract: " + from.get(x)); - log(" " + to.get(x)); + log("Extract: " + from.get(x)); + log(" " + to.get(x)); } - for (int x = 0; x < execs.size(); x++) { - log("Exec: " + execs.get(x)); + for (File file : execs) { + log("Exec: " + file); } if (!archive.exists()) error("Could not find archive: " + archive); + PROGRESS.setMaxProgress(from.size() + execs.size()); + int amount = 0; + try (FileSystem fs = FileSystems.newFileSystem(archive.toPath(), null)) { for (int x = 0; x < from.size(); x++) { Path path = fs.getPath(from.get(x)); @@ -95,26 +85,14 @@ public void process(String[] args) throws IOException { if (!optional.contains(toF.getAbsolutePath()) || !toF.exists()) Files.copy(path, toF.toPath(), StandardCopyOption.REPLACE_EXISTING); - /* - if (filesReplace != null && filesReplace.contains(file)) { - List lines = Files.readAllLines(path).stream() - .map(s -> { - for (Map.Entry entry : tokens.entrySet()) { - s = s.replace(entry.getKey(), entry.getValue()); - } - return s; - }).collect(Collectors.toList()); - Files.write(copyTo, lines); - } else { - Files.copy(path, copyTo, StandardCopyOption.REPLACE_EXISTING); - } - */ + PROGRESS.setProgress(++amount); } } for (File exec : execs) { if (!exec.setExecutable(true)) log("Couldn't set executable bit for file: " + exec.getAbsolutePath()); + PROGRESS.setProgress(++amount); } } catch (OptionException e) { parser.printHelpOn(System.out); diff --git a/src/main/java/net/neoforged/installertools/ExtractInheritance.java b/src/main/java/net/neoforged/installertools/ExtractInheritance.java index 2ee6b6a..f14219a 100644 --- a/src/main/java/net/neoforged/installertools/ExtractInheritance.java +++ b/src/main/java/net/neoforged/installertools/ExtractInheritance.java @@ -82,6 +82,9 @@ public void process(String[] args) throws IOException { OptionSpec libraryO = parser.accepts("lib").withRequiredArg().ofType(File.class); OptionSpec annotationsO = parser.accepts("annotations"); + // We don't know how long reading the jars will take + PROGRESS.setIndeterminate(true); + try { OptionSet options = parser.parse(args); @@ -108,8 +111,17 @@ public void process(String[] args) throws IOException { readJar(lib, libClasses, annotations); } - for (Entry entry : inClasses.entrySet()) + PROGRESS.setIndeterminate(false); + PROGRESS.setMaxProgress(inClasses.size()); + + int am = 0; + for (Entry entry : inClasses.entrySet()) { resolveClass(entry.getValue(), annotations); + if ((++am) % 10 == 0) { + PROGRESS.setProgress(am); + } + } + PROGRESS.setProgress(am); Files.write(output.toPath(), GSON.toJson(inClasses).getBytes(StandardCharsets.UTF_8)); diff --git a/src/main/java/net/neoforged/installertools/Task.java b/src/main/java/net/neoforged/installertools/Task.java index 70057f7..fd95d5b 100644 --- a/src/main/java/net/neoforged/installertools/Task.java +++ b/src/main/java/net/neoforged/installertools/Task.java @@ -18,9 +18,13 @@ */ package net.neoforged.installertools; +import net.neoforged.cliutils.progress.ProgressReporter; + import java.io.IOException; public abstract class Task { + protected static final ProgressReporter PROGRESS = ProgressReporter.getDefault(); + public abstract void process(String[] args) throws IOException; protected void error(String message) {