blob: d1bae084281c2f638ea7e1431da8547c3da5243b [file] [log] [blame]
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:meta/meta.dart';
import '../../base/file_system.dart';
import '../../base/project_migrator.dart';
import '../../base/version.dart';
import '../../project.dart';
import '../android_studio.dart';
import '../gradle_utils.dart';
import '../java.dart';
// Android Studio 2022.2 "Flamingo" is the first to bundle a Java 17 JDK.
// Previous versions bundled a Java 11 JDK.
@visibleForTesting
final Version androidStudioFlamingo = Version(2022, 2, 0);
@visibleForTesting
const String gradleVersion7_6_1 = r'7.6.1';
// String that can be placed in the gradle-wrapper.properties to opt out of this
// migrator.
@visibleForTesting
const String optOutFlag = 'NoFlutterGradleWrapperUpgrade';
// Only the major version matters.
final Version flamingoBundledJava = Version(17, 0, 0);
// These gradle versions were chosen because they
// 1. Were output by 'flutter create' at some point in flutter's history and
// 2. Are less than 7.3, the lowest supported gradle version for JDK 17
const List<String> gradleVersionsToUpgradeFrom =
<String>['5.6.2', '6.7'];
// Define log messages as constants to re-use in testing.
@visibleForTesting
const String gradleWrapperNotFound =
'gradle-wrapper.properties not found, skipping Gradle-Java version compatibility check.';
@visibleForTesting
const String androidStudioNotFound =
'Android Studio version could not be detected, '
'skipping Gradle-Java version compatibility check.';
@visibleForTesting
const String androidStudioVersionBelowFlamingo =
'Version of Android Studio is less than Flamingo (the first impacted version),'
' no migration attempted.';
@visibleForTesting
const String javaVersionNot17 =
'Version of Java is different than impacted version, no migration attempted.';
@visibleForTesting
const String javaVersionNotFound =
'Version of Java not found, no migration attempted.';
@visibleForTesting
const String conflictDetected = 'Conflict detected between versions of Android Studio '
'and Gradle, upgrading Gradle version from current to 7.4';
@visibleForTesting
const String gradleVersionNotFound = 'Failed to parse Gradle version from distribution url, '
'skipping Gradle-Java version compatibility check.';
@visibleForTesting
const String optOutFlagEnabled = 'Skipping Android Studio Java-Gradle compatibility '
"because opt out flag: '$optOutFlag' is enabled in gradle-wrapper.properties file.";
@visibleForTesting
const String errorWhileMigrating = 'Encountered an error while attempting Gradle-Java '
'version compatibility check, skipping migration attempt. Error was: ';
/// Migrate to a newer version of Gradle when the existing one does not support
/// the version of Java provided by the detected Android Studio version.
///
/// For more info see the Gradle-Java compatibility matrix:
/// https://docs.gradle.org/current/userguide/compatibility.html
class AndroidStudioJavaGradleConflictMigration extends ProjectMigrator {
AndroidStudioJavaGradleConflictMigration(
super.logger,
{required AndroidProject project,
AndroidStudio? androidStudio,
required Java? java,
}) : _gradleWrapperPropertiesFile = getGradleWrapperFile(project.hostAppGradleRoot),
_androidStudio = androidStudio,
_java = java;
final File _gradleWrapperPropertiesFile;
final AndroidStudio? _androidStudio;
final Java? _java;
@override
Future<void> migrate() async {
try {
if (!_gradleWrapperPropertiesFile.existsSync()) {
logger.printTrace(gradleWrapperNotFound);
return;
}
if (_androidStudio == null || _androidStudio.version == null) {
logger.printTrace(androidStudioNotFound);
return;
} else if (_androidStudio.version!.major < androidStudioFlamingo.major) {
logger.printTrace(androidStudioVersionBelowFlamingo);
return;
}
if (_java?.version == null) {
logger.printTrace(javaVersionNotFound);
return;
}
if (_java!.version!.major != flamingoBundledJava.major) {
logger.printTrace(javaVersionNot17);
return;
}
processFileLines(_gradleWrapperPropertiesFile);
} on Exception catch (e) {
logger.printTrace(errorWhileMigrating + e.toString());
} on Error catch (e) {
logger.printTrace(errorWhileMigrating + e.toString());
}
}
@override
String migrateFileContents(String fileContents) {
if (fileContents.contains(optOutFlag)) {
logger.printTrace(optOutFlagEnabled);
return fileContents;
}
final RegExpMatch? gradleDistributionUrl = gradleOrgVersionMatch.firstMatch(fileContents);
if (gradleDistributionUrl == null
|| gradleDistributionUrl.groupCount < 1
|| gradleDistributionUrl[1] == null) {
logger.printTrace(gradleVersionNotFound);
return fileContents;
}
final String existingVersionString = gradleDistributionUrl[1]!;
if (gradleVersionsToUpgradeFrom.contains(existingVersionString)) {
logger.printStatus('Conflict detected between Android Studio Java version and Gradle version, '
'upgrading Gradle version from $existingVersionString to $gradleVersion7_6_1.');
final String? gradleDistributionUrlString = gradleDistributionUrl.group(0);
if (gradleDistributionUrlString != null) {
final String upgradedDistributionUrl =
gradleDistributionUrlString.replaceAll(existingVersionString, gradleVersion7_6_1);
fileContents = fileContents.replaceFirst(gradleOrgVersionMatch, upgradedDistributionUrl);
} else {
logger.printTrace(gradleVersionNotFound);
}
}
return fileContents;
}
}