blob: 39e2b98483c6b5bfff2065ad24403ceb859941b9 [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/os.dart';
import '../../base/platform.dart';
import '../../base/process.dart';
import '../../base/project_migrator.dart';
import '../../base/version.dart';
import '../../project.dart';
import '../android_sdk.dart';
import '../android_studio.dart';
import '../gradle_utils.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);
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.";
/// 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 FileSystem fileSystem,
required ProcessUtils processUtils,
required Platform platform,
required OperatingSystemUtils os,
AndroidSdk? androidSdk,
}) : _gradleWrapperPropertiesFile = getGradleWrapperFile(project.hostAppGradleRoot),
_androidStudio = androidStudio,
_fileSystem = fileSystem,
_processUtils = processUtils,
_platform = platform,
_os = os,
_androidSdk = androidSdk;
final File _gradleWrapperPropertiesFile;
final AndroidStudio? _androidStudio;
final FileSystem _fileSystem;
final ProcessUtils _processUtils;
final Platform _platform;
final OperatingSystemUtils _os;
final AndroidSdk? _androidSdk;
@override
void migrate() {
if (!_gradleWrapperPropertiesFile.existsSync()) {
logger.printTrace(gradleWrapperNotFound);
return;
}
if (_androidStudio == null) {
logger.printTrace(androidStudioNotFound);
return;
} else if (_androidStudio!.version!.major < androidStudioFlamingo.major) {
logger.printTrace(androidStudioVersionBelowFlamingo);
return;
}
final String? javaVersionString = _androidSdk?.getJavaVersion(
androidStudio: _androidStudio,
fileSystem: _fileSystem,
operatingSystemUtils: _os,
platform: _platform,
processUtils: _processUtils,
);
final Version? javaVersion = Version.parse(javaVersionString);
if (javaVersion == null) {
logger.printTrace(javaVersionNotFound);
return;
}
if (javaVersion.major != flamingoBundledJava.major) {
logger.printTrace(javaVersionNot17);
return;
}
processFileLines(_gradleWrapperPropertiesFile);
}
@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) {
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)!;
final String upgradedDistributionUrl =
gradleDistributionUrlString.replaceAll(existingVersionString, _gradleVersion7_6_1);
fileContents = fileContents.replaceFirst(gradleOrgVersionMatch, upgradedDistributionUrl);
}
return fileContents;
}
}