Skip to content

Commit 4688f5f

Browse files
committed
fix: fixed JPM_CACHE environment variable handling
Fixes #101
1 parent 29613e2 commit 4688f5f

4 files changed

Lines changed: 336 additions & 12 deletions

File tree

pom.xml

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,25 @@
4141
<version.slf4j>2.0.17</version.slf4j>
4242
<version.spotless>3.0.0</version.spotless>
4343
<version.google-java-format>1.22.0</version.google-java-format>
44-
<version.junit>6.0.0</version.junit>
44+
<version.junit>6.0.3</version.junit>
45+
<version.junit-pioneer>2.3.0</version.junit-pioneer>
4546
<version.mockito>5.20.0</version.mockito>
4647
<version.assertj>3.27.6</version.assertj>
4748
<version.maven-enforcer>3.5.0</version.maven-enforcer>
4849
</properties>
4950

51+
<dependencyManagement>
52+
<dependencies>
53+
<dependency>
54+
<groupId>org.junit</groupId>
55+
<artifactId>junit-bom</artifactId>
56+
<version>${version.junit}</version>
57+
<type>pom</type>
58+
<scope>import</scope>
59+
</dependency>
60+
</dependencies>
61+
</dependencyManagement>
62+
5063
<dependencies>
5164
<dependency>
5265
<groupId>eu.maveniverse.maven.mima</groupId>
@@ -98,7 +111,17 @@
98111
<dependency>
99112
<groupId>org.junit.jupiter</groupId>
100113
<artifactId>junit-jupiter</artifactId>
101-
<version>${version.junit}</version>
114+
<scope>test</scope>
115+
</dependency>
116+
<dependency>
117+
<groupId>org.junit.platform</groupId>
118+
<artifactId>junit-platform-launcher</artifactId>
119+
<scope>test</scope>
120+
</dependency>
121+
<dependency>
122+
<groupId>org.junit-pioneer</groupId>
123+
<artifactId>junit-pioneer</artifactId>
124+
<version>${version.junit-pioneer}</version>
102125
<scope>test</scope>
103126
</dependency>
104127
<dependency>
@@ -279,6 +302,9 @@
279302
<plugin>
280303
<groupId>org.apache.maven.plugins</groupId>
281304
<artifactId>maven-surefire-plugin</artifactId>
305+
<configuration>
306+
<argLine>--add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED</argLine>
307+
</configuration>
282308
</plugin>
283309
<plugin>
284310
<groupId>org.apache.maven.plugins</groupId>

src/main/java/org/codejive/jpm/Main.java

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import java.io.*;
1616
import java.net.MalformedURLException;
1717
import java.net.URL;
18+
import java.nio.file.InvalidPathException;
1819
import java.nio.file.Path;
1920
import java.util.*;
2021
import java.util.concurrent.Callable;
@@ -90,7 +91,7 @@ public Integer call() throws Exception {
9091
Jpm.builder()
9192
.directory(artifactsMixin.directory)
9293
.noLinks(artifactsMixin.noLinks)
93-
.cacheDir(artifactsMixin.cacheDir)
94+
.cacheDir(artifactsMixin.getCacheDir())
9495
.build()
9596
.copy(
9697
artifactsMixin.artifactNames,
@@ -163,7 +164,7 @@ public Integer call() throws Exception {
163164
Jpm.builder()
164165
.directory(depsMixin.directory)
165166
.noLinks(depsMixin.noLinks)
166-
.cacheDir(depsMixin.cacheDir)
167+
.cacheDir(depsMixin.getCacheDir())
167168
.appFile(appInfoFileMixin.appInfoFile)
168169
.build()
169170
.install(
@@ -177,7 +178,7 @@ public Integer call() throws Exception {
177178
Jpm.builder()
178179
.directory(depsMixin.directory)
179180
.noLinks(depsMixin.noLinks)
180-
.cacheDir(depsMixin.cacheDir)
181+
.cacheDir(depsMixin.getCacheDir())
181182
.appFile(appInfoFileMixin.appInfoFile)
182183
.build()
183184
.copy(
@@ -219,7 +220,7 @@ String[] search(String artifactPattern) {
219220
return Jpm.builder()
220221
.directory(depsMixin.directory)
221222
.noLinks(depsMixin.noLinks)
222-
.cacheDir(depsMixin.cacheDir)
223+
.cacheDir(depsMixin.getCacheDir())
223224
.appFile(appInfoFileMixin.appInfoFile)
224225
.build()
225226
.search(artifactPattern, Math.min(max, 200), backend);
@@ -320,7 +321,7 @@ public Integer call() throws Exception {
320321
Jpm.builder()
321322
.directory(optionalArtifactsMixin.directory)
322323
.noLinks(optionalArtifactsMixin.noLinks)
323-
.cacheDir(optionalArtifactsMixin.cacheDir)
324+
.cacheDir(optionalArtifactsMixin.getCacheDir())
324325
.appFile(appInfoFileMixin.appInfoFile)
325326
.build()
326327
.install(
@@ -351,7 +352,7 @@ public Integer call() throws Exception {
351352
Jpm.builder()
352353
.directory(optionalArtifactsMixin.directory)
353354
.noLinks(optionalArtifactsMixin.noLinks)
354-
.cacheDir(optionalArtifactsMixin.cacheDir)
355+
.cacheDir(optionalArtifactsMixin.getCacheDir())
355356
.appFile(appInfoFileMixin.appInfoFile)
356357
.build()
357358
.path(
@@ -409,7 +410,7 @@ public Integer call() throws Exception {
409410
return Jpm.builder()
410411
.directory(depsMixin.directory)
411412
.noLinks(depsMixin.noLinks)
412-
.cacheDir(depsMixin.cacheDir)
413+
.cacheDir(depsMixin.getCacheDir())
413414
.appFile(appInfoFileMixin.appInfoFile)
414415
.verbose(!quietMixin.quiet)
415416
.build()
@@ -468,7 +469,7 @@ public Integer call() throws Exception {
468469
Jpm.builder()
469470
.directory(depsMixin.directory)
470471
.noLinks(depsMixin.noLinks)
471-
.cacheDir(depsMixin.cacheDir)
472+
.cacheDir(depsMixin.getCacheDir())
472473
.appFile(appInfoFileMixin.appInfoFile)
473474
.build()
474475
.listActions();
@@ -514,7 +515,7 @@ public Integer call() throws Exception {
514515
Jpm.builder()
515516
.directory(depsMixin.directory)
516517
.noLinks(depsMixin.noLinks)
517-
.cacheDir(depsMixin.cacheDir)
518+
.cacheDir(depsMixin.getCacheDir())
518519
.appFile(appInfoFileMixin.appInfoFile)
519520
.verbose(!quietMixin.quiet)
520521
.build()
@@ -548,7 +549,7 @@ public Integer call() throws Exception {
548549
return Jpm.builder()
549550
.directory(depsMixin.directory)
550551
.noLinks(depsMixin.noLinks)
551-
.cacheDir(depsMixin.cacheDir)
552+
.cacheDir(depsMixin.getCacheDir())
552553
.appFile(appInfoFileMixin.appInfoFile)
553554
.build()
554555
.executeAction(actionName(), args, depsMixin.getRepositoryMap());
@@ -624,6 +625,23 @@ static class DepsMixin {
624625
"Directory where downloaded artifacts will be cached (default: value of JPM_CACHE environment variable; whatever is set in Maven's settings.xml or $HOME/.m2/repository")
625626
Path cacheDir;
626627

628+
Path getCacheDir() {
629+
if (cacheDir != null) {
630+
return cacheDir;
631+
}
632+
String envCache = System.getenv("JPM_CACHE");
633+
if (envCache != null && !envCache.isEmpty()) {
634+
try {
635+
return Path.of(envCache);
636+
} catch (InvalidPathException e) {
637+
System.err.println(
638+
"Warning: Invalid path in JPM_CACHE environment variable, ignoring: "
639+
+ envCache);
640+
}
641+
}
642+
return null;
643+
}
644+
627645
Map<String, String> getRepositoryMap() {
628646
Map<String, String> repoMap = new HashMap<>();
629647
for (String repo : repositories) {
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
package org.codejive.jpm;
2+
3+
import static org.assertj.core.api.Assertions.*;
4+
5+
import java.io.ByteArrayOutputStream;
6+
import java.io.IOException;
7+
import java.io.PrintStream;
8+
import java.nio.file.Files;
9+
import java.nio.file.Path;
10+
import org.junit.jupiter.api.AfterEach;
11+
import org.junit.jupiter.api.BeforeEach;
12+
import org.junit.jupiter.api.Test;
13+
import org.junit.jupiter.api.io.TempDir;
14+
import org.junitpioneer.jupiter.ClearEnvironmentVariable;
15+
import org.junitpioneer.jupiter.SetEnvironmentVariable;
16+
import picocli.CommandLine;
17+
18+
/** Integration tests for the --cache option and JPM_CACHE environment variable. */
19+
class MainCacheIntegrationTest {
20+
21+
@TempDir Path tempDir;
22+
@TempDir Path cacheDir1;
23+
@TempDir Path cacheDir2;
24+
25+
private String originalUserDir;
26+
private PrintStream originalOut;
27+
private PrintStream originalErr;
28+
private ByteArrayOutputStream outContent;
29+
private ByteArrayOutputStream errContent;
30+
31+
@BeforeEach
32+
void setUp() {
33+
originalUserDir = System.getProperty("user.dir");
34+
System.setProperty("user.dir", tempDir.toString());
35+
System.setProperty("picocli.ansi", "false");
36+
37+
// Capture stdout and stderr
38+
originalOut = System.out;
39+
originalErr = System.err;
40+
outContent = new ByteArrayOutputStream();
41+
errContent = new ByteArrayOutputStream();
42+
System.setOut(new PrintStream(outContent));
43+
System.setErr(new PrintStream(errContent));
44+
}
45+
46+
@AfterEach
47+
void tearDown() {
48+
System.setProperty("user.dir", originalUserDir);
49+
System.setOut(originalOut);
50+
System.setErr(originalErr);
51+
}
52+
53+
@Test
54+
@ClearEnvironmentVariable(key = "JPM_CACHE")
55+
void testPathCommandWithCacheOption() throws IOException {
56+
// Create app.yml
57+
createSimpleAppYml();
58+
59+
CommandLine cmd = Main.getCommandLine();
60+
int exitCode = cmd.execute("path", "--cache", cacheDir1.toString());
61+
62+
// Exit code 0 or 1 is acceptable (1 means dependency not found, which is expected)
63+
assertThat(exitCode).isIn(0, 1);
64+
}
65+
66+
@Test
67+
@SetEnvironmentVariable(key = "JPM_CACHE", value = "/tmp/env-cache")
68+
void testPathCommandWithEnvironmentVariable() throws IOException {
69+
// Create app.yml
70+
createSimpleAppYml();
71+
72+
CommandLine cmd = Main.getCommandLine();
73+
int exitCode = cmd.execute("path");
74+
75+
// The command should succeed with JPM_CACHE set
76+
assertThat(exitCode).isIn(0, 1);
77+
}
78+
79+
@Test
80+
@SetEnvironmentVariable(key = "JPM_CACHE", value = "/tmp/env-cache")
81+
void testCopyCommandCacheOptionOverridesEnvironmentVariable() throws IOException {
82+
CommandLine cmd = Main.getCommandLine();
83+
int exitCode =
84+
cmd.execute(
85+
"copy", "--cache", cacheDir1.toString(), "--quiet", "fake:artifact:1.0.0");
86+
87+
// The command should use cacheDir1 (from --cache) not /tmp/env-cache
88+
// Even though it will fail to resolve, it should parse correctly
89+
assertThat(exitCode).isIn(0, 1); // May fail to resolve, but shouldn't crash
90+
}
91+
92+
@Test
93+
@ClearEnvironmentVariable(key = "JPM_CACHE")
94+
void testInstallCommandWithShortCacheOption() throws IOException {
95+
createSimpleAppYml();
96+
97+
CommandLine cmd = Main.getCommandLine();
98+
int exitCode =
99+
cmd.execute(
100+
"install", "-c", cacheDir1.toString(), "--quiet", "fake:artifact:1.0.0");
101+
102+
// The -c short form should work the same as --cache
103+
assertThat(exitCode).isIn(0, 1); // May fail to resolve, but shouldn't crash
104+
}
105+
106+
@Test
107+
void testCacheOptionInHelp() {
108+
CommandLine cmd = Main.getCommandLine();
109+
int exitCode = cmd.execute("copy", "--help");
110+
111+
// PicoCLI may return 0 or 2 for help depending on configuration
112+
// What matters is that the help text is displayed
113+
String output = outContent.toString() + errContent.toString();
114+
assertThat(output)
115+
.contains("-c, --cache")
116+
.contains("Directory where downloaded artifacts will be cached")
117+
.contains("JPM_CACHE");
118+
}
119+
120+
@Test
121+
@SetEnvironmentVariable(key = "JPM_CACHE", value = " ")
122+
void testGetCacheDirWithWhitespaceOnlyEnvironmentVariable() throws IOException {
123+
// An environment variable with only whitespace should be treated as empty
124+
createSimpleAppYml();
125+
126+
CommandLine cmd = Main.getCommandLine();
127+
// This should not crash - whitespace-only JPM_CACHE should be ignored
128+
int exitCode = cmd.execute("path");
129+
130+
assertThat(exitCode).isIn(0, 1);
131+
}
132+
133+
@Test
134+
@ClearEnvironmentVariable(key = "JPM_CACHE")
135+
void testCacheOptionWithRelativePath() throws IOException {
136+
createSimpleAppYml();
137+
138+
CommandLine cmd = Main.getCommandLine();
139+
int exitCode = cmd.execute("path", "--cache", "./my-cache");
140+
141+
assertThat(exitCode).isIn(0, 1);
142+
// Should accept relative paths
143+
}
144+
145+
@Test
146+
@ClearEnvironmentVariable(key = "JPM_CACHE")
147+
void testCacheOptionWithAbsolutePath() throws IOException {
148+
createSimpleAppYml();
149+
150+
CommandLine cmd = Main.getCommandLine();
151+
int exitCode = cmd.execute("path", "--cache", cacheDir1.toAbsolutePath().toString());
152+
153+
assertThat(exitCode).isIn(0, 1);
154+
// Should accept absolute paths
155+
}
156+
157+
private void createSimpleAppYml() throws IOException {
158+
String yamlContent =
159+
"dependencies:\n"
160+
+ " fake:dummy: \"1.2.3\"\n"
161+
+ "\n"
162+
+ "actions:\n"
163+
+ " build: \"echo building\"\n";
164+
Files.writeString(tempDir.resolve("app.yml"), yamlContent);
165+
}
166+
}

0 commit comments

Comments
 (0)