1*bcb5dc79SHONG Yifan# Copyright 2018 The Bazel Authors. All rights reserved. 2*bcb5dc79SHONG Yifan# 3*bcb5dc79SHONG Yifan# Licensed under the Apache License, Version 2.0 (the "License"); 4*bcb5dc79SHONG Yifan# you may not use this file except in compliance with the License. 5*bcb5dc79SHONG Yifan# You may obtain a copy of the License at 6*bcb5dc79SHONG Yifan# 7*bcb5dc79SHONG Yifan# http://www.apache.org/licenses/LICENSE-2.0 8*bcb5dc79SHONG Yifan# 9*bcb5dc79SHONG Yifan# Unless required by applicable law or agreed to in writing, software 10*bcb5dc79SHONG Yifan# distributed under the License is distributed on an "AS IS" BASIS, 11*bcb5dc79SHONG Yifan# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*bcb5dc79SHONG Yifan# See the License for the specific language governing permissions and 13*bcb5dc79SHONG Yifan# limitations under the License. 14*bcb5dc79SHONG Yifan 15*bcb5dc79SHONG Yifan"""Skylib module containing functions for checking Bazel versions.""" 16*bcb5dc79SHONG Yifan 17*bcb5dc79SHONG Yifandef _get_bazel_version(): 18*bcb5dc79SHONG Yifan """Returns the current Bazel version""" 19*bcb5dc79SHONG Yifan 20*bcb5dc79SHONG Yifan return native.bazel_version 21*bcb5dc79SHONG Yifan 22*bcb5dc79SHONG Yifandef _extract_version_number(bazel_version): 23*bcb5dc79SHONG Yifan """Extracts the semantic version number from a version string 24*bcb5dc79SHONG Yifan 25*bcb5dc79SHONG Yifan Args: 26*bcb5dc79SHONG Yifan bazel_version: the version string that begins with the semantic version 27*bcb5dc79SHONG Yifan e.g. "1.2.3rc1 abc1234" where "abc1234" is a commit hash. 28*bcb5dc79SHONG Yifan 29*bcb5dc79SHONG Yifan Returns: 30*bcb5dc79SHONG Yifan The semantic version string, like "1.2.3". 31*bcb5dc79SHONG Yifan """ 32*bcb5dc79SHONG Yifan for i in range(len(bazel_version)): 33*bcb5dc79SHONG Yifan c = bazel_version[i] 34*bcb5dc79SHONG Yifan if not (c.isdigit() or c == "."): 35*bcb5dc79SHONG Yifan return bazel_version[:i] 36*bcb5dc79SHONG Yifan return bazel_version 37*bcb5dc79SHONG Yifan 38*bcb5dc79SHONG Yifan# Parse the bazel version string from `native.bazel_version`. 39*bcb5dc79SHONG Yifan# e.g. 40*bcb5dc79SHONG Yifan# "0.10.0rc1 abc123d" => (0, 10, 0) 41*bcb5dc79SHONG Yifan# "0.3.0" => (0, 3, 0) 42*bcb5dc79SHONG Yifandef _parse_bazel_version(bazel_version): 43*bcb5dc79SHONG Yifan """Parses a version string into a 3-tuple of ints 44*bcb5dc79SHONG Yifan 45*bcb5dc79SHONG Yifan int tuples can be compared directly using binary operators (<, >). 46*bcb5dc79SHONG Yifan 47*bcb5dc79SHONG Yifan For a development build of Bazel, this returns an unspecified version tuple 48*bcb5dc79SHONG Yifan that compares higher than any released version. 49*bcb5dc79SHONG Yifan 50*bcb5dc79SHONG Yifan Args: 51*bcb5dc79SHONG Yifan bazel_version: the Bazel version string 52*bcb5dc79SHONG Yifan 53*bcb5dc79SHONG Yifan Returns: 54*bcb5dc79SHONG Yifan An int 3-tuple of a (major, minor, patch) version. 55*bcb5dc79SHONG Yifan """ 56*bcb5dc79SHONG Yifan 57*bcb5dc79SHONG Yifan version = _extract_version_number(bazel_version) 58*bcb5dc79SHONG Yifan if not version: 59*bcb5dc79SHONG Yifan return (999999, 999999, 999999) 60*bcb5dc79SHONG Yifan return tuple([int(n) for n in version.split(".")]) 61*bcb5dc79SHONG Yifan 62*bcb5dc79SHONG Yifandef _is_at_most(threshold, version): 63*bcb5dc79SHONG Yifan """Check that a version is lower or equals to a threshold. 64*bcb5dc79SHONG Yifan 65*bcb5dc79SHONG Yifan Args: 66*bcb5dc79SHONG Yifan threshold: the maximum version string 67*bcb5dc79SHONG Yifan version: the version string to be compared to the threshold 68*bcb5dc79SHONG Yifan 69*bcb5dc79SHONG Yifan Returns: 70*bcb5dc79SHONG Yifan True if version <= threshold. 71*bcb5dc79SHONG Yifan """ 72*bcb5dc79SHONG Yifan return _parse_bazel_version(version) <= _parse_bazel_version(threshold) 73*bcb5dc79SHONG Yifan 74*bcb5dc79SHONG Yifandef _is_at_least(threshold, version): 75*bcb5dc79SHONG Yifan """Check that a version is higher or equals to a threshold. 76*bcb5dc79SHONG Yifan 77*bcb5dc79SHONG Yifan Args: 78*bcb5dc79SHONG Yifan threshold: the minimum version string 79*bcb5dc79SHONG Yifan version: the version string to be compared to the threshold 80*bcb5dc79SHONG Yifan 81*bcb5dc79SHONG Yifan Returns: 82*bcb5dc79SHONG Yifan True if version >= threshold. 83*bcb5dc79SHONG Yifan """ 84*bcb5dc79SHONG Yifan 85*bcb5dc79SHONG Yifan return _parse_bazel_version(version) >= _parse_bazel_version(threshold) 86*bcb5dc79SHONG Yifan 87*bcb5dc79SHONG Yifandef _check_bazel_version(minimum_bazel_version, maximum_bazel_version = None, bazel_version = None): 88*bcb5dc79SHONG Yifan """Check that the version of Bazel is valid within the specified range. 89*bcb5dc79SHONG Yifan 90*bcb5dc79SHONG Yifan Args: 91*bcb5dc79SHONG Yifan minimum_bazel_version: minimum version of Bazel expected 92*bcb5dc79SHONG Yifan maximum_bazel_version: maximum version of Bazel expected 93*bcb5dc79SHONG Yifan bazel_version: the version of Bazel to check. Used for testing, defaults to native.bazel_version 94*bcb5dc79SHONG Yifan """ 95*bcb5dc79SHONG Yifan if not bazel_version: 96*bcb5dc79SHONG Yifan if "bazel_version" not in dir(native): 97*bcb5dc79SHONG Yifan fail("Current Bazel version is lower than 0.2.1; expected at least {}".format( 98*bcb5dc79SHONG Yifan minimum_bazel_version, 99*bcb5dc79SHONG Yifan )) 100*bcb5dc79SHONG Yifan elif not native.bazel_version: 101*bcb5dc79SHONG Yifan # Using a non-release version, assume it is good. 102*bcb5dc79SHONG Yifan return 103*bcb5dc79SHONG Yifan else: 104*bcb5dc79SHONG Yifan bazel_version = native.bazel_version 105*bcb5dc79SHONG Yifan 106*bcb5dc79SHONG Yifan if not _is_at_least( 107*bcb5dc79SHONG Yifan threshold = minimum_bazel_version, 108*bcb5dc79SHONG Yifan version = bazel_version, 109*bcb5dc79SHONG Yifan ): 110*bcb5dc79SHONG Yifan fail("Current Bazel version is {}; expected at least {}".format( 111*bcb5dc79SHONG Yifan bazel_version, 112*bcb5dc79SHONG Yifan minimum_bazel_version, 113*bcb5dc79SHONG Yifan )) 114*bcb5dc79SHONG Yifan 115*bcb5dc79SHONG Yifan if maximum_bazel_version: 116*bcb5dc79SHONG Yifan if not _is_at_most( 117*bcb5dc79SHONG Yifan threshold = maximum_bazel_version, 118*bcb5dc79SHONG Yifan version = bazel_version, 119*bcb5dc79SHONG Yifan ): 120*bcb5dc79SHONG Yifan fail("Current Bazel version is {}; expected at most {}".format( 121*bcb5dc79SHONG Yifan bazel_version, 122*bcb5dc79SHONG Yifan maximum_bazel_version, 123*bcb5dc79SHONG Yifan )) 124*bcb5dc79SHONG Yifan 125*bcb5dc79SHONG Yifan pass 126*bcb5dc79SHONG Yifan 127*bcb5dc79SHONG Yifanversions = struct( 128*bcb5dc79SHONG Yifan get = _get_bazel_version, 129*bcb5dc79SHONG Yifan parse = _parse_bazel_version, 130*bcb5dc79SHONG Yifan check = _check_bazel_version, 131*bcb5dc79SHONG Yifan is_at_most = _is_at_most, 132*bcb5dc79SHONG Yifan is_at_least = _is_at_least, 133*bcb5dc79SHONG Yifan) 134