Skip to content

Commit 7850e25

Browse files
authored
Is executable doesn't mean a+x (flutter#47359)
1 parent 1967a36 commit 7850e25

File tree

2 files changed

+43
-4
lines changed

2 files changed

+43
-4
lines changed

packages/flutter_tools/lib/src/android/gradle_utils.dart

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ class GradleUtils {
107107
return !destinationFile.existsSync();
108108
},
109109
onFileCopied: (File sourceFile, File destinationFile) {
110-
if (_hasExecutePermission(sourceFile)) {
110+
if (_hasAnyExecutableFlagSet(sourceFile)) {
111111
_giveExecutePermissionIfNeeded(destinationFile);
112112
}
113113
},
@@ -153,17 +153,25 @@ String getGradleVersionForAndroidPlugin(Directory directory) {
153153

154154
const int _kExecPermissionMask = 0x49; // a+x
155155

156-
/// Returns [true] if [executable] has execute permission.
157-
bool _hasExecutePermission(File executable) {
156+
/// Returns [true] if [executable] has all executable flag set.
157+
bool _hasAllExecutableFlagSet(File executable) {
158158
final FileStat stat = executable.statSync();
159159
assert(stat.type != FileSystemEntityType.notFound);
160160
printTrace('${executable.path} mode: ${stat.mode} ${stat.modeString()}.');
161161
return stat.mode & _kExecPermissionMask == _kExecPermissionMask;
162162
}
163163

164+
/// Returns [true] if [executable] has any executable flag set.
165+
bool _hasAnyExecutableFlagSet(File executable) {
166+
final FileStat stat = executable.statSync();
167+
assert(stat.type != FileSystemEntityType.notFound);
168+
printTrace('${executable.path} mode: ${stat.mode} ${stat.modeString()}.');
169+
return stat.mode & _kExecPermissionMask != 0;
170+
}
171+
164172
/// Gives execute permission to [executable] if it doesn't have it already.
165173
void _giveExecutePermissionIfNeeded(File executable) {
166-
if (!_hasExecutePermission(executable)) {
174+
if (!_hasAllExecutableFlagSet(executable)) {
167175
printTrace('Trying to give execute permission to ${executable.path}.');
168176
os.makeExecutable(executable);
169177
}

packages/flutter_tools/test/general.shard/android/gradle_utils_test.dart

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,37 @@ void main() {
285285
GradleUtils: () => gradleUtils,
286286
});
287287

288+
testUsingContext('gives execute permission to gradle even when not all permission flags are set', () {
289+
final FlutterProject flutterProject = MockFlutterProject();
290+
final AndroidProject androidProject = MockAndroidProject();
291+
when(flutterProject.android).thenReturn(androidProject);
292+
293+
final FileStat gradleStat = MockFileStat();
294+
when(gradleStat.mode).thenReturn(400);
295+
296+
final File gradlew = MockFile();
297+
when(gradlew.path).thenReturn('gradlew');
298+
when(gradlew.absolute).thenReturn(gradlew);
299+
when(gradlew.statSync()).thenReturn(gradleStat);
300+
when(gradlew.existsSync()).thenReturn(true);
301+
302+
final Directory androidDirectory = MockDirectory();
303+
when(androidDirectory.childFile(gradlewFilename)).thenReturn(gradlew);
304+
when(androidProject.hostAppGradleRoot).thenReturn(androidDirectory);
305+
306+
when(gradleUtils.injectGradleWrapperIfNeeded(any)).thenReturn(null);
307+
when(gradleUtils.migrateToR8(any)).thenReturn(null);
308+
309+
GradleUtils().getExecutable(flutterProject);
310+
311+
verify(operatingSystemUtils.makeExecutable(gradlew)).called(1);
312+
}, overrides: <Type, Generator>{
313+
FileSystem: () => memoryFileSystem,
314+
ProcessManager: () => FakeProcessManager.any(),
315+
OperatingSystemUtils: () => operatingSystemUtils,
316+
GradleUtils: () => gradleUtils,
317+
});
318+
288319
testUsingContext('doesn\'t give execute permission to gradle if not needed', () {
289320
final FlutterProject flutterProject = MockFlutterProject();
290321
final AndroidProject androidProject = MockAndroidProject();

0 commit comments

Comments
 (0)