1// Copyright 2017 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5class Version implements Comparable<Version> { 6 /// Creates a new [Version] object. 7 factory Version(int major, int minor, int patch, {String text}) { 8 if (text == null) { 9 text = major == null ? '0' : '$major'; 10 if (minor != null) 11 text = '$text.$minor'; 12 if (patch != null) 13 text = '$text.$patch'; 14 } 15 16 return Version._(major ?? 0, minor ?? 0, patch ?? 0, text); 17 } 18 19 Version._(this.major, this.minor, this.patch, this._text) { 20 if (major < 0) 21 throw ArgumentError('Major version must be non-negative.'); 22 if (minor < 0) 23 throw ArgumentError('Minor version must be non-negative.'); 24 if (patch < 0) 25 throw ArgumentError('Patch version must be non-negative.'); 26 } 27 28 /// Creates a new [Version] by parsing [text]. 29 factory Version.parse(String text) { 30 final Match match = versionPattern.firstMatch(text ?? ''); 31 if (match == null) { 32 return null; 33 } 34 35 try { 36 final int major = int.parse(match[1] ?? '0'); 37 final int minor = int.parse(match[3] ?? '0'); 38 final int patch = int.parse(match[5] ?? '0'); 39 return Version._(major, minor, patch, text); 40 } on FormatException { 41 return null; 42 } 43 } 44 45 /// Returns the primary version out of a list of candidates. 46 /// 47 /// This is the highest-numbered stable version. 48 static Version primary(List<Version> versions) { 49 Version primary; 50 for (Version version in versions) { 51 if (primary == null || (version > primary)) { 52 primary = version; 53 } 54 } 55 return primary; 56 } 57 58 59 static Version get unknown => Version(0, 0, 0, text: 'unknown'); 60 61 /// The major version number: "1" in "1.2.3". 62 final int major; 63 64 /// The minor version number: "2" in "1.2.3". 65 final int minor; 66 67 /// The patch version number: "3" in "1.2.3". 68 final int patch; 69 70 /// The original string representation of the version number. 71 /// 72 /// This preserves textual artifacts like leading zeros that may be left out 73 /// of the parsed version. 74 final String _text; 75 76 static final RegExp versionPattern = 77 RegExp(r'^(\d+)(\.(\d+)(\.(\d+))?)?'); 78 79 /// Two [Version]s are equal if their version numbers are. The version text 80 /// is ignored. 81 @override 82 bool operator ==(dynamic other) { 83 if (other is! Version) 84 return false; 85 return major == other.major && minor == other.minor && patch == other.patch; 86 } 87 88 @override 89 int get hashCode => major ^ minor ^ patch; 90 91 bool operator <(Version other) => compareTo(other) < 0; 92 bool operator >(Version other) => compareTo(other) > 0; 93 bool operator <=(Version other) => compareTo(other) <= 0; 94 bool operator >=(Version other) => compareTo(other) >= 0; 95 96 @override 97 int compareTo(Version other) { 98 if (major != other.major) 99 return major.compareTo(other.major); 100 if (minor != other.minor) 101 return minor.compareTo(other.minor); 102 return patch.compareTo(other.patch); 103 } 104 105 @override 106 String toString() => _text; 107} 108