92 lines
2.5 KiB
Dart
92 lines
2.5 KiB
Dart
|
|
class ParsedVersion {
|
||
|
|
final int major;
|
||
|
|
final int minor;
|
||
|
|
final int patch;
|
||
|
|
final String? prerelease;
|
||
|
|
final String? build;
|
||
|
|
|
||
|
|
const ParsedVersion({
|
||
|
|
required this.major,
|
||
|
|
required this.minor,
|
||
|
|
required this.patch,
|
||
|
|
this.prerelease,
|
||
|
|
this.build,
|
||
|
|
});
|
||
|
|
|
||
|
|
bool get hasPrerelease => prerelease != null && prerelease!.isNotEmpty;
|
||
|
|
|
||
|
|
bool sameCore(ParsedVersion other) {
|
||
|
|
return major == other.major && minor == other.minor && patch == other.patch;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
final RegExp _versionPattern = RegExp(
|
||
|
|
r'^[vV]?(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+([0-9A-Za-z.-]+))?$',
|
||
|
|
);
|
||
|
|
|
||
|
|
ParsedVersion? parseVersion(String tag) {
|
||
|
|
final match = _versionPattern.firstMatch(tag.trim());
|
||
|
|
if (match == null) return null;
|
||
|
|
|
||
|
|
return ParsedVersion(
|
||
|
|
major: int.parse(match.group(1)!),
|
||
|
|
minor: int.parse(match.group(2)!),
|
||
|
|
patch: int.parse(match.group(3)!),
|
||
|
|
prerelease: match.group(4),
|
||
|
|
build: match.group(5),
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
bool isNewerVersion(String localTag, String remoteTag) {
|
||
|
|
final local = parseVersion(localTag);
|
||
|
|
final remote = parseVersion(remoteTag);
|
||
|
|
if (local == null || remote == null) return false;
|
||
|
|
|
||
|
|
if (remote.hasPrerelease) {
|
||
|
|
if (!local.hasPrerelease || !local.sameCore(remote)) return false;
|
||
|
|
return _comparePrerelease(remote.prerelease!, local.prerelease!) > 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
final coreCompare = _compareCore(remote, local);
|
||
|
|
if (coreCompare != 0) return coreCompare > 0;
|
||
|
|
return local.hasPrerelease;
|
||
|
|
}
|
||
|
|
|
||
|
|
int _compareCore(ParsedVersion a, ParsedVersion b) {
|
||
|
|
final major = a.major.compareTo(b.major);
|
||
|
|
if (major != 0) return major;
|
||
|
|
final minor = a.minor.compareTo(b.minor);
|
||
|
|
if (minor != 0) return minor;
|
||
|
|
return a.patch.compareTo(b.patch);
|
||
|
|
}
|
||
|
|
|
||
|
|
int _comparePrerelease(String a, String b) {
|
||
|
|
final left = a.split('.');
|
||
|
|
final right = b.split('.');
|
||
|
|
final length = left.length > right.length ? left.length : right.length;
|
||
|
|
|
||
|
|
for (var i = 0; i < length; i++) {
|
||
|
|
if (i >= left.length) return -1;
|
||
|
|
if (i >= right.length) return 1;
|
||
|
|
|
||
|
|
final leftPart = left[i];
|
||
|
|
final rightPart = right[i];
|
||
|
|
final leftNumber = int.tryParse(leftPart);
|
||
|
|
final rightNumber = int.tryParse(rightPart);
|
||
|
|
|
||
|
|
if (leftNumber != null && rightNumber != null) {
|
||
|
|
final numberCompare = leftNumber.compareTo(rightNumber);
|
||
|
|
if (numberCompare != 0) return numberCompare;
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (leftNumber != null) return -1;
|
||
|
|
if (rightNumber != null) return 1;
|
||
|
|
|
||
|
|
final textCompare = leftPart.compareTo(rightPart);
|
||
|
|
if (textCompare != 0) return textCompare;
|
||
|
|
}
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|