// Copyright 2015 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.rules.apple; import com.google.common.base.Joiner; import com.google.common.base.Preconditions; import com.google.common.base.Splitter; import com.google.common.base.Strings; import com.google.common.collect.ComparisonChain; import com.google.common.collect.ImmutableList; import com.google.common.collect.Ordering; import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable; import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec; import com.google.devtools.build.lib.skylarkbuildapi.apple.DottedVersionApi; import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter; import java.util.ArrayList; import java.util.Objects; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.annotation.Nullable; /** * Represents a value with multiple components, separated by periods, for example {@code 4.5.6} or * {@code 5.0.1beta2}. Components must start with a non-negative integer and at least one component * must be present. * *
Specifically, the format of a component is {@code \d+([a-z]+\d*)?}. * *
Dotted versions are ordered using natural integer sorting on components in order from first to * last where any missing element is considered to have the value 0 if they don't contain any * non-numeric characters. For example: * *
* 3.1.25 > 3.1.1 * 3.1.20 > 3.1.2 * 3.1.1 > 3.1 * 3.1 == 3.1.0.0 * 3.2 > 3.1.8 ** *
If the component contains any alphabetic characters after the leading integer, it is * considered smaller than any components with the same integer but larger than any * component with a smaller integer. If the integers are the same, the alphabetic sequences are * compared lexicographically, and if they turn out to be the same, the final (optional) * integer is compared. As with the leading integer, this final integer is considered to be 0 if not * present. For example: * *
* 3.1.1 > 3.1.1beta3 * 3.1.1beta1 > 3.1.0 * 3.1 > 3.1.0alpha1 * * 3.1.0beta0 > 3.1.0alpha5.6 * 3.4.2alpha2 > 3.4.2alpha1 * 3.4.2alpha2 > 3.4.2alpha1.5 * 3.1alpha1 > 3.1alpha ** *
This class is immutable and can safely be shared among threads.
*/
@Immutable
@AutoCodec
public final class DottedVersion implements DottedVersionApi For example, a dotted version of "7.3.0" will return "7" if one is requested, "7.3" if two
* are requested, "7.3.0" if three are requested, and "7.3.0.0" if four are requested.
*
* @param numComponents a positive number of dot-separated numbers that should be present in the
* returned string representation
*/
public String toStringWithComponents(int numComponents) {
Preconditions.checkArgument(numComponents > 0,
"Can't serialize as a version with %s components", numComponents);
ImmutableList.Builder For example, a dotted version of "7.3" will return "7.3" with either one or two components
* requested, "7.3.0" if three are requested, and "7.3.0.0" if four are requested.
*
* Trailing zero components at the end of a string representation will not be removed. For
* example, a dotted version of "1.0.0" will return "1.0.0" if only one or two components are
* requested.
*
* @param numMinComponents the minimum number of dot-separated numbers that should be present in
* the returned string representation
*/
public String toStringWithMinimumComponents(int numMinComponents) {
return toStringWithComponents(Math.max(this.numOriginalComponents, numMinComponents));
}
/**
* Returns true if this version number has any alphabetic characters, such as 'alpha' in
* "7.3alpha.2".
*/
public boolean hasAlphabeticCharacters() {
for (Component component : components) {
if (!Objects.equals(component.alphaSequence, NO_ALPHA_SEQUENCE)) {
return true;
}
}
return false;
}
/**
* Returns the number of components in this version number. For example, "7.3.0" has three
* components.
*/
public int numComponents() {
return components.size();
}
@Override
public String toString() {
return stringRepresentation;
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (other == null || getClass() != other.getClass()) {
return false;
}
return compareTo((DottedVersion) other) == 0;
}
@Override
public int hashCode() {
return Objects.hash(components);
}
private Component getComponent(int groupIndex) {
if (components.size() > groupIndex) {
return components.get(groupIndex);
}
return ZERO_COMPONENT;
}
@Override
public void repr(SkylarkPrinter printer) {
printer.append(stringRepresentation);
}
@AutoCodec.VisibleForSerialization
@AutoCodec
static final class Component implements Comparable