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