Skip to content

Commit

Permalink
[env-manager] support inline args for env command
Browse files Browse the repository at this point in the history
  • Loading branch information
rmannibucau committed Feb 10, 2024
1 parent 3541027 commit 5e1ce46
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 6 deletions.
34 changes: 29 additions & 5 deletions env-manager/src/main/java/io/yupiik/dev/command/Env.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import io.yupiik.dev.shared.MessageHelper;
import io.yupiik.dev.shared.Os;
import io.yupiik.dev.shared.RcService;
import io.yupiik.fusion.framework.api.main.Args;
import io.yupiik.fusion.framework.build.api.cli.Command;
import io.yupiik.fusion.framework.build.api.configuration.Property;
import io.yupiik.fusion.framework.build.api.configuration.RootConfiguration;
Expand All @@ -34,12 +35,14 @@
import java.util.logging.Handler;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import java.util.stream.IntStream;
import java.util.stream.Stream;

import static java.io.File.pathSeparator;
import static java.util.Optional.ofNullable;
import static java.util.logging.Level.FINE;
import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toMap;

@Command(name = "env", description = "Creates a script you can eval in a shell to prepare the environment from a file. Often used as `eval $(yem env--env-rc .yemrc)`")
public class Env implements Runnable {
Expand All @@ -48,12 +51,14 @@ public class Env implements Runnable {
private final RcService rc;
private final Os os;
private final MessageHelper messageHelper;
private final Args args;

public Env(final Conf conf, final Os os, final RcService rc, final MessageHelper messageHelper) {
public Env(final Conf conf, final Os os, final RcService rc, final MessageHelper messageHelper, final Args args) {
this.conf = conf;
this.os = os;
this.rc = rc;
this.messageHelper = messageHelper;
this.args = args;
}

@Override
Expand All @@ -72,14 +77,33 @@ public void run() {

final var tools = rc.loadPropertiesFrom(conf.rc(), conf.defaultRc());
final var inlineProps = new Properties();
// check if we have any --xxxx-version arg and if so we inject all args in props
// there is no real chance of conflict with default props so we can do it
if (args.args().size() > 1 /* "env" */ &&
args.args().stream().anyMatch(a -> a.startsWith("--") && !Objects.equals("--version", a) && a.endsWith("-version"))) {
final var params = args.args().subList(1, args.args().size());
if (!params.isEmpty()) {
inlineProps.putAll(IntStream.range(0, params.size() / 2)
.boxed()
.filter(f -> {
final var key = params.get(2 * f);
return key.startsWith("--env-") && key.lastIndexOf('-') > "--env-".length() /* default options */;
})
.collect(toMap(d -> {
final var key = params.get(2 * d);
return key.substring("--env-".length()).replace('-', '.');
}, i -> params.get(2 * i + 1))));
}
}
if (conf.inlineRc() != null && !conf.inlineRc().isBlank()) {
try (final var reader = new StringReader(conf.inlineRc().replace("\\n", "\n"))) {
inlineProps.load(reader);
} catch (final IOException e) {
throw new IllegalStateException(e);
}
}
if (tools == null || (inlineProps.isEmpty() && tools.global().isEmpty() && tools.local().isEmpty())) { // nothing to do

if ((tools == null || (tools.global().isEmpty() && tools.local().isEmpty())) && inlineProps.isEmpty()) { // nothing to do
return;
}

Expand Down Expand Up @@ -115,7 +139,7 @@ public void close() throws SecurityException {
logger.addHandler(tempHandler);

try {
rc.match(inlineProps, tools.local(), tools.global())
(tools == null ? rc.match(inlineProps) : rc.match(inlineProps, tools.local(), tools.global()))
.thenAccept(resolved -> createScript(resolved, export, quote, pathName, hasTerm, pathVar, tools, messages, comment))
.toCompletableFuture()
.get();
Expand Down Expand Up @@ -168,7 +192,7 @@ private void createScript(final List<RcService.MatchedPath> rawResolved,
.collect(joining(pathsSeparator, "", pathsSeparator)) + pathVar + quote + ";\n" :
"";
final var home = System.getProperty("user.home", "");
final var echos = Boolean.parseBoolean(tools.global().getProperty("echo", tools.local().getProperty("echo", "true"))) ?
final var echos = tools == null || Boolean.parseBoolean(tools.global().getProperty("echo", tools.local().getProperty("echo", "true"))) ?
resolved.stream()
// don't log too much, if it does not change, don't re-log it
.filter(Predicate.not(it -> Objects.equals(it.path().toString(), System.getenv(it.properties().envPathVarName()))))
Expand Down Expand Up @@ -214,7 +238,7 @@ private void resetOriginalPath(final String export, final String pathName, final
public record Conf(
@Property(documentation = "By default if `YEM_ORIGINAL_PATH` exists in the environment variables it is used as `PATH` base to not keep appending path to the `PATH` indefinively. This can be disabled setting this property to `false`", defaultValue = "false") boolean skipReset,
@Property(documentation = "Should `~/.yupiik/yem/rc` be ignored or not. If present it defines default versions and uses the same syntax than `yemrc`.", defaultValue = "System.getProperty(\"user.home\") + \"/.yupiik/yem/rc\"") String defaultRc,
@Property(documentation = "Enables to set inline a rc file, ex: `eval $(yem env --inlineRc 'java.version=17.0.9')`, you can use EOL too: `eval $(yem env --inlineRc 'java.version=17.\\njava.relaxed = true')`. Note that to persist the change even if you automatically switch from the global `yemrc` file the context, we set `YEM_$TOOLPATHVARNAME_OVERRIDEN` environment variable. To reset the value to the global configuration just `unset` this variable (ex: `unset YEM_JAVA_PATH_OVERRIDEN`)") String inlineRc,
@Property(documentation = "Enables to set inline a rc file, ex: `eval $(yem env --inlineRc 'java.version=17.0.9')`, you can use EOL too: `eval $(yem env --inlineRc 'java.version=17.\\njava.relaxed = true')`. Note that to persist the change even if you automatically switch from the global `yemrc` file the context, we set `YEM_$TOOLPATHVARNAME_OVERRIDEN` environment variable. To reset the value to the global configuration just `unset` this variable (ex: `unset YEM_JAVA_PATH_OVERRIDEN`). Note that you can also just set the values inline as args without that option: `eval $(yem env --java-version 17. --java-relaxed true ...)`.") String inlineRc,
@Property(documentation = "Env file location to read to generate the script. Note that `auto` will try to pick `.yemrc` and if not there will use `.sdkmanrc` if present.", defaultValue = "\"auto\"") String rc) {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import io.yupiik.fusion.framework.build.api.order.Order;

import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Stream;

import static java.util.Optional.ofNullable;
Expand All @@ -44,10 +45,12 @@ private Args enrich(final List<String> args) {
return new Args(args);
}
final var prefix = "--" + args.get(0) + '-';
final var counter = new AtomicInteger();
return new Args(args.stream()
.peek(it -> counter.getAndIncrement())
.flatMap(i -> !"--".equals(i) && i.startsWith("--") && !i.startsWith(prefix) ?
(i.substring("--".length()).contains("-") ?
Stream.of(prefix + i.substring("--".length()), i) :
Stream.of(prefix + i.substring("--".length()), args.size() > counter.get() ? args.get(counter.get()) : "", i) :
Stream.of(prefix + i.substring("--".length()))) :
Stream.of(i))
.toList());
Expand Down
27 changes: 27 additions & 0 deletions env-manager/src/test/java/io/yupiik/dev/command/CommandsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,33 @@ void env(@TempDir final Path work, final URI uri) throws IOException {
.strip());
}

@Test
@DisabledOnOs(WINDOWS)
void envInline(@TempDir final Path work, final URI uri) {
final var out = captureOutput(work, uri,
"env",
"--skipReset", "true",
"--env-rc", work.resolve("missing_rc").toString(),
"--env-defaultRc", work.resolve("missing_defaultRc").toString(),
"--java-version", "21",
"--java-relaxed", "true",
"--java-installIfMissing", "true");
assertEquals(("""
echo "[yem] Installing java@21.32.17-ca-jdk21.0.2";
export YEM_ORIGINAL_PATH="...";
export PATH="$work/zulu/21.32.17-ca-jdk21.0.2/distribution_exploded:$PATH";
export JAVA_HOME="$work/zulu/21.32.17-ca-jdk21.0.2/distribution_exploded";
export JAVA_VERSION="21.0.2";
export YEM_JAVA_HOME_OVERRIDEN="21.0.2";
echo "[yem] Resolved java @ 21.0.2 to '$work/zulu/21.32.17-ca-jdk21.0.2/distribution_exploded'\";""")
.replace("$work", work.toString()),
out
.replaceAll("#.*", "")
.replaceFirst("export YEM_ORIGINAL_PATH=\"[^\"]+\"", "export YEM_ORIGINAL_PATH=\"...\"")
.strip());
}

@Test
@DisabledOnOs(WINDOWS)
void envSdkManRc(@TempDir final Path work, final URI uri) throws IOException {
Expand Down

0 comments on commit 5e1ce46

Please sign in to comment.