Skip to content
This repository has been archived by the owner on Jan 18, 2024. It is now read-only.

Commit

Permalink
[cli] Skip ejecting iOS on Windows
Browse files Browse the repository at this point in the history
  • Loading branch information
brentvatne committed Oct 14, 2020
1 parent 2418139 commit d7ef459
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 24 deletions.
11 changes: 1 addition & 10 deletions packages/expo-cli/src/commands/eject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,21 +55,12 @@ export default function (program: Command) {
.command('eject [path]')
.description(
// TODO: Use Learn more link when it lands
`Create native iOS and Android project files. Read more: https://expo.fyi/eject`
`Create native iOS and Android project files. Read more: https://docs.expo.io/bare/customizing/`
)
.longDescription(
'Create Xcode and Android Studio projects for your app. Use this if you need to add custom native functionality.'
)
.helpGroup('eject')
.option(
'--eject-method [type]',
`Eject method to use. [Depreacted]: Ejecting to ExpoKit is not available on SDK >= 37 and not recommended for older SDK versions. We recommend updating to SDK >= 37 and ejecting to bare.`,
(value: string) => value.toLowerCase()
)
.option(
'-f --force',
'Will attempt to generate an iOS project even when the system is not running macOS. Unsafe and may fail.'
)
.option('--no-install', 'Skip installing npm packages and CocoaPods.')
.option('--npm', 'Use npm to install dependencies. (default when Yarn is not installed)')
.asyncActionProjectDir(action);
Expand Down
62 changes: 50 additions & 12 deletions packages/expo-cli/src/commands/eject/Eject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import maybeBailOnGitStatusAsync from '../utils/maybeBailOnGitStatusAsync';
import { getOrPromptForBundleIdentifier, getOrPromptForPackage } from './ConfigValidation';

type DependenciesMap = { [key: string]: string | number };
type PlatformsArray = ('ios' | 'android')[];

export type EjectAsyncOptions = {
verbose?: boolean;
Expand All @@ -50,14 +51,31 @@ export type EjectAsyncOptions = {
export async function ejectAsync(projectRoot: string, options?: EjectAsyncOptions): Promise<void> {
if (await maybeBailOnGitStatusAsync()) return;

const platforms: PlatformsArray = ['android'];

// Skip ejecting for iOS on Windows
if (process.platform !== 'win32') {
platforms.push('ios');
}

const { exp, pkg } = await ensureConfigAsync(projectRoot);
const tempDir = temporary.directory();

if (!platforms.includes('ios')) {
log.warn(
`⚠️ Skipping generating the iOS native project files. Run ${chalk.bold(
'expo eject'
)} again from macOS or Linux to generate the iOS project.`
);
log.newLine();
}

const { hasNewProjectFiles, needsPodInstall } = await createNativeProjectsFromTemplateAsync(
projectRoot,
exp,
pkg,
tempDir
tempDir,
platforms
);
// Set this to true when we can detect that the user is running eject to sync new changes rather than ejecting to bare.
// This will be used to prevent the node modules from being nuked every time.
Expand All @@ -77,13 +95,18 @@ export async function ejectAsync(projectRoot: string, options?: EjectAsyncOption
}

// Apply Expo config to native projects
await configureIOSStepAsync(projectRoot);
await configureAndroidStepAsync(projectRoot);
if (platforms.includes('ios')) {
await configureIOSStepAsync(projectRoot);
}

if (platforms.includes('android')) {
await configureAndroidStepAsync(projectRoot);
}

// Install CocoaPods
let podsInstalled: boolean = false;
// err towards running pod install less because it's slow and users can easily run npx pod-install afterwards.
if (shouldInstall && needsPodInstall) {
if (platforms.includes('ios') && shouldInstall && needsPodInstall) {
podsInstalled = await CreateApp.installCocoaPodsAsync(projectRoot);
}

Expand Down Expand Up @@ -154,8 +177,14 @@ export async function ejectAsync(projectRoot: string, options?: EjectAsyncOption
'To compile and run your project in development, execute one of the following commands:'
);

log.nested(`- ${chalk.bold(packageManager === 'npm' ? 'npm run ios' : 'yarn ios')}`);
log.nested(`- ${chalk.bold(packageManager === 'npm' ? 'npm run android' : 'yarn android')}`);
if (platforms.includes('ios')) {
log.nested(`- ${chalk.bold(packageManager === 'npm' ? 'npm run ios' : 'yarn ios')}`);
}

if (platforms.includes('android')) {
log.nested(`- ${chalk.bold(packageManager === 'npm' ? 'npm run android' : 'yarn android')}`);
}

log.nested(`- ${chalk.bold(packageManager === 'npm' ? 'npm run web' : 'yarn web')}`);
}
}
Expand Down Expand Up @@ -503,8 +532,8 @@ export function hashForDependencyMap(deps: DependenciesMap): string {
return createFileHash(depsString);
}

export function getTargetPaths(pkg: PackageJSONConfig) {
const targetPaths = ['ios', 'android'];
export function getTargetPaths(pkg: PackageJSONConfig, platforms: PlatformsArray) {
const targetPaths: string[] = [...platforms];

// Only create index.js if we are going to replace the app "main" entry point
if (shouldDeleteMainField(pkg.main)) {
Expand All @@ -524,11 +553,13 @@ async function cloneNativeDirectoriesAsync({
tempDir,
exp,
pkg,
platforms,
}: {
projectRoot: string;
tempDir: string;
exp: Pick<ExpoConfig, 'name' | 'sdkVersion'>;
pkg: PackageJSONConfig;
platforms: PlatformsArray;
}): Promise<string[]> {
const templateSpec = await validateBareTemplateExistsAsync(exp.sdkVersion!);

Expand All @@ -538,7 +569,7 @@ async function cloneNativeDirectoriesAsync({
'Creating native project directories (./ios and ./android) and updating .gitignore'
);

const targetPaths = getTargetPaths(pkg);
const targetPaths = getTargetPaths(pkg, platforms);

let copiedPaths: string[] = [];
let skippedPaths: string[] = [];
Expand All @@ -550,7 +581,7 @@ async function cloneNativeDirectoriesAsync({
path.join(tempDir, '.gitignore')
);

let message = `Created native projects`;
let message = `Created native project${platforms.length > 1 ? 's' : ''}`;

if (skippedPaths.length) {
message += log.chalk.dim(
Expand Down Expand Up @@ -590,11 +621,18 @@ async function createNativeProjectsFromTemplateAsync(
projectRoot: string,
exp: ExpoConfig,
pkg: PackageJSONConfig,
tempDir: string
tempDir: string,
platforms: PlatformsArray
): Promise<
{ hasNewProjectFiles: boolean; needsPodInstall: boolean } & DependenciesModificationResults
> {
const copiedPaths = await cloneNativeDirectoriesAsync({ projectRoot, tempDir, exp, pkg });
const copiedPaths = await cloneNativeDirectoriesAsync({
projectRoot,
tempDir,
exp,
pkg,
platforms,
});

writeMetroConfig({ projectRoot, pkg, tempDir });

Expand Down
11 changes: 9 additions & 2 deletions packages/expo-cli/src/commands/eject/__tests__/Eject-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,22 @@ describe('hashForDependencyMap', () => {

describe('getTargetPaths', () => {
it(`should include index.js when pkg.main should be deleted`, () => {
expect(getTargetPaths({ main: 'node_modules/expo/AppEntry.js' })).toEqual([
expect(getTargetPaths({ main: 'node_modules/expo/AppEntry.js' }, ['ios', 'android'])).toEqual([
'ios',
'android',
'index.js',
]);
});

it(`should not include index.js when pkg.main is left alone`, () => {
expect(getTargetPaths({ main: './src/index.js' })).toEqual(['ios', 'android']);
expect(getTargetPaths({ main: './src/index.js' }, ['ios', 'android'])).toEqual([
'ios',
'android',
]);
});

it(`should only include paths for given platforms`, () => {
expect(getTargetPaths({ main: './src/index.js' }, ['ios'])).toEqual(['ios']);
});
});

Expand Down

0 comments on commit d7ef459

Please sign in to comment.