Unverified Commit f7f1685c authored by xster's avatar xster Committed by GitHub

Make sure broken pod install runs triggers pod install on next flutter build (#14753)

parent 297fd943
...@@ -57,18 +57,19 @@ class CocoaPods { ...@@ -57,18 +57,19 @@ class CocoaPods {
Future<bool> get isCocoaPodsInitialized => fs.isDirectory(fs.path.join(homeDirPath, '.cocoapods', 'repos', 'master')); Future<bool> get isCocoaPodsInitialized => fs.isDirectory(fs.path.join(homeDirPath, '.cocoapods', 'repos', 'master'));
Future<Null> processPods({ Future<Null> processPods({
@required Directory appIosDir, @required Directory appIosDirectory,
// For backward compatibility with previously created Podfile only. // For backward compatibility with previously created Podfile only.
@required String iosEngineDir, @required String iosEngineDir,
bool isSwift: false, bool isSwift: false,
bool flutterPodChanged: true, bool flutterPodChanged: true,
}) async { }) async {
if (!(await appIosDir.childFile('Podfile').exists())) { if (!(await appIosDirectory.childFile('Podfile').exists())) {
throwToolExit('Podfile missing'); throwToolExit('Podfile missing');
} }
if (await _checkPodCondition()) { if (await _checkPodCondition()) {
if (_shouldRunPodInstall(appIosDir.path, flutterPodChanged)) if (_shouldRunPodInstall(appIosDirectory, flutterPodChanged)) {
await _runPodInstall(appIosDir, iosEngineDir); await _runPodInstall(appIosDirectory, iosEngineDir);
}
} }
} }
...@@ -100,18 +101,18 @@ class CocoaPods { ...@@ -100,18 +101,18 @@ class CocoaPods {
return true; return true;
} }
/// Ensures the `ios` sub-project of the Flutter project at [directory] /// Ensures the `ios` sub-project of the Flutter project at [appDirectory]
/// contains a suitable `Podfile` and that its `Flutter/Xxx.xcconfig` files /// contains a suitable `Podfile` and that its `Flutter/Xxx.xcconfig` files
/// include pods configuration. /// include pods configuration.
void setupPodfile(String directory) { void setupPodfile(String appDirectory) {
if (!xcodeProjectInterpreter.canInterpretXcodeProjects) { if (!xcodeProjectInterpreter.canInterpretXcodeProjects) {
// Don't do anything for iOS when host platform doesn't support it. // Don't do anything for iOS when host platform doesn't support it.
return; return;
} }
final String podfilePath = fs.path.join(directory, 'ios', 'Podfile'); final String podfilePath = fs.path.join(appDirectory, 'ios', 'Podfile');
if (!fs.file(podfilePath).existsSync()) { if (!fs.file(podfilePath).existsSync()) {
final bool isSwift = xcodeProjectInterpreter.getBuildSettings( final bool isSwift = xcodeProjectInterpreter.getBuildSettings(
fs.path.join(directory, 'ios', 'Runner.xcodeproj'), fs.path.join(appDirectory, 'ios', 'Runner.xcodeproj'),
'Runner', 'Runner',
).containsKey('SWIFT_VERSION'); ).containsKey('SWIFT_VERSION');
final File podfileTemplate = fs.file(fs.path.join( final File podfileTemplate = fs.file(fs.path.join(
...@@ -124,12 +125,12 @@ class CocoaPods { ...@@ -124,12 +125,12 @@ class CocoaPods {
)); ));
podfileTemplate.copySync(podfilePath); podfileTemplate.copySync(podfilePath);
} }
_addPodsDependencyToFlutterXcconfig(directory, 'Debug'); _addPodsDependencyToFlutterXcconfig(appDirectory, 'Debug');
_addPodsDependencyToFlutterXcconfig(directory, 'Release'); _addPodsDependencyToFlutterXcconfig(appDirectory, 'Release');
} }
void _addPodsDependencyToFlutterXcconfig(String directory, String mode) { void _addPodsDependencyToFlutterXcconfig(String appDirectory, String mode) {
final File file = fs.file(fs.path.join(directory, 'ios', 'Flutter', '$mode.xcconfig')); final File file = fs.file(fs.path.join(appDirectory, 'ios', 'Flutter', '$mode.xcconfig'));
if (file.existsSync()) { if (file.existsSync()) {
final String content = file.readAsStringSync(); final String content = file.readAsStringSync();
final String include = '#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.${mode final String include = '#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.${mode
...@@ -140,9 +141,9 @@ class CocoaPods { ...@@ -140,9 +141,9 @@ class CocoaPods {
} }
/// Ensures that pod install is deemed needed on next check. /// Ensures that pod install is deemed needed on next check.
void invalidatePodInstallOutput(String directory) { void invalidatePodInstallOutput(String appDirectory) {
final File manifest = fs.file( final File manifest = fs.file(
fs.path.join(directory, 'ios', 'Pods', 'Manifest.lock'), fs.path.join(appDirectory, 'ios', 'Pods', 'Manifest.lock'),
); );
if (manifest.existsSync()) if (manifest.existsSync())
manifest.deleteSync(); manifest.deleteSync();
...@@ -154,22 +155,23 @@ class CocoaPods { ...@@ -154,22 +155,23 @@ class CocoaPods {
// 2. The podfile.lock doesn't exist // 2. The podfile.lock doesn't exist
// 3. The Pods/Manifest.lock doesn't exist (It is deleted when plugins change) // 3. The Pods/Manifest.lock doesn't exist (It is deleted when plugins change)
// 4. The podfile.lock doesn't match Pods/Manifest.lock. // 4. The podfile.lock doesn't match Pods/Manifest.lock.
bool _shouldRunPodInstall(String appDir, bool flutterPodChanged) { bool _shouldRunPodInstall(Directory appIosDirectory, bool flutterPodChanged) {
if (flutterPodChanged) if (flutterPodChanged)
return true; return true;
// Check if podfile.lock and Pods/Manifest.lock exist and match. // Check if podfile.lock and Pods/Manifest.lock exist and match.
final File podfileLockFile = fs.file(fs.path.join(appDir, 'Podfile.lock')); final File podfileLockFile = appIosDirectory.childFile('Podfile.lock');
final File manifestLockFile = fs.file(fs.path.join(appDir, 'Pods', 'Manifest.lock')); final File manifestLockFile =
appIosDirectory.childFile(fs.path.join('Pods', 'Manifest.lock'));
return !podfileLockFile.existsSync() return !podfileLockFile.existsSync()
|| !manifestLockFile.existsSync() || !manifestLockFile.existsSync()
|| podfileLockFile.readAsStringSync() != manifestLockFile.readAsStringSync(); || podfileLockFile.readAsStringSync() != manifestLockFile.readAsStringSync();
} }
Future<Null> _runPodInstall(Directory bundle, String engineDirectory) async { Future<Null> _runPodInstall(Directory appIosDirectory, String engineDirectory) async {
final Status status = logger.startProgress('Running pod install...', expectSlowOperation: true); final Status status = logger.startProgress('Running pod install...', expectSlowOperation: true);
final ProcessResult result = await processManager.run( final ProcessResult result = await processManager.run(
<String>['pod', 'install', '--verbose'], <String>['pod', 'install', '--verbose'],
workingDirectory: bundle.path, workingDirectory: appIosDirectory.path,
environment: <String, String>{ environment: <String, String>{
// For backward compatibility with previously created Podfile only. // For backward compatibility with previously created Podfile only.
'FLUTTER_FRAMEWORK_DIR': engineDirectory, 'FLUTTER_FRAMEWORK_DIR': engineDirectory,
...@@ -190,6 +192,7 @@ class CocoaPods { ...@@ -190,6 +192,7 @@ class CocoaPods {
} }
} }
if (result.exitCode != 0) { if (result.exitCode != 0) {
invalidatePodInstallOutput(appIosDirectory.parent.path);
_diagnosePodInstallFailure(result); _diagnosePodInstallFailure(result);
throwToolExit('Error running pod install'); throwToolExit('Error running pod install');
} }
......
...@@ -268,7 +268,7 @@ Future<XcodeBuildResult> buildXcodeProject({ ...@@ -268,7 +268,7 @@ Future<XcodeBuildResult> buildXcodeProject({
if (hasPlugins()) { if (hasPlugins()) {
final String currentGeneratedXcconfig = readGeneratedXcconfig(app.appDirectory); final String currentGeneratedXcconfig = readGeneratedXcconfig(app.appDirectory);
await cocoaPods.processPods( await cocoaPods.processPods(
appIosDir: appDirectory, appIosDirectory: appDirectory,
iosEngineDir: flutterFrameworkDir(buildInfo.mode), iosEngineDir: flutterFrameworkDir(buildInfo.mode),
isSwift: app.isSwift, isSwift: app.isSwift,
flutterPodChanged: (previousGeneratedXcconfig != currentGeneratedXcconfig), flutterPodChanged: (previousGeneratedXcconfig != currentGeneratedXcconfig),
......
...@@ -129,7 +129,7 @@ void main() { ...@@ -129,7 +129,7 @@ void main() {
projectUnderTest.childFile('Podfile').createSync(); projectUnderTest.childFile('Podfile').createSync();
cocoaPodsUnderTest = const TestCocoaPods(false); cocoaPodsUnderTest = const TestCocoaPods(false);
await cocoaPodsUnderTest.processPods( await cocoaPodsUnderTest.processPods(
appIosDir: projectUnderTest, appIosDirectory: projectUnderTest,
iosEngineDir: 'engine/path', iosEngineDir: 'engine/path',
); );
verifyNever(mockProcessManager.run( verifyNever(mockProcessManager.run(
...@@ -148,7 +148,7 @@ void main() { ...@@ -148,7 +148,7 @@ void main() {
cocoaPodsUnderTest = const TestCocoaPods(true); cocoaPodsUnderTest = const TestCocoaPods(true);
try { try {
await cocoaPodsUnderTest.processPods( await cocoaPodsUnderTest.processPods(
appIosDir: projectUnderTest, appIosDirectory: projectUnderTest,
iosEngineDir: 'engine/path', iosEngineDir: 'engine/path',
); );
fail('ToolExit expected'); fail('ToolExit expected');
...@@ -198,7 +198,7 @@ Note: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by ...@@ -198,7 +198,7 @@ Note: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by
)); ));
try { try {
await cocoaPodsUnderTest.processPods( await cocoaPodsUnderTest.processPods(
appIosDir: projectUnderTest, appIosDirectory: projectUnderTest,
iosEngineDir: 'engine/path', iosEngineDir: 'engine/path',
); );
fail('ToolExit expected'); fail('ToolExit expected');
...@@ -222,7 +222,7 @@ Note: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by ...@@ -222,7 +222,7 @@ Note: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by
..createSync(recursive: true) ..createSync(recursive: true)
..writeAsString('Existing lock file.'); ..writeAsString('Existing lock file.');
await cocoaPodsUnderTest.processPods( await cocoaPodsUnderTest.processPods(
appIosDir: projectUnderTest, appIosDirectory: projectUnderTest,
iosEngineDir: 'engine/path', iosEngineDir: 'engine/path',
flutterPodChanged: false, flutterPodChanged: false,
); );
...@@ -244,7 +244,7 @@ Note: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by ...@@ -244,7 +244,7 @@ Note: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by
..createSync() ..createSync()
..writeAsString('Existing lock file.'); ..writeAsString('Existing lock file.');
await cocoaPodsUnderTest.processPods( await cocoaPodsUnderTest.processPods(
appIosDir: projectUnderTest, appIosDirectory: projectUnderTest,
iosEngineDir: 'engine/path', iosEngineDir: 'engine/path',
flutterPodChanged: false, flutterPodChanged: false,
); );
...@@ -272,7 +272,7 @@ Note: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by ...@@ -272,7 +272,7 @@ Note: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by
..createSync(recursive: true) ..createSync(recursive: true)
..writeAsString('Different lock file.'); ..writeAsString('Different lock file.');
await cocoaPodsUnderTest.processPods( await cocoaPodsUnderTest.processPods(
appIosDir: projectUnderTest, appIosDirectory: projectUnderTest,
iosEngineDir: 'engine/path', iosEngineDir: 'engine/path',
flutterPodChanged: false, flutterPodChanged: false,
); );
...@@ -300,7 +300,7 @@ Note: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by ...@@ -300,7 +300,7 @@ Note: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by
..createSync(recursive: true) ..createSync(recursive: true)
..writeAsString('Existing lock file.'); ..writeAsString('Existing lock file.');
await cocoaPodsUnderTest.processPods( await cocoaPodsUnderTest.processPods(
appIosDir: projectUnderTest, appIosDirectory: projectUnderTest,
iosEngineDir: 'engine/path', iosEngineDir: 'engine/path',
flutterPodChanged: true, flutterPodChanged: true,
); );
...@@ -328,7 +328,7 @@ Note: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by ...@@ -328,7 +328,7 @@ Note: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by
..createSync(recursive: true) ..createSync(recursive: true)
..writeAsString('Existing lock file.'); ..writeAsString('Existing lock file.');
await cocoaPodsUnderTest.processPods( await cocoaPodsUnderTest.processPods(
appIosDir: projectUnderTest, appIosDirectory: projectUnderTest,
iosEngineDir: 'engine/path', iosEngineDir: 'engine/path',
flutterPodChanged: false, flutterPodChanged: false,
); );
...@@ -341,6 +341,41 @@ Note: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by ...@@ -341,6 +341,41 @@ Note: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by
FileSystem: () => fs, FileSystem: () => fs,
ProcessManager: () => mockProcessManager, ProcessManager: () => mockProcessManager,
}); });
testUsingContext('a failed pod install deletes Pods/Manifest.lock', () async {
projectUnderTest.childFile('Podfile')
..createSync()
..writeAsString('Existing Podfile');
projectUnderTest.childFile('Podfile.lock')
..createSync()
..writeAsString('Existing lock file.');
projectUnderTest.childFile('Pods/Manifest.lock')
..createSync(recursive: true)
..writeAsString('Existing lock file.');
when(mockProcessManager.run(
<String>['pod', 'install', '--verbose'],
workingDirectory: 'project/ios',
environment: <String, String>{
'FLUTTER_FRAMEWORK_DIR': 'engine/path',
'COCOAPODS_DISABLE_STATS': 'true',
},
)).thenReturn(new ProcessResult(1, 1, 'fails for some reason', ''));
try {
await cocoaPodsUnderTest.processPods(
appIosDirectory: projectUnderTest,
iosEngineDir: 'engine/path',
flutterPodChanged: true,
);
fail('Tool throw expected when pod install fails');
} on ToolExit {
expect(projectUnderTest.childFile('Pods/Manifest.lock').existsSync(), isFalse);
}
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => mockProcessManager,
});
}); });
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment