Skip to content

Commit aa4d5af

Browse files
authored
fix: fixed repo parsing and added tests
1 parent 8e65772 commit aa4d5af

File tree

5 files changed

+375
-15
lines changed

5 files changed

+375
-15
lines changed

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

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -278,12 +278,4 @@ public List<String> listActions() throws IOException {
278278
AppInfo appInfo = AppInfo.read();
279279
return new ArrayList<>(appInfo.getActionNames());
280280
}
281-
282-
private static boolean isWindows() {
283-
String os =
284-
System.getProperty("os.name")
285-
.toLowerCase(Locale.ENGLISH)
286-
.replaceAll("[^a-z0-9]+", "");
287-
return os.startsWith("win");
288-
}
289281
}

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

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -518,18 +518,26 @@ static class BaseArtifactsMixin {
518518
Map<String, String> getRepositoryMap() {
519519
Map<String, String> repoMap = new HashMap<>();
520520
for (String repo : repositories) {
521+
String name;
522+
String url;
521523
int eq = repo.indexOf('=');
522-
if (eq > 0) {
523-
repoMap.put(repo.substring(0, eq), repo.substring(eq + 1));
524+
if (eq >= 0) {
525+
name = repo.substring(0, eq);
526+
url = repo.substring(eq + 1);
524527
} else {
525-
String name = repo;
528+
name = "";
529+
url = repo;
530+
}
531+
if (name.isEmpty()) {
526532
try {
527-
URL url = new URL(repo);
528-
name = url.getHost();
533+
URL x = new URL(repo);
534+
name = x.getHost();
529535
} catch (MalformedURLException e) {
530-
// Ignore
536+
name = "repo" + (repoMap.size() + 1);
531537
}
532-
repoMap.put(name, repo);
538+
}
539+
if (!url.isEmpty()) {
540+
repoMap.put(name, url);
533541
}
534542
}
535543
return repoMap;

src/test/java/org/codejive/jpm/MainIntegrationTest.java

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,56 @@ void testDoAliasWithArgs() throws IOException {
259259
}
260260
}
261261

262+
@Test
263+
void testCopyCommandWithRepositoryOptions() throws IOException {
264+
// Test copy command with --repo options
265+
CommandLine cmd = Main.getCommandLine();
266+
int exitCode =
267+
cmd.execute(
268+
"copy",
269+
"--repo",
270+
"central=https://repo1.maven.org/maven2",
271+
"--repo",
272+
"https://jcenter.bintray.com",
273+
"com.google.guava:guava:31.1-jre");
274+
275+
// The command should execute successfully (even if dependency resolution might fail)
276+
assertThat(exitCode >= 0).isTrue();
277+
}
278+
279+
@Test
280+
void testInstallCommandWithRepositoryOptions() throws IOException {
281+
CommandLine cmd = Main.getCommandLine();
282+
int exitCode =
283+
cmd.execute(
284+
"install",
285+
"--repo",
286+
"central=https://repo1.maven.org/maven2",
287+
"com.google.guava:guava:31.1-jre");
288+
289+
// The command should execute successfully (even if dependency resolution might fail)
290+
assertThat(exitCode >= 0).isTrue();
291+
}
292+
293+
@Test
294+
void testPathCommandWithRepositoryOptionsAndAppYml() throws IOException {
295+
// Create app.yml with repositories
296+
createAppYmlWithRepositories();
297+
298+
try (TestOutputCapture capture = captureOutput()) {
299+
CommandLine cmd = Main.getCommandLine();
300+
int exitCode =
301+
cmd.execute(
302+
"path",
303+
"--repo",
304+
"jcenter=https://jcenter.bintray.com",
305+
"com.google.guava:guava:31.1-jre");
306+
307+
// The command should execute (even if dependency resolution might fail)
308+
assertThat(exitCode >= 0).isTrue();
309+
}
310+
}
311+
262312
private void createAppYml() throws IOException {
263313
String yamlContent =
264314
"dependencies:\n"
@@ -287,4 +337,19 @@ private void createAppYmlWithoutBuildAction() throws IOException {
287337
+ " hello: \"echo Hello World\"\n";
288338
Files.writeString(tempDir.resolve("app.yml"), yamlContent);
289339
}
340+
341+
private void createAppYmlWithRepositories() throws IOException {
342+
String yamlContent =
343+
"dependencies:\n"
344+
+ " com.github.lalyos:jfiglet: \"0.0.9\"\n"
345+
+ "\n"
346+
+ "repositories:\n"
347+
+ " central: \"https://repo1.maven.org/maven2\"\n"
348+
+ " custom: \"https://my.custom.repo/maven2\"\n"
349+
+ "\n"
350+
+ "actions:\n"
351+
+ " build: \"javac -cp {{deps}} *.java\"\n"
352+
+ " test: \"java -cp {{deps}} TestRunner\"\n";
353+
Files.writeString(tempDir.resolve("app.yml"), yamlContent);
354+
}
290355
}
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
package org.codejive.jpm;
2+
3+
import static org.assertj.core.api.Assertions.*;
4+
5+
import java.util.ArrayList;
6+
import java.util.List;
7+
import java.util.Map;
8+
import org.junit.jupiter.api.Test;
9+
10+
/** Tests for Main class CLI repository option parsing. */
11+
class MainRepositoryOptionsTest {
12+
13+
@Test
14+
void testGetRepositoryMapWithNamedRepositories() {
15+
Main.BaseArtifactsMixin mixin = new Main.BaseArtifactsMixin();
16+
mixin.repositories =
17+
List.of(
18+
"central=https://repo1.maven.org/maven2",
19+
"jcenter=https://jcenter.bintray.com",
20+
"custom=https://my.custom.repo/maven2");
21+
22+
Map<String, String> result = mixin.getRepositoryMap();
23+
24+
assertThat(result).hasSize(3);
25+
assertThat(result)
26+
.containsEntry("central", "https://repo1.maven.org/maven2")
27+
.containsEntry("jcenter", "https://jcenter.bintray.com")
28+
.containsEntry("custom", "https://my.custom.repo/maven2");
29+
}
30+
31+
@Test
32+
void testGetRepositoryMapWithUnnamedRepositories() {
33+
Main.BaseArtifactsMixin mixin = new Main.BaseArtifactsMixin();
34+
mixin.repositories =
35+
List.of(
36+
"https://repo1.maven.org/maven2",
37+
"https://jcenter.bintray.com",
38+
"https://my.custom.repo/maven2");
39+
40+
Map<String, String> result = mixin.getRepositoryMap();
41+
42+
assertThat(result).hasSize(3);
43+
// For unnamed repos, the hostname should be used as the name
44+
assertThat(result)
45+
.containsEntry("repo1.maven.org", "https://repo1.maven.org/maven2")
46+
.containsEntry("jcenter.bintray.com", "https://jcenter.bintray.com")
47+
.containsEntry("my.custom.repo", "https://my.custom.repo/maven2");
48+
}
49+
50+
@Test
51+
void testGetRepositoryMapWithMixedRepositories() {
52+
Main.BaseArtifactsMixin mixin = new Main.BaseArtifactsMixin();
53+
mixin.repositories =
54+
List.of(
55+
"central=https://repo1.maven.org/maven2",
56+
"https://jcenter.bintray.com",
57+
"custom=https://my.custom.repo/maven2",
58+
"https://oss.sonatype.org/content/repositories/snapshots");
59+
60+
Map<String, String> result = mixin.getRepositoryMap();
61+
62+
assertThat(result).hasSize(4);
63+
assertThat(result)
64+
.containsEntry("central", "https://repo1.maven.org/maven2")
65+
.containsEntry("jcenter.bintray.com", "https://jcenter.bintray.com")
66+
.containsEntry("custom", "https://my.custom.repo/maven2")
67+
.containsEntry(
68+
"oss.sonatype.org",
69+
"https://oss.sonatype.org/content/repositories/snapshots");
70+
}
71+
72+
@Test
73+
void testGetRepositoryMapWithEmptyList() {
74+
Main.BaseArtifactsMixin mixin = new Main.BaseArtifactsMixin();
75+
mixin.repositories = new ArrayList<>();
76+
77+
Map<String, String> result = mixin.getRepositoryMap();
78+
79+
assertThat(result).isEmpty();
80+
}
81+
82+
@Test
83+
void testGetRepositoryMapWithInvalidUrls() {
84+
Main.BaseArtifactsMixin mixin = new Main.BaseArtifactsMixin();
85+
mixin.repositories =
86+
List.of(
87+
"invalid-url",
88+
"also-invalid",
89+
"file:///local/path"); // Valid URL but not HTTP
90+
91+
Map<String, String> result = mixin.getRepositoryMap();
92+
93+
assertThat(result).hasSize(3);
94+
// For invalid URLs, the entire string should be used as both name and URL
95+
assertThat(result)
96+
.containsEntry("repo1", "invalid-url")
97+
.containsEntry("repo2", "also-invalid");
98+
// For file:// URLs, getHost() returns null/empty, so name becomes empty
99+
assertThat(result).containsEntry("", "file:///local/path");
100+
}
101+
102+
@Test
103+
void testGetRepositoryMapWithEqualsInUrl() {
104+
Main.BaseArtifactsMixin mixin = new Main.BaseArtifactsMixin();
105+
mixin.repositories =
106+
List.of(
107+
"nexus=https://nexus.example.com/repository/maven-public/?foo=bar",
108+
"https://repo.example.com/path?param=value&other=test");
109+
110+
Map<String, String> result = mixin.getRepositoryMap();
111+
112+
assertThat(result).hasSize(2);
113+
assertThat(result)
114+
.containsEntry(
115+
"nexus", "https://nexus.example.com/repository/maven-public/?foo=bar");
116+
// The second URL has = in it, so it gets split at the first =
117+
assertThat(result).containsEntry("https://repo.example.com/path?param", "value&other=test");
118+
}
119+
120+
@Test
121+
void testGetRepositoryMapWithDuplicateNames() {
122+
Main.BaseArtifactsMixin mixin = new Main.BaseArtifactsMixin();
123+
mixin.repositories =
124+
List.of(
125+
"central=https://repo1.maven.org/maven2",
126+
"central=https://repo.maven.apache.org/maven2"); // Duplicate name
127+
128+
Map<String, String> result = mixin.getRepositoryMap();
129+
130+
assertThat(result).hasSize(1);
131+
// The last one should win
132+
assertThat(result).containsEntry("central", "https://repo.maven.apache.org/maven2");
133+
}
134+
135+
@Test
136+
void testGetRepositoryMapWithEmptyNameOrUrl() {
137+
Main.BaseArtifactsMixin mixin = new Main.BaseArtifactsMixin();
138+
mixin.repositories = List.of("=https://repo1.maven.org/maven2", "name=", "=");
139+
140+
Map<String, String> result = mixin.getRepositoryMap();
141+
142+
assertThat(result).hasSize(1);
143+
// When = is at the beginning, it's not treated as a name=value separator
144+
assertThat(result).containsEntry("repo1", "https://repo1.maven.org/maven2");
145+
}
146+
}

0 commit comments

Comments
 (0)