FlutterVersion.parse constructor
FlutterVersion.parse(
- String version
Implementation
factory FlutterVersion.parse(String version) {
// Match pattern: [fork/]version[@channel]
final pattern = RegExp(
r'^(?:(?<fork>[^/]+)/)?(?<version>[^@]+)(?:@(?<channel>\w+))?$',
);
final match = pattern.firstMatch(version);
if (match == null) {
throw FormatException('Invalid version format: $version');
}
// Extract components
final forkName = match.namedGroup('fork');
final versionPart = match.namedGroup('version')!;
final channelPart = match.namedGroup('channel');
// Handle custom versions
if (versionPart.startsWith('custom_')) {
if (forkName != null || channelPart != null) {
throw FormatException(
'Custom versions cannot have fork or channel specifications',
);
}
return FlutterVersion.custom(versionPart);
}
// Handle channel versions
if (isFlutterChannel(versionPart)) {
return FlutterVersion.channel(versionPart, fork: forkName);
}
// Handle release versions with channel
if (channelPart != null) {
if (!isFlutterChannel(channelPart)) {
throw FormatException('Invalid channel: $channelPart');
}
final nameToUse = '$versionPart@$channelPart';
return FlutterVersion.release(
nameToUse,
releaseChannel: FlutterChannel.fromValue(channelPart),
fork: forkName,
);
}
// Try to parse as semantic version
try {
// Create a version to check for validation only
String checkVersion = versionPart;
if (versionPart.startsWith('v')) {
// Strip 'v' only for validation check
checkVersion = versionPart.substring(1);
}
// Validate format - Version.parse throws FormatException on invalid input
// ignore: avoid-unused-instances
Version.parse(checkVersion);
// Use the original version string (preserving v if present)
return FlutterVersion.release(versionPart, fork: forkName);
} catch (e) {
// Not a valid semver, treat as git reference
return FlutterVersion.gitReference(versionPart, fork: forkName);
}
}