| // 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.analysis; |
| |
| import com.google.common.annotations.VisibleForTesting; |
| import com.google.common.collect.ImmutableMap; |
| import com.google.common.collect.Maps; |
| import com.google.common.flogger.GoogleLogger; |
| import java.util.Date; |
| import java.util.Map; |
| import java.util.stream.Collectors; |
| import javax.annotation.Nullable; |
| |
| /** |
| * Determines the version information of the current process. |
| * |
| * <p>The version information is a dictionary mapping from string keys to string values. For |
| * build stamping, it should have the key "Build label", which contains among others a |
| * XXXXXXX-YYYY.MM.DD string to indicate the version of the release. If no data is available |
| * (eg. when running non-released version), {@link #isAvailable()} returns false. |
| */ |
| public class BlazeVersionInfo { |
| public static final String BUILD_LABEL = "Build label"; |
| /** Key for the release timestamp is seconds. */ |
| public static final String BUILD_TIMESTAMP = "Build timestamp as int"; |
| |
| private static final GoogleLogger logger = GoogleLogger.forEnclosingClass(); |
| |
| private static BlazeVersionInfo instance = null; |
| |
| private final Map<String, String> buildData = Maps.newTreeMap(); |
| |
| public BlazeVersionInfo(Map<String, String> info) { |
| buildData.putAll(info); |
| } |
| |
| /** |
| * Accessor method for BlazeVersionInfo singleton. |
| * |
| * <p>If setBuildInfo was not called, returns an empty BlazeVersionInfo instance, which should |
| * not be persisted. |
| */ |
| public static synchronized BlazeVersionInfo instance() { |
| if (instance == null) { |
| return new BlazeVersionInfo(ImmutableMap.<String, String>of()); |
| } |
| return instance; |
| } |
| |
| private static void logVersionInfo(BlazeVersionInfo info) { |
| if (info.getSummary() == null) { |
| logger.atWarning().log("Bazel release version information not available"); |
| } else { |
| logger.atInfo().log("Bazel version info: %s", info.getSummary()); |
| } |
| } |
| |
| /** |
| * Sets build info. |
| * |
| * <p>This should be called once in the program execution, as early soon as possible, so we |
| * can have the version information even before modules are initialized. |
| */ |
| public static synchronized void setBuildInfo(Map<String, String> info) { |
| if (instance != null) { |
| throw new IllegalStateException("setBuildInfo called twice."); |
| } |
| instance = new BlazeVersionInfo(info); |
| logVersionInfo(instance); |
| } |
| |
| /** |
| * Indicates whether version information is available. |
| */ |
| public boolean isAvailable() { |
| return !buildData.isEmpty(); |
| } |
| |
| /** |
| * Returns the summary which gets displayed in the 'version' command. The summary is a list of |
| * formatted key / value pairs. |
| */ |
| @Nullable |
| public String getSummary() { |
| if (buildData.isEmpty()) { |
| return null; |
| } |
| return buildData.entrySet().stream() |
| .map(e -> e.getKey() + ": " + e.getValue()) |
| .collect(Collectors.joining("\n")); |
| } |
| |
| /** |
| * Returns true iff this binary is released--that is, a |
| * binary built with a release label. |
| */ |
| public boolean isReleasedBlaze() { |
| String buildLabel = buildData.get(BUILD_LABEL); |
| return buildLabel != null && buildLabel.length() > 0; |
| } |
| |
| /** |
| * Returns the release label, if any, or "development version". |
| */ |
| public String getReleaseName() { |
| String buildLabel = buildData.get(BUILD_LABEL); |
| return (buildLabel != null && buildLabel.length() > 0) |
| ? "release " + buildLabel |
| : "development version"; |
| } |
| |
| /** |
| * Returns the version, if any, or {@code ""}. The returned version number is easier to process |
| * than the version returned by #getReleaseName(). |
| */ |
| public String getVersion() { |
| String buildLabel = buildData.get(BUILD_LABEL); |
| return buildLabel != null ? buildLabel : ""; |
| } |
| |
| /** |
| * Returns the release timestamp in seconds. |
| */ |
| public long getTimestamp() { |
| String timestamp = buildData.get(BUILD_TIMESTAMP); |
| if (timestamp == null || timestamp.equals("0")) { |
| return new Date().getTime(); |
| } |
| return Long.parseLong(timestamp); |
| } |
| |
| @VisibleForTesting |
| public Map<String, String> getBuildData() { |
| return buildData; |
| } |
| } |