diff --git a/packages/flutter_tools/lib/src/android/gradle_utils.dart b/packages/flutter_tools/lib/src/android/gradle_utils.dart index 7aef19c1d71..7802358d2d7 100644 --- a/packages/flutter_tools/lib/src/android/gradle_utils.dart +++ b/packages/flutter_tools/lib/src/android/gradle_utils.dart @@ -107,7 +107,7 @@ class GradleUtils { return !destinationFile.existsSync(); }, onFileCopied: (File sourceFile, File destinationFile) { - if (_hasExecutePermission(sourceFile)) { + if (_hasAnyExecutableFlagSet(sourceFile)) { _giveExecutePermissionIfNeeded(destinationFile); } }, @@ -153,17 +153,25 @@ String getGradleVersionForAndroidPlugin(Directory directory) { const int _kExecPermissionMask = 0x49; // a+x -/// Returns [true] if [executable] has execute permission. -bool _hasExecutePermission(File executable) { +/// Returns [true] if [executable] has all executable flag set. +bool _hasAllExecutableFlagSet(File executable) { final FileStat stat = executable.statSync(); assert(stat.type != FileSystemEntityType.notFound); printTrace('${executable.path} mode: ${stat.mode} ${stat.modeString()}.'); return stat.mode & _kExecPermissionMask == _kExecPermissionMask; } +/// Returns [true] if [executable] has any executable flag set. +bool _hasAnyExecutableFlagSet(File executable) { + final FileStat stat = executable.statSync(); + assert(stat.type != FileSystemEntityType.notFound); + printTrace('${executable.path} mode: ${stat.mode} ${stat.modeString()}.'); + return stat.mode & _kExecPermissionMask != 0; +} + /// Gives execute permission to [executable] if it doesn't have it already. void _giveExecutePermissionIfNeeded(File executable) { - if (!_hasExecutePermission(executable)) { + if (!_hasAllExecutableFlagSet(executable)) { printTrace('Trying to give execute permission to ${executable.path}.'); os.makeExecutable(executable); } diff --git a/packages/flutter_tools/test/general.shard/android/gradle_utils_test.dart b/packages/flutter_tools/test/general.shard/android/gradle_utils_test.dart index b5cdc97fc15..d0cca2af978 100644 --- a/packages/flutter_tools/test/general.shard/android/gradle_utils_test.dart +++ b/packages/flutter_tools/test/general.shard/android/gradle_utils_test.dart @@ -285,6 +285,37 @@ void main() { GradleUtils: () => gradleUtils, }); + testUsingContext('gives execute permission to gradle even when not all permission flags are set', () { + final FlutterProject flutterProject = MockFlutterProject(); + final AndroidProject androidProject = MockAndroidProject(); + when(flutterProject.android).thenReturn(androidProject); + + final FileStat gradleStat = MockFileStat(); + when(gradleStat.mode).thenReturn(400); + + final File gradlew = MockFile(); + when(gradlew.path).thenReturn('gradlew'); + when(gradlew.absolute).thenReturn(gradlew); + when(gradlew.statSync()).thenReturn(gradleStat); + when(gradlew.existsSync()).thenReturn(true); + + final Directory androidDirectory = MockDirectory(); + when(androidDirectory.childFile(gradlewFilename)).thenReturn(gradlew); + when(androidProject.hostAppGradleRoot).thenReturn(androidDirectory); + + when(gradleUtils.injectGradleWrapperIfNeeded(any)).thenReturn(null); + when(gradleUtils.migrateToR8(any)).thenReturn(null); + + GradleUtils().getExecutable(flutterProject); + + verify(operatingSystemUtils.makeExecutable(gradlew)).called(1); + }, overrides: { + FileSystem: () => memoryFileSystem, + ProcessManager: () => FakeProcessManager.any(), + OperatingSystemUtils: () => operatingSystemUtils, + GradleUtils: () => gradleUtils, + }); + testUsingContext('doesn\'t give execute permission to gradle if not needed', () { final FlutterProject flutterProject = MockFlutterProject(); final AndroidProject androidProject = MockAndroidProject();