blob: 7972829cd3eb97679e39803891274b7291d0d3b0 [file] [log] [blame]
// 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;
}
}