|  | // 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; | 
|  | } | 
|  | } |