diff options
6 files changed, 127 insertions, 11 deletions
@@ -1,5 +1,7 @@ package(default_visibility = ["//scripts/release:__pkg__"]) +exports_files(["LICENSE"]) + filegroup( name = "git", srcs = glob([".git/**"]), diff --git a/src/main/java/com/google/devtools/build/lib/BUILD b/src/main/java/com/google/devtools/build/lib/BUILD index 8be69a6b48..2ffe989c1f 100644 --- a/src/main/java/com/google/devtools/build/lib/BUILD +++ b/src/main/java/com/google/devtools/build/lib/BUILD @@ -1089,12 +1089,25 @@ java_library( ], ) +genrule( + name = "merge_licenses", + srcs = [ + "//:LICENSE", + "//third_party:srcs", + ], + outs = ["runtime/commands/LICENSE"], + cmd = "$(location merge_licenses.sh) $(SRCS) > \"$@\"", + tools = ["merge_licenses.sh"], +) + java_library( name = "bazel", resources = glob([ "runtime/commands/*.txt", "runtime/mobileinstall/*.txt", - ]), + ]) + [ + ":runtime/commands/LICENSE", + ], exports = [":runtime"], ) diff --git a/src/main/java/com/google/devtools/build/lib/merge_licenses.sh b/src/main/java/com/google/devtools/build/lib/merge_licenses.sh new file mode 100755 index 0000000000..f2d72e4b89 --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/merge_licenses.sh @@ -0,0 +1,28 @@ +#!/bin/sh +# +# Copyright 2017 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. +# + +set -eu + +for src in "$@"; do + for substr in 'ASSEMBLY_EXCEPTION' 'DISCLAIMER' 'LICENSE' 'license' 'THIRD_PARTY_README'; do + if [ -z "${src##*$substr*}" ]; then + echo "===== $src =====" + cat "$src" + echo; echo + fi + done +done diff --git a/src/main/java/com/google/devtools/build/lib/runtime/BuiltinCommandModule.java b/src/main/java/com/google/devtools/build/lib/runtime/BuiltinCommandModule.java index 3e5a2a5b9d..3f6703efa4 100644 --- a/src/main/java/com/google/devtools/build/lib/runtime/BuiltinCommandModule.java +++ b/src/main/java/com/google/devtools/build/lib/runtime/BuiltinCommandModule.java @@ -20,6 +20,7 @@ import com.google.devtools.build.lib.runtime.commands.CoverageCommand; import com.google.devtools.build.lib.runtime.commands.DumpCommand; import com.google.devtools.build.lib.runtime.commands.HelpCommand; import com.google.devtools.build.lib.runtime.commands.InfoCommand; +import com.google.devtools.build.lib.runtime.commands.LicenseCommand; import com.google.devtools.build.lib.runtime.commands.ProfileCommand; import com.google.devtools.build.lib.runtime.commands.QueryCommand; import com.google.devtools.build.lib.runtime.commands.RunCommand; @@ -48,5 +49,9 @@ public final class BuiltinCommandModule extends BlazeModule { new ShutdownCommand(), new TestCommand(), new VersionCommand()); + // Only enable the "license" command when this binary has an embedded LICENSE file. + if (LicenseCommand.isSupported()) { + builder.addCommands(new LicenseCommand()); + } } } diff --git a/src/main/java/com/google/devtools/build/lib/runtime/commands/LicenseCommand.java b/src/main/java/com/google/devtools/build/lib/runtime/commands/LicenseCommand.java new file mode 100644 index 0000000000..5dc8a3a1b2 --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/runtime/commands/LicenseCommand.java @@ -0,0 +1,60 @@ +// Copyright 2017 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.analysis.NoBuildEvent; +import com.google.devtools.build.lib.runtime.BlazeCommand; +import com.google.devtools.build.lib.runtime.Command; +import com.google.devtools.build.lib.runtime.CommandEnvironment; +import com.google.devtools.build.lib.util.ExitCode; +import com.google.devtools.build.lib.util.ResourceFileLoader; +import com.google.devtools.build.lib.util.io.OutErr; +import com.google.devtools.common.options.OptionsParser; +import com.google.devtools.common.options.OptionsProvider; +import java.io.IOException; + +/** A command that prints an embedded license text. */ +@Command( + name = "license", + allowResidue = true, + mustRunInWorkspace = false, + shortDescription = "Prints the license of this software.", + help = "Prints the license of this software.\n\n%{options}" +) +public class LicenseCommand implements BlazeCommand { + + public static boolean isSupported() { + return ResourceFileLoader.resourceExists(LicenseCommand.class, "LICENSE"); + } + + @Override + public ExitCode exec(CommandEnvironment env, OptionsProvider options) { + env.getEventBus().post(new NoBuildEvent()); + OutErr outErr = env.getReporter().getOutErr(); + + outErr.printOutLn("Licenses of all components included in this binary:\n"); + + try { + outErr.printOutLn(ResourceFileLoader.loadResource(this.getClass(), "LICENSE")); + } catch (IOException e) { + throw new IllegalStateException( + "I/O error while trying to print 'LICENSE' resource: " + e.getMessage(), e); + } + + return ExitCode.SUCCESS; + } + + @Override + public void editOptions(CommandEnvironment env, OptionsParser optionsParser) {} +} diff --git a/src/main/java/com/google/devtools/build/lib/util/ResourceFileLoader.java b/src/main/java/com/google/devtools/build/lib/util/ResourceFileLoader.java index 8fde6890f9..a773f4ad41 100644 --- a/src/main/java/com/google/devtools/build/lib/util/ResourceFileLoader.java +++ b/src/main/java/com/google/devtools/build/lib/util/ResourceFileLoader.java @@ -16,7 +16,6 @@ package com.google.devtools.build.lib.util; import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.io.ByteStreams; - import java.io.IOException; import java.io.InputStream; @@ -29,6 +28,14 @@ public final class ResourceFileLoader { private ResourceFileLoader() {} + public static boolean resourceExists(Class<?> relativeToClass, String resourceName) { + try (InputStream resourceStream = getResourceAsStream(relativeToClass, resourceName)) { + return resourceStream != null; + } catch (IOException e) { + return false; + } + } + /** * Loads a text resource that is located in a directory on the Java classpath that * corresponds to the package of <code>relativeToClass</code> using UTF8 encoding. @@ -38,20 +45,21 @@ public final class ResourceFileLoader { */ public static String loadResource(Class<?> relativeToClass, String resourceName) throws IOException { + try (InputStream stream = getResourceAsStream(relativeToClass, resourceName)) { + if (stream == null) { + throw new IOException(resourceName + " not found."); + } + return new String(ByteStreams.toByteArray(stream), UTF_8); + } + } + + private static InputStream getResourceAsStream(Class<?> relativeToClass, String resourceName) { ClassLoader loader = relativeToClass.getClassLoader(); // TODO(bazel-team): use relativeToClass.getPackage().getName(). String className = relativeToClass.getName(); String packageName = className.substring(0, className.lastIndexOf('.')); String path = packageName.replace('.', '/'); String resource = path + '/' + resourceName; - InputStream stream = loader.getResourceAsStream(resource); - if (stream == null) { - throw new IOException(resourceName + " not found."); - } - try { - return new String(ByteStreams.toByteArray(stream), UTF_8); - } finally { - stream.close(); - } + return loader.getResourceAsStream(resource); } } |