// 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.devtools.build.lib.util.StringUtilities; import java.util.Date; import java.util.Map; import java.util.logging.Logger; /** * 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"; private final Map<String, String> buildData = Maps.newTreeMap(); private static BlazeVersionInfo instance = null; private static final Logger LOG = Logger.getLogger(BlazeVersionInfo.class.getName()); /** Key for the release timestamp is seconds. */ public static final String BUILD_TIMESTAMP = "Build timestamp as int"; 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) { LOG.warning("Blaze release version information not available"); } else { LOG.info("Blaze version info: " + 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. */ public String getSummary() { if (buildData.isEmpty()) { return null; } return StringUtilities.layoutTable(buildData); } /** * 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 HEAD. 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; } }