diff --git a/src/main/java/it/mulders/mcs/App.java b/src/main/java/it/mulders/mcs/App.java index a90f7fbc..e835d944 100644 --- a/src/main/java/it/mulders/mcs/App.java +++ b/src/main/java/it/mulders/mcs/App.java @@ -12,11 +12,41 @@ public static void main(final String... args) { } // Visible for testing - static int doMain(final String... args) { - System.setProperties(new SystemPropertyLoader().getProperties()); - var cli = new Cli(); + static int doMain(final String... originalArgs) { + return doMain(new Cli(), new SystemPropertyLoader(), originalArgs); + } + + static int doMain(final Cli cli, final SystemPropertyLoader systemPropertyLoader, final String... originalArgs) { + System.setProperties(systemPropertyLoader.getProperties()); var program = new CommandLine(cli, new CommandClassFactory(cli)) .setExecutionExceptionHandler(new McsExecutionExceptionHandler()); + + var args = isInvocationWithoutSearchCommand(program, originalArgs) + ? prependSearchCommandToArgs(originalArgs) + : originalArgs; + return program.execute(args); } + + static boolean isInvocationWithoutSearchCommand(CommandLine program, String... args) { + try { + program.parseArgs(args); + return false; + } catch (CommandLine.ParameterException pe1) { + try { + program.parseArgs(prependSearchCommandToArgs(args)); + return true; + } catch (CommandLine.ParameterException pe2) { + return false; + } + } + } + + static String[] prependSearchCommandToArgs(String... originalArgs) { + var args = new String[originalArgs.length + 1]; + args[0] = "search"; + System.arraycopy(originalArgs, 0, args, 1, originalArgs.length); + + return args; + } } diff --git a/src/main/java/it/mulders/mcs/cli/SystemPropertyLoader.java b/src/main/java/it/mulders/mcs/cli/SystemPropertyLoader.java index 763f407e..6b2a640c 100644 --- a/src/main/java/it/mulders/mcs/cli/SystemPropertyLoader.java +++ b/src/main/java/it/mulders/mcs/cli/SystemPropertyLoader.java @@ -20,26 +20,24 @@ public class SystemPropertyLoader { "mcs.config" ); - private final Properties properties; + private final Properties properties = new Properties();; public SystemPropertyLoader() { this(MCS_PROPERTIES_FILE); } protected SystemPropertyLoader(final Path source) { - var input = new Properties(); + properties.putAll(System.getProperties()); if (Files.exists(source) && Files.isRegularFile(source)) { + var input = new Properties(); try (var reader = Files.newBufferedReader(source)) { input.load(reader); + properties.putAll(input); } catch (IOException ioe) { System.err.printf("Failed to load %s: %s%n", source, ioe.getLocalizedMessage()); } } - - this.properties = new Properties(); - properties.putAll(System.getProperties()); - properties.putAll(input); } public Properties getProperties() { diff --git a/src/test/java/it/mulders/mcs/AppIT.java b/src/test/java/it/mulders/mcs/AppIT.java index 45421d83..30159cdd 100644 --- a/src/test/java/it/mulders/mcs/AppIT.java +++ b/src/test/java/it/mulders/mcs/AppIT.java @@ -1,14 +1,37 @@ package it.mulders.mcs; +import it.mulders.mcs.cli.Cli; +import it.mulders.mcs.cli.SystemPropertyLoader; import org.assertj.core.api.WithAssertions; import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.DisplayNameGeneration; import org.junit.jupiter.api.Test; +import java.util.Properties; + import static com.github.stefanbirkner.systemlambda.SystemLambda.tapSystemOut; @DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) class AppIT implements WithAssertions { + private final Cli command = new Cli() { + @Override + public SearchCommand createSearchCommand() { + return new SearchCommand() { + public Integer call() { + return 0; + } + }; + } + + @Override + public ClassSearchCommand createClassSearchCommand() { + return new ClassSearchCommand() { + public Integer call() { + return 0; + } + }; + } + }; @Test void should_show_version() throws Exception { var output = tapSystemOut(() -> App.doMain("-V")); @@ -24,4 +47,25 @@ void should_exit_cleanly() { void should_exit_nonzero_on_wrong_invocation() { assertThat(App.doMain("--does-not-exist")).isNotEqualTo(0); } + + @Test + void runs_without_search_command_specified() { + assertThat(App.doMain(command, new SystemPropertyLoader(), "info.picocli:picocli")).isEqualTo(0); + } + + @Test + void should_load_additional_system_properties() { + var loader = new SystemPropertyLoader() { + @Override + public Properties getProperties() { + var tmp = super.getProperties(); + tmp.put("example", "value"); + return tmp; + } + }; + + App.doMain(command, loader, "info.picocli:picocli"); + + assertThat(System.getProperty("example")).isEqualTo("value"); + } } \ No newline at end of file diff --git a/src/test/java/it/mulders/mcs/AppTest.java b/src/test/java/it/mulders/mcs/AppTest.java new file mode 100644 index 00000000..ec5a2db9 --- /dev/null +++ b/src/test/java/it/mulders/mcs/AppTest.java @@ -0,0 +1,55 @@ +package it.mulders.mcs; + +import it.mulders.mcs.cli.Cli; +import it.mulders.mcs.cli.CommandClassFactory; +import org.assertj.core.api.WithAssertions; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import picocli.CommandLine; + +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) +class AppTest implements WithAssertions { + @Nested + class PrependSearchCommandToArgs { + @Test + void should_prepend_search_to_command_line_args() { + assertThat(App.prependSearchCommandToArgs("info.picocli:picocli")) + .isEqualTo(new String[] { "search", "info.picocli:picocli"}); + assertThat(App.prependSearchCommandToArgs("-h")) + .isEqualTo(new String[] { "search", "-h"}); + assertThat(App.prependSearchCommandToArgs()) + .isEqualTo(new String[] { "search" }); + } + } + + @Nested + class IsInvocationWithoutSearchCommand { + private final Cli cli = new Cli(); + private final CommandLine program = new CommandLine(cli, new CommandClassFactory(cli)); + + @Test + void should_detect_when_search_command_is_not_present() { + assertThat(App.isInvocationWithoutSearchCommand(program, "info.picocli:picocli")).isTrue(); + assertThat(App.isInvocationWithoutSearchCommand(program, "info.picocli", "picocli")).isTrue(); + assertThat(App.isInvocationWithoutSearchCommand(program, "info.picocli", "picocli", "4.7.5")).isTrue(); + } + + @Test + void should_detect_when_search_command_is_present() { + assertThat(App.isInvocationWithoutSearchCommand(program, "search", "info.picocli:picocli")).isFalse(); + assertThat(App.isInvocationWithoutSearchCommand(program, "search", "--help")).isFalse(); + } + + @Test + void invoking_help_is_not_invoking_search_help() { + assertThat(App.isInvocationWithoutSearchCommand(program, "--help")).isFalse(); + } + + @Test + void invoking_help_is_not_invoking_search_version() { + assertThat(App.isInvocationWithoutSearchCommand(program, "-V")).isFalse(); + } + } +} \ No newline at end of file