Add support for --json for `audit classpath`.
Summary:
Return the classpath for multiple targets, grouped by
target; sort stuff to make sure the output is stable.
Note: this doesn't throw if one of the targets
provided does not have a classpath; it's omitted from the output
instead.
diff --git a/src/com/facebook/buck/cli/AuditClasspathCommand.java b/src/com/facebook/buck/cli/AuditClasspathCommand.java
index 4672a92..1fa829e 100644
--- a/src/com/facebook/buck/cli/AuditClasspathCommand.java
+++ b/src/com/facebook/buck/cli/AuditClasspathCommand.java
@@ -27,10 +27,13 @@
import com.facebook.buck.rules.BuildRuleType;
import com.facebook.buck.rules.DependencyGraph;
import com.facebook.buck.util.HumanReadableException;
+import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
+import com.google.common.collect.TreeMultimap;
import java.io.IOException;
import java.util.List;
@@ -83,6 +86,8 @@
if (options.shouldGenerateDotOutput()) {
return printDotOutput(partialGraph.getDependencyGraph());
+ } else if (options.shouldGenerateJsonOutput()) {
+ return printJsonClasspath(partialGraph);
} else {
return printClasspath(partialGraph);
}
@@ -132,6 +137,35 @@
return 0;
}
+ @VisibleForTesting
+ int printJsonClasspath(PartialGraph partialGraph) throws IOException {
+ DependencyGraph graph = partialGraph.getDependencyGraph();
+ List<BuildTarget> targets = partialGraph.getTargets();
+ Multimap<String, String> targetClasspaths = TreeMultimap.create();
+
+ for (BuildTarget target : targets) {
+ BuildRule rule = graph.findBuildRuleByTarget(target);
+ if (!(rule instanceof HasClasspathEntries)) {
+ continue;
+ }
+
+ HasClasspathEntries classpathEntries = (HasClasspathEntries) rule;
+ targetClasspaths.putAll(
+ target.getFullyQualifiedName(),
+ classpathEntries.getTransitiveClasspathEntries().values());
+ }
+
+ ObjectMapper mapper = new ObjectMapper();
+
+ // Note: using `asMap` here ensures that the keys are sorted
+ mapper.writeValue(
+ console.getStdOut(),
+ targetClasspaths.asMap());
+
+ return 0;
+ }
+
+
@Override
String getUsageIntro() {
return "provides facilities to audit build targets' classpaths";
diff --git a/src/com/facebook/buck/cli/AuditCommandOptions.java b/src/com/facebook/buck/cli/AuditCommandOptions.java
index fdcd1b1..5667a27 100644
--- a/src/com/facebook/buck/cli/AuditCommandOptions.java
+++ b/src/com/facebook/buck/cli/AuditCommandOptions.java
@@ -36,6 +36,10 @@
usage = "Print dependencies as Dot graph")
private boolean generateDotOutput;
+ @Option(name = "--json",
+ usage = "Output in JSON format")
+ private boolean generateJsonOutput;
+
@Argument
private List<String> arguments = Lists.newArrayList();
@@ -54,4 +58,8 @@
public boolean shouldGenerateDotOutput() {
return generateDotOutput;
}
+
+ public boolean shouldGenerateJsonOutput() {
+ return generateJsonOutput;
+ }
}
diff --git a/test/com/facebook/buck/cli/AuditClasspathCommandTest.java b/test/com/facebook/buck/cli/AuditClasspathCommandTest.java
index a0fc18a..8f31a96 100644
--- a/test/com/facebook/buck/cli/AuditClasspathCommandTest.java
+++ b/test/com/facebook/buck/cli/AuditClasspathCommandTest.java
@@ -42,6 +42,7 @@
import com.facebook.buck.util.environment.Platform;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
@@ -50,6 +51,7 @@
import org.junit.Test;
import java.io.File;
+import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.SortedSet;
@@ -176,4 +178,43 @@
assertEquals(expectedClasspath, console.getTextWrittenToStdOut());
assertEquals("", console.getTextWrittenToStdErr());
}
+
+ private static final String EXPECTED_JSON = Joiner.on("").join(
+ "{",
+ "\"//:test-android-library\":",
+ "[",
+ "\"buck-out/gen/lib__test-android-library__output/test-android-library.jar\",",
+ "\"buck-out/gen/lib__test-java-library__output/test-java-library.jar\"",
+ "],",
+ "\"//:test-java-library\":",
+ "[",
+ "\"buck-out/gen/lib__test-java-library__output/test-java-library.jar\"",
+ "]",
+ "}");
+
+ @Test
+ public void testJsonClassPathOutput() throws IOException {
+ // Build a DependencyGraph of build rules manually.
+ BuildRuleResolver ruleResolver = new BuildRuleResolver();
+ ImmutableList<String> targets = ImmutableList.of(
+ "//:test-android-library",
+ "//:test-java-library");
+
+ ruleResolver.buildAndAddToIndex(
+ DefaultJavaLibraryRule.newJavaLibraryRuleBuilder(new FakeAbstractBuildRuleBuilderParams())
+ .setBuildTarget(BuildTargetFactory.newInstance("//:test-java-library"))
+ .addSrc("src/com/facebook/TestJavaLibrary.java"));
+ ruleResolver.buildAndAddToIndex(
+ DefaultJavaLibraryRule.newJavaLibraryRuleBuilder(new FakeAbstractBuildRuleBuilderParams())
+ .setBuildTarget(BuildTargetFactory.newInstance("//:test-android-library"))
+ .addSrc("src/com/facebook/TestAndroidLibrary.java")
+ .addDep(BuildTargetFactory.newInstance("//:test-java-library")));
+
+ PartialGraph partialGraph = createGraphFromBuildRules(ruleResolver, targets);
+ auditClasspathCommand.printJsonClasspath(partialGraph);
+
+ assertEquals(EXPECTED_JSON, console.getTextWrittenToStdOut());
+ assertEquals("", console.getTextWrittenToStdErr());
+ }
+
}