aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com
diff options
context:
space:
mode:
authorGravatar Luis Fernando Pino Duque <lpino@google.com>2016-05-03 15:44:16 +0000
committerGravatar Kristina Chodorow <kchodorow@google.com>2016-05-03 21:31:21 +0000
commitf07b76e5fc9a07cbc0b2b45d5bfe8eb4b1ec2e03 (patch)
tree737d4e6348234360403a65bc3dacedf1d5b432ab /src/main/java/com
parent4b71d2e1bc3afa0ce0a5b6e68dac3c559654d975 (diff)
Redesign InfoItem to use classes instead of the InfoKey enum. This way the InfoItems can
now take parameters. -- MOS_MIGRATED_REVID=121379097
Diffstat (limited to 'src/main/java/com')
-rw-r--r--src/main/java/com/google/devtools/build/lib/runtime/BlazeModule.java31
-rw-r--r--src/main/java/com/google/devtools/build/lib/runtime/commands/HelpCommand.java10
-rw-r--r--src/main/java/com/google/devtools/build/lib/runtime/commands/InfoCommand.java303
-rw-r--r--src/main/java/com/google/devtools/build/lib/runtime/commands/InfoItem.java627
-rw-r--r--src/main/java/com/google/devtools/build/lib/runtime/commands/InfoKey.java95
5 files changed, 683 insertions, 383 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/BlazeModule.java b/src/main/java/com/google/devtools/build/lib/runtime/BlazeModule.java
index a75e20722a..0037fd0d2f 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/BlazeModule.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/BlazeModule.java
@@ -14,7 +14,6 @@
package com.google.devtools.build.lib.runtime;
import com.google.common.base.Predicate;
-import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.actions.ActionContextConsumer;
@@ -24,7 +23,6 @@ import com.google.devtools.build.lib.analysis.BlazeDirectories;
import com.google.devtools.build.lib.analysis.BlazeVersionInfo;
import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider;
import com.google.devtools.build.lib.analysis.WorkspaceStatusAction;
-import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.exec.OutputService;
import com.google.devtools.build.lib.packages.NoSuchThingException;
@@ -35,6 +33,7 @@ import com.google.devtools.build.lib.query2.QueryEnvironmentFactory;
import com.google.devtools.build.lib.query2.engine.QueryEnvironment.QueryFunction;
import com.google.devtools.build.lib.query2.output.OutputFormatter;
import com.google.devtools.build.lib.rules.test.CoverageReportActionFactory;
+import com.google.devtools.build.lib.runtime.commands.InfoItem;
import com.google.devtools.build.lib.runtime.proto.InvocationPolicyOuterClass.InvocationPolicy;
import com.google.devtools.build.lib.skyframe.DiffAwareness;
import com.google.devtools.build.lib.skyframe.PrecomputedValue.Injected;
@@ -254,34 +253,6 @@ public abstract class BlazeModule {
}
/**
- * A item that is returned by "blaze info".
- */
- public interface InfoItem {
- /**
- * The name of the info key.
- */
- String getName();
-
- /**
- * The help description of the info key.
- */
- String getDescription();
-
- /**
- * Whether the key is printed when "blaze info" is invoked without arguments.
- *
- * <p>This is usually true for info keys that take multiple lines, thus, cannot really be
- * included in the output of argumentless "blaze info".
- */
- boolean isHidden();
-
- /**
- * Returns the value of the info key. The return value is directly printed to stdout.
- */
- byte[] get(Supplier<BuildConfiguration> configurationSupplier) throws AbruptExitException;
- }
-
- /**
* Returns the additional information this module provides to "blaze info".
*
* <p>This method will be called at the beginning of each "blaze info" command (after
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/commands/HelpCommand.java b/src/main/java/com/google/devtools/build/lib/runtime/commands/HelpCommand.java
index a514596719..08ef73eae8 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/commands/HelpCommand.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/commands/HelpCommand.java
@@ -159,7 +159,7 @@ public final class HelpCommand implements BlazeCommand {
emitTargetSyntaxHelp(outErr, getOptionCategories(runtime));
return ExitCode.SUCCESS;
} else if (helpSubject.equals("info-keys")) {
- emitInfoKeysHelp(runtime, outErr);
+ emitInfoKeysHelp(env, outErr);
return ExitCode.SUCCESS;
} else if (helpSubject.equals("completion")) {
emitCompletionHelp(runtime, outErr);
@@ -218,8 +218,8 @@ public final class HelpCommand implements BlazeCommand {
outErr.printOutLn("BAZEL_COMMAND_LIST=\"" + SPACE_JOINER.join(commands) + "\"");
outErr.printOutLn("BAZEL_INFO_KEYS=\"");
- for (InfoKey key : InfoKey.values()) {
- outErr.printOutLn(key.getName());
+ for (String name : InfoCommand.getHardwiredInfoItemNames(Constants.PRODUCT_NAME)) {
+ outErr.printOutLn(name);
}
outErr.printOutLn("\"");
@@ -253,8 +253,8 @@ public final class HelpCommand implements BlazeCommand {
OptionsParser.HelpVerbosity.MEDIUM));
}
- private void emitInfoKeysHelp(BlazeRuntime runtime, OutErr outErr) {
- for (BlazeModule.InfoItem item : InfoCommand.getInfoItemMap(runtime,
+ private void emitInfoKeysHelp(CommandEnvironment env, OutErr outErr) {
+ for (InfoItem item : InfoCommand.getInfoItemMap(env,
OptionsParser.newOptionsParser(
ImmutableList.<Class<? extends OptionsBase>>of())).values()) {
outErr.printOut(String.format("%-23s %s\n", item.getName(), item.getDescription()));
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/commands/InfoCommand.java b/src/main/java/com/google/devtools/build/lib/runtime/commands/InfoCommand.java
index fd5adcbc96..a2badf3c31 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/commands/InfoCommand.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/commands/InfoCommand.java
@@ -13,51 +13,31 @@
// limitations under the License.
package com.google.devtools.build.lib.runtime.commands;
-import com.google.common.base.Joiner;
-import com.google.common.base.Predicate;
-import com.google.common.base.Predicates;
import com.google.common.base.Supplier;
-import com.google.common.collect.Iterables;
-import com.google.devtools.build.lib.analysis.BlazeVersionInfo;
+import com.google.common.base.Verify;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.devtools.build.lib.Constants;
import com.google.devtools.build.lib.analysis.NoBuildEvent;
import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
import com.google.devtools.build.lib.analysis.config.InvalidConfigurationException;
import com.google.devtools.build.lib.events.Event;
-import com.google.devtools.build.lib.packages.Attribute;
-import com.google.devtools.build.lib.packages.BuildType;
-import com.google.devtools.build.lib.packages.ProtoUtils;
-import com.google.devtools.build.lib.packages.RuleClass;
-import com.google.devtools.build.lib.packages.RuleClassProvider;
import com.google.devtools.build.lib.pkgcache.PackageCacheOptions;
-import com.google.devtools.build.lib.query2.proto.proto2api.Build.AllowedRuleClassInfo;
-import com.google.devtools.build.lib.query2.proto.proto2api.Build.AttributeDefinition;
-import com.google.devtools.build.lib.query2.proto.proto2api.Build.BuildLanguage;
-import com.google.devtools.build.lib.query2.proto.proto2api.Build.RuleDefinition;
import com.google.devtools.build.lib.runtime.BlazeCommand;
-import com.google.devtools.build.lib.runtime.BlazeCommandDispatcher;
import com.google.devtools.build.lib.runtime.BlazeModule;
import com.google.devtools.build.lib.runtime.BlazeRuntime;
import com.google.devtools.build.lib.runtime.Command;
import com.google.devtools.build.lib.runtime.CommandEnvironment;
import com.google.devtools.build.lib.util.AbruptExitException;
import com.google.devtools.build.lib.util.ExitCode;
-import com.google.devtools.build.lib.util.OsUtils;
-import com.google.devtools.build.lib.util.StringUtilities;
import com.google.devtools.build.lib.util.io.OutErr;
import com.google.devtools.common.options.Option;
import com.google.devtools.common.options.OptionsBase;
import com.google.devtools.common.options.OptionsParser;
import com.google.devtools.common.options.OptionsProvider;
-import java.io.ByteArrayOutputStream;
import java.io.IOException;
-import java.io.PrintWriter;
-import java.lang.management.GarbageCollectorMXBean;
-import java.lang.management.ManagementFactory;
-import java.lang.management.MemoryMXBean;
-import java.lang.management.MemoryUsage;
import java.nio.charset.StandardCharsets;
-import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
@@ -115,68 +95,6 @@ public class InfoCommand implements BlazeCommand {
}
}
- private static class HardwiredInfoItem implements BlazeModule.InfoItem {
- private final InfoKey key;
- private final BlazeRuntime runtime;
- private final OptionsProvider commandOptions;
-
- private HardwiredInfoItem(InfoKey key, BlazeRuntime runtime, OptionsProvider commandOptions) {
- this.key = key;
- this.runtime = runtime;
- this.commandOptions = commandOptions;
- }
-
- @Override
- public String getName() {
- return key.getName();
- }
-
- @Override
- public String getDescription() {
- return key.getDescription();
- }
-
- @Override
- public boolean isHidden() {
- return key.isHidden();
- }
-
- @Override
- public byte[] get(Supplier<BuildConfiguration> configurationSupplier) {
- return print(getInfoItem(runtime, key, configurationSupplier, commandOptions));
- }
- }
-
- private static class MakeInfoItem implements BlazeModule.InfoItem {
- private final String name;
- private final String value;
-
- private MakeInfoItem(String name, String value) {
- this.name = name;
- this.value = value;
- }
-
- @Override
- public String getName() {
- return name;
- }
-
- @Override
- public String getDescription() {
- return "Make environment variable '" + name + "'";
- }
-
- @Override
- public boolean isHidden() {
- return false;
- }
-
- @Override
- public byte[] get(Supplier<BuildConfiguration> configurationSupplier) {
- return print(value);
- }
- }
-
@Override
public void editOptions(CommandEnvironment env, OptionsParser optionsParser) { }
@@ -220,13 +138,13 @@ public class InfoCommand implements BlazeCommand {
}
};
- Map<String, BlazeModule.InfoItem> items = getInfoItemMap(runtime, optionsProvider);
+ Map<String, InfoItem> items = getInfoItemMap(env, optionsProvider);
try {
if (infoOptions.showMakeEnvironment) {
Map<String, String> makeEnv = configurationSupplier.get().getMakeEnvironment();
for (Map.Entry<String, String> entry : makeEnv.entrySet()) {
- BlazeModule.InfoItem item = new MakeInfoItem(entry.getKey(), entry.getValue());
+ InfoItem item = new InfoItem.MakeInfoItem(entry.getKey(), entry.getValue());
items.put(item.getName(), item);
}
}
@@ -242,7 +160,7 @@ public class InfoCommand implements BlazeCommand {
if (key != null) { // print just the value for the specified key:
byte[] value;
if (items.containsKey(key)) {
- value = items.get(key).get(configurationSupplier);
+ value = items.get(key).get(configurationSupplier, env);
} else {
env.getReporter().handle(Event.error("unknown key: '" + key + "'"));
return ExitCode.COMMAND_LINE_ERROR;
@@ -256,13 +174,13 @@ public class InfoCommand implements BlazeCommand {
}
} else { // print them all
configurationSupplier.get(); // We'll need this later anyway
- for (BlazeModule.InfoItem infoItem : items.values()) {
+ for (InfoItem infoItem : items.values()) {
if (infoItem.isHidden()) {
continue;
}
outErr.getOutputStream().write(
(infoItem.getName() + ": ").getBytes(StandardCharsets.UTF_8));
- outErr.getOutputStream().write(infoItem.get(configurationSupplier));
+ outErr.getOutputStream().write(infoItem.get(configurationSupplier, env));
}
}
} catch (AbruptExitException e) {
@@ -275,177 +193,56 @@ public class InfoCommand implements BlazeCommand {
return ExitCode.SUCCESS;
}
- /**
- * Compute and return the info for the given key. Only keys that are not hidden are supported
- * here.
- */
- private static Object getInfoItem(BlazeRuntime runtime, InfoKey key,
- Supplier<BuildConfiguration> configurationSupplier, OptionsProvider options) {
- switch (key) {
- // directories
- case WORKSPACE : return runtime.getWorkspace().getWorkspace();
- case INSTALL_BASE : return runtime.getWorkspace().getInstallBase();
- case OUTPUT_BASE : return runtime.getWorkspace().getOutputBase();
- case EXECUTION_ROOT : return runtime.getWorkspace().getExecRoot();
- case OUTPUT_PATH : return runtime.getWorkspace().getOutputPath();
- // These are the only (non-hidden) info items that require a configuration, because the
- // corresponding paths contain the short name. Maybe we should recommend using the symlinks
- // or make them hidden by default?
- case BLAZE_BIN : return configurationSupplier.get().getBinDirectory().getPath();
- case BLAZE_GENFILES : return configurationSupplier.get().getGenfilesDirectory().getPath();
- case BLAZE_TESTLOGS : return configurationSupplier.get().getTestLogsDirectory().getPath();
-
- // logs
- case COMMAND_LOG : return BlazeCommandDispatcher.getCommandLogPath(
- runtime.getWorkspace().getOutputBase());
- case MESSAGE_LOG :
- // NB: Duplicated in EventLogModule
- return runtime.getWorkspace().getOutputBase().getRelative("message.log");
-
- // misc
- case RELEASE : return BlazeVersionInfo.instance().getReleaseName();
- case SERVER_PID : return OsUtils.getpid();
- case PACKAGE_PATH : return getPackagePath(options);
-
- // memory statistics
- case GC_COUNT :
- case GC_TIME :
- // The documentation is not very clear on what it means to have more than
- // one GC MXBean, so we just sum them up.
- int gcCount = 0;
- int gcTime = 0;
- for (GarbageCollectorMXBean gcBean : ManagementFactory.getGarbageCollectorMXBeans()) {
- gcCount += gcBean.getCollectionCount();
- gcTime += gcBean.getCollectionTime();
- }
- if (key == InfoKey.GC_COUNT) {
- return gcCount + "";
- } else {
- return gcTime + "ms";
- }
-
- case MAX_HEAP_SIZE :
- return StringUtilities.prettyPrintBytes(getMemoryUsage().getMax());
- case USED_HEAP_SIZE :
- case COMMITTED_HEAP_SIZE :
- return StringUtilities.prettyPrintBytes(key == InfoKey.USED_HEAP_SIZE ?
- getMemoryUsage().getUsed() : getMemoryUsage().getCommitted());
-
- case USED_HEAP_SIZE_AFTER_GC :
- // Note that this info value is not printed by default, but only when explicitly requested.
- System.gc();
- return StringUtilities.prettyPrintBytes(getMemoryUsage().getUsed());
-
- case DEFAULTS_PACKAGE:
- return runtime.getDefaultsPackageContent();
-
- case BUILD_LANGUAGE:
- return getBuildLanguageDefinition(runtime.getRuleClassProvider());
-
- case DEFAULT_PACKAGE_PATH:
- return Joiner.on(":").join(options.getOptions(PackageCacheOptions.class).packagePath);
-
- default:
- throw new IllegalArgumentException("missing implementation for " + key);
- }
- }
-
- private static MemoryUsage getMemoryUsage() {
- MemoryMXBean memBean = ManagementFactory.getMemoryMXBean();
- return memBean.getHeapMemoryUsage();
- }
-
- /**
- * Get the package_path variable for the given set of options.
- */
- private static String getPackagePath(OptionsProvider options) {
- PackageCacheOptions packageCacheOptions =
- options.getOptions(PackageCacheOptions.class);
- return Joiner.on(":").join(packageCacheOptions.packagePath);
- }
-
- private static AllowedRuleClassInfo getAllowedRuleClasses(
- Collection<RuleClass> ruleClasses, Attribute attr) {
- AllowedRuleClassInfo.Builder info = AllowedRuleClassInfo.newBuilder();
- info.setPolicy(AllowedRuleClassInfo.AllowedRuleClasses.ANY);
-
- if (attr.isStrictLabelCheckingEnabled()
- && attr.getAllowedRuleClassesPredicate() != Predicates.<RuleClass>alwaysTrue()) {
- info.setPolicy(AllowedRuleClassInfo.AllowedRuleClasses.SPECIFIED);
- Predicate<RuleClass> filter = attr.getAllowedRuleClassesPredicate();
- for (RuleClass otherClass : Iterables.filter(ruleClasses, filter)) {
- if (otherClass.isDocumented()) {
- info.addAllowedRuleClass(otherClass.getName());
- }
- }
- }
-
- return info.build();
- }
-
- /**
- * Returns a byte array containing a proto-buffer describing the build language.
- */
- private static byte[] getBuildLanguageDefinition(RuleClassProvider provider) {
- BuildLanguage.Builder resultPb = BuildLanguage.newBuilder();
- Collection<RuleClass> ruleClasses = provider.getRuleClassMap().values();
- for (RuleClass ruleClass : ruleClasses) {
- if (!ruleClass.isDocumented()) {
- continue;
- }
-
- RuleDefinition.Builder rulePb = RuleDefinition.newBuilder();
- rulePb.setName(ruleClass.getName());
- for (Attribute attr : ruleClass.getAttributes()) {
- if (!attr.isDocumented()) {
- continue;
- }
-
- AttributeDefinition.Builder attrPb = AttributeDefinition.newBuilder();
- attrPb.setName(attr.getName());
- // The protocol compiler, in its infinite wisdom, generates the field as one of the
- // integer type and the getTypeEnum() method is missing. WTF?
- attrPb.setType(ProtoUtils.getDiscriminatorFromType(attr.getType()));
- attrPb.setMandatory(attr.isMandatory());
-
- if (BuildType.isLabelType(attr.getType())) {
- attrPb.setAllowedRuleClasses(getAllowedRuleClasses(ruleClasses, attr));
- }
-
- rulePb.addAttribute(attrPb);
- }
-
- resultPb.addRule(rulePb);
+ static Map<String, InfoItem> getHardwiredInfoItemMap(OptionsProvider commandOptions,
+ String productName) {
+ List<InfoItem> hardwiredInfoItems = ImmutableList.<InfoItem>of(
+ new InfoItem.WorkspaceInfoItem(),
+ new InfoItem.InstallBaseInfoItem(),
+ new InfoItem.OutputBaseInfoItem(),
+ new InfoItem.ExecutionRootInfoItem(),
+ new InfoItem.OutputPathInfoItem(),
+ new InfoItem.BlazeBinInfoItem(productName),
+ new InfoItem.BlazeGenfilesInfoItem(productName),
+ new InfoItem.BlazeTestlogsInfoItem(productName),
+ new InfoItem.CommandLogInfoItem(),
+ new InfoItem.MessageLogInfoItem(),
+ new InfoItem.ReleaseInfoItem(productName),
+ new InfoItem.ServerPidInfoItem(productName),
+ new InfoItem.PackagePathInfoItem(commandOptions),
+ new InfoItem.UsedHeapSizeInfoItem(),
+ new InfoItem.UsedHeapSizeAfterGcInfoItem(),
+ new InfoItem.CommitedHeapSizeInfoItem(),
+ new InfoItem.MaxHeapSizeInfoItem(),
+ new InfoItem.GcTimeInfoItem(),
+ new InfoItem.GcCountInfoItem(),
+ new InfoItem.DefaultsPackageInfoItem(),
+ new InfoItem.BuildLanguageInfoItem(),
+ new InfoItem.DefaultPackagePathInfoItem(commandOptions));
+ ImmutableMap.Builder<String, InfoItem> result = new ImmutableMap.Builder<>();
+ for (InfoItem item : hardwiredInfoItems) {
+ result.put(item.getName(), item);
}
-
- return resultPb.build().toByteArray();
+ return result.build();
}
- private static byte[] print(Object value) {
- if (value instanceof byte[]) {
- return (byte[]) value;
+ public static List<String> getHardwiredInfoItemNames(String productName) {
+ ImmutableList.Builder<String> result = new ImmutableList.Builder<>();
+ for (String name : InfoCommand.getHardwiredInfoItemMap(null, productName).keySet()) {
+ result.add(name);
}
- ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
- PrintWriter writer = new PrintWriter(outputStream);
- writer.print(value + "\n");
- writer.flush();
- return outputStream.toByteArray();
+ return result.build();
}
- static Map<String, BlazeModule.InfoItem> getInfoItemMap(
- BlazeRuntime runtime, OptionsProvider commandOptions) {
- Map<String, BlazeModule.InfoItem> result = new TreeMap<>(); // order by key
- for (BlazeModule module : runtime.getBlazeModules()) {
- for (BlazeModule.InfoItem item : module.getInfoItems()) {
+ static Map<String, InfoItem> getInfoItemMap(
+ CommandEnvironment env, OptionsProvider commandOptions) {
+ Map<String, InfoItem> result = new TreeMap<>(); // order by key
+ for (BlazeModule module : env.getRuntime().getBlazeModules()) {
+ for (InfoItem item : module.getInfoItems()) {
+ Verify.verify(!result.containsKey(item.getName()));
result.put(item.getName(), item);
}
}
-
- for (InfoKey key : InfoKey.values()) {
- BlazeModule.InfoItem item = new HardwiredInfoItem(key, runtime, commandOptions);
- result.put(item.getName(), item);
- }
-
+ result.putAll(getHardwiredInfoItemMap(commandOptions, Constants.PRODUCT_NAME));
return result;
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/commands/InfoItem.java b/src/main/java/com/google/devtools/build/lib/runtime/commands/InfoItem.java
new file mode 100644
index 0000000000..923f29ce0c
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/runtime/commands/InfoItem.java
@@ -0,0 +1,627 @@
+// Copyright 2014 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package com.google.devtools.build.lib.runtime.commands;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.common.base.Joiner;
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+import com.google.common.base.Supplier;
+import com.google.common.collect.Iterables;
+import com.google.devtools.build.lib.Constants;
+import com.google.devtools.build.lib.analysis.BlazeVersionInfo;
+import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
+import com.google.devtools.build.lib.packages.Attribute;
+import com.google.devtools.build.lib.packages.BuildType;
+import com.google.devtools.build.lib.packages.ProtoUtils;
+import com.google.devtools.build.lib.packages.RuleClass;
+import com.google.devtools.build.lib.packages.RuleClassProvider;
+import com.google.devtools.build.lib.pkgcache.PackageCacheOptions;
+import com.google.devtools.build.lib.query2.proto.proto2api.Build.AllowedRuleClassInfo;
+import com.google.devtools.build.lib.query2.proto.proto2api.Build.AttributeDefinition;
+import com.google.devtools.build.lib.query2.proto.proto2api.Build.BuildLanguage;
+import com.google.devtools.build.lib.query2.proto.proto2api.Build.RuleDefinition;
+import com.google.devtools.build.lib.runtime.BlazeCommandDispatcher;
+import com.google.devtools.build.lib.runtime.CommandEnvironment;
+import com.google.devtools.build.lib.util.AbruptExitException;
+import com.google.devtools.build.lib.util.OsUtils;
+import com.google.devtools.build.lib.util.StringUtilities;
+import com.google.devtools.common.options.OptionsProvider;
+import java.io.ByteArrayOutputStream;
+import java.io.PrintWriter;
+import java.lang.management.GarbageCollectorMXBean;
+import java.lang.management.ManagementFactory;
+import java.lang.management.MemoryMXBean;
+import java.lang.management.MemoryUsage;
+import java.util.Collection;
+
+/**
+ * An item that is returned by <code>blaze info</code>.
+ */
+public abstract class InfoItem {
+ protected final String name;
+ protected final String description;
+ protected final boolean hidden;
+
+ protected InfoItem(String name,
+ String description,
+ boolean hidden) {
+ this.name = name;
+ this.description = description;
+ this.hidden = hidden;
+ }
+
+ protected InfoItem(String name,
+ String description) {
+ this(name, description, false);
+ }
+
+ /**
+ * The name of the info key.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * The help description of the info key.
+ */
+ public String getDescription() {
+ return description;
+ }
+
+ /**
+ * Whether the key is printed when "blaze info" is invoked without arguments.
+ *
+ * <p>This is usually true for info keys that take multiple lines, thus, cannot really be
+ * included in the output of argumentless "blaze info".
+ */
+ public boolean isHidden() {
+ return hidden;
+ }
+
+ /**
+ * Returns the value of the info key. The return value is directly printed to stdout.
+ * @param env TODO(lpino):
+ */
+ public abstract byte[] get(Supplier<BuildConfiguration> configurationSupplier,
+ CommandEnvironment env) throws AbruptExitException;
+
+ private static byte[] print(Object value) {
+ if (value instanceof byte[]) {
+ return (byte[]) value;
+ }
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ PrintWriter writer = new PrintWriter(outputStream);
+ writer.print(value + "\n");
+ writer.flush();
+ return outputStream.toByteArray();
+ }
+
+ /**
+ * Info item for the workspace directory.
+ */
+ public static final class WorkspaceInfoItem extends InfoItem {
+ public WorkspaceInfoItem() {
+ super("workspace",
+ "The working directory of the server.");
+ }
+
+ @Override
+ public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
+ throws AbruptExitException {
+ checkNotNull(env);
+ return print(env.getRuntime().getWorkspace().getWorkspace());
+ }
+ }
+
+ /**
+ * Info item for the install_base directory.
+ */
+ public static final class InstallBaseInfoItem extends InfoItem {
+ public InstallBaseInfoItem() {
+ super("install_base",
+ "The installation base directory.",
+ false);
+ }
+
+ @Override
+ public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
+ throws AbruptExitException {
+ checkNotNull(env);
+ return print(env.getRuntime().getWorkspace().getInstallBase());
+ }
+ }
+
+ /**
+ * Info item for the output_base directory.
+ */
+ public static final class OutputBaseInfoItem extends InfoItem {
+ public OutputBaseInfoItem() {
+ super("output_base",
+ "A directory for shared " + Constants.PRODUCT_NAME
+ + " state as well as tool and strategy specific subdirectories.",
+ false);
+ }
+
+ @Override
+ public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
+ throws AbruptExitException {
+ checkNotNull(env);
+ return print(env.getRuntime().getWorkspace().getOutputBase());
+ }
+ }
+
+ /**
+ * Info item for the execution_root directory.
+ */
+ public static final class ExecutionRootInfoItem extends InfoItem {
+ public ExecutionRootInfoItem() {
+ super("execution_root",
+ "A directory that makes all input and output files visible to the build.",
+ false);
+ }
+
+ @Override
+ public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
+ throws AbruptExitException {
+ checkNotNull(env);
+ return print(env.getRuntime().getWorkspace().getExecRoot());
+ }
+ }
+
+ /**
+ * Info item for the output_path directory.
+ */
+ public static final class OutputPathInfoItem extends InfoItem {
+ public OutputPathInfoItem() {
+ super("output_path",
+ "Output directory",
+ false);
+ }
+
+ @Override
+ public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
+ throws AbruptExitException {
+ checkNotNull(env);
+ return print(env.getRuntime().getWorkspace().getOutputPath());
+ }
+ }
+
+ /**
+ * Info item for the {blaze,bazel}-bin directory.
+ */
+ public static final class BlazeBinInfoItem extends InfoItem {
+ public BlazeBinInfoItem(String productName) {
+ super(productName + "-bin",
+ "Configuration dependent directory for binaries.",
+ false);
+ }
+
+ // This is one of the three (non-hidden) info items that require a configuration, because the
+ // corresponding paths contain the short name. Maybe we should recommend using the symlinks
+ // or make them hidden by default?
+ @Override
+ public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
+ throws AbruptExitException {
+ checkNotNull(configurationSupplier);
+ return print(configurationSupplier.get().getBinDirectory().getPath());
+ }
+ }
+
+ /**
+ * Info item for the {blaze,bazel}-genfiles directory.
+ */
+ public static final class BlazeGenfilesInfoItem extends InfoItem {
+ public BlazeGenfilesInfoItem(String productName) {
+ super(productName + "-genfiles",
+ "Configuration dependent directory for generated files.",
+ false);
+ }
+
+ // This is one of the three (non-hidden) info items that require a configuration, because the
+ // corresponding paths contain the short name. Maybe we should recommend using the symlinks
+ // or make them hidden by default?
+ @Override
+ public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
+ throws AbruptExitException {
+ checkNotNull(configurationSupplier);
+ return print(configurationSupplier.get().getGenfilesDirectory().getPath());
+ }
+ }
+
+ /**
+ * Info item for the {blaze,bazel}-testlogs directory.
+ */
+ public static final class BlazeTestlogsInfoItem extends InfoItem {
+ public BlazeTestlogsInfoItem(String productName) {
+ super(productName + "-testlogs",
+ "Configuration dependent directory for logs from a test run.",
+ false);
+ }
+
+ // This is one of the three (non-hidden) info items that require a configuration, because the
+ // corresponding paths contain the short name. Maybe we should recommend using the symlinks
+ // or make them hidden by default?
+ @Override
+ public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
+ throws AbruptExitException {
+ checkNotNull(configurationSupplier);
+ return print(configurationSupplier.get().getTestLogsDirectory().getPath());
+ }
+ }
+
+ /**
+ * Info item for the command log
+ */
+ public static final class CommandLogInfoItem extends InfoItem {
+ public CommandLogInfoItem() {
+ super("command_log",
+ "Location of the log containg the output from the build commands.",
+ false);
+ }
+
+ @Override
+ public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
+ throws AbruptExitException {
+ checkNotNull(env);
+ return print(BlazeCommandDispatcher.getCommandLogPath(
+ env.getRuntime().getWorkspace().getOutputBase()));
+ }
+ }
+
+ /**
+ * Info item for the message log
+ */
+ public static final class MessageLogInfoItem extends InfoItem {
+ public MessageLogInfoItem() {
+ super("message_log" ,
+ "Location of a log containing machine readable message in LogMessage protobuf format.",
+ false);
+ }
+
+ @Override
+ public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
+ throws AbruptExitException {
+ checkNotNull(configurationSupplier);
+ // NB: Duplicated in EventLogModule
+ return print(env.getRuntime().getWorkspace().getOutputBase().getRelative("message.log"));
+ }
+ }
+
+ /**
+ * Info item for release
+ */
+ public static final class ReleaseInfoItem extends InfoItem {
+ public ReleaseInfoItem(String productName) {
+ super("release",
+ productName + " release identifier",
+ false);
+ }
+
+ @Override
+ public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
+ throws AbruptExitException {
+ return print(BlazeVersionInfo.instance().getReleaseName());
+ }
+ }
+
+ /**
+ * Info item for server_pid
+ */
+ public static final class ServerPidInfoItem extends InfoItem {
+ public ServerPidInfoItem(String productName) {
+ super("server_pid",
+ productName + " process id",
+ false);
+ }
+
+ @Override
+ public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
+ throws AbruptExitException {
+ return print(OsUtils.getpid());
+ }
+ }
+
+ /**
+ * Info item for package_path
+ */
+ public static final class PackagePathInfoItem extends InfoItem {
+ private final OptionsProvider commandOptions;
+
+ public PackagePathInfoItem(OptionsProvider commandOptions) {
+ super("package_path",
+ "The search path for resolving package labels.",
+ false);
+ this.commandOptions = commandOptions;
+ }
+
+ @Override
+ public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
+ throws AbruptExitException {
+ checkNotNull(commandOptions);
+ PackageCacheOptions packageCacheOptions =
+ commandOptions.getOptions(PackageCacheOptions.class);
+ return print(Joiner.on(":").join(packageCacheOptions.packagePath));
+ }
+ }
+
+ private static MemoryUsage getMemoryUsage() {
+ MemoryMXBean memBean = ManagementFactory.getMemoryMXBean();
+ return memBean.getHeapMemoryUsage();
+ }
+
+ /**
+ * Info item for the used heap size
+ */
+ public static final class UsedHeapSizeInfoItem extends InfoItem {
+ public UsedHeapSizeInfoItem() {
+ super("used-heap-size",
+ "The amount of used memory in bytes. Note that this is not a "
+ + "good indicator of the actual memory use, as it includes any remaining inaccessible "
+ + "memory.",
+ false);
+ }
+
+ @Override
+ public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
+ throws AbruptExitException {
+ return print(StringUtilities.prettyPrintBytes(getMemoryUsage().getUsed()));
+ }
+ }
+
+ /**
+ * Info item for the used heap size after garbage collection
+ */
+ public static final class UsedHeapSizeAfterGcInfoItem extends InfoItem {
+ public UsedHeapSizeAfterGcInfoItem() {
+ super("used-heap-size-after-gc",
+ "The amount of used memory in bytes after a call to System.gc().",
+ true);
+ }
+
+ @Override
+ public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
+ throws AbruptExitException {
+ System.gc();
+ return print(StringUtilities.prettyPrintBytes(getMemoryUsage().getUsed()));
+ }
+ }
+
+ /**
+ * Info item for the committed heap size
+ */
+ public static final class CommitedHeapSizeInfoItem extends InfoItem {
+ public CommitedHeapSizeInfoItem() {
+ super("committed-heap-size",
+ "The amount of memory in bytes that is committed for the Java virtual machine to use",
+ false);
+ }
+
+ @Override
+ public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
+ throws AbruptExitException {
+ return print(StringUtilities.prettyPrintBytes(getMemoryUsage().getCommitted()));
+ }
+ }
+
+ /**
+ * Info item for the max heap size
+ */
+ public static final class MaxHeapSizeInfoItem extends InfoItem {
+ public MaxHeapSizeInfoItem() {
+ super("max-heap-size",
+ "The maximum amount of memory in bytes that can be used for memory management.",
+ false);
+ }
+
+ @Override
+ public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
+ throws AbruptExitException {
+ return print(StringUtilities.prettyPrintBytes(getMemoryUsage().getMax()));
+ }
+ }
+
+ /**
+ * Info item for the gc-count
+ */
+ public static final class GcCountInfoItem extends InfoItem {
+ public GcCountInfoItem() {
+ super("gc-count",
+ "Number of garbage collection runs.",
+ false);
+ }
+
+ @Override
+ public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
+ throws AbruptExitException {
+ // The documentation is not very clear on what it means to have more than
+ // one GC MXBean, so we just sum them up.
+ int gcCount = 0;
+ for (GarbageCollectorMXBean gcBean : ManagementFactory.getGarbageCollectorMXBeans()) {
+ gcCount += gcBean.getCollectionCount();
+ }
+ return print(gcCount + "");
+ }
+ }
+
+ /**
+ * Info item for the gc-time
+ */
+ public static final class GcTimeInfoItem extends InfoItem {
+ public GcTimeInfoItem() {
+ super("gc-time",
+ "The approximate accumulated time spend on garbage collection.",
+ false);
+ }
+
+ @Override
+ public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
+ throws AbruptExitException {
+ // The documentation is not very clear on what it means to have more than
+ // one GC MXBean, so we just sum them up.
+ int gcTime = 0;
+ for (GarbageCollectorMXBean gcBean : ManagementFactory.getGarbageCollectorMXBeans()) {
+ gcTime += gcBean.getCollectionTime();
+ }
+ return print(gcTime + "ms");
+ }
+ }
+
+ /**
+ * Info item for the default package. It is deprecated, it still works, when
+ * explicitly requested, but are not shown by default. It prints multi-line messages and thus
+ * don't play well with grep. We don't print them unless explicitly requested.
+ * @deprecated
+ */
+ @Deprecated
+ public static final class DefaultsPackageInfoItem extends InfoItem {
+ public DefaultsPackageInfoItem() {
+ super("defaults-package",
+ "Default packages used as implicit dependencies",
+ true);
+ }
+
+ @Override
+ public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
+ throws AbruptExitException {
+ checkNotNull(env);
+ return print(env.getRuntime().getDefaultsPackageContent());
+ }
+ }
+
+ private static AllowedRuleClassInfo getAllowedRuleClasses(
+ Collection<RuleClass> ruleClasses, Attribute attr) {
+ AllowedRuleClassInfo.Builder info = AllowedRuleClassInfo.newBuilder();
+ info.setPolicy(AllowedRuleClassInfo.AllowedRuleClasses.ANY);
+
+ if (attr.isStrictLabelCheckingEnabled()
+ && attr.getAllowedRuleClassesPredicate() != Predicates.<RuleClass>alwaysTrue()) {
+ info.setPolicy(AllowedRuleClassInfo.AllowedRuleClasses.SPECIFIED);
+ Predicate<RuleClass> filter = attr.getAllowedRuleClassesPredicate();
+ for (RuleClass otherClass : Iterables.filter(ruleClasses, filter)) {
+ if (otherClass.isDocumented()) {
+ info.addAllowedRuleClass(otherClass.getName());
+ }
+ }
+ }
+
+ return info.build();
+ }
+
+ /**
+ * Returns a byte array containing a proto-buffer describing the build language.
+ */
+ private static byte[] getBuildLanguageDefinition(RuleClassProvider provider) {
+ BuildLanguage.Builder resultPb = BuildLanguage.newBuilder();
+ Collection<RuleClass> ruleClasses = provider.getRuleClassMap().values();
+ for (RuleClass ruleClass : ruleClasses) {
+ if (!ruleClass.isDocumented()) {
+ continue;
+ }
+
+ RuleDefinition.Builder rulePb = RuleDefinition.newBuilder();
+ rulePb.setName(ruleClass.getName());
+ for (Attribute attr : ruleClass.getAttributes()) {
+ if (!attr.isDocumented()) {
+ continue;
+ }
+
+ AttributeDefinition.Builder attrPb = AttributeDefinition.newBuilder();
+ attrPb.setName(attr.getName());
+ // The protocol compiler, in its infinite wisdom, generates the field as one of the
+ // integer type and the getTypeEnum() method is missing. WTF?
+ attrPb.setType(ProtoUtils.getDiscriminatorFromType(attr.getType()));
+ attrPb.setMandatory(attr.isMandatory());
+
+ if (BuildType.isLabelType(attr.getType())) {
+ attrPb.setAllowedRuleClasses(getAllowedRuleClasses(ruleClasses, attr));
+ }
+
+ rulePb.addAttribute(attrPb);
+ }
+
+ resultPb.addRule(rulePb);
+ }
+
+ return resultPb.build().toByteArray();
+ }
+
+ /**
+ * Info item for the build language. It is deprecated, it still works, when
+ * explicitly requested, but are not shown by default. It prints multi-line messages and thus
+ * don't play well with grep. We don't print them unless explicitly requested.
+ * @Deprecated
+ */
+ @Deprecated
+ public static final class BuildLanguageInfoItem extends InfoItem {
+ public BuildLanguageInfoItem() {
+ super("build-language",
+ "A protobuffer with the build language structure",
+ true);
+ }
+
+ @Override
+ public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
+ throws AbruptExitException {
+ checkNotNull(env);
+ return print(getBuildLanguageDefinition(env.getRuntime().getRuleClassProvider()));
+ }
+ }
+
+ /**
+ * Info item for the default package path. It is deprecated, it still works, when
+ * explicitly requested, but are not shown by default. It prints multi-line messages and thus
+ * don't play well with grep. We don't print them unless explicitly requested.
+ * @deprecated
+ */
+ @Deprecated
+ public static final class DefaultPackagePathInfoItem extends InfoItem {
+ private final OptionsProvider commandOptions;
+
+ public DefaultPackagePathInfoItem(OptionsProvider commandOptions) {
+ super("default-package-path",
+ "The default package path",
+ true);
+ this.commandOptions = commandOptions;
+ }
+
+ @Override
+ public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
+ throws AbruptExitException {
+ checkNotNull(commandOptions);
+ return print(Joiner.on(":").join(
+ commandOptions.getOptions(PackageCacheOptions.class).packagePath));
+ }
+ }
+
+ /**
+ * Info item for the make environment.
+ */
+ public static class MakeInfoItem extends InfoItem {
+ public MakeInfoItem(String name, String description) {
+ super(name, description, false);
+ }
+ @Override
+ public String getDescription() {
+ return "Make environment variable '" + name + "'";
+ }
+
+ @Override
+ public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env) {
+ return print(description);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/commands/InfoKey.java b/src/main/java/com/google/devtools/build/lib/runtime/commands/InfoKey.java
deleted file mode 100644
index 5dcf36f975..0000000000
--- a/src/main/java/com/google/devtools/build/lib/runtime/commands/InfoKey.java
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright 2014 The Bazel Authors. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-package com.google.devtools.build.lib.runtime.commands;
-
-import com.google.devtools.build.lib.Constants;
-
-/**
- * An enumeration of all the valid info keys, excepting the make environment
- * variables.
- */
-public enum InfoKey {
- // directories
- WORKSPACE("workspace", "The working directory of the server."),
- INSTALL_BASE("install_base", "The installation base directory."),
- OUTPUT_BASE("output_base",
- "A directory for shared " + Constants.PRODUCT_NAME + " state as well as tool and strategy "
- + "specific subdirectories."),
- EXECUTION_ROOT("execution_root",
- "A directory that makes all input and output files visible to the build."),
- OUTPUT_PATH("output_path", "Output directory"),
- BLAZE_BIN(Constants.PRODUCT_NAME + "-bin",
- "Configuration dependent directory for binaries."),
- BLAZE_GENFILES(Constants.PRODUCT_NAME + "-genfiles",
- "Configuration dependent directory for generated files."),
- BLAZE_TESTLOGS(Constants.PRODUCT_NAME + "-testlogs",
- "Configuration dependent directory for logs from a test run."),
-
- // logs
- COMMAND_LOG("command_log", "Location of the log containg the output from the build commands."),
- MESSAGE_LOG("message_log" ,
- "Location of a log containing machine readable message in LogMessage protobuf format."),
-
- // misc
- RELEASE("release", Constants.PRODUCT_NAME + " release identifier"),
- SERVER_PID("server_pid", Constants.PRODUCT_NAME + " process id"),
- PACKAGE_PATH("package_path", "The search path for resolving package labels."),
-
- // memory statistics
- USED_HEAP_SIZE("used-heap-size", "The amount of used memory in bytes. Note that this is not a "
- + "good indicator of the actual memory use, as it includes any remaining inaccessible "
- + "memory."),
- USED_HEAP_SIZE_AFTER_GC("used-heap-size-after-gc",
- "The amount of used memory in bytes after a call to System.gc().", true),
- COMMITTED_HEAP_SIZE("committed-heap-size",
- "The amount of memory in bytes that is committed for the Java virtual machine to use"),
- MAX_HEAP_SIZE("max-heap-size",
- "The maximum amount of memory in bytes that can be used for memory management."),
- GC_COUNT("gc-count", "Number of garbage collection runs."),
- GC_TIME("gc-time", "The approximate accumulated time spend on garbage collection."),
-
- // These are deprecated, they still work, when explicitly requested, but are not shown by default
-
- // These keys print multi-line messages and thus don't play well with grep. We don't print them
- // unless explicitly requested
- DEFAULTS_PACKAGE("defaults-package", "Default packages used as implicit dependencies", true),
- BUILD_LANGUAGE("build-language", "A protobuffer with the build language structure", true),
- DEFAULT_PACKAGE_PATH("default-package-path", "The default package path", true);
-
- private final String name;
- private final String description;
- private final boolean hidden;
-
- private InfoKey(String name, String description) {
- this(name, description, false);
- }
-
- private InfoKey(String name, String description, boolean hidden) {
- this.name = name;
- this.description = description;
- this.hidden = hidden;
- }
-
- public String getName() {
- return name;
- }
-
- public String getDescription() {
- return description;
- }
-
- public boolean isHidden() {
- return hidden;
- }
-}