1import { Command } from '@expo/commander'; 2import chalk from 'chalk'; 3import { hashElement } from 'folder-hash'; 4import path from 'path'; 5import process from 'process'; 6 7import { podInstallAsync } from '../CocoaPods'; 8import { EXPO_DIR } from '../Constants'; 9import logger from '../Logger'; 10 11type ActionOptions = { 12 force: boolean; 13 verbose: boolean; 14}; 15 16async function action(options: ActionOptions) { 17 if (process.platform !== 'darwin') { 18 throw new Error('This command is not supported on this platform.'); 19 } 20 21 for (const relativeProjectPath of ['ios', 'apps/bare-expo/ios']) { 22 const absoluteProjectPath = path.join(EXPO_DIR, relativeProjectPath); 23 const podfileLockHash = await md5(path.join(absoluteProjectPath, 'Podfile.lock')); 24 const manifestLockHash = await md5(path.join(absoluteProjectPath, 'Pods/Manifest.lock')); 25 26 if (!manifestLockHash || podfileLockHash !== manifestLockHash || options.force) { 27 logger.info(` Installing pods in ${chalk.yellow(relativeProjectPath)} directory`); 28 29 try { 30 await podInstallAsync(absoluteProjectPath, { 31 stdio: options.verbose ? 'inherit' : 'pipe', 32 }); 33 } catch (e) { 34 if (!options.verbose) { 35 // In this case, the output has already been printed. 36 logger.error(` Installation failed with output: ${e.output}`); 37 } 38 return; 39 } 40 } 41 } 42 logger.success(' All iOS projects have up-to-date local pods'); 43} 44 45async function md5(path: string): Promise<string | null> { 46 try { 47 const { hash } = await hashElement(path, { 48 algo: 'md5', 49 encoding: 'hex', 50 files: { 51 ignoreBasename: true, 52 ignoreRootName: true, 53 }, 54 }); 55 return hash; 56 } catch { 57 return null; 58 } 59} 60 61export default (program: Command) => { 62 program 63 .command('pod-install') 64 .alias('pods') 65 .description('Installs pods in the directories where they are not in-sync') 66 .option('-f, --force', 'Whether to force installing pods in all projects.', false) 67 .option('-v, --verbose', 'Whether to inherit logs from `pod install` command.', false) 68 .asyncAction(action); 69}; 70