From 6ef88d640965032ba612d7dd935d6630f15098cc Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Tue, 15 Aug 2017 10:18:09 -0400 Subject: [PATCH 1/2] Add `--package-json-only` command line option. --- bin/ember-cli-update.js | 4 +++- src/args.js | 5 +++++ src/index.js | 1 + 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/bin/ember-cli-update.js b/bin/ember-cli-update.js index c9365b944..b896bb773 100755 --- a/bin/ember-cli-update.js +++ b/bin/ember-cli-update.js @@ -13,9 +13,11 @@ const argv = require('yargs') const from = argv['from']; const to = argv['to']; const ignoreConflicts = argv['ignore-conflicts']; +const packageJsonOnly = argv['package-json-only']; emberCliUpdate({ from, to, - ignoreConflicts + ignoreConflicts, + packageJsonOnly }); diff --git a/src/args.js b/src/args.js index 3fa79240f..601a4b9f6 100644 --- a/src/args.js +++ b/src/args.js @@ -12,5 +12,10 @@ module.exports = { type: 'boolean', default: false, description: 'Handle merge conflicts yourself' + }, + 'package-json-only': { + type: 'boolean', + default: false, + description: 'Attempt to automatically merge package.json changes' } }; diff --git a/src/index.js b/src/index.js index bc3eb4e01..18c76ae42 100644 --- a/src/index.js +++ b/src/index.js @@ -11,6 +11,7 @@ module.exports = function emberCliUpdate(options) { let from = options.from; let to = options.to; let ignoreConflicts = options.ignoreConflicts; + let packageJsonOnly = options.packageJsonOnly; let versions = JSON.parse( run('npm info ember-cli versions --json') From d49962f4fdd86c75d57c4f2bef1add34bb50ab4b Mon Sep 17 00:00:00 2001 From: Robert Jackson Date: Tue, 15 Aug 2017 10:20:03 -0400 Subject: [PATCH 2/2] Add `auto-merge-package-json` utility function. --- package.json | 4 ++ src/auto-merge-package-json.js | 76 ++++++++++++++++++++++++++++++++++ src/index.js | 5 +++ 3 files changed, 85 insertions(+) create mode 100644 src/auto-merge-package-json.js diff --git a/package.json b/package.json index 0211161fc..9ac72c6d3 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,11 @@ "dependencies": { "debug": "^3.0.0", "git-diff-apply": "^0.2.0", + "got": "^7.1.0", + "rfc6902": "^1.3.0", "semver": "^5.4.1", + "sort-package-json": "^1.7.0", + "three-way-merger": "^0.2.0", "yargs": "^8.0.2" }, "devDependencies": { diff --git a/src/auto-merge-package-json.js b/src/auto-merge-package-json.js new file mode 100644 index 000000000..baa31bcc7 --- /dev/null +++ b/src/auto-merge-package-json.js @@ -0,0 +1,76 @@ +'use strict'; + +const fs = require('fs'); +const got = require('got'); +const sortPackageJson = require('sort-package-json'); +const ThreeWayMerger = require('three-way-merger'); +const rfc6902 = require('rfc6902'); + +function clone(obj) { + return JSON.parse(JSON.stringify(obj)); +} + +function applyDependencyOperations(operations, source) { + operations.add.forEach((dep) => source[dep.name] = dep.version); + operations.remove.forEach((dep) => delete source[dep.name]); + operations.change.forEach((dep) => source[dep.name] = dep.version); +} + +function mergeDependencyChanges(source, ours, theirs) { + let mergeOperations = ThreeWayMerger.merge({ source, ours, theirs }); + + // get a fresh copy so we don't mutate the passed in arg + let result = clone(ours); + + applyDependencyOperations(mergeOperations.dependencies, result.dependencies); + applyDependencyOperations(mergeOperations.devDependencies, result.devDependencies); + + return result; +} + +function deleteDeps(input) { + delete input.dependencies; + delete input.devDependencies; +} + +function mergeNonDependencyChanges(_source, _ours, _theirs) { + let source = clone(_source); + let ours = clone(_ours); + let theirs = clone(_theirs); + + deleteDeps(source); + deleteDeps(ours); + deleteDeps(theirs); + + let fromSourceToOurs = rfc6902.createPatch(source, ours); + + rfc6902.applyPatch(theirs, fromSourceToOurs); + + return theirs; +} + +module.exports = function autoMergePackageJson(projectType, from, to) { + let projectKeyword = projectType === 'app' ? 'new' : 'addon'; + let remoteUrl = `https://rawgit.com/ember-cli/ember-${projectKeyword}-output`; + + return Promise.all([ + got(`${remoteUrl}/${from}/package.json`, { json: true }), + got(`${remoteUrl}/${to}/package.json`, { json: true }), + ]) + .then((results) => { + let fromPackageJson = results[0].body; + let toPackageJson = results[1].body; + let currentPackageJson = JSON.parse(fs.readFileSync('package.json', { encoding: 'utf-8' })); + + let mergedDependenciesPackageJson = mergeDependencyChanges(fromPackageJson, currentPackageJson, toPackageJson); + let mergedOtherPackageJson = mergeNonDependencyChanges(fromPackageJson, currentPackageJson, toPackageJson); + + let finalMergedPackageJson = mergedOtherPackageJson; + finalMergedPackageJson.dependencies = mergedDependenciesPackageJson.dependencies; + finalMergedPackageJson.devDependencies = mergedDependenciesPackageJson.devDependencies; + + let sortedPackageJson = sortPackageJson(finalMergedPackageJson); + + fs.writeFileSync('package.json', JSON.stringify(sortedPackageJson, null, 2) + '\n', { encoding: 'utf-8' }); + }); +} diff --git a/src/index.js b/src/index.js index 18c76ae42..132723bfb 100644 --- a/src/index.js +++ b/src/index.js @@ -32,6 +32,11 @@ module.exports = function emberCliUpdate(options) { let remoteUrl = `https://github.com/ember-cli/ember-${projectKeyword}-output`; + if (packageJsonOnly) { + const autoMergePackageJson = require('./auto-merge-package-json'); + return autoMergePackageJson(projectType, startTag, endTag); + } + return gitDiffApply({ remoteUrl, startTag,