From a830a0c1da2e50f961b8a8186aafef25a48b485c Mon Sep 17 00:00:00 2001
From: Stuart Douglas <stuart.w.douglas@gmail.com>
Date: Tue, 7 Feb 2023 13:47:50 +1100
Subject: [PATCH] Allow editing of params at any time

Currently it is only possible to edit command line parameters in dev
mode after the application has exited. This means that if you have long
running applications (or accidently hang your app) you can't restart
with different parameters.
---
 .../console/ConsoleStateManager.java          | 22 ++++++++++++++++
 .../deployment/dev/IsolatedDevModeMain.java   | 26 +------------------
 .../dev/RuntimeUpdatesProcessor.java          | 12 +++++++++
 .../io/quarkus/test/QuarkusDevModeTest.java   |  1 +
 4 files changed, 36 insertions(+), 25 deletions(-)

diff --git a/core/deployment/src/main/java/io/quarkus/deployment/console/ConsoleStateManager.java b/core/deployment/src/main/java/io/quarkus/deployment/console/ConsoleStateManager.java
index a21da1453d722..fb4ab24ab5cab 100644
--- a/core/deployment/src/main/java/io/quarkus/deployment/console/ConsoleStateManager.java
+++ b/core/deployment/src/main/java/io/quarkus/deployment/console/ConsoleStateManager.java
@@ -26,10 +26,13 @@
 import java.util.logging.Level;
 import java.util.stream.Collectors;
 
+import org.jboss.logging.Logger;
 import org.jboss.logmanager.LogManager;
 
 import io.quarkus.deployment.dev.RuntimeUpdatesProcessor;
+import io.quarkus.deployment.dev.testing.MessageFormat;
 import io.quarkus.deployment.dev.testing.TestSupport;
+import io.quarkus.deployment.util.CommandLineUtil;
 import io.quarkus.dev.console.QuarkusConsole;
 import io.quarkus.dev.spi.DevModeType;
 
@@ -97,6 +100,25 @@ void installBuiltins(DevModeType devModeType) {
             commands.add(new ConsoleCommand('s', "Force restart", null, () -> {
                 forceRestart();
             }));
+            commands.add(new ConsoleCommand('e', "Edits the command line parameters and restarts",
+                    "to edit command line args (currently '" + MessageFormat.GREEN
+                            + String.join(" ", RuntimeUpdatesProcessor.INSTANCE.getCommandLineArgs()) + MessageFormat.RESET
+                            + "')",
+                    100, new ConsoleCommand.HelpState(() -> BLUE,
+                            () -> String.join(" ", RuntimeUpdatesProcessor.INSTANCE.getCommandLineArgs())),
+                    new Consumer<String>() {
+                        @Override
+                        public void accept(String args) {
+                            try {
+                                RuntimeUpdatesProcessor.INSTANCE.setCommandLineArgs(
+                                        CommandLineUtil.translateCommandline(args));
+                            } catch (Exception e) {
+                                Logger.getLogger(ConsoleStateManager.class).errorf(e, "Failed to parse command line %s", args);
+                                return;
+                            }
+                            RuntimeUpdatesProcessor.INSTANCE.doScan(true, true);
+                        }
+                    }));
 
             commands.add(new ConsoleCommand('i', "Toggle instrumentation based reload",
                     new ConsoleCommand.HelpState(() -> RuntimeUpdatesProcessor.INSTANCE.instrumentationEnabled()), () -> {
diff --git a/core/deployment/src/main/java/io/quarkus/deployment/dev/IsolatedDevModeMain.java b/core/deployment/src/main/java/io/quarkus/deployment/dev/IsolatedDevModeMain.java
index 2f0a5402a4bc6..745e6a94317b2 100644
--- a/core/deployment/src/main/java/io/quarkus/deployment/dev/IsolatedDevModeMain.java
+++ b/core/deployment/src/main/java/io/quarkus/deployment/dev/IsolatedDevModeMain.java
@@ -1,7 +1,5 @@
 package io.quarkus.deployment.dev;
 
-import static io.quarkus.deployment.dev.testing.MessageFormat.BLUE;
-
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.Closeable;
@@ -42,10 +40,8 @@
 import io.quarkus.deployment.builditem.ApplicationClassPredicateBuildItem;
 import io.quarkus.deployment.console.ConsoleCommand;
 import io.quarkus.deployment.console.ConsoleStateManager;
-import io.quarkus.deployment.dev.testing.MessageFormat;
 import io.quarkus.deployment.dev.testing.TestSupport;
 import io.quarkus.deployment.steps.ClassTransformingBuildStep;
-import io.quarkus.deployment.util.CommandLineUtil;
 import io.quarkus.dev.appstate.ApplicationStartException;
 import io.quarkus.dev.console.DevConsoleManager;
 import io.quarkus.dev.spi.DeploymentFailedStartHandler;
@@ -110,27 +106,7 @@ public void accept(Integer integer) {
                                         () -> {
                                             consoleContext.reset();
                                             RuntimeUpdatesProcessor.INSTANCE.doScan(true, true);
-                                        }),
-                                        new ConsoleCommand('e', "Edits the command line parameters and restarts",
-                                                "to edit command line args (currently '" + MessageFormat.GREEN
-                                                        + String.join(" ", context.getArgs()) + MessageFormat.RESET + "')",
-                                                100, new ConsoleCommand.HelpState(() -> BLUE,
-                                                        () -> String.join(" ", context.getArgs())),
-                                                new Consumer<String>() {
-                                                    @Override
-                                                    public void accept(String args) {
-                                                        try {
-                                                            context.setArgs(
-                                                                    CommandLineUtil.translateCommandline(args));
-                                                        } catch (Exception e) {
-                                                            log.error("Failed to parse command line", e);
-                                                            return;
-                                                        }
-                                                        consoleContext.reset();
-                                                        RuntimeUpdatesProcessor.INSTANCE.doScan(true, true);
-                                                    }
-                                                }));
-
+                                        }));
                             }
                         });
 
diff --git a/core/deployment/src/main/java/io/quarkus/deployment/dev/RuntimeUpdatesProcessor.java b/core/deployment/src/main/java/io/quarkus/deployment/dev/RuntimeUpdatesProcessor.java
index c72ffcdf0f0f5..d256e61e2b500 100644
--- a/core/deployment/src/main/java/io/quarkus/deployment/dev/RuntimeUpdatesProcessor.java
+++ b/core/deployment/src/main/java/io/quarkus/deployment/dev/RuntimeUpdatesProcessor.java
@@ -1252,4 +1252,16 @@ boolean isWatchedFileRestartNeeded(String changedFile) {
         }
     }
 
+    public String[] getCommandLineArgs() {
+        String[] contextArgs = context.getArgs();
+        if (contextArgs == null) {
+            return new String[0];
+        }
+        return contextArgs;
+    }
+
+    public RuntimeUpdatesProcessor setCommandLineArgs(String[] commandLineArgs) {
+        this.context.setArgs(commandLineArgs);
+        return this;
+    }
 }
diff --git a/test-framework/junit5-internal/src/main/java/io/quarkus/test/QuarkusDevModeTest.java b/test-framework/junit5-internal/src/main/java/io/quarkus/test/QuarkusDevModeTest.java
index 9a449d60c72f8..f3806306e8cf8 100644
--- a/test-framework/junit5-internal/src/main/java/io/quarkus/test/QuarkusDevModeTest.java
+++ b/test-framework/junit5-internal/src/main/java/io/quarkus/test/QuarkusDevModeTest.java
@@ -286,6 +286,7 @@ public void close() throws Throwable {
             context.setTest(true);
             context.setAbortOnFailedStart(!allowFailedStart);
             context.getBuildSystemProperties().put("quarkus.banner.enabled", "false");
+            context.getBuildSystemProperties().put("quarkus.console.disable-input", "true"); //surefire communicates via stdin, we don't want the test to be reading input
             context.getBuildSystemProperties().putAll(buildSystemProperties);
             devModeMain = new DevModeMain(context);
             devModeMain.start();