Skip to content

Commit 3f283fd

Browse files
committed
make output file optional and create output file if necessary
1 parent 598585b commit 3f283fd

File tree

2 files changed

+61
-26
lines changed

2 files changed

+61
-26
lines changed

framework/codemodder-base/src/main/java/io/codemodder/CLI.java

Lines changed: 33 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -274,20 +274,25 @@ public Integer call() throws IOException {
274274
logEnteringPhase(Logs.ExecutionPhase.STARTING);
275275
log.info("codemodder: java/{}", CLI.class.getPackage().getImplementationVersion());
276276

277-
if (output == null) {
278-
log.error("The output file is required");
279-
return ERROR_CANT_WRITE_OUTPUT_FILE;
280-
}
281-
282277
if (projectDirectory == null) {
283278
log.error("No project directory specified");
284279
return ERROR_CANT_READ_PROJECT_DIRECTORY;
285280
}
286281

287-
Path outputPath = output.toPath();
288-
if (!Files.isWritable(outputPath) && !Files.isWritable(outputPath.getParent())) {
289-
log.error("The output file (or its parent directory) is not writable");
290-
return ERROR_CANT_WRITE_OUTPUT_FILE;
282+
Path outputPath = null;
283+
if (output != null) {
284+
outputPath = output.toPath();
285+
286+
// check if the output file parent directory doesn't exist
287+
if (!Files.exists(outputPath.getParent())) {
288+
// create it
289+
Files.createDirectories(outputPath.getParent());
290+
}
291+
292+
if (!Files.isWritable(outputPath) && !Files.isWritable(outputPath.getParent())) {
293+
log.error("The output file (or its parent directory) is not writable");
294+
return ERROR_CANT_WRITE_OUTPUT_FILE;
295+
}
291296
}
292297

293298
Path projectPath = projectDirectory.toPath();
@@ -454,23 +459,25 @@ public Integer call() throws IOException {
454459
logEnteringPhase(Logs.ExecutionPhase.REPORT);
455460
logMetrics(results);
456461

457-
// write out the output
458-
if (OutputFormat.CODETF.equals(outputFormat)) {
459-
CodeTFReport report =
460-
reportGenerator.createReport(
461-
projectDirectory.toPath(),
462-
String.join(" ", args),
463-
sarifs == null
464-
? List.of()
465-
: sarifs.stream().map(Path::of).collect(Collectors.toList()),
466-
results,
467-
elapsed);
468-
ObjectMapper mapper = new ObjectMapper();
469-
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
470-
Files.writeString(outputPath, mapper.writeValueAsString(report));
471-
log.debug("report file: {}", outputPath);
472-
} else if (OutputFormat.DIFF.equals(outputFormat)) {
473-
throw new UnsupportedOperationException("not supported yet");
462+
// write out the output if they want it
463+
if (outputPath != null) {
464+
if (OutputFormat.CODETF.equals(outputFormat)) {
465+
CodeTFReport report =
466+
reportGenerator.createReport(
467+
projectDirectory.toPath(),
468+
String.join(" ", args),
469+
sarifs == null
470+
? List.of()
471+
: sarifs.stream().map(Path::of).collect(Collectors.toList()),
472+
results,
473+
elapsed);
474+
ObjectMapper mapper = new ObjectMapper();
475+
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
476+
Files.writeString(outputPath, mapper.writeValueAsString(report));
477+
log.debug("report file: {}", outputPath);
478+
} else if (OutputFormat.DIFF.equals(outputFormat)) {
479+
throw new UnsupportedOperationException("not supported yet");
480+
}
474481
}
475482

476483
log.debug("elapsed: {}ms", elapsed);

framework/codemodder-base/src/test/java/io/codemodder/CLITest.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,23 @@ void setup(final @TempDir Path tmpDir) throws IOException {
6161
List.of(barJavaFile.toAbsolutePath().toString())));
6262
}
6363

64+
@Test
65+
void it_works_normally() throws IOException {
66+
Path outputFile = Files.createTempFile("codetf", ".json");
67+
String[] args =
68+
new String[] {"--dont-exit", "--output", outputFile.toString(), workingRepoDir.toString()};
69+
Runner.run(List.of(Cloud9Changer.class), args);
70+
assertThat(Files.readString(fooJavaFile)).contains("cloud9");
71+
assertThat(Files.exists(outputFile)).isTrue();
72+
}
73+
74+
@Test
75+
void it_works_without_output_file() throws IOException {
76+
String[] args = new String[] {"--dont-exit", workingRepoDir.toString()};
77+
Runner.run(List.of(Cloud9Changer.class), args);
78+
assertThat(Files.readString(fooJavaFile)).contains("cloud9");
79+
}
80+
6481
/**
6582
* Runs the CLI with arguments that we know will cause it to fail, and asserts that the exit code
6683
* denotes failure and an error message is captured in the alternative stderr stream.
@@ -107,6 +124,17 @@ private static void writeLogMessageToFile(final Path outputFile, final String pr
107124
log.info("this is a test");
108125
}
109126

127+
@Test
128+
void output_file_parent_dirs_created() throws IOException {
129+
Path normalCodetf = Files.createTempDirectory("exists");
130+
Path outputFile = normalCodetf.resolve("doesnt/exist/codetf.json");
131+
String[] args =
132+
new String[] {"--dont-exit", "--output", outputFile.toString(), workingRepoDir.toString()};
133+
Runner.run(List.of(Cloud9Changer.class), args);
134+
assertThat(Files.readString(fooJavaFile)).contains("cloud9");
135+
assertThat(Files.exists(outputFile)).isTrue();
136+
}
137+
110138
@Test
111139
void dry_run_works() throws IOException {
112140
Path normalCodetf = Files.createTempFile("normal", ".codetf");

0 commit comments

Comments
 (0)