detectVersion static method

Future<String?> detectVersion(
  1. String appRoot
)

Detects one stable marketing version from conventional project files.

Literal MARKETING_VERSION build settings take precedence over a literal CFBundleShortVersionString. Dynamic build-setting references are ignored.

Implementation

static Future<String?> detectVersion(String appRoot) async {
  final iosDirectory = Directory(p.join(appRoot, 'ios'));
  if (!(await iosDirectory.exists())) return null;
  final projects =
      (await iosDirectory.list(followLinks: false).toList())
          .whereType<Directory>()
          .where((entry) => p.extension(entry.path) == '.xcodeproj')
          .toList()
        ..sort((left, right) => left.path.compareTo(right.path));
  final projectVersions = <String>{};
  for (final project in projects) {
    final settings = File(p.join(project.path, 'project.pbxproj'));
    if (!(await settings.exists())) continue;
    final source = await settings.readAsString();
    projectVersions.addAll(
      _stableVersions(
        RegExp(
          r'^\s*MARKETING_VERSION\s*=\s*"?([^";]+)"?;\s*$',
          multiLine: true,
        ).allMatches(source).map((match) => match.group(1)),
      ),
    );
  }
  if (projectVersions.isNotEmpty) {
    return _oneVersion(projectVersions);
  }

  final infoPlist = File(p.join(iosDirectory.path, 'Runner', 'Info.plist'));
  if (!(await infoPlist.exists())) return null;
  final source = await infoPlist.readAsString();
  final match = RegExp(
    r'<key>\s*CFBundleShortVersionString\s*</key>\s*'
    r'<string>\s*([^<$]+)\s*</string>',
    multiLine: true,
  ).firstMatch(source);
  final versions = _stableVersions(<String?>[match?.group(1)]);
  return versions.isEmpty ? null : versions.single;
}