Is executable doesn't mean a+x (#47359)
diff --git a/packages/flutter_tools/lib/src/android/gradle_utils.dart b/packages/flutter_tools/lib/src/android/gradle_utils.dart
index 7aef19c..7802358 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 @@
return !destinationFile.existsSync();
},
onFileCopied: (File sourceFile, File destinationFile) {
- if (_hasExecutePermission(sourceFile)) {
+ if (_hasAnyExecutableFlagSet(sourceFile)) {
_giveExecutePermissionIfNeeded(destinationFile);
}
},
@@ -153,17 +153,25 @@
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 b5cdc97..d0cca2a 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 @@
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: <Type, Generator>{
+ 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();