Skip to content

Commit cfa8bde

Browse files
committed
Allow executing multiple commands
1 parent 1f1da03 commit cfa8bde

6 files changed

Lines changed: 233 additions & 132 deletions

File tree

‎app.yml‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ dependencies:
99
org.slf4j:slf4j-simple: "2.0.17"
1010

1111
actions:
12-
build: "./mvnw clean compile"
13-
run: "java -jar target/jpm-0.4.1-cli.jar"
14-
test: "./mvnw test"
12+
clean: ".{/}mvnw clean"
13+
build: ".{/}mvnw spotless:apply package -DskipTests"
14+
run: "java -jar target{/}jpm-0.4.1-cli.jar"
15+
test: ".{/}mvnw test"

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

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -177,16 +177,10 @@ private static String[] getArtifacts(String[] artifactNames, AppInfo appInfo) {
177177
* @throws DependencyResolutionException If an error occurred during dependency resolution
178178
* @throws InterruptedException If the action execution was interrupted
179179
*/
180-
public int executeAction(String actionName)
180+
public int executeAction(String actionName, List<String> args)
181181
throws IOException, DependencyResolutionException, InterruptedException {
182182
AppInfo appInfo = AppInfo.read();
183183

184-
// Validate action name is provided
185-
if (actionName == null || actionName.trim().isEmpty()) {
186-
throw new IllegalArgumentException(
187-
"Action name is required. Use --list to see available actions.");
188-
}
189-
190184
// Get the action command
191185
String command = appInfo.getAction(actionName);
192186
if (command == null) {
@@ -202,7 +196,7 @@ public int executeAction(String actionName)
202196
classpath = this.path(new String[0]); // Empty array means use dependencies from app.yml
203197
}
204198

205-
return ScriptUtils.executeScript(command, classpath);
199+
return ScriptUtils.executeScript(command, args, classpath);
206200
}
207201

208202
/**

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

Lines changed: 157 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,11 @@
4646
Main.Search.class,
4747
Main.Install.class,
4848
Main.PrintPath.class,
49-
Main.Do.class
49+
Main.Do.class,
50+
Main.Clean.class,
51+
Main.Build.class,
52+
Main.Run.class,
53+
Main.Test.class
5054
})
5155
public class Main {
5256

@@ -72,8 +76,8 @@ static class Copy implements Callable<Integer> {
7276
public Integer call() throws Exception {
7377
SyncStats stats =
7478
Jpm.builder()
75-
.directory(artifactsMixin.copyMixin.directory)
76-
.noLinks(artifactsMixin.copyMixin.noLinks)
79+
.directory(artifactsMixin.depsMixin.directory)
80+
.noLinks(artifactsMixin.depsMixin.noLinks)
7781
.build()
7882
.copy(artifactsMixin.artifactNames, sync);
7983
if (!quietMixin.quiet) {
@@ -94,7 +98,7 @@ public Integer call() throws Exception {
9498
+ "Example:\n jpm search httpclient\n")
9599
static class Search implements Callable<Integer> {
96100
@Mixin QuietMixin quietMixin;
97-
@Mixin CopyMixin copyMixin;
101+
@Mixin DepsMixin depsMixin;
98102

99103
@Option(
100104
names = {"-i", "--interactive"},
@@ -133,8 +137,8 @@ public Integer call() throws Exception {
133137
if ("install".equals(artifactAction)) {
134138
SyncStats stats =
135139
Jpm.builder()
136-
.directory(copyMixin.directory)
137-
.noLinks(copyMixin.noLinks)
140+
.directory(depsMixin.directory)
141+
.noLinks(depsMixin.noLinks)
138142
.build()
139143
.install(new String[] {selectedArtifact});
140144
if (!quietMixin.quiet) {
@@ -143,8 +147,8 @@ public Integer call() throws Exception {
143147
} else if ("copy".equals(artifactAction)) {
144148
SyncStats stats =
145149
Jpm.builder()
146-
.directory(copyMixin.directory)
147-
.noLinks(copyMixin.noLinks)
150+
.directory(depsMixin.directory)
151+
.noLinks(depsMixin.noLinks)
148152
.build()
149153
.copy(new String[] {selectedArtifact}, false);
150154
if (!quietMixin.quiet) {
@@ -175,8 +179,8 @@ public Integer call() throws Exception {
175179
String[] search(String artifactPattern) {
176180
try {
177181
return Jpm.builder()
178-
.directory(copyMixin.directory)
179-
.noLinks(copyMixin.noLinks)
182+
.directory(depsMixin.directory)
183+
.noLinks(depsMixin.noLinks)
180184
.build()
181185
.search(artifactPattern, Math.min(max, 200));
182186
} catch (IOException e) {
@@ -272,8 +276,8 @@ static class Install implements Callable<Integer> {
272276
public Integer call() throws Exception {
273277
SyncStats stats =
274278
Jpm.builder()
275-
.directory(optionalArtifactsMixin.copyMixin.directory)
276-
.noLinks(optionalArtifactsMixin.copyMixin.noLinks)
279+
.directory(optionalArtifactsMixin.depsMixin.directory)
280+
.noLinks(optionalArtifactsMixin.depsMixin.noLinks)
277281
.build()
278282
.install(optionalArtifactsMixin.artifactNames);
279283
if (!quietMixin.quiet) {
@@ -297,8 +301,8 @@ static class PrintPath implements Callable<Integer> {
297301
public Integer call() throws Exception {
298302
List<Path> files =
299303
Jpm.builder()
300-
.directory(optionalArtifactsMixin.copyMixin.directory)
301-
.noLinks(optionalArtifactsMixin.copyMixin.noLinks)
304+
.directory(optionalArtifactsMixin.depsMixin.directory)
305+
.noLinks(optionalArtifactsMixin.depsMixin.noLinks)
302306
.build()
303307
.path(optionalArtifactsMixin.artifactNames);
304308
if (!files.isEmpty()) {
@@ -318,7 +322,7 @@ public Integer call() throws Exception {
318322
"Executes an action command defined in the app.yml file. Actions can use variable substitution for classpath.\n\n"
319323
+ "Example:\n jpm do build\n jpm do test\n")
320324
static class Do implements Callable<Integer> {
321-
@Mixin CopyMixin copyMixin;
325+
@Mixin DepsMixin depsMixin;
322326

323327
@Option(
324328
names = {"-l", "--list"},
@@ -327,19 +331,28 @@ static class Do implements Callable<Integer> {
327331
private boolean list;
328332

329333
@Parameters(
330-
paramLabel = "actionName",
334+
paramLabel = "action",
331335
description = "Name of the action to execute as defined in app.yml",
332-
arity = "0..1")
336+
arity = "0..*",
337+
index = "0")
333338
private String actionName;
334339

340+
@Parameters(
341+
paramLabel = "actionsAndArguments",
342+
description =
343+
"Optional additional actions and/or arguments to be passed to the action(s)",
344+
arity = "0..*",
345+
index = "1..*")
346+
private ArrayList<String> actsAndArgs = new ArrayList<>();
347+
335348
@Override
336349
public Integer call() throws Exception {
337350
try {
338351
if (list) {
339352
List<String> actionNames =
340353
Jpm.builder()
341-
.directory(copyMixin.directory)
342-
.noLinks(copyMixin.noLinks)
354+
.directory(depsMixin.directory)
355+
.noLinks(depsMixin.noLinks)
343356
.build()
344357
.listActions();
345358
if (actionNames.isEmpty()) {
@@ -348,22 +361,118 @@ public Integer call() throws Exception {
348361
System.out.println("Available actions:");
349362
actionNames.forEach(n -> System.out.println(" " + n));
350363
}
351-
return 0;
352364
} else {
353-
return Jpm.builder()
354-
.directory(copyMixin.directory)
355-
.noLinks(copyMixin.noLinks)
356-
.build()
357-
.executeAction(actionName);
365+
if (actionName == null || actionName.isEmpty()) {
366+
System.err.println(
367+
"Action name is required. Use --list to see available actions.");
368+
return 1;
369+
}
370+
// Split the full arguments list in multiple actions and their arguments
371+
int idx = 0;
372+
actsAndArgs.add(0, actionName);
373+
while (idx < actsAndArgs.size()) {
374+
String action = actsAndArgs.get(idx);
375+
if (action.startsWith("-")) {
376+
System.err.println(
377+
"Unexpected argument, was expecting an action name: " + action);
378+
return 1;
379+
}
380+
idx++;
381+
List<String> args = new ArrayList<>();
382+
while (idx < actsAndArgs.size() && actsAndArgs.get(idx).startsWith("-")) {
383+
String opt = actsAndArgs.get(idx);
384+
if (opt.equals("-a") || opt.equals("--arg")) {
385+
args.add(actsAndArgs.get(++idx));
386+
} else if (opt.startsWith("-a=") || opt.startsWith("--arg=")) {
387+
args.add(opt.substring(opt.indexOf('=') + 1));
388+
} else {
389+
System.err.println(
390+
"Unexpected argument, was expecting an action argument like '-a' or '--arg', not: "
391+
+ opt);
392+
return 1;
393+
}
394+
idx++;
395+
}
396+
int exitCode =
397+
Jpm.builder()
398+
.directory(depsMixin.directory)
399+
.noLinks(depsMixin.noLinks)
400+
.build()
401+
.executeAction(action, args);
402+
if (exitCode != 0) {
403+
return exitCode;
404+
}
405+
}
358406
}
359407
} catch (Exception e) {
360408
System.err.println(e.getMessage());
361409
return 1;
362410
}
411+
return 0;
412+
}
413+
}
414+
415+
abstract static class DoAlias implements Callable<Integer> {
416+
@Mixin DoAliasMixin doAliasMixin;
417+
418+
abstract String actionName();
419+
420+
@Override
421+
public Integer call() throws Exception {
422+
try {
423+
return Jpm.builder()
424+
.directory(doAliasMixin.depsMixin.directory)
425+
.noLinks(doAliasMixin.depsMixin.noLinks)
426+
.build()
427+
.executeAction(actionName(), doAliasMixin.args);
428+
} catch (Exception e) {
429+
System.err.println(e.getMessage());
430+
return 1;
431+
}
432+
}
433+
}
434+
435+
@Command(
436+
name = "clean",
437+
description = "Executes the 'clean' action as defined in the app.yml file.")
438+
static class Clean extends DoAlias {
439+
@Override
440+
String actionName() {
441+
return "clean";
442+
}
443+
}
444+
445+
@Command(
446+
name = "build",
447+
description = "Executes the 'build' action as defined in the app.yml file.")
448+
static class Build extends DoAlias {
449+
@Override
450+
String actionName() {
451+
return "build";
452+
}
453+
}
454+
455+
@Command(
456+
name = "run",
457+
description = "Executes the 'run' action as defined in the app.yml file.")
458+
static class Run extends DoAlias {
459+
@Override
460+
String actionName() {
461+
return "run";
462+
}
463+
}
464+
465+
@Command(
466+
name = "test",
467+
description = "Executes the 'test' action as defined in the app.yml file.")
468+
static class Test extends DoAlias {
469+
@Override
470+
String actionName() {
471+
return "test";
363472
}
364473
}
365474

366-
static class CopyMixin {
475+
static class DepsMixin {
367476
@Option(
368477
names = {"-d", "--directory"},
369478
description = "Directory to copy artifacts to",
@@ -377,8 +486,20 @@ static class CopyMixin {
377486
boolean noLinks;
378487
}
379488

489+
static class DoAliasMixin {
490+
@Mixin DepsMixin depsMixin;
491+
492+
@Parameters(
493+
paramLabel = "arguments",
494+
description =
495+
"Optional arguments to be passed to the action",
496+
arity = "0..*",
497+
index = "0..*")
498+
ArrayList<String> args = new ArrayList<>();
499+
}
500+
380501
static class ArtifactsMixin {
381-
@Mixin CopyMixin copyMixin;
502+
@Mixin DepsMixin depsMixin;
382503

383504
@Parameters(
384505
paramLabel = "artifacts",
@@ -389,7 +510,7 @@ static class ArtifactsMixin {
389510
}
390511

391512
static class OptionalArtifactsMixin {
392-
@Mixin CopyMixin copyMixin;
513+
@Mixin DepsMixin depsMixin;
393514

394515
@Parameters(
395516
paramLabel = "artifacts",
@@ -413,30 +534,19 @@ private static void printStats(SyncStats stats) {
413534
(Integer) stats.copied, (Integer) stats.updated, (Integer) stats.deleted);
414535
}
415536

537+
public static CommandLine getCommandLine() {
538+
return new CommandLine(new Main())
539+
.setStopAtPositional(true)
540+
.setAllowOptionsAsOptionParameters(true)
541+
.setAllowSubcommandsAsOptionParameters(true);
542+
}
543+
416544
/**
417545
* Main entry point for the jpm command line tool.
418546
*
419547
* @param args The command line arguments.
420548
*/
421549
public static void main(String... args) {
422-
if (args.length == 0) {
423-
System.err.println(
424-
"Running 'jpm search --interactive', try 'jpm --help' for more options");
425-
args = new String[] {"search", "--interactive"};
426-
}
427-
428-
// Handle common aliases
429-
if (args.length > 0) {
430-
String firstArg = args[0];
431-
if ("build".equals(firstArg) || "test".equals(firstArg) || "run".equals(firstArg)) {
432-
// Convert "jpm build", "jpm test", "jpm run" to "jpm do <command>"
433-
String[] newArgs = new String[args.length + 1];
434-
newArgs[0] = "do";
435-
System.arraycopy(args, 0, newArgs, 1, args.length);
436-
args = newArgs;
437-
}
438-
}
439-
440-
new CommandLine(new Main()).execute(args);
550+
getCommandLine().execute(args);
441551
}
442552
}

0 commit comments

Comments
 (0)