Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 15 additions & 5 deletions packages/cli/src/commands/upgrade/__tests__/upgrade.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ jest.mock('@react-native-community/cli-tools', () => ({
error: jest.fn((...args) => mockPushLog('error', args)),
warn: jest.fn((...args) => mockPushLog('warn', args)),
success: jest.fn((...args) => mockPushLog('success', args)),
debug: jest.fn((...args) => mockPushLog('debug', args)),
log: jest.fn((...args) => mockPushLog(args)),
},
}));
Expand Down Expand Up @@ -252,7 +253,8 @@ test('cleans up if patching fails,', async () => {
if (command === 'git' && args[0] === 'apply') {
return Promise.reject({
code: 1,
stderr: 'error: .flowconfig: does not exist in index\n',
stderr:
'error: .flowconfig: does not exist in index\nerror: ios/MyApp.xcodeproj/project.pbxproj: patch does not apply',
});
}
if (command === 'git' && args[0] === 'rev-parse') {
Expand All @@ -272,16 +274,24 @@ test('cleans up if patching fails,', async () => {
[fs] write tmp-upgrade-rn.patch
$ execa git rev-parse --show-prefix
$ execa git apply --binary --check tmp-upgrade-rn.patch --exclude=package.json -p2 --3way --directory=
info Applying diff (excluding: package.json, .flowconfig)...
$ execa git apply tmp-upgrade-rn.patch --exclude=package.json --exclude=.flowconfig -p2 --3way --directory=
info Applying diff...
warn Excluding files that exist in the template, but not in your project:
- .flowconfig
error Excluding files that failed to apply the diff:
- ios/MyApp.xcodeproj/project.pbxproj
Please make sure to check the actual changes after the upgrade command is finished.
You can find them in our Upgrade Helper web app: https://react-native-community.github.io/upgrade-helper/?from=0.57.8&to=0.58.4
$ execa git apply tmp-upgrade-rn.patch --exclude=package.json --exclude=.flowconfig --exclude=ios/MyApp.xcodeproj/project.pbxproj -p2 --3way --directory=
debug \\"git apply\\" failed. Error output:
error: .flowconfig: does not exist in index
error Automatically applying diff failed
error: ios/MyApp.xcodeproj/project.pbxproj: patch does not apply
error Automatically applying diff failed. We did our best to automatically upgrade as many files as possible
[fs] unlink tmp-upgrade-rn.patch
$ execa git status -s
error Patch failed to apply for unknown reason. Please fall back to manual way of upgrading
info You may find these resources helpful:
• Release notes: https://github.com/facebook/react-native/releases/tag/v0.58.4
Comparison between versions: https://github.com/react-native-community/rn-diff-purge/compare/release/0.57.8..release/0.58.4
Manual Upgrade Helper: https://react-native-community.github.io/upgrade-helper/?from=0.57.8&to=0.58.4
• Git diff: https://raw.githubusercontent.com/react-native-community/rn-diff-purge/diffs/diffs/0.57.8..0.58.4.diff"
`);
}, 60000);
Expand Down
68 changes: 46 additions & 22 deletions packages/cli/src/commands/upgrade/upgrade.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ type FlagsT = {
legacy: boolean | void,
};

const rnDiffPurgeUrl =
'https://github.com/react-native-community/rn-diff-purge';
const rnDiffPurgeRawDiffsUrl =
// https://react-native-community.github.io/upgrade-helper/?from=0.59.10&to=0.60.0-rc.3
const webDiffUrl = 'https://react-native-community.github.io/upgrade-helper';
const rawDiffUrl =
'https://raw.githubusercontent.com/react-native-community/rn-diff-purge/diffs/diffs';

const getLatestRNVersion = async (): Promise<string> => {
Expand Down Expand Up @@ -46,9 +46,7 @@ const getPatch = async (currentVersion, newVersion, config) => {
logger.info(`Fetching diff between v${currentVersion} and v${newVersion}...`);

try {
patch = await fetch(
`${rnDiffPurgeRawDiffsUrl}/${currentVersion}..${newVersion}.diff`,
);
patch = await fetch(`${rawDiffUrl}/${currentVersion}..${newVersion}.diff`);
} catch (error) {
logger.error(
`Failed to fetch diff for react-native@${newVersion}. Maybe it's not released yet?`,
Expand Down Expand Up @@ -166,15 +164,17 @@ const applyPatch = async (
newVersion: string,
tmpPatchFile: string,
) => {
let filesToExclude = ['package.json'];
const defaultExcludes = ['package.json'];
let filesThatDontExist = [];
let filesThatFailedToApply = [];
// $FlowFixMe ThenableChildProcess is incompatible with Promise
const {stdout: relativePathFromRoot} = await execa('git', [
'rev-parse',
'--show-prefix',
]);
try {
try {
const excludes = filesToExclude.map(
const excludes = defaultExcludes.map(
e => `--exclude=${path.join(relativePathFromRoot, e)}`,
);
await execa('git', [
Expand All @@ -192,19 +192,41 @@ const applyPatch = async (
]);
logger.info('Applying diff...');
} catch (error) {
filesToExclude = [
...filesToExclude,
...error.stderr
.split('\n')
const errorLines = error.stderr.split('\n');
filesThatDontExist = [
...errorLines
.filter(x => x.includes('does not exist in index'))
.map(x => x.replace(/^error: (.*): does not exist in index$/, '$1')),
].filter(Boolean);

logger.info(`Applying diff (excluding: ${filesToExclude.join(', ')})...`);
} finally {
const excludes = filesToExclude.map(
e => `--exclude=${path.join(relativePathFromRoot, e)}`,
filesThatFailedToApply = errorLines
.filter(x => x.includes('patch does not apply'))
.map(x => x.replace(/^error: (.*): patch does not apply$/, '$1'))
.filter(Boolean);

logger.info('Applying diff...');
logger.warn(
`Excluding files that exist in the template, but not in your project:\n${filesThatDontExist
.map(file => ` - ${chalk.bold(file)}`)
.join('\n')}`,
);
if (filesThatFailedToApply.length) {
logger.error(
`Excluding files that failed to apply the diff:\n${filesThatFailedToApply
.map(file => ` - ${chalk.bold(file)}`)
.join(
'\n',
)}\nPlease make sure to check the actual changes after the upgrade command is finished.\nYou can find them in our Upgrade Helper web app: ${chalk.underline.dim(
`${webDiffUrl}/?from=${currentVersion}&to=${newVersion}`,
)}`,
);
}
} finally {
const excludes = [
...defaultExcludes,
...filesThatDontExist,
...filesThatFailedToApply,
].map(e => `--exclude=${path.join(relativePathFromRoot, e)}`);
await execa('git', [
'apply',
tmpPatchFile,
Expand All @@ -216,9 +238,11 @@ const applyPatch = async (
}
} catch (error) {
if (error.stderr) {
logger.log(`${chalk.dim(error.stderr.trim())}`);
logger.debug(`"git apply" failed. Error output:\n${error.stderr}`);
}
logger.error('Automatically applying diff failed');
logger.error(
'Automatically applying diff failed. We did our best to automatically upgrade as many files as possible',
);
return false;
}
return true;
Expand Down Expand Up @@ -279,7 +303,7 @@ async function upgrade(argv: Array<string>, ctx: ConfigT, args: FlagsT) {
if (!patchSuccess) {
if (stdout) {
logger.warn(
'Continuing after failure. Most of the files are upgraded but you will need to deal with some conflicts manually',
'Continuing after failure. Some of the files are upgraded but you will need to deal with conflicts manually',
);
await installDeps(newVersion, projectDir);
logger.info('Running "git status" to check what changed...');
Expand All @@ -304,11 +328,11 @@ async function upgrade(argv: Array<string>, ctx: ConfigT, args: FlagsT) {
• Release notes: ${chalk.underline.dim(
`https://github.com/facebook/react-native/releases/tag/v${newVersion}`,
)}
Comparison between versions: ${chalk.underline.dim(
`${rnDiffPurgeUrl}/compare/release/${currentVersion}..release/${newVersion}`,
Manual Upgrade Helper: ${chalk.underline.dim(
`${webDiffUrl}/?from=${currentVersion}&to=${newVersion}`,
)}
• Git diff: ${chalk.underline.dim(
`${rnDiffPurgeRawDiffsUrl}/${currentVersion}..${newVersion}.diff`,
`${rawDiffUrl}/${currentVersion}..${newVersion}.diff`,
)}`);

throw new CLIError(
Expand Down