From 8e608e16d3c0eac06939e291855ee87fdcdcaf31 Mon Sep 17 00:00:00 2001 From: Tomasz Misiukiewicz Date: Thu, 21 Sep 2023 08:57:50 +0200 Subject: [PATCH 01/22] remove pod installation from init process --- packages/cli/src/commands/init/init.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/packages/cli/src/commands/init/init.ts b/packages/cli/src/commands/init/init.ts index 30ad44c1f..38df84b61 100644 --- a/packages/cli/src/commands/init/init.ts +++ b/packages/cli/src/commands/init/init.ts @@ -18,7 +18,6 @@ import { } from './template'; import {changePlaceholderInTemplate} from './editTemplate'; import * as PackageManager from '../../tools/packageManager'; -import {installPods} from '@react-native-community/cli-doctor'; import banner from './banner'; import TemplateAndVersionError from './errors/TemplateAndVersionError'; import {getBunVersionIfAvailable} from '../../tools/bun'; @@ -198,10 +197,6 @@ async function installDependencies({ root, }); - if (process.platform === 'darwin') { - await installPods(loader); - } - loader.succeed(); } From 1b83851970680f45e56695f3205ca4b8c60d1384 Mon Sep 17 00:00:00 2001 From: Tomasz Misiukiewicz Date: Thu, 21 Sep 2023 08:58:15 +0200 Subject: [PATCH 02/22] create dependency hashes and store it in cache --- packages/cli-platform-ios/package.json | 3 ++ .../src/commands/runIOS/index.ts | 3 ++ packages/cli-platform-ios/src/tools/pods.ts | 50 +++++++++++++++++++ packages/cli-tools/src/index.ts | 1 + .../src/releaseChecker/releaseCacheManager.ts | 6 ++- yarn.lock | 10 ++++ 6 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 packages/cli-platform-ios/src/tools/pods.ts diff --git a/packages/cli-platform-ios/package.json b/packages/cli-platform-ios/package.json index 710f28947..3744a40d3 100644 --- a/packages/cli-platform-ios/package.json +++ b/packages/cli-platform-ios/package.json @@ -8,7 +8,9 @@ }, "dependencies": { "@react-native-community/cli-tools": "12.0.0-alpha.13", + "@react-native-community/cli-doctor": "12.0.0-alpha.13", "chalk": "^4.1.2", + "crypto-js": "^4.1.1", "execa": "^5.0.0", "fast-xml-parser": "^4.0.12", "glob": "^7.1.3", @@ -16,6 +18,7 @@ }, "devDependencies": { "@react-native-community/cli-types": "12.0.0-alpha.13", + "@types/crypto-js": "^4.1.2", "@types/glob": "^7.1.1", "@types/lodash": "^4.14.149", "hasbin": "^1.2.3" diff --git a/packages/cli-platform-ios/src/commands/runIOS/index.ts b/packages/cli-platform-ios/src/commands/runIOS/index.ts index eb0b95244..a8c6f9449 100644 --- a/packages/cli-platform-ios/src/commands/runIOS/index.ts +++ b/packages/cli-platform-ios/src/commands/runIOS/index.ts @@ -30,6 +30,7 @@ import listIOSDevices from '../../tools/listIOSDevices'; import {promptForDeviceSelection} from '../../tools/prompts'; import getSimulators from '../../tools/getSimulators'; import {getXcodeProjectAndDir} from '../buildIOS/getXcodeProjectAndDir'; +import resolvePods from '../../tools/pods'; export interface FlagsT extends BuildFlags { simulator?: string; @@ -47,6 +48,8 @@ async function runIOS(_: Array, ctx: Config, args: FlagsT) { let {packager, port} = args; + await resolvePods(ctx.root); + const packagerStatus = await isPackagerRunning(port); if ( diff --git a/packages/cli-platform-ios/src/tools/pods.ts b/packages/cli-platform-ios/src/tools/pods.ts new file mode 100644 index 000000000..93399f1cc --- /dev/null +++ b/packages/cli-platform-ios/src/tools/pods.ts @@ -0,0 +1,50 @@ +import path from 'path'; +import md5 from 'crypto-js/md5'; +import {cacheManager} from '@react-native-community/cli-tools'; + +export function getPackageJson(root: string) { + return require(path.join(root, 'package.json')); +} + +export function normalizeDependencies(dependencies: Record) { + return Object.entries(dependencies) + .map(([name, version]) => `${name}@${version}`) + .sort(); +} + +export function dependenciesToString(dependencies: string[]) { + return dependencies.join('\n'); +} + +function generateMd5Hash(text: string) { + return md5(text).toString(); +} + +function compareMd5Hashes(hash1: string, hash2: string) { + return hash1 === hash2; +} + +export default async function resolvePods(root: string) { + const packageJson = getPackageJson(root); + const dependencies = normalizeDependencies({ + ...packageJson.dependencies, + ...packageJson.devDependencies, + }); + const dependenciesString = dependenciesToString(dependencies); + const currentDependenciesHash = generateMd5Hash(dependenciesString); + const cachedDependenciesHash = cacheManager.get( + packageJson.name, + 'dependencies', + ); + + if (!cachedDependenciesHash) { + cacheManager.set(packageJson.name, 'dependencies', currentDependenciesHash); + } + + if ( + !cachedDependenciesHash || + !compareMd5Hashes(currentDependenciesHash, cachedDependenciesHash) + ) { + console.log('pod install'); + } +} diff --git a/packages/cli-tools/src/index.ts b/packages/cli-tools/src/index.ts index 5628d5265..350e72d63 100644 --- a/packages/cli-tools/src/index.ts +++ b/packages/cli-tools/src/index.ts @@ -14,5 +14,6 @@ export * as link from './doclink'; export {default as startServerInNewWindow} from './startServerInNewWindow'; export {default as handlePortUnavailable} from './handlePortUnavailable'; export * from './port'; +export {default as cacheManager} from './releaseChecker/releaseCacheManager'; export * from './errors'; diff --git a/packages/cli-tools/src/releaseChecker/releaseCacheManager.ts b/packages/cli-tools/src/releaseChecker/releaseCacheManager.ts index 08cae4161..6fbe68886 100644 --- a/packages/cli-tools/src/releaseChecker/releaseCacheManager.ts +++ b/packages/cli-tools/src/releaseChecker/releaseCacheManager.ts @@ -4,7 +4,11 @@ import os from 'os'; import appDirs from 'appdirsjs'; import logger from '../logger'; -type ReleaseCacheKey = 'eTag' | 'lastChecked' | 'latestVersion'; +type ReleaseCacheKey = + | 'eTag' + | 'lastChecked' + | 'latestVersion' + | 'dependencies'; type Cache = {[key in ReleaseCacheKey]?: string}; function loadCache(name: string): Cache | undefined { diff --git a/yarn.lock b/yarn.lock index c2e043e05..95f0616fb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2076,6 +2076,11 @@ dependencies: "@types/node" "*" +"@types/crypto-js@^4.1.2": + version "4.1.2" + resolved "https://registry.yarnpkg.com/@types/crypto-js/-/crypto-js-4.1.2.tgz#fb56b34f397d9ae2335611e416f15e7d65e276e6" + integrity sha512-t33RNmTu5ufG/sorROIafiCVJMx3jz95bXUMoPAZcUD14fxMXnuTzqzXZoxpR0tNx2xpw11Dlmem9vGCsrSOfA== + "@types/envinfo@^7.8.1": version "7.8.1" resolved "https://registry.yarnpkg.com/@types/envinfo/-/envinfo-7.8.1.tgz#1915df82c16d637e92146645c70db9360eb099c6" @@ -4035,6 +4040,11 @@ crypto-browserify@^3.11.0: randombytes "^2.0.0" randomfill "^1.0.3" +crypto-js@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-4.1.1.tgz#9e485bcf03521041bd85844786b83fb7619736cf" + integrity sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw== + css-color-names@0.0.4, css-color-names@^0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0" From 2489a9c80a4b14ef1a017b0d23bbab89ea921605 Mon Sep 17 00:00:00 2001 From: Tomasz Misiukiewicz Date: Thu, 21 Sep 2023 08:58:16 +0200 Subject: [PATCH 03/22] move installPods from doctor to platform-ios --- packages/cli-doctor/src/index.ts | 1 - .../cli-doctor/src/tools/healthchecks/cocoaPods.ts | 2 +- packages/cli-platform-ios/src/commands/runIOS/index.ts | 4 ++-- packages/cli-platform-ios/src/index.ts | 1 + .../src/tools/installPods.ts | 10 +++++----- packages/cli-platform-ios/src/tools/pods.ts | 6 ++++-- .../src/tools/runBundleInstall.ts | 5 ++--- 7 files changed, 15 insertions(+), 14 deletions(-) rename packages/{cli-doctor => cli-platform-ios}/src/tools/installPods.ts (95%) rename packages/{cli-doctor => cli-platform-ios}/src/tools/runBundleInstall.ts (88%) diff --git a/packages/cli-doctor/src/index.ts b/packages/cli-doctor/src/index.ts index 876158283..06e64ff66 100644 --- a/packages/cli-doctor/src/index.ts +++ b/packages/cli-doctor/src/index.ts @@ -9,4 +9,3 @@ export const commands = {info, doctor}; * refactor the init in order to remove that connection. */ export {default as versionRanges} from './tools/versionRanges'; -export {default as installPods} from './tools/installPods'; diff --git a/packages/cli-doctor/src/tools/healthchecks/cocoaPods.ts b/packages/cli-doctor/src/tools/healthchecks/cocoaPods.ts index af9057a11..82edcfa47 100644 --- a/packages/cli-doctor/src/tools/healthchecks/cocoaPods.ts +++ b/packages/cli-doctor/src/tools/healthchecks/cocoaPods.ts @@ -1,6 +1,6 @@ import execa from 'execa'; +import {runSudo} from '@react-native-community/cli-platform-ios'; import {doesSoftwareNeedToBeFixed} from '../checkInstallation'; -import {runSudo} from '../installPods'; import {logError} from './common'; import {HealthCheckInterface} from '../../types'; import versionRanges from '../versionRanges'; diff --git a/packages/cli-platform-ios/src/commands/runIOS/index.ts b/packages/cli-platform-ios/src/commands/runIOS/index.ts index a8c6f9449..b3d26517b 100644 --- a/packages/cli-platform-ios/src/commands/runIOS/index.ts +++ b/packages/cli-platform-ios/src/commands/runIOS/index.ts @@ -48,8 +48,6 @@ async function runIOS(_: Array, ctx: Config, args: FlagsT) { let {packager, port} = args; - await resolvePods(ctx.root); - const packagerStatus = await isPackagerRunning(port); if ( @@ -83,6 +81,8 @@ async function runIOS(_: Array, ctx: Config, args: FlagsT) { const {xcodeProject, sourceDir} = getXcodeProjectAndDir(ctx.project.ios); + await resolvePods(ctx.root); + process.chdir(sourceDir); if (args.binaryPath) { diff --git a/packages/cli-platform-ios/src/index.ts b/packages/cli-platform-ios/src/index.ts index a612686d2..c88b8cf7f 100644 --- a/packages/cli-platform-ios/src/index.ts +++ b/packages/cli-platform-ios/src/index.ts @@ -4,3 +4,4 @@ export {default as commands} from './commands'; export {projectConfig, dependencyConfig, findPodfilePaths} from './config'; +export {runSudo} from './tools/installPods'; diff --git a/packages/cli-doctor/src/tools/installPods.ts b/packages/cli-platform-ios/src/tools/installPods.ts similarity index 95% rename from packages/cli-doctor/src/tools/installPods.ts rename to packages/cli-platform-ios/src/tools/installPods.ts index 3f531f64d..ef0aafd02 100644 --- a/packages/cli-doctor/src/tools/installPods.ts +++ b/packages/cli-platform-ios/src/tools/installPods.ts @@ -1,5 +1,6 @@ import fs from 'fs'; import execa from 'execa'; +import {Ora} from 'ora'; import chalk from 'chalk'; import { logger, @@ -9,10 +10,9 @@ import { } from '@react-native-community/cli-tools'; import sudo from 'sudo-prompt'; import runBundleInstall from './runBundleInstall'; -import {Loader} from '../types'; async function runPodInstall( - loader: Loader, + loader: Ora, shouldHandleRepoUpdate: boolean = true, ) { try { @@ -52,7 +52,7 @@ async function runPodInstall( } } -async function runPodUpdate(loader: Loader) { +async function runPodUpdate(loader: Ora) { try { loader.start( `Updating CocoaPods repositories ${chalk.dim( @@ -97,7 +97,7 @@ async function installCocoaPodsWithGem() { } } -async function installCocoaPods(loader: Loader) { +async function installCocoaPods(loader: Ora) { loader.stop(); loader.start('Installing CocoaPods'); @@ -118,7 +118,7 @@ async function installCocoaPods(loader: Loader) { } } -async function installPods(loader?: Loader) { +async function installPods(loader?: Ora) { loader = loader || new NoopLoader(); try { if (!fs.existsSync('ios')) { diff --git a/packages/cli-platform-ios/src/tools/pods.ts b/packages/cli-platform-ios/src/tools/pods.ts index 93399f1cc..fe458b4b1 100644 --- a/packages/cli-platform-ios/src/tools/pods.ts +++ b/packages/cli-platform-ios/src/tools/pods.ts @@ -1,6 +1,7 @@ import path from 'path'; import md5 from 'crypto-js/md5'; -import {cacheManager} from '@react-native-community/cli-tools'; +import {cacheManager, getLoader} from '@react-native-community/cli-tools'; +import installPods from './installPods'; export function getPackageJson(root: string) { return require(path.join(root, 'package.json')); @@ -45,6 +46,7 @@ export default async function resolvePods(root: string) { !cachedDependenciesHash || !compareMd5Hashes(currentDependenciesHash, cachedDependenciesHash) ) { - console.log('pod install'); + const loader = getLoader('Installing CocoaPods...'); + await installPods(loader); } } diff --git a/packages/cli-doctor/src/tools/runBundleInstall.ts b/packages/cli-platform-ios/src/tools/runBundleInstall.ts similarity index 88% rename from packages/cli-doctor/src/tools/runBundleInstall.ts rename to packages/cli-platform-ios/src/tools/runBundleInstall.ts index ce601528f..ca46bfa1c 100644 --- a/packages/cli-doctor/src/tools/runBundleInstall.ts +++ b/packages/cli-platform-ios/src/tools/runBundleInstall.ts @@ -1,9 +1,8 @@ import execa from 'execa'; import {CLIError, logger, link} from '@react-native-community/cli-tools'; +import type {Ora} from 'ora'; -import {Loader} from '../types'; - -async function runBundleInstall(loader: Loader) { +async function runBundleInstall(loader: Ora) { try { loader.start('Installing Ruby Gems'); From 220f78afbbbaa381f78e7f949e0532f97add2ab3 Mon Sep 17 00:00:00 2001 From: Tomasz Misiukiewicz Date: Thu, 21 Sep 2023 09:01:08 +0200 Subject: [PATCH 04/22] install pods on run-ios and build-ios --- .../src/commands/buildIOS/index.ts | 4 +++ .../src/commands/runIOS/index.ts | 5 ++-- .../cli-platform-ios/src/tools/installPods.ts | 8 +++-- packages/cli-platform-ios/src/tools/pods.ts | 30 +++++++++++++++++-- 4 files changed, 40 insertions(+), 7 deletions(-) diff --git a/packages/cli-platform-ios/src/commands/buildIOS/index.ts b/packages/cli-platform-ios/src/commands/buildIOS/index.ts index 08ba61b0c..eee3f1b29 100644 --- a/packages/cli-platform-ios/src/commands/buildIOS/index.ts +++ b/packages/cli-platform-ios/src/commands/buildIOS/index.ts @@ -11,10 +11,14 @@ import {buildProject} from './buildProject'; import {BuildFlags, buildOptions} from './buildOptions'; import {getConfiguration} from './getConfiguration'; import {getXcodeProjectAndDir} from './getXcodeProjectAndDir'; +import resolvePods from '../../tools/pods'; async function buildIOS(_: Array, ctx: Config, args: BuildFlags) { const {xcodeProject, sourceDir} = getXcodeProjectAndDir(ctx.project.ios); + // check if pods need to be installed + await resolvePods(ctx.root); + process.chdir(sourceDir); const {scheme, mode} = await getConfiguration(xcodeProject, sourceDir, args); diff --git a/packages/cli-platform-ios/src/commands/runIOS/index.ts b/packages/cli-platform-ios/src/commands/runIOS/index.ts index b3d26517b..00df08e7e 100644 --- a/packages/cli-platform-ios/src/commands/runIOS/index.ts +++ b/packages/cli-platform-ios/src/commands/runIOS/index.ts @@ -48,6 +48,9 @@ async function runIOS(_: Array, ctx: Config, args: FlagsT) { let {packager, port} = args; + // check if pods need to be installed + await resolvePods(ctx.root); + const packagerStatus = await isPackagerRunning(port); if ( @@ -81,8 +84,6 @@ async function runIOS(_: Array, ctx: Config, args: FlagsT) { const {xcodeProject, sourceDir} = getXcodeProjectAndDir(ctx.project.ios); - await resolvePods(ctx.root); - process.chdir(sourceDir); if (args.binaryPath) { diff --git a/packages/cli-platform-ios/src/tools/installPods.ts b/packages/cli-platform-ios/src/tools/installPods.ts index ef0aafd02..17d0c85be 100644 --- a/packages/cli-platform-ios/src/tools/installPods.ts +++ b/packages/cli-platform-ios/src/tools/installPods.ts @@ -11,6 +11,10 @@ import { import sudo from 'sudo-prompt'; import runBundleInstall from './runBundleInstall'; +interface PodInstallOptions { + skipBundleInstall?: boolean; +} + async function runPodInstall( loader: Ora, shouldHandleRepoUpdate: boolean = true, @@ -118,7 +122,7 @@ async function installCocoaPods(loader: Ora) { } } -async function installPods(loader?: Ora) { +async function installPods(loader?: Ora, options?: PodInstallOptions) { loader = loader || new NoopLoader(); try { if (!fs.existsSync('ios')) { @@ -133,7 +137,7 @@ async function installPods(loader?: Ora) { return; } - if (fs.existsSync('../Gemfile')) { + if (fs.existsSync('../Gemfile') && !options?.skipBundleInstall) { await runBundleInstall(loader); } diff --git a/packages/cli-platform-ios/src/tools/pods.ts b/packages/cli-platform-ios/src/tools/pods.ts index fe458b4b1..49a5be04f 100644 --- a/packages/cli-platform-ios/src/tools/pods.ts +++ b/packages/cli-platform-ios/src/tools/pods.ts @@ -1,6 +1,12 @@ import path from 'path'; +import fs from 'fs-extra'; import md5 from 'crypto-js/md5'; -import {cacheManager, getLoader} from '@react-native-community/cli-tools'; +import chalk from 'chalk'; +import { + CLIError, + cacheManager, + getLoader, +} from '@react-native-community/cli-tools'; import installPods from './installPods'; export function getPackageJson(root: string) { @@ -27,6 +33,8 @@ function compareMd5Hashes(hash1: string, hash2: string) { export default async function resolvePods(root: string) { const packageJson = getPackageJson(root); + const podsPath = path.join(root, 'ios', 'Pods'); + const arePodsInstalled = fs.existsSync(podsPath); const dependencies = normalizeDependencies({ ...packageJson.dependencies, ...packageJson.devDependencies, @@ -44,9 +52,25 @@ export default async function resolvePods(root: string) { if ( !cachedDependenciesHash || - !compareMd5Hashes(currentDependenciesHash, cachedDependenciesHash) + !compareMd5Hashes(currentDependenciesHash, cachedDependenciesHash) || + !arePodsInstalled ) { const loader = getLoader('Installing CocoaPods...'); - await installPods(loader); + try { + await installPods(loader, {skipBundleInstall: !!cachedDependenciesHash}); + cacheManager.set( + packageJson.name, + 'dependencies', + currentDependenciesHash, + ); + loader.succeed(); + } catch { + loader.fail(); + throw new CLIError( + `Something when wrong while installing CocoaPods. Please run ${chalk.bold( + 'pod install', + )} manually`, + ); + } } } From a6bea5e17d2e4454a4501377ddd719d209a93ca3 Mon Sep 17 00:00:00 2001 From: Tomasz Misiukiewicz Date: Thu, 21 Sep 2023 09:01:44 +0200 Subject: [PATCH 05/22] add --force-pods flag to run-ios --- .../cli-platform-ios/src/commands/buildIOS/index.ts | 2 +- .../cli-platform-ios/src/commands/runIOS/index.ts | 2 +- packages/cli-platform-ios/src/tools/pods.ts | 12 ++++++++++-- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/packages/cli-platform-ios/src/commands/buildIOS/index.ts b/packages/cli-platform-ios/src/commands/buildIOS/index.ts index eee3f1b29..e9cf5846f 100644 --- a/packages/cli-platform-ios/src/commands/buildIOS/index.ts +++ b/packages/cli-platform-ios/src/commands/buildIOS/index.ts @@ -17,7 +17,7 @@ async function buildIOS(_: Array, ctx: Config, args: BuildFlags) { const {xcodeProject, sourceDir} = getXcodeProjectAndDir(ctx.project.ios); // check if pods need to be installed - await resolvePods(ctx.root); + await resolvePods(ctx.root, {forceInstall: args.forcePods}); process.chdir(sourceDir); diff --git a/packages/cli-platform-ios/src/commands/runIOS/index.ts b/packages/cli-platform-ios/src/commands/runIOS/index.ts index 00df08e7e..1c99c97f2 100644 --- a/packages/cli-platform-ios/src/commands/runIOS/index.ts +++ b/packages/cli-platform-ios/src/commands/runIOS/index.ts @@ -49,7 +49,7 @@ async function runIOS(_: Array, ctx: Config, args: FlagsT) { let {packager, port} = args; // check if pods need to be installed - await resolvePods(ctx.root); + await resolvePods(ctx.root, {forceInstall: args.forcePods}); const packagerStatus = await isPackagerRunning(port); diff --git a/packages/cli-platform-ios/src/tools/pods.ts b/packages/cli-platform-ios/src/tools/pods.ts index 49a5be04f..285428893 100644 --- a/packages/cli-platform-ios/src/tools/pods.ts +++ b/packages/cli-platform-ios/src/tools/pods.ts @@ -9,6 +9,10 @@ import { } from '@react-native-community/cli-tools'; import installPods from './installPods'; +interface ResolvePodsOptions { + forceInstall?: boolean; +} + export function getPackageJson(root: string) { return require(path.join(root, 'package.json')); } @@ -31,7 +35,10 @@ function compareMd5Hashes(hash1: string, hash2: string) { return hash1 === hash2; } -export default async function resolvePods(root: string) { +export default async function resolvePods( + root: string, + options?: ResolvePodsOptions, +) { const packageJson = getPackageJson(root); const podsPath = path.join(root, 'ios', 'Pods'); const arePodsInstalled = fs.existsSync(podsPath); @@ -53,7 +60,8 @@ export default async function resolvePods(root: string) { if ( !cachedDependenciesHash || !compareMd5Hashes(currentDependenciesHash, cachedDependenciesHash) || - !arePodsInstalled + !arePodsInstalled || + options?.forceInstall ) { const loader = getLoader('Installing CocoaPods...'); try { From afc3acbcd77e54013079c051bce85c23e2652397 Mon Sep 17 00:00:00 2001 From: Tomasz Misiukiewicz Date: Thu, 21 Sep 2023 09:01:44 +0200 Subject: [PATCH 06/22] add tests --- .../src/__tests__/pods.test.ts | 32 +++++++++++++++++++ packages/cli-platform-ios/src/tools/pods.ts | 5 +-- 2 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 packages/cli-platform-ios/src/__tests__/pods.test.ts diff --git a/packages/cli-platform-ios/src/__tests__/pods.test.ts b/packages/cli-platform-ios/src/__tests__/pods.test.ts new file mode 100644 index 000000000..4370432ed --- /dev/null +++ b/packages/cli-platform-ios/src/__tests__/pods.test.ts @@ -0,0 +1,32 @@ +import {compareMd5Hashes, normalizeDependencies} from '../tools/pods'; + +const packageJson = { + name: 'test-package', + dependencies: {dep1: '1.0.0'}, + devDependencies: {dep2: '2.0.0'}, +}; + +describe('compareMd5Hashes', () => { + it('should return false if hashes are different', () => { + const result = compareMd5Hashes('hash1', 'hash2'); + + expect(result).toBe(false); + }); + + it('should return true if hashes are the same', () => { + const result = compareMd5Hashes('hash', 'hash'); + + expect(result).toBe(true); + }); +}); + +describe('normalizeDependencies', () => { + it('should normalize dependencies', () => { + const dependencies = { + ...packageJson.dependencies, + ...packageJson.devDependencies, + }; + const result = normalizeDependencies(dependencies); + expect(result).toEqual(['dep1@1.0.0', 'dep2@2.0.0']); + }); +}); diff --git a/packages/cli-platform-ios/src/tools/pods.ts b/packages/cli-platform-ios/src/tools/pods.ts index 285428893..c7d07d331 100644 --- a/packages/cli-platform-ios/src/tools/pods.ts +++ b/packages/cli-platform-ios/src/tools/pods.ts @@ -27,11 +27,11 @@ export function dependenciesToString(dependencies: string[]) { return dependencies.join('\n'); } -function generateMd5Hash(text: string) { +export function generateMd5Hash(text: string) { return md5(text).toString(); } -function compareMd5Hashes(hash1: string, hash2: string) { +export function compareMd5Hashes(hash1: string, hash2: string) { return hash1 === hash2; } @@ -41,6 +41,7 @@ export default async function resolvePods( ) { const packageJson = getPackageJson(root); const podsPath = path.join(root, 'ios', 'Pods'); + console.log({packageJson, podsPath}); const arePodsInstalled = fs.existsSync(podsPath); const dependencies = normalizeDependencies({ ...packageJson.dependencies, From a108f68ec67ce7925ce46d9f88594a878d9ab811 Mon Sep 17 00:00:00 2001 From: Tomasz Misiukiewicz Date: Thu, 21 Sep 2023 09:03:03 +0200 Subject: [PATCH 07/22] add tests for pods installation --- packages/cli-platform-ios/README.md | 6 ++ .../src/__tests__/pods.test.ts | 73 ++++++++++++++++++- packages/cli-platform-ios/src/tools/pods.ts | 5 -- 3 files changed, 78 insertions(+), 6 deletions(-) diff --git a/packages/cli-platform-ios/README.md b/packages/cli-platform-ios/README.md index 4dc15d0e3..e72a582bf 100644 --- a/packages/cli-platform-ios/README.md +++ b/packages/cli-platform-ios/README.md @@ -113,6 +113,9 @@ Installs passed binary instead of building a fresh one. > default: false List all available iOS devices and simulators and let you choose one to run the app. +#### `--force-pods`, + +Force running `pod install` before running an app ### `build-ios` @@ -165,6 +168,9 @@ Example: npx react-native build-ios --extra-params "-jobs 4" ``` +#### `--force-pods`, + +Force running `pod install` before running an app ### `log-ios` Usage: diff --git a/packages/cli-platform-ios/src/__tests__/pods.test.ts b/packages/cli-platform-ios/src/__tests__/pods.test.ts index 4370432ed..189e3a2e7 100644 --- a/packages/cli-platform-ios/src/__tests__/pods.test.ts +++ b/packages/cli-platform-ios/src/__tests__/pods.test.ts @@ -1,4 +1,21 @@ -import {compareMd5Hashes, normalizeDependencies} from '../tools/pods'; +import {writeFiles, getTempDirectory, cleanup} from '../../../../jest/helpers'; +import installPods from '../tools/installPods'; +import resolvePods, { + compareMd5Hashes, + normalizeDependencies, +} from '../tools/pods'; + +const mockGet = jest.fn(); +const mockSet = jest.fn(); +jest.mock('@react-native-community/cli-tools', () => ({ + ...Object.assign(jest.requireActual('@react-native-community/cli-tools')), + cacheManager: { + get: mockGet, + set: mockSet, + }, +})); +jest.mock('../tools/installPods', () => jest.fn()); +const dependencyHash = 'abecd1ad748898def530ff27362e14ba'; const packageJson = { name: 'test-package', @@ -6,6 +23,20 @@ const packageJson = { devDependencies: {dep2: '2.0.0'}, }; +const DIR = getTempDirectory('root_test'); + +const createTempFiles = (rest?: Record) => { + writeFiles(DIR, { + 'package.json': JSON.stringify(packageJson), + ...rest, + }); +}; + +beforeEach(async () => { + await cleanup(DIR); + jest.resetAllMocks(); +}); + describe('compareMd5Hashes', () => { it('should return false if hashes are different', () => { const result = compareMd5Hashes('hash1', 'hash2'); @@ -30,3 +61,43 @@ describe('normalizeDependencies', () => { expect(result).toEqual(['dep1@1.0.0', 'dep2@2.0.0']); }); }); + +describe('resolvePods', () => { + it('should install pods if they are not installed', async () => { + createTempFiles({'ios/Podfile/Manifest.lock': ''}); + + await resolvePods(DIR); + + expect(installPods).toHaveBeenCalled(); + }); + + it('should install pods when force option is set to true', async () => { + createTempFiles(); + + await resolvePods(DIR, {forceInstall: true}); + + expect(installPods).toHaveBeenCalled(); + }); + + it('should install pods when there is no cached hash of dependencies', async () => { + createTempFiles(); + + await resolvePods(DIR); + + expect(mockSet).toHaveBeenCalledWith( + packageJson.name, + 'dependencies', + dependencyHash, + ); + }); + + it('should skip pods installation if the cached hash and current hash are the same', async () => { + createTempFiles({'ios/Pods/Manifest.lock': ''}); + + mockGet.mockImplementation(() => dependencyHash); + + await resolvePods(DIR); + + expect(installPods).not.toHaveBeenCalled(); + }); +}); diff --git a/packages/cli-platform-ios/src/tools/pods.ts b/packages/cli-platform-ios/src/tools/pods.ts index c7d07d331..014c12e3a 100644 --- a/packages/cli-platform-ios/src/tools/pods.ts +++ b/packages/cli-platform-ios/src/tools/pods.ts @@ -41,7 +41,6 @@ export default async function resolvePods( ) { const packageJson = getPackageJson(root); const podsPath = path.join(root, 'ios', 'Pods'); - console.log({packageJson, podsPath}); const arePodsInstalled = fs.existsSync(podsPath); const dependencies = normalizeDependencies({ ...packageJson.dependencies, @@ -54,10 +53,6 @@ export default async function resolvePods( 'dependencies', ); - if (!cachedDependenciesHash) { - cacheManager.set(packageJson.name, 'dependencies', currentDependenciesHash); - } - if ( !cachedDependenciesHash || !compareMd5Hashes(currentDependenciesHash, cachedDependenciesHash) || From 7ee08d039c0efa51041f01b10ca2c8ce6d5765f2 Mon Sep 17 00:00:00 2001 From: Tomasz Misiukiewicz Date: Thu, 21 Sep 2023 09:03:03 +0200 Subject: [PATCH 08/22] use crypto and rename releaseCacheManager to cacheManager --- packages/cli-platform-ios/package.json | 2 -- .../cli-platform-ios/src/tools/installPods.ts | 2 +- packages/cli-platform-ios/src/tools/pods.ts | 4 ++-- .../releaseCacheManager.ts => cacheManager.ts} | 16 ++++++---------- packages/cli-tools/src/index.ts | 2 +- .../src/releaseChecker/getLatestRelease.ts | 2 +- .../src/releaseChecker/printNewRelease.ts | 2 +- yarn.lock | 10 ---------- 8 files changed, 12 insertions(+), 28 deletions(-) rename packages/cli-tools/src/{releaseChecker/releaseCacheManager.ts => cacheManager.ts} (78%) diff --git a/packages/cli-platform-ios/package.json b/packages/cli-platform-ios/package.json index 3744a40d3..585d4d97d 100644 --- a/packages/cli-platform-ios/package.json +++ b/packages/cli-platform-ios/package.json @@ -10,7 +10,6 @@ "@react-native-community/cli-tools": "12.0.0-alpha.13", "@react-native-community/cli-doctor": "12.0.0-alpha.13", "chalk": "^4.1.2", - "crypto-js": "^4.1.1", "execa": "^5.0.0", "fast-xml-parser": "^4.0.12", "glob": "^7.1.3", @@ -18,7 +17,6 @@ }, "devDependencies": { "@react-native-community/cli-types": "12.0.0-alpha.13", - "@types/crypto-js": "^4.1.2", "@types/glob": "^7.1.1", "@types/lodash": "^4.14.149", "hasbin": "^1.2.3" diff --git a/packages/cli-platform-ios/src/tools/installPods.ts b/packages/cli-platform-ios/src/tools/installPods.ts index 17d0c85be..0fcde1dbe 100644 --- a/packages/cli-platform-ios/src/tools/installPods.ts +++ b/packages/cli-platform-ios/src/tools/installPods.ts @@ -1,6 +1,6 @@ import fs from 'fs'; import execa from 'execa'; -import {Ora} from 'ora'; +import type {Ora} from 'ora'; import chalk from 'chalk'; import { logger, diff --git a/packages/cli-platform-ios/src/tools/pods.ts b/packages/cli-platform-ios/src/tools/pods.ts index 014c12e3a..e18e6bdc2 100644 --- a/packages/cli-platform-ios/src/tools/pods.ts +++ b/packages/cli-platform-ios/src/tools/pods.ts @@ -1,6 +1,6 @@ import path from 'path'; import fs from 'fs-extra'; -import md5 from 'crypto-js/md5'; +import {createHash} from 'crypto'; import chalk from 'chalk'; import { CLIError, @@ -28,7 +28,7 @@ export function dependenciesToString(dependencies: string[]) { } export function generateMd5Hash(text: string) { - return md5(text).toString(); + return createHash('md5').update(text).digest('hex'); } export function compareMd5Hashes(hash1: string, hash2: string) { diff --git a/packages/cli-tools/src/releaseChecker/releaseCacheManager.ts b/packages/cli-tools/src/cacheManager.ts similarity index 78% rename from packages/cli-tools/src/releaseChecker/releaseCacheManager.ts rename to packages/cli-tools/src/cacheManager.ts index 6fbe68886..367d7b513 100644 --- a/packages/cli-tools/src/releaseChecker/releaseCacheManager.ts +++ b/packages/cli-tools/src/cacheManager.ts @@ -2,14 +2,10 @@ import path from 'path'; import fs from 'fs'; import os from 'os'; import appDirs from 'appdirsjs'; -import logger from '../logger'; +import logger from './logger'; -type ReleaseCacheKey = - | 'eTag' - | 'lastChecked' - | 'latestVersion' - | 'dependencies'; -type Cache = {[key in ReleaseCacheKey]?: string}; +type CacheKey = 'eTag' | 'lastChecked' | 'latestVersion' | 'dependencies'; +type Cache = {[key in CacheKey]?: string}; function loadCache(name: string): Cache | undefined { try { @@ -24,7 +20,7 @@ function loadCache(name: string): Cache | undefined { // Create cache file since it doesn't exist. saveCache(name, {}); } - logger.debug('No release cache found'); + logger.debug('No cache found'); return undefined; } } @@ -52,7 +48,7 @@ function getCacheRootPath() { return cachePath; } -function get(name: string, key: ReleaseCacheKey): string | undefined { +function get(name: string, key: CacheKey): string | undefined { const cache = loadCache(name); if (cache) { return cache[key]; @@ -60,7 +56,7 @@ function get(name: string, key: ReleaseCacheKey): string | undefined { return undefined; } -function set(name: string, key: ReleaseCacheKey, value: string) { +function set(name: string, key: CacheKey, value: string) { const cache = loadCache(name); if (cache) { cache[key] = value; diff --git a/packages/cli-tools/src/index.ts b/packages/cli-tools/src/index.ts index 350e72d63..ada81b638 100644 --- a/packages/cli-tools/src/index.ts +++ b/packages/cli-tools/src/index.ts @@ -14,6 +14,6 @@ export * as link from './doclink'; export {default as startServerInNewWindow} from './startServerInNewWindow'; export {default as handlePortUnavailable} from './handlePortUnavailable'; export * from './port'; -export {default as cacheManager} from './releaseChecker/releaseCacheManager'; +export {default as cacheManager} from './cacheManager'; export * from './errors'; diff --git a/packages/cli-tools/src/releaseChecker/getLatestRelease.ts b/packages/cli-tools/src/releaseChecker/getLatestRelease.ts index 7b438cb3f..e9989f223 100644 --- a/packages/cli-tools/src/releaseChecker/getLatestRelease.ts +++ b/packages/cli-tools/src/releaseChecker/getLatestRelease.ts @@ -1,5 +1,5 @@ import semver from 'semver'; -import cacheManager from './releaseCacheManager'; +import cacheManager from '../cacheManager'; import {fetch} from '../fetch'; import logger from '../logger'; diff --git a/packages/cli-tools/src/releaseChecker/printNewRelease.ts b/packages/cli-tools/src/releaseChecker/printNewRelease.ts index 4653b9f12..d9f13e429 100644 --- a/packages/cli-tools/src/releaseChecker/printNewRelease.ts +++ b/packages/cli-tools/src/releaseChecker/printNewRelease.ts @@ -4,7 +4,7 @@ import * as link from '../doclink'; import logger from '../logger'; import {Release} from './getLatestRelease'; -import cacheManager from './releaseCacheManager'; +import cacheManager from '../cacheManager'; /** * Notifies the user that a newer version of React Native is available. diff --git a/yarn.lock b/yarn.lock index 95f0616fb..c2e043e05 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2076,11 +2076,6 @@ dependencies: "@types/node" "*" -"@types/crypto-js@^4.1.2": - version "4.1.2" - resolved "https://registry.yarnpkg.com/@types/crypto-js/-/crypto-js-4.1.2.tgz#fb56b34f397d9ae2335611e416f15e7d65e276e6" - integrity sha512-t33RNmTu5ufG/sorROIafiCVJMx3jz95bXUMoPAZcUD14fxMXnuTzqzXZoxpR0tNx2xpw11Dlmem9vGCsrSOfA== - "@types/envinfo@^7.8.1": version "7.8.1" resolved "https://registry.yarnpkg.com/@types/envinfo/-/envinfo-7.8.1.tgz#1915df82c16d637e92146645c70db9360eb099c6" @@ -4040,11 +4035,6 @@ crypto-browserify@^3.11.0: randombytes "^2.0.0" randomfill "^1.0.3" -crypto-js@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-4.1.1.tgz#9e485bcf03521041bd85844786b83fb7619736cf" - integrity sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw== - css-color-names@0.0.4, css-color-names@^0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0" From bedd5d97716d6ecafa6ac15e9075c89bbca5d642 Mon Sep 17 00:00:00 2001 From: Tomasz Misiukiewicz Date: Thu, 21 Sep 2023 09:03:03 +0200 Subject: [PATCH 09/22] move run sudo to cli-tools --- packages/cli-doctor/package.json | 1 - .../src/tools/healthchecks/cocoaPods.ts | 2 +- packages/cli-platform-ios/src/index.ts | 2 +- .../cli-platform-ios/src/tools/installPods.ts | 16 ++-------------- packages/cli-tools/package.json | 3 ++- packages/cli-tools/src/index.ts | 1 + packages/cli-tools/src/runSudo.ts | 13 +++++++++++++ 7 files changed, 20 insertions(+), 18 deletions(-) create mode 100644 packages/cli-tools/src/runSudo.ts diff --git a/packages/cli-doctor/package.json b/packages/cli-doctor/package.json index af811e369..62bae44fb 100644 --- a/packages/cli-doctor/package.json +++ b/packages/cli-doctor/package.json @@ -24,7 +24,6 @@ "prompts": "^2.4.2", "semver": "^7.5.2", "strip-ansi": "^5.2.0", - "sudo-prompt": "^9.0.0", "wcwidth": "^1.0.1", "yaml": "^2.2.1" }, diff --git a/packages/cli-doctor/src/tools/healthchecks/cocoaPods.ts b/packages/cli-doctor/src/tools/healthchecks/cocoaPods.ts index 82edcfa47..64443cd4b 100644 --- a/packages/cli-doctor/src/tools/healthchecks/cocoaPods.ts +++ b/packages/cli-doctor/src/tools/healthchecks/cocoaPods.ts @@ -1,5 +1,5 @@ import execa from 'execa'; -import {runSudo} from '@react-native-community/cli-platform-ios'; +import {runSudo} from '@react-native-community/cli-tools'; import {doesSoftwareNeedToBeFixed} from '../checkInstallation'; import {logError} from './common'; import {HealthCheckInterface} from '../../types'; diff --git a/packages/cli-platform-ios/src/index.ts b/packages/cli-platform-ios/src/index.ts index c88b8cf7f..9a91427f2 100644 --- a/packages/cli-platform-ios/src/index.ts +++ b/packages/cli-platform-ios/src/index.ts @@ -2,6 +2,6 @@ * iOS platform files */ +export {runSudo} from '@react-native-community/cli-tools'; export {default as commands} from './commands'; export {projectConfig, dependencyConfig, findPodfilePaths} from './config'; -export {runSudo} from './tools/installPods'; diff --git a/packages/cli-platform-ios/src/tools/installPods.ts b/packages/cli-platform-ios/src/tools/installPods.ts index 0fcde1dbe..08ecadb93 100644 --- a/packages/cli-platform-ios/src/tools/installPods.ts +++ b/packages/cli-platform-ios/src/tools/installPods.ts @@ -7,8 +7,8 @@ import { NoopLoader, link, CLIError, + runSudo, } from '@react-native-community/cli-tools'; -import sudo from 'sudo-prompt'; import runBundleInstall from './runBundleInstall'; interface PodInstallOptions { @@ -77,18 +77,6 @@ async function runPodUpdate(loader: Ora) { } } -function runSudo(command: string): Promise { - return new Promise((resolve, reject) => { - sudo.exec(command, {name: 'React Native CLI'}, (error) => { - if (error) { - reject(error); - } - - resolve(); - }); - }); -} - async function installCocoaPodsWithGem() { const options = ['install', 'cocoapods', '--no-document']; @@ -157,6 +145,6 @@ async function installPods(loader?: Ora, options?: PodInstallOptions) { } } -export {runSudo, installCocoaPods}; +export {installCocoaPods}; export default installPods; diff --git a/packages/cli-tools/package.json b/packages/cli-tools/package.json index 4403f8855..b69e474cb 100644 --- a/packages/cli-tools/package.json +++ b/packages/cli-tools/package.json @@ -15,7 +15,8 @@ "open": "^6.2.0", "ora": "^5.4.1", "semver": "^7.5.2", - "shell-quote": "^1.7.3" + "shell-quote": "^1.7.3", + "sudo-prompt": "^9.0.0" }, "devDependencies": { "@react-native-community/cli-types": "12.0.0-alpha.13", diff --git a/packages/cli-tools/src/index.ts b/packages/cli-tools/src/index.ts index ada81b638..f25fcdb86 100644 --- a/packages/cli-tools/src/index.ts +++ b/packages/cli-tools/src/index.ts @@ -15,5 +15,6 @@ export {default as startServerInNewWindow} from './startServerInNewWindow'; export {default as handlePortUnavailable} from './handlePortUnavailable'; export * from './port'; export {default as cacheManager} from './cacheManager'; +export {default as runSudo} from './runSudo'; export * from './errors'; diff --git a/packages/cli-tools/src/runSudo.ts b/packages/cli-tools/src/runSudo.ts new file mode 100644 index 000000000..eb406783c --- /dev/null +++ b/packages/cli-tools/src/runSudo.ts @@ -0,0 +1,13 @@ +import sudo from 'sudo-prompt'; + +export default function runSudo(command: string): Promise { + return new Promise((resolve, reject) => { + sudo.exec(command, {name: 'React Native CLI'}, (error) => { + if (error) { + reject(error); + } + + resolve(); + }); + }); +} From 628cd79b741908763d081f398bcaf979563d2e50 Mon Sep 17 00:00:00 2001 From: Tomasz Misiukiewicz Date: Thu, 21 Sep 2023 09:04:10 +0200 Subject: [PATCH 10/22] use findPodfilePath --- .../cli-platform-ios/src/commands/buildIOS/buildOptions.ts | 1 + packages/cli-platform-ios/src/tools/pods.ts | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/cli-platform-ios/src/commands/buildIOS/buildOptions.ts b/packages/cli-platform-ios/src/commands/buildIOS/buildOptions.ts index 27ebd690e..54bb00a40 100644 --- a/packages/cli-platform-ios/src/commands/buildIOS/buildOptions.ts +++ b/packages/cli-platform-ios/src/commands/buildIOS/buildOptions.ts @@ -8,6 +8,7 @@ export type BuildFlags = { interactive?: boolean; destination?: string; extraParams?: string[]; + forcePods?: boolean; }; export const buildOptions = [ diff --git a/packages/cli-platform-ios/src/tools/pods.ts b/packages/cli-platform-ios/src/tools/pods.ts index e18e6bdc2..917910f98 100644 --- a/packages/cli-platform-ios/src/tools/pods.ts +++ b/packages/cli-platform-ios/src/tools/pods.ts @@ -8,6 +8,7 @@ import { getLoader, } from '@react-native-community/cli-tools'; import installPods from './installPods'; +import findPodfilePath from '../config/findPodfilePath'; interface ResolvePodsOptions { forceInstall?: boolean; @@ -40,7 +41,11 @@ export default async function resolvePods( options?: ResolvePodsOptions, ) { const packageJson = getPackageJson(root); - const podsPath = path.join(root, 'ios', 'Pods'); + const podfilePath = findPodfilePath(root); + const iosFolderPath = podfilePath + ? podfilePath.slice(0, podfilePath.lastIndexOf('/')) + : path.join(root, 'ios'); + const podsPath = path.join(iosFolderPath, 'Pods'); const arePodsInstalled = fs.existsSync(podsPath); const dependencies = normalizeDependencies({ ...packageJson.dependencies, From 81ad72a1baf5f8000f3e23a81b849cc7e7c8f05b Mon Sep 17 00:00:00 2001 From: Tomasz Misiukiewicz Date: Thu, 21 Sep 2023 09:04:27 +0200 Subject: [PATCH 11/22] resolve only native dependencies for pod check --- .../src/commands/buildIOS/index.ts | 2 +- .../src/commands/runIOS/index.ts | 2 +- packages/cli-platform-ios/src/tools/pods.ts | 27 ++++++++++++++----- 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/packages/cli-platform-ios/src/commands/buildIOS/index.ts b/packages/cli-platform-ios/src/commands/buildIOS/index.ts index e9cf5846f..1da8bb8f4 100644 --- a/packages/cli-platform-ios/src/commands/buildIOS/index.ts +++ b/packages/cli-platform-ios/src/commands/buildIOS/index.ts @@ -17,7 +17,7 @@ async function buildIOS(_: Array, ctx: Config, args: BuildFlags) { const {xcodeProject, sourceDir} = getXcodeProjectAndDir(ctx.project.ios); // check if pods need to be installed - await resolvePods(ctx.root, {forceInstall: args.forcePods}); + await resolvePods(ctx.root, ctx.dependencies, {forceInstall: args.forcePods}); process.chdir(sourceDir); diff --git a/packages/cli-platform-ios/src/commands/runIOS/index.ts b/packages/cli-platform-ios/src/commands/runIOS/index.ts index 1c99c97f2..30f584301 100644 --- a/packages/cli-platform-ios/src/commands/runIOS/index.ts +++ b/packages/cli-platform-ios/src/commands/runIOS/index.ts @@ -49,7 +49,7 @@ async function runIOS(_: Array, ctx: Config, args: FlagsT) { let {packager, port} = args; // check if pods need to be installed - await resolvePods(ctx.root, {forceInstall: args.forcePods}); + await resolvePods(ctx.root, ctx.dependencies, {forceInstall: args.forcePods}); const packagerStatus = await isPackagerRunning(port); diff --git a/packages/cli-platform-ios/src/tools/pods.ts b/packages/cli-platform-ios/src/tools/pods.ts index 917910f98..c65047a65 100644 --- a/packages/cli-platform-ios/src/tools/pods.ts +++ b/packages/cli-platform-ios/src/tools/pods.ts @@ -9,18 +9,27 @@ import { } from '@react-native-community/cli-tools'; import installPods from './installPods'; import findPodfilePath from '../config/findPodfilePath'; +import {DependencyConfig} from '@react-native-community/cli-types'; interface ResolvePodsOptions { forceInstall?: boolean; } +interface NativeDependencies { + [key: string]: DependencyConfig; +} + export function getPackageJson(root: string) { return require(path.join(root, 'package.json')); } -export function normalizeDependencies(dependencies: Record) { - return Object.entries(dependencies) - .map(([name, version]) => `${name}@${version}`) +export function getIosDependencies( + dependencies: NativeDependencies, + dependenciesVersions: Record, +) { + return Object.keys(dependencies) + .filter((dependency) => dependencies[dependency].platforms.ios) + .map((dependency) => `${dependency}@${dependenciesVersions[dependency]}`) .sort(); } @@ -38,6 +47,7 @@ export function compareMd5Hashes(hash1: string, hash2: string) { export default async function resolvePods( root: string, + nativeDependencies: NativeDependencies, options?: ResolvePodsOptions, ) { const packageJson = getPackageJson(root); @@ -47,11 +57,16 @@ export default async function resolvePods( : path.join(root, 'ios'); const podsPath = path.join(iosFolderPath, 'Pods'); const arePodsInstalled = fs.existsSync(podsPath); - const dependencies = normalizeDependencies({ + const dependenciesVersions = { ...packageJson.dependencies, ...packageJson.devDependencies, - }); - const dependenciesString = dependenciesToString(dependencies); + }; + const iosDependencies = getIosDependencies( + nativeDependencies, + dependenciesVersions, + ); + + const dependenciesString = dependenciesToString(iosDependencies); const currentDependenciesHash = generateMd5Hash(dependenciesString); const cachedDependenciesHash = cacheManager.get( packageJson.name, From a3b9248c6db02a82afcfcd29205a68d3b779a22f Mon Sep 17 00:00:00 2001 From: Tomasz Misiukiewicz Date: Thu, 21 Sep 2023 09:04:27 +0200 Subject: [PATCH 12/22] update pod installation tests --- .../src/__tests__/pods.test.ts | 65 +++++++++++++++---- 1 file changed, 53 insertions(+), 12 deletions(-) diff --git a/packages/cli-platform-ios/src/__tests__/pods.test.ts b/packages/cli-platform-ios/src/__tests__/pods.test.ts index 189e3a2e7..a78afb804 100644 --- a/packages/cli-platform-ios/src/__tests__/pods.test.ts +++ b/packages/cli-platform-ios/src/__tests__/pods.test.ts @@ -1,9 +1,6 @@ import {writeFiles, getTempDirectory, cleanup} from '../../../../jest/helpers'; import installPods from '../tools/installPods'; -import resolvePods, { - compareMd5Hashes, - normalizeDependencies, -} from '../tools/pods'; +import resolvePods, {compareMd5Hashes, getIosDependencies} from '../tools/pods'; const mockGet = jest.fn(); const mockSet = jest.fn(); @@ -15,7 +12,7 @@ jest.mock('@react-native-community/cli-tools', () => ({ }, })); jest.mock('../tools/installPods', () => jest.fn()); -const dependencyHash = 'abecd1ad748898def530ff27362e14ba'; +const dependencyHash = 'd41d8cd98f00b204e9800998ecf8427e'; const packageJson = { name: 'test-package', @@ -23,6 +20,28 @@ const packageJson = { devDependencies: {dep2: '2.0.0'}, }; +const commonDepConfig = { + root: '', + platforms: { + ios: { + podspecPath: '', + scriptPhases: [], + configurations: [], + }, + }, +}; + +const dependenciesConfig = { + dep1: { + name: 'dep1', + ...commonDepConfig, + }, + dep2: { + name: 'dep2', + ...commonDepConfig, + }, +}; + const DIR = getTempDirectory('root_test'); const createTempFiles = (rest?: Record) => { @@ -51,13 +70,13 @@ describe('compareMd5Hashes', () => { }); }); -describe('normalizeDependencies', () => { - it('should normalize dependencies', () => { +describe('getIosDependencies', () => { + it('should return only dependencies with native code', () => { const dependencies = { ...packageJson.dependencies, ...packageJson.devDependencies, }; - const result = normalizeDependencies(dependencies); + const result = getIosDependencies(dependenciesConfig, dependencies); expect(result).toEqual(['dep1@1.0.0', 'dep2@2.0.0']); }); }); @@ -66,7 +85,7 @@ describe('resolvePods', () => { it('should install pods if they are not installed', async () => { createTempFiles({'ios/Podfile/Manifest.lock': ''}); - await resolvePods(DIR); + await resolvePods(DIR, {}); expect(installPods).toHaveBeenCalled(); }); @@ -74,7 +93,7 @@ describe('resolvePods', () => { it('should install pods when force option is set to true', async () => { createTempFiles(); - await resolvePods(DIR, {forceInstall: true}); + await resolvePods(DIR, {}, {forceInstall: true}); expect(installPods).toHaveBeenCalled(); }); @@ -82,7 +101,7 @@ describe('resolvePods', () => { it('should install pods when there is no cached hash of dependencies', async () => { createTempFiles(); - await resolvePods(DIR); + await resolvePods(DIR, {}); expect(mockSet).toHaveBeenCalledWith( packageJson.name, @@ -96,8 +115,30 @@ describe('resolvePods', () => { mockGet.mockImplementation(() => dependencyHash); - await resolvePods(DIR); + await resolvePods(DIR, {}); expect(installPods).not.toHaveBeenCalled(); }); + + it('should install pods if the cached hash and current hash are different', async () => { + createTempFiles({'ios/Pods/Manifest.lock': ''}); + + mockGet.mockImplementation(() => dependencyHash); + + await resolvePods(DIR, { + dep1: { + name: 'dep1', + root: '', + platforms: { + ios: { + podspecPath: '', + scriptPhases: [], + configurations: [], + }, + }, + }, + }); + + expect(installPods).toHaveBeenCalled(); + }); }); From 6b7dbef700488e4761c0ea0a51b1acd8f5d9593a Mon Sep 17 00:00:00 2001 From: Tomasz Misiukiewicz Date: Thu, 21 Sep 2023 09:04:27 +0200 Subject: [PATCH 13/22] add version property to dependency config & use it to hash dependencies --- docs/platforms.md | 1 + packages/cli-platform-ios/src/config/index.ts | 4 ++++ packages/cli-platform-ios/src/tools/pods.ts | 20 ++++++------------- packages/cli-types/src/ios.ts | 1 + 4 files changed, 12 insertions(+), 14 deletions(-) diff --git a/docs/platforms.md b/docs/platforms.md index 0af5930e2..d55e9189d 100644 --- a/docs/platforms.md +++ b/docs/platforms.md @@ -111,6 +111,7 @@ On Android and iOS, this function returns a dependency configuration for: ```ts type IOSDependencyConfig = { podspecPath: string; + version: string; scriptPhases: Array; configurations: string[]; }; diff --git a/packages/cli-platform-ios/src/config/index.ts b/packages/cli-platform-ios/src/config/index.ts index d54e6cab9..31a5291d4 100644 --- a/packages/cli-platform-ios/src/config/index.ts +++ b/packages/cli-platform-ios/src/config/index.ts @@ -66,8 +66,12 @@ export function dependencyConfig( return null; } + const packageJson = require(path.join(folder, 'package.json')); + const version = packageJson.version; + return { podspecPath, + version, configurations: userConfig.configurations || [], scriptPhases: userConfig.scriptPhases || [], }; diff --git a/packages/cli-platform-ios/src/tools/pods.ts b/packages/cli-platform-ios/src/tools/pods.ts index c65047a65..93e741dc7 100644 --- a/packages/cli-platform-ios/src/tools/pods.ts +++ b/packages/cli-platform-ios/src/tools/pods.ts @@ -23,13 +23,13 @@ export function getPackageJson(root: string) { return require(path.join(root, 'package.json')); } -export function getIosDependencies( - dependencies: NativeDependencies, - dependenciesVersions: Record, -) { +export function getIosDependencies(dependencies: NativeDependencies) { return Object.keys(dependencies) .filter((dependency) => dependencies[dependency].platforms.ios) - .map((dependency) => `${dependency}@${dependenciesVersions[dependency]}`) + .map( + (dependency) => + `${dependency}@${dependencies[dependency].platforms.ios?.version}`, + ) .sort(); } @@ -57,15 +57,7 @@ export default async function resolvePods( : path.join(root, 'ios'); const podsPath = path.join(iosFolderPath, 'Pods'); const arePodsInstalled = fs.existsSync(podsPath); - const dependenciesVersions = { - ...packageJson.dependencies, - ...packageJson.devDependencies, - }; - const iosDependencies = getIosDependencies( - nativeDependencies, - dependenciesVersions, - ); - + const iosDependencies = getIosDependencies(nativeDependencies); const dependenciesString = dependenciesToString(iosDependencies); const currentDependenciesHash = generateMd5Hash(dependenciesString); const cachedDependenciesHash = cacheManager.get( diff --git a/packages/cli-types/src/ios.ts b/packages/cli-types/src/ios.ts index 3c0b54163..a8d18da89 100644 --- a/packages/cli-types/src/ios.ts +++ b/packages/cli-types/src/ios.ts @@ -21,6 +21,7 @@ export interface IOSProjectConfig { export interface IOSDependencyConfig { podspecPath: string; + version: string; scriptPhases: Array; configurations: string[]; } From 8fd0b652fe91ccaa4f0e4f09f0ae6b33b85a37dd Mon Sep 17 00:00:00 2001 From: Tomasz Misiukiewicz Date: Thu, 21 Sep 2023 09:04:28 +0200 Subject: [PATCH 14/22] cr updates --- packages/cli-config/src/schema.ts | 1 + packages/cli-platform-ios/src/config/index.ts | 10 ++++++++-- packages/cli-platform-ios/src/tools/pods.ts | 10 ++++++++-- packages/cli-types/src/ios.ts | 2 +- 4 files changed, 18 insertions(+), 5 deletions(-) diff --git a/packages/cli-config/src/schema.ts b/packages/cli-config/src/schema.ts index e2bbfbc1c..ee4ed7074 100644 --- a/packages/cli-config/src/schema.ts +++ b/packages/cli-config/src/schema.ts @@ -122,6 +122,7 @@ export const projectConfig = t // IOSDependencyConfig .object({ podspecPath: t.string(), + version: t.string(), configurations: t.array().items(t.string()).default([]), scriptPhases: t.array().items(t.object()).default([]), }) diff --git a/packages/cli-platform-ios/src/config/index.ts b/packages/cli-platform-ios/src/config/index.ts index 31a5291d4..99511a7ca 100644 --- a/packages/cli-platform-ios/src/config/index.ts +++ b/packages/cli-platform-ios/src/config/index.ts @@ -17,6 +17,7 @@ import { IOSProjectConfig, IOSDependencyConfig, } from '@react-native-community/cli-types'; +import {CLIError} from '@react-native-community/cli-tools'; /** * Returns project config by analyzing given folder and applying some user defaults @@ -66,8 +67,13 @@ export function dependencyConfig( return null; } - const packageJson = require(path.join(folder, 'package.json')); - const version = packageJson.version; + let version = ''; + try { + const packageJson = require(path.join(folder, 'package.json')); + version = packageJson.version; + } catch { + throw new CLIError(`Could not read package.json file from ${folder}`); + } return { podspecPath, diff --git a/packages/cli-platform-ios/src/tools/pods.ts b/packages/cli-platform-ios/src/tools/pods.ts index 93e741dc7..42632cbf4 100644 --- a/packages/cli-platform-ios/src/tools/pods.ts +++ b/packages/cli-platform-ios/src/tools/pods.ts @@ -9,7 +9,10 @@ import { } from '@react-native-community/cli-tools'; import installPods from './installPods'; import findPodfilePath from '../config/findPodfilePath'; -import {DependencyConfig} from '@react-native-community/cli-types'; +import { + DependencyConfig, + IOSDependencyConfig, +} from '@react-native-community/cli-types'; interface ResolvePodsOptions { forceInstall?: boolean; @@ -28,7 +31,10 @@ export function getIosDependencies(dependencies: NativeDependencies) { .filter((dependency) => dependencies[dependency].platforms.ios) .map( (dependency) => - `${dependency}@${dependencies[dependency].platforms.ios?.version}`, + `${dependency}@${ + (dependencies[dependency].platforms.ios as IOSDependencyConfig) + .version + }`, ) .sort(); } diff --git a/packages/cli-types/src/ios.ts b/packages/cli-types/src/ios.ts index a8d18da89..808791d44 100644 --- a/packages/cli-types/src/ios.ts +++ b/packages/cli-types/src/ios.ts @@ -28,7 +28,7 @@ export interface IOSDependencyConfig { export type IOSDependencyParams = Omit< Partial, - 'podspecPath' + 'podspecPath' | 'version' >; /** From 573a0474353795fd78fbb4f4cd8dc29054cbf1aa Mon Sep 17 00:00:00 2001 From: Tomasz Misiukiewicz Date: Thu, 21 Sep 2023 09:04:28 +0200 Subject: [PATCH 15/22] add pod installation prompt to init --- packages/cli-platform-ios/package.json | 1 - packages/cli-platform-ios/src/index.ts | 2 +- packages/cli/src/commands/init/init.ts | 17 +++++++++++++++++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/packages/cli-platform-ios/package.json b/packages/cli-platform-ios/package.json index 585d4d97d..710f28947 100644 --- a/packages/cli-platform-ios/package.json +++ b/packages/cli-platform-ios/package.json @@ -8,7 +8,6 @@ }, "dependencies": { "@react-native-community/cli-tools": "12.0.0-alpha.13", - "@react-native-community/cli-doctor": "12.0.0-alpha.13", "chalk": "^4.1.2", "execa": "^5.0.0", "fast-xml-parser": "^4.0.12", diff --git a/packages/cli-platform-ios/src/index.ts b/packages/cli-platform-ios/src/index.ts index 9a91427f2..5242bb9fe 100644 --- a/packages/cli-platform-ios/src/index.ts +++ b/packages/cli-platform-ios/src/index.ts @@ -2,6 +2,6 @@ * iOS platform files */ -export {runSudo} from '@react-native-community/cli-tools'; export {default as commands} from './commands'; export {projectConfig, dependencyConfig, findPodfilePaths} from './config'; +export {default as installPods} from './tools/installPods'; diff --git a/packages/cli/src/commands/init/init.ts b/packages/cli/src/commands/init/init.ts index 38df84b61..bbf66e336 100644 --- a/packages/cli/src/commands/init/init.ts +++ b/packages/cli/src/commands/init/init.ts @@ -2,6 +2,8 @@ import os from 'os'; import path from 'path'; import fs from 'fs-extra'; import {validateProjectName} from './validate'; +import {prompt} from 'prompts'; +import chalk from 'chalk'; import DirectoryAlreadyExistsError from './errors/DirectoryAlreadyExistsError'; import printRunInstructions from './printRunInstructions'; import { @@ -10,6 +12,7 @@ import { getLoader, Loader, } from '@react-native-community/cli-tools'; +import {installPods} from '@react-native-community/cli-platform-ios'; import { installTemplatePackage, getTemplateConfig, @@ -169,6 +172,20 @@ async function createFromTemplate({ loader, root: projectDirectory, }); + + if (process.platform === 'darwin') { + const {installCocoapods} = await prompt({ + type: 'confirm', + name: 'installCocoapods', + message: `Do you want to install CocoaPods? ${chalk.reset.dim( + 'Only needed if you run your project in Xcode directly', + )}`, + }); + + if (installCocoapods) { + await installPods(loader); + } + } } else { loader.succeed('Dependencies installation skipped'); } From ce2e11c3981891b09dceb820d49ed96b6fba5990 Mon Sep 17 00:00:00 2001 From: Tomasz Misiukiewicz Date: Thu, 21 Sep 2023 09:04:28 +0200 Subject: [PATCH 16/22] better error handling when package.json not found --- packages/cli-platform-ios/src/config/index.ts | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/packages/cli-platform-ios/src/config/index.ts b/packages/cli-platform-ios/src/config/index.ts index 99511a7ca..0232a4874 100644 --- a/packages/cli-platform-ios/src/config/index.ts +++ b/packages/cli-platform-ios/src/config/index.ts @@ -5,6 +5,7 @@ * LICENSE file in the root directory of this source tree. * */ +import chalk from 'chalk'; import path from 'path'; import fs from 'fs'; import findPodfilePath from './findPodfilePath'; @@ -67,12 +68,20 @@ export function dependencyConfig( return null; } - let version = ''; + let version = 'unresolved'; + try { const packageJson = require(path.join(folder, 'package.json')); - version = packageJson.version; + + if (packageJson.version) { + version = packageJson.version; + } } catch { - throw new CLIError(`Could not read package.json file from ${folder}`); + throw new CLIError( + `Failed to locate package.json file from ${chalk.underline( + folder, + )}. This is most likely issue with your node_modules folder being corrupted. Please force install dependencies and try again`, + ); } return { From d2cd20f705478d9ea8e7ee9ae799e955c55b4f28 Mon Sep 17 00:00:00 2001 From: Tomasz Misiukiewicz Date: Thu, 21 Sep 2023 09:04:28 +0200 Subject: [PATCH 17/22] add --install-pods flag to init --- docs/commands.md | 4 ++++ packages/cli/src/commands/init/index.ts | 5 +++++ packages/cli/src/commands/init/init.ts | 30 +++++++++++++++++-------- 3 files changed, 30 insertions(+), 9 deletions(-) diff --git a/docs/commands.md b/docs/commands.md index bef3d4e1c..eab8776ab 100644 --- a/docs/commands.md +++ b/docs/commands.md @@ -96,6 +96,10 @@ module.exports = { Skip dependencies installation +#### `--install-pods [boolean]` + +Determine if CocoaPods should be installed when initializing a project. If set to `true` it will install pods, if set to `false`, it will skip the step entirely. If not used, prompt will be displayed + #### `--npm` > [!WARNING] > `--npm` is deprecated and will be removed in the future. Please use `--pm npm` instead. diff --git a/packages/cli/src/commands/init/index.ts b/packages/cli/src/commands/init/index.ts index af773e319..be2aaee2f 100644 --- a/packages/cli/src/commands/init/index.ts +++ b/packages/cli/src/commands/init/index.ts @@ -37,6 +37,11 @@ export default { name: '--skip-install', description: 'Skips dependencies installation step', }, + { + name: '--install-pods [boolean]', + description: + 'Determine if CocoaPods should be installed when initializing a project', + }, { name: '--package-name ', description: diff --git a/packages/cli/src/commands/init/init.ts b/packages/cli/src/commands/init/init.ts index bbf66e336..28c519fb3 100644 --- a/packages/cli/src/commands/init/init.ts +++ b/packages/cli/src/commands/init/init.ts @@ -40,6 +40,7 @@ type Options = { skipInstall?: boolean; version?: string; packageName?: string; + installPods?: string; }; interface TemplateOptions { @@ -51,6 +52,7 @@ interface TemplateOptions { projectTitle?: string; skipInstall?: boolean; packageName?: string; + installCocoaPods?: string; } function doesDirectoryExist(dir: string) { @@ -95,6 +97,7 @@ async function createFromTemplate({ projectTitle, skipInstall, packageName, + installCocoaPods, }: TemplateOptions) { logger.debug('Initializing new project'); logger.log(banner); @@ -174,16 +177,24 @@ async function createFromTemplate({ }); if (process.platform === 'darwin') { - const {installCocoapods} = await prompt({ - type: 'confirm', - name: 'installCocoapods', - message: `Do you want to install CocoaPods? ${chalk.reset.dim( - 'Only needed if you run your project in Xcode directly', - )}`, - }); - - if (installCocoapods) { + const installPodsValue = String(installCocoaPods); + + if (installPodsValue === 'true') { await installPods(loader); + loader.succeed(); + } else if (installPodsValue === 'undefined') { + const {installCocoapods} = await prompt({ + type: 'confirm', + name: 'installCocoapods', + message: `Do you want to install CocoaPods? ${chalk.reset.dim( + 'Only needed if you run your project in Xcode directly', + )}`, + }); + + if (installCocoapods) { + await installPods(loader); + loader.succeed(); + } } } } else { @@ -262,6 +273,7 @@ async function createProject( projectTitle: options.title, skipInstall: options.skipInstall, packageName: options.packageName, + installCocoaPods: options.installPods, }); } From 560b32b465cc0de3d9651174309340731f30f976 Mon Sep 17 00:00:00 2001 From: Tomasz Misiukiewicz Date: Thu, 21 Sep 2023 09:04:57 +0200 Subject: [PATCH 18/22] update tests --- .../__snapshots__/index-test.ts.snap | 5 +++++ .../cli-config/src/__tests__/index-test.ts | 9 +++++++++ packages/cli-platform-ios/README.md | 4 ++-- .../src/__tests__/pods.test.ts | 20 +++++-------------- 4 files changed, 21 insertions(+), 17 deletions(-) diff --git a/packages/cli-config/src/__tests__/__snapshots__/index-test.ts.snap b/packages/cli-config/src/__tests__/__snapshots__/index-test.ts.snap index 10dc100fd..453523b62 100644 --- a/packages/cli-config/src/__tests__/__snapshots__/index-test.ts.snap +++ b/packages/cli-config/src/__tests__/__snapshots__/index-test.ts.snap @@ -11,6 +11,7 @@ Object { ], "podspecPath": "<>/node_modules/react-native-test/ReactNativeTest.podspec", "scriptPhases": Array [], + "version": "unresolved", }, }, "root": "<>/node_modules/react-native-test", @@ -57,6 +58,7 @@ Object { "path": "./phase.sh", }, ], + "version": "unresolved", }, }, "root": "<>/node_modules/react-native-test", @@ -107,6 +109,7 @@ Object { "show_env_vars_in_log": false, }, ], + "version": "unresolved", }, }, "root": "<>/node_modules/react-native-test", @@ -131,6 +134,7 @@ Object { "configurations": Array [], "podspecPath": "<>/node_modules/react-native-test/ReactNativeTest.podspec", "scriptPhases": Array [], + "version": "unresolved", }, }, "root": "<>/node_modules/react-native-test", @@ -149,6 +153,7 @@ Object { ], "podspecPath": "<>/node_modules/react-native-test/ReactNativeTest.podspec", "scriptPhases": Array [], + "version": "unresolved", }, }, "root": "<>/node_modules/react-native-test", diff --git a/packages/cli-config/src/__tests__/index-test.ts b/packages/cli-config/src/__tests__/index-test.ts index 4ace69973..104ed7de0 100644 --- a/packages/cli-config/src/__tests__/index-test.ts +++ b/packages/cli-config/src/__tests__/index-test.ts @@ -241,6 +241,14 @@ test('supports dependencies from user configuration with custom root and propert writeFiles(DIR, { ...REACT_NATIVE_MOCK, 'native-libs/local-lib/LocalRNLibrary.podspec': '', + 'native-libs/local-lib/package.json': ` + { + "name": "local-lib", + "version": "0.0.1", + "dependencies": { + "react-native": "0.0.1" + } + }`, 'react-native.config.js': ` const path = require('path'); const root = path.resolve('${escapePathSeparator( @@ -276,6 +284,7 @@ module.exports = { "configurations": Array [], "podspecPath": "custom-path", "scriptPhases": Array [], + "version": "0.0.1", }, }, "root": "<>/native-libs/local-lib", diff --git a/packages/cli-platform-ios/README.md b/packages/cli-platform-ios/README.md index e72a582bf..48d7592bd 100644 --- a/packages/cli-platform-ios/README.md +++ b/packages/cli-platform-ios/README.md @@ -115,7 +115,7 @@ Installs passed binary instead of building a fresh one. List all available iOS devices and simulators and let you choose one to run the app. #### `--force-pods`, -Force running `pod install` before running an app +Force running `pod install` before building an app ### `build-ios` @@ -170,7 +170,7 @@ npx react-native build-ios --extra-params "-jobs 4" #### `--force-pods`, -Force running `pod install` before running an app +Force running `pod install` before building an app ### `log-ios` Usage: diff --git a/packages/cli-platform-ios/src/__tests__/pods.test.ts b/packages/cli-platform-ios/src/__tests__/pods.test.ts index a78afb804..5c5552c93 100644 --- a/packages/cli-platform-ios/src/__tests__/pods.test.ts +++ b/packages/cli-platform-ios/src/__tests__/pods.test.ts @@ -17,7 +17,7 @@ const dependencyHash = 'd41d8cd98f00b204e9800998ecf8427e'; const packageJson = { name: 'test-package', dependencies: {dep1: '1.0.0'}, - devDependencies: {dep2: '2.0.0'}, + devDependencies: {dep2: '1.0.0'}, }; const commonDepConfig = { @@ -25,6 +25,7 @@ const commonDepConfig = { platforms: { ios: { podspecPath: '', + version: '1.0.0', scriptPhases: [], configurations: [], }, @@ -72,12 +73,8 @@ describe('compareMd5Hashes', () => { describe('getIosDependencies', () => { it('should return only dependencies with native code', () => { - const dependencies = { - ...packageJson.dependencies, - ...packageJson.devDependencies, - }; - const result = getIosDependencies(dependenciesConfig, dependencies); - expect(result).toEqual(['dep1@1.0.0', 'dep2@2.0.0']); + const result = getIosDependencies(dependenciesConfig); + expect(result).toEqual(['dep1@1.0.0', 'dep2@1.0.0']); }); }); @@ -128,14 +125,7 @@ describe('resolvePods', () => { await resolvePods(DIR, { dep1: { name: 'dep1', - root: '', - platforms: { - ios: { - podspecPath: '', - scriptPhases: [], - configurations: [], - }, - }, + ...commonDepConfig, }, }); From 5f32ae5903021783592d3d2d2e94f6c0c9085727 Mon Sep 17 00:00:00 2001 From: Tomasz Misiukiewicz Date: Thu, 21 Sep 2023 09:04:57 +0200 Subject: [PATCH 19/22] fix config tests --- __e2e__/config.test.ts | 2 +- __e2e__/init.test.ts | 6 ++++++ __e2e__/root.test.ts | 3 +-- packages/cli-platform-ios/README.md | 2 +- packages/cli/src/commands/init/init.ts | 2 +- 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/__e2e__/config.test.ts b/__e2e__/config.test.ts index 477a38984..f5e8e4baa 100644 --- a/__e2e__/config.test.ts +++ b/__e2e__/config.test.ts @@ -49,7 +49,7 @@ beforeAll(() => { // Initialise React Native project - runCLI(DIR, ['init', 'TestProject']); + runCLI(DIR, ['init', 'TestProject', '--install-pods']); // Link CLI to the project const pkgs = [ diff --git a/__e2e__/init.test.ts b/__e2e__/init.test.ts index 845ac7908..0fb0eb967 100644 --- a/__e2e__/init.test.ts +++ b/__e2e__/init.test.ts @@ -79,6 +79,8 @@ test('init --template filepath', () => { '--template', templatePath, 'TestInit', + '--install-pods', + 'false', ]); expect(stdout).toContain('Run instructions'); @@ -103,6 +105,8 @@ test('init --template file with custom directory', () => { projectName, '--directory', 'custom-path', + '--install-pods', + 'false', ]); // make sure --directory option is used in run instructions @@ -149,6 +153,8 @@ test('init uses npm as the package manager with --npm', () => { templatePath, 'TestInit', '--npm', + '--install-pods', + 'false', ]); expect(stdout).toContain('Run instructions'); diff --git a/__e2e__/root.test.ts b/__e2e__/root.test.ts index c59b9ae97..cb262d2a7 100644 --- a/__e2e__/root.test.ts +++ b/__e2e__/root.test.ts @@ -23,8 +23,7 @@ beforeAll(() => { writeFiles(cwd, {}); // Initialise React Native project - runCLI(cwd, ['init', 'TestProject']); - + runCLI(cwd, ['init', 'TestProject', '--install-pods']); // Link CLI to the project const pkgs = [ '@react-native-community/cli-platform-ios', diff --git a/packages/cli-platform-ios/README.md b/packages/cli-platform-ios/README.md index 48d7592bd..20210cd1a 100644 --- a/packages/cli-platform-ios/README.md +++ b/packages/cli-platform-ios/README.md @@ -115,7 +115,7 @@ Installs passed binary instead of building a fresh one. List all available iOS devices and simulators and let you choose one to run the app. #### `--force-pods`, -Force running `pod install` before building an app +Force running `pod install` before running an app ### `build-ios` diff --git a/packages/cli/src/commands/init/init.ts b/packages/cli/src/commands/init/init.ts index 28c519fb3..60dba4c14 100644 --- a/packages/cli/src/commands/init/init.ts +++ b/packages/cli/src/commands/init/init.ts @@ -186,7 +186,7 @@ async function createFromTemplate({ const {installCocoapods} = await prompt({ type: 'confirm', name: 'installCocoapods', - message: `Do you want to install CocoaPods? ${chalk.reset.dim( + message: `Do you want to install CocoaPods now? ${chalk.reset.dim( 'Only needed if you run your project in Xcode directly', )}`, }); From 86a547ead0b2ea38be0715cb388fcafa55a828db Mon Sep 17 00:00:00 2001 From: Tomasz Misiukiewicz Date: Thu, 21 Sep 2023 09:04:57 +0200 Subject: [PATCH 20/22] set hash in cache when initializing new project --- __e2e__/init.test.ts | 9 ++++++++- packages/cli/src/commands/init/init.ts | 16 ++++++++++++++-- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/__e2e__/init.test.ts b/__e2e__/init.test.ts index 0fb0eb967..384784d7b 100644 --- a/__e2e__/init.test.ts +++ b/__e2e__/init.test.ts @@ -61,7 +61,14 @@ test('init fails if the directory already exists', () => { test('init should prompt for the project name', () => { createCustomTemplateFiles(); - const {stdout} = runCLI(DIR, ['init', 'test', '--template', templatePath]); + const {stdout} = runCLI(DIR, [ + 'init', + 'test', + '--template', + templatePath, + '--install-pods', + 'false', + ]); (prompts as jest.MockedFunction).mockReturnValue( Promise.resolve({ diff --git a/packages/cli/src/commands/init/init.ts b/packages/cli/src/commands/init/init.ts index 60dba4c14..d54d58b21 100644 --- a/packages/cli/src/commands/init/init.ts +++ b/packages/cli/src/commands/init/init.ts @@ -11,6 +11,7 @@ import { logger, getLoader, Loader, + cacheManager, } from '@react-native-community/cli-tools'; import {installPods} from '@react-native-community/cli-platform-ios'; import { @@ -26,7 +27,7 @@ import TemplateAndVersionError from './errors/TemplateAndVersionError'; import {getBunVersionIfAvailable} from '../../tools/bun'; import {getNpmVersionIfAvailable} from '../../tools/npm'; import {getYarnVersionIfAvailable} from '../../tools/yarn'; -import prompts from 'prompts'; +import {createHash} from 'crypto'; const DEFAULT_VERSION = 'latest'; @@ -88,6 +89,15 @@ function getTemplateName(cwd: string) { return name; } +//set cache to empty string to prevent installing cocoapods on freshly created project +function setEmptyHashForCachedDependencies(projectName: string) { + cacheManager.set( + projectName, + 'dependencies', + createHash('md5').update('').digest('hex'), + ); +} + async function createFromTemplate({ projectName, templateUri, @@ -182,6 +192,7 @@ async function createFromTemplate({ if (installPodsValue === 'true') { await installPods(loader); loader.succeed(); + setEmptyHashForCachedDependencies(projectName); } else if (installPodsValue === 'undefined') { const {installCocoapods} = await prompt({ type: 'confirm', @@ -194,6 +205,7 @@ async function createFromTemplate({ if (installCocoapods) { await installPods(loader); loader.succeed(); + setEmptyHashForCachedDependencies(projectName); } } } @@ -300,7 +312,7 @@ export default (async function initialize( options: Options, ) { if (!projectName) { - const {projName} = await prompts({ + const {projName} = await prompt({ type: 'text', name: 'projName', message: 'How would you like to name the app?', From 5f386b49056e794b79466bd39e9aa91c0c11776b Mon Sep 17 00:00:00 2001 From: Tomasz Misiukiewicz Date: Thu, 21 Sep 2023 09:04:57 +0200 Subject: [PATCH 21/22] try/catch require package.json --- packages/cli-platform-ios/src/tools/pods.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/cli-platform-ios/src/tools/pods.ts b/packages/cli-platform-ios/src/tools/pods.ts index 42632cbf4..cb56f1085 100644 --- a/packages/cli-platform-ios/src/tools/pods.ts +++ b/packages/cli-platform-ios/src/tools/pods.ts @@ -23,7 +23,13 @@ interface NativeDependencies { } export function getPackageJson(root: string) { - return require(path.join(root, 'package.json')); + try { + return require(path.join(root, 'package.json')); + } catch { + throw new CLIError( + 'No package.json found. Please make sure the file exists in the current folder.', + ); + } } export function getIosDependencies(dependencies: NativeDependencies) { From 9754e12b0ee5cb93caaae71f1e63f86087811d06 Mon Sep 17 00:00:00 2001 From: Tomasz Misiukiewicz Date: Thu, 21 Sep 2023 09:42:29 +0200 Subject: [PATCH 22/22] update type for installCocoaPods --- packages/cli/src/commands/init/init.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/cli/src/commands/init/init.ts b/packages/cli/src/commands/init/init.ts index d54d58b21..b6351cb19 100644 --- a/packages/cli/src/commands/init/init.ts +++ b/packages/cli/src/commands/init/init.ts @@ -41,7 +41,7 @@ type Options = { skipInstall?: boolean; version?: string; packageName?: string; - installPods?: string; + installPods?: string | boolean; }; interface TemplateOptions { @@ -53,7 +53,7 @@ interface TemplateOptions { projectTitle?: string; skipInstall?: boolean; packageName?: string; - installCocoaPods?: string; + installCocoaPods?: string | boolean; } function doesDirectoryExist(dir: string) {