From a1323c5ec0e11324ee4a0ba2f1238b75273615e4 Mon Sep 17 00:00:00 2001 From: Tako Schotanus Date: Tue, 20 Jan 2026 22:17:35 +0100 Subject: [PATCH] fix: No longer showing stack traces by default Added -v/--verbose flags that will show stack traces when enabled. Fixes #96 --- src/main/java/org/codejive/jpm/Main.java | 35 +++++++++++++++++++- src/test/java/org/codejive/jpm/MainTest.java | 14 +++++++- 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/codejive/jpm/Main.java b/src/main/java/org/codejive/jpm/Main.java index 2670097..6f6c031 100644 --- a/src/main/java/org/codejive/jpm/Main.java +++ b/src/main/java/org/codejive/jpm/Main.java @@ -61,6 +61,10 @@ }) public class Main { + static boolean verbose = false; + + @Mixin VerboseMixin verboseMixin; + @Command( name = "copy", aliases = {"c"}, @@ -69,6 +73,7 @@ public class Main { + "By default jpm will try to create symbolic links to conserve space.\n\n" + "Example:\n jpm copy org.apache.httpcomponents:httpclient:4.5.14\n") static class Copy implements Callable { + @Mixin VerboseMixin verboseMixin; @Mixin QuietMixin quietMixin; @Mixin ArtifactsMixin artifactsMixin; @@ -107,6 +112,7 @@ public Integer call() throws Exception { + "match the given (partial) name.\n\n" + "Example:\n jpm search httpclient\n") static class Search implements Callable { + @Mixin VerboseMixin verboseMixin; @Mixin QuietMixin quietMixin; @Mixin DepsMixin depsMixin; @@ -290,6 +296,7 @@ private static String getSelectedId( + "If no artifacts are passed the app.yml file will be left untouched and only the existing dependencies in the file will be copied.\n\n" + "Example:\n jpm install org.apache.httpcomponents:httpclient:4.5.14\n") static class Install implements Callable { + @Mixin VerboseMixin verboseMixin; @Mixin QuietMixin quietMixin; @Mixin OptionalArtifactsMixin optionalArtifactsMixin; @@ -318,6 +325,7 @@ public Integer call() throws Exception { + "If no artifacts are passed the classpath for the dependencies defined in the app.yml file will be printed instead.\n\n" + "Example:\n jpm path org.apache.httpcomponents:httpclient:4.5.14\n") static class PrintPath implements Callable { + @Mixin VerboseMixin verboseMixin; @Mixin OptionalArtifactsMixin optionalArtifactsMixin; @Override @@ -367,6 +375,7 @@ public Integer call() throws Exception { + " jpm exec javac -cp {{deps}} -d out/classes --source-path src/main/java App.java\n" + " jpm exec @kotlinc -cp {{deps}} -d out/classes src/main/kotlin/App.kt\n") static class Exec implements Callable { + @Mixin VerboseMixin verboseMixin; @Mixin DepsMixin depsMixin; @Mixin QuietMixin quietMixin; @@ -403,6 +412,7 @@ public Integer call() throws Exception { + " jpm do test --arg verbose\n" + " jpm do build -a --fresh test -a verbose\n") static class Do implements Callable { + @Mixin VerboseMixin verboseMixin; @Mixin DepsMixin depsMixin; @Mixin QuietMixin quietMixin; @@ -496,6 +506,7 @@ public Integer call() throws Exception { } abstract static class DoAlias implements Callable { + @Mixin VerboseMixin verboseMixin; @Mixin DepsMixin depsMixin; @Unmatched List args = new ArrayList<>(); @@ -628,6 +639,15 @@ static class OptionalArtifactsMixin extends BaseArtifactsMixin { private String[] artifactNames = {}; } + static class VerboseMixin { + @Option( + names = {"-v", "--verbose"}, + description = "Enable verbose output for debugging") + public void setVerbose(boolean verbose) { + Main.verbose = verbose; + } + } + static class QuietMixin { @Option( names = {"-q", "--quiet"}, @@ -642,11 +662,24 @@ private static void printStats(SyncResult stats) { (Integer) stats.copied, (Integer) stats.updated, (Integer) stats.deleted); } + static CommandLine.IExecutionExceptionHandler errorHandler = + (ex, commandLine, parseResult) -> { + System.err.println("Error: " + ex.getMessage()); + if (verbose) { + ex.printStackTrace(); + } else { + System.err.println( + "(Run with --verbose for more details. If you believe you found a bug in jpm, open an issue at https://github.com/codejive/java-jpm/issues)"); + } + return commandLine.getCommandSpec().exitCodeOnExecutionException(); + }; + public static CommandLine getCommandLine() { return new CommandLine(new Main()) .setStopAtPositional(true) .setAllowOptionsAsOptionParameters(true) - .setAllowSubcommandsAsOptionParameters(true); + .setAllowSubcommandsAsOptionParameters(true) + .setExecutionExceptionHandler(errorHandler); } /** diff --git a/src/test/java/org/codejive/jpm/MainTest.java b/src/test/java/org/codejive/jpm/MainTest.java index 740d546..c977eb9 100644 --- a/src/test/java/org/codejive/jpm/MainTest.java +++ b/src/test/java/org/codejive/jpm/MainTest.java @@ -242,7 +242,7 @@ void testMainWithNoArgs() { int exitCode = cmd.execute(); assertThat(exitCode >= 0).isTrue(); // Should not be negative (internal error) assertThat(capture.getErr()).contains("Missing required subcommand"); - assertThat(capture.getErr()).contains("Usage: jpm [-hV] [COMMAND]"); + assertThat(capture.getErr()).contains("Usage: jpm [-hvV] [COMMAND]"); assertThat(capture.getErr()) .contains("Simple command line tool for managing Maven artifacts"); } @@ -290,4 +290,16 @@ private void createAppYmlWithoutBuildAction() throws IOException { + " hello: \"echo Hello World\"\n"; Files.writeString(tempDir.resolve("app.yml"), yamlContent); } + + @Test + void testVerboseFlag() { + try (TestOutputCapture capture = captureOutput()) { + CommandLine cmd = Main.getCommandLine(); + int exitCode = cmd.execute("--help"); + assertThat(exitCode).isEqualTo(0); + String output = capture.getOut(); + assertThat(output).contains("-v, --verbose"); + assertThat(output).contains("Enable verbose output for debugging"); + } + } }