Upgrade: now uses the diff-match-patch to upgrade stacks that has been realized (#60)

* making upgrade process use a devdep instead of extra just.stacks key in package.json

* change files

* nicer error messages

* applies patches with diff-match-patch instead of doing git diff / apply

* patching works!

* fixing if no diffinfo is found to upgrade

* fixing per PR feedback
This commit is contained in:
Kenneth Chau 2019-04-10 13:26:15 -07:00 коммит произвёл GitHub
Родитель b81b8e893d
Коммит 43c9b9b52d
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
21 изменённых файлов: 310 добавлений и 318 удалений

Просмотреть файл

@ -0,0 +1,11 @@
{
"changes": [
{
"packageName": "just-scripts-utils",
"comment": "Fixing up the temp path to also use version in path",
"type": "minor"
}
],
"packageName": "just-scripts-utils",
"email": "kchau@microsoft.com"
}

Просмотреть файл

@ -0,0 +1,11 @@
{
"changes": [
{
"packageName": "just-scripts",
"comment": "Fixing up the upgrade scripts to use devdeps instead of just.stacks; also uses a diff / apply method to get upgrades working",
"type": "minor"
}
],
"packageName": "just-scripts",
"email": "kchau@microsoft.com"
}

Просмотреть файл

@ -20,6 +20,7 @@ dependencies:
'@rush-temp/just-task-docs': 'file:projects/just-task-docs.tgz'
'@rush-temp/just-task-logger': 'file:projects/just-task-logger.tgz'
'@rush-temp/just-task-scripts': 'file:projects/just-task-scripts.tgz'
'@types/diff-match-patch': 1.0.32
'@types/glob': 7.1.1
'@types/handlebars': 4.0.40
'@types/jest': 23.3.13
@ -40,6 +41,7 @@ dependencies:
'@uifabric/experiments': 6.54.2
chalk: 2.4.2
cpx: 1.5.0
diff-match-patch: 1.0.4
docusaurus: 1.7.2
fs-extra: 7.0.1
glob: 7.1.3
@ -333,7 +335,6 @@ packages:
integrity: sha512-wNHxLkEKTQ2ay0tnsam2z7fGZUi+05ziDJflEt3AZTP3oXLKHJp9HqhfroB/vdMvt3sda9fAbq7FsG8QPDrZBg==
/@babel/plugin-proposal-class-properties/7.3.0/@babel!core@7.2.2:
dependencies:
'@babel/core': 7.2.2
'@babel/helper-create-class-features-plugin': /@babel/helper-create-class-features-plugin/7.3.2/@babel!core@7.2.2
'@babel/helper-plugin-utils': 7.0.0
dev: false
@ -373,7 +374,6 @@ packages:
integrity: sha512-DjeMS+J2+lpANkYLLO+m6GjoTMygYglKmRe6cDTbFv3L9i6mmiE8fe6B8MtCSLZpVXscD5kn7s6SgtHrDoBWoA==
/@babel/plugin-proposal-object-rest-spread/7.3.2/@babel!core@7.2.2:
dependencies:
'@babel/core': 7.2.2
'@babel/helper-plugin-utils': 7.0.0
'@babel/plugin-syntax-object-rest-spread': /@babel/plugin-syntax-object-rest-spread/7.2.0/@babel!core@7.2.2
dev: false
@ -1217,7 +1217,6 @@ packages:
integrity: sha512-FHKrD6Dxf30e8xgHQO0zJZpUPfVZg+Xwgz5/RdSWCbza9QLNk4Qbp40ctRoqDxml3O8RMzB1DU55SXeDG6PqHQ==
/@babel/preset-env/7.3.1/@babel!core@7.2.2:
dependencies:
'@babel/core': 7.2.2
'@babel/helper-module-imports': 7.0.0
'@babel/helper-plugin-utils': 7.0.0
'@babel/plugin-proposal-async-generator-functions': /@babel/plugin-proposal-async-generator-functions/7.2.0/@babel!core@7.2.2
@ -1281,7 +1280,6 @@ packages:
integrity: sha512-oayxyPS4Zj+hF6Et11BwuBkmpgT/zMxyuZgFrMeZID6Hdh3dGlk4sHCAhdBCpuCKW2ppBfl2uCCetlrUIJRY3w==
/@babel/preset-react/7.0.0/@babel!core@7.2.2:
dependencies:
'@babel/core': 7.2.2
'@babel/helper-plugin-utils': 7.0.0
'@babel/plugin-transform-react-display-name': /@babel/plugin-transform-react-display-name/7.2.0/@babel!core@7.2.2
'@babel/plugin-transform-react-jsx': /@babel/plugin-transform-react-jsx/7.3.0/@babel!core@7.2.2
@ -1309,7 +1307,6 @@ packages:
integrity: sha512-f/+CRmaCe7rVEvcvPvxeA8j5aJhHC3aJie7YuqcMDhUOuyWLA7J/aNrTaHIzoWPEhpHA54mec4Mm8fv8KBlv3g==
/@babel/register/7.0.0/@babel!core@7.2.2:
dependencies:
'@babel/core': 7.2.2
core-js: 2.6.3
find-cache-dir: 1.0.0
home-or-tmp: 3.0.0
@ -1428,6 +1425,10 @@ packages:
dev: false
resolution:
integrity: sha512-m+D4NbQdDlTVaO7QgXAnatR3IDxQYDMBtRhgSCi5rs9R1LPq1y7/2aqa1FJ2IWjFm1mOV63swDxonnCDlHgHMA==
/@types/diff-match-patch/1.0.32:
dev: false
resolution:
integrity: sha512-bPYT5ECFiblzsVzyURaNhljBH2Gh1t9LowgUwciMrNAhFewLkHT2H0Mto07Y4/3KCOGZHRQll3CTtQZ0X11D/A==
/@types/events/3.0.0:
dev: false
resolution:
@ -1605,28 +1606,10 @@ packages:
react-dom: ^0.14.9 || ^15.0.1-0 || ^16.0.0-0
resolution:
integrity: sha512-iFwuoFUQoS6H6paxrRsVCxQnw2SqnxhS+EBh54Gb3A6HxS2IKzGAE5c4tnZcqjXNPxXTvXgt5iQg3xycIa95cg==
/@uifabric/charting/0.28.5/react-dom@16.7.0+react@16.7.0:
/@uifabric/charting/0.28.5/react-dom@16.7.0:
dependencies:
'@microsoft/load-themed-styles': 1.8.56
'@types/d3-array': 1.2.1
'@types/d3-axis': 1.0.10
'@types/d3-scale': 2.0.0
'@types/d3-selection': 1.3.0
'@types/d3-shape': 1.3.0
'@types/d3-time-format': 2.1.0
'@uifabric/icons': 6.3.0
'@uifabric/set-version': 1.1.3
d3-array: 1.2.1
d3-axis: 1.0.8
d3-scale: 2.0.0
d3-selection: 1.3.0
d3-shape: 1.3.4
d3-time-format: 2.1.3
office-ui-fabric-react: /office-ui-fabric-react/6.133.0/react-dom@16.7.0+react@16.7.0
prop-types: 15.6.2
react: 16.7.0
react-dom: /react-dom/16.7.0/react@16.7.0
tslib: 1.9.3
office-ui-fabric-react: /office-ui-fabric-react/6.133.0/react-dom@16.7.0
react-dom: 16.7.0
dev: false
id: registry.npmjs.org/@uifabric/charting/0.28.5
peerDependencies:
@ -1659,27 +1642,14 @@ packages:
react-dom: '>=16.3.2-0 <17.0.0'
resolution:
integrity: sha512-+1z5RUSP5gWfB5VIcD1A7O1ITbzwBEvCOOn0Md5vOhozrcDPxEAcoIve29Ckckd/05xmMAYTjgQVMjgE4y8Rng==
/@uifabric/experiments/6.54.2/react-dom@16.7.0+react@16.7.0:
/@uifabric/experiments/6.54.2/react-dom@16.7.0:
dependencies:
'@microsoft/load-themed-styles': 1.8.56
'@uifabric/azure-themes': 0.1.5
'@uifabric/charting': /@uifabric/charting/0.28.5/react-dom@16.7.0+react@16.7.0
'@uifabric/file-type-icons': /@uifabric/file-type-icons/6.4.1/react-dom@16.7.0+react@16.7.0
'@uifabric/fluent-theme': 0.13.4
'@uifabric/foundation': /@uifabric/foundation/0.7.1/react-dom@16.7.0+react@16.7.0
'@uifabric/icons': 6.3.0
'@uifabric/merge-styles': 6.15.2
'@uifabric/set-version': 1.1.3
'@uifabric/styling': 6.41.0
'@uifabric/theme-samples': 0.1.4
'@uifabric/utilities': /@uifabric/utilities/6.29.0/react-dom@16.7.0+react@16.7.0
'@uifabric/variants': 6.14.0
deep-assign: 2.0.0
office-ui-fabric-react: /office-ui-fabric-react/6.133.0/react-dom@16.7.0+react@16.7.0
prop-types: 15.6.2
react: 16.7.0
react-dom: /react-dom/16.7.0/react@16.7.0
tslib: 1.9.3
'@uifabric/charting': /@uifabric/charting/0.28.5/react-dom@16.7.0
'@uifabric/file-type-icons': /@uifabric/file-type-icons/6.4.1/react-dom@16.7.0
'@uifabric/foundation': /@uifabric/foundation/0.7.1/react-dom@16.7.0
'@uifabric/utilities': /@uifabric/utilities/6.29.0/react-dom@16.7.0
office-ui-fabric-react: /office-ui-fabric-react/6.133.0/react-dom@16.7.0
react-dom: 16.7.0
dev: false
id: registry.npmjs.org/@uifabric/experiments/6.54.2
peerDependencies:
@ -1698,13 +1668,9 @@ packages:
react-dom: '>=16.3.2-0 <17.0.0'
resolution:
integrity: sha512-T6wGiA/RjLqRE+P5RRObpcRJ+ejh4ZwZX584GgEymOCcU7kjzWSZR7imTA65FbUMUhXxR68b3oiWgPSaCAXE8w==
/@uifabric/file-type-icons/6.4.1/react-dom@16.7.0+react@16.7.0:
/@uifabric/file-type-icons/6.4.1/react-dom@16.7.0:
dependencies:
'@uifabric/set-version': 1.1.3
'@uifabric/styling': 6.41.0
react: 16.7.0
react-dom: /react-dom/16.7.0/react@16.7.0
tslib: 1.9.3
react-dom: 16.7.0
dev: false
id: registry.npmjs.org/@uifabric/file-type-icons/6.4.1
peerDependencies:
@ -1735,14 +1701,10 @@ packages:
react-dom: ^0.14.9 || ^15.0.1-0 || ^16.0.0-0
resolution:
integrity: sha512-YrdaJXAe4x7whaj7/x1fhFsBGao0vAec6mVIAYCvC09AK+puEYDahIloVWA6vLTRlWzzOZWsvN3S3Z1tzfhIRw==
/@uifabric/foundation/0.7.1/react-dom@16.7.0+react@16.7.0:
/@uifabric/foundation/0.7.1/react-dom@16.7.0:
dependencies:
'@uifabric/set-version': 1.1.3
'@uifabric/styling': 6.41.0
'@uifabric/utilities': /@uifabric/utilities/6.29.0/react-dom@16.7.0+react@16.7.0
react: 16.7.0
react-dom: /react-dom/16.7.0/react@16.7.0
tslib: 1.9.3
'@uifabric/utilities': /@uifabric/utilities/6.29.0/react-dom@16.7.0
react-dom: 16.7.0
dev: false
id: registry.npmjs.org/@uifabric/foundation/0.7.1
peerDependencies:
@ -1802,14 +1764,9 @@ packages:
react-dom: '>=16.3.2-0 <17.0.0'
resolution:
integrity: sha512-2VKRadp+pGV5PFubSYCUTU4Sg3NdztECFiEvgyVDIrGYZhSwOVHMwAKb+I9hr990OLCb+gSK3rekJp/To9NZFQ==
/@uifabric/utilities/6.29.0/react-dom@16.7.0+react@16.7.0:
/@uifabric/utilities/6.29.0/react-dom@16.7.0:
dependencies:
'@uifabric/merge-styles': 6.15.2
'@uifabric/set-version': 1.1.3
prop-types: 15.6.2
react: 16.7.0
react-dom: /react-dom/16.7.0/react@16.7.0
tslib: 1.9.3
react-dom: 16.7.0
dev: false
id: registry.npmjs.org/@uifabric/utilities/6.29.0
peerDependencies:
@ -4088,6 +4045,10 @@ packages:
node: '>=0.8.0'
resolution:
integrity: sha1-bfwP+dAQAKLt8oZTccrDFulJd68=
/diff-match-patch/1.0.4:
dev: false
resolution:
integrity: sha512-Uv3SW8bmH9nAtHKaKSanOQmj2DnlH65fUpcrMdfdaOxUG02QQ4YGZ8AE7kKOMisF7UqvOlGKVYWRvezdncW9lg==
/diff/3.5.0:
dev: false
engines:
@ -7216,21 +7177,6 @@ packages:
marked: ^0.4.0 || ^0.5.0 || ^0.6.0
resolution:
integrity: sha512-Yr1yVS0BbDG55vx7be1D0mdv+jGs9AW563o/Tt/7FTsId2J0yqhrTeXAqq/Q0DyyXltIn6CSxzesQuFqXgafjQ==
/marked-terminal/3.2.0/marked@0.6.0:
dependencies:
ansi-escapes: 3.2.0
cardinal: 2.1.1
chalk: 2.4.2
cli-table: 0.3.1
marked: 0.6.0
node-emoji: 1.8.1
supports-hyperlinks: 1.0.1
dev: false
id: registry.npmjs.org/marked-terminal/3.2.0
peerDependencies:
marked: ^0.4.0 || ^0.5.0 || ^0.6.0
resolution:
integrity: sha512-Yr1yVS0BbDG55vx7be1D0mdv+jGs9AW563o/Tt/7FTsId2J0yqhrTeXAqq/Q0DyyXltIn6CSxzesQuFqXgafjQ==
/marked/0.6.0:
dev: false
engines:
@ -7853,18 +7799,10 @@ packages:
react-dom: '>=16.3.2-0 <17.0.0'
resolution:
integrity: sha512-FbDUIfiy+X9+rYg4r2FWWem2Y9bdiqYDHv+qRY9kW5FYA30mb4VjlByLnJZnm4erKm0i/RCLUWJ5+TP88PgdeA==
/office-ui-fabric-react/6.133.0/react-dom@16.7.0+react@16.7.0:
/office-ui-fabric-react/6.133.0/react-dom@16.7.0:
dependencies:
'@microsoft/load-themed-styles': 1.8.56
'@uifabric/icons': 6.3.0
'@uifabric/merge-styles': 6.15.2
'@uifabric/set-version': 1.1.3
'@uifabric/styling': 6.41.0
'@uifabric/utilities': /@uifabric/utilities/6.29.0/react-dom@16.7.0+react@16.7.0
prop-types: 15.6.2
react: 16.7.0
react-dom: /react-dom/16.7.0/react@16.7.0
tslib: 1.9.3
'@uifabric/utilities': /@uifabric/utilities/6.29.0/react-dom@16.7.0
react-dom: 16.7.0
dev: false
id: registry.npmjs.org/office-ui-fabric-react/6.133.0
peerDependencies:
@ -8883,7 +8821,6 @@ packages:
loose-envify: 1.4.0
object-assign: 4.1.1
prop-types: 15.6.2
react: 16.7.0
scheduler: 0.12.0
dev: false
id: registry.npmjs.org/react-dom/16.7.0
@ -10360,7 +10297,6 @@ packages:
loader-utils: 1.2.3
micromatch: 3.1.10
semver: 5.6.0
typescript: 3.3.3
dev: false
engines:
node: '>=6.11.5'
@ -10761,7 +10697,6 @@ packages:
loader-utils: 1.2.3
supports-color: 5.5.0
v8-compile-cache: 2.0.2
webpack: 4.29.5
yargs: 12.0.5
dev: false
engines:
@ -11037,10 +10972,10 @@ packages:
'@types/yargs': 12.0.1
fs-extra: 7.0.1
prompts: 2.0.1
ts-loader: /ts-loader/5.3.3/typescript@3.3.3
ts-loader: 5.3.3
typescript: 3.3.3
webpack: 4.29.5
webpack-cli: /webpack-cli/3.2.1/webpack@4.29.5
webpack-cli: 3.2.1
yargs: 12.0.5
dev: false
name: '@rush-temp/create-just'
@ -11054,7 +10989,7 @@ packages:
dev: false
name: '@rush-temp/example-lib'
resolution:
integrity: sha512-Z8ADj+DpjglEG4REQHlAoy6KevG1sADdXSDbru28DRIwd7U52mMk8V//pFdhWZuqWNPHRVRKfY+xQj4XWc85Ww==
integrity: sha512-3+xq8HskaGhtHvn+ieW0N5bCRF3XHKJXZabeOaNRPP8fv3G6sJI51ABe2f6rRwZrDDVojSITvf8iOVjTcORn0w==
tarball: 'file:projects/example-lib.tgz'
version: 0.0.0
'file:projects/just-scenario-tests.tgz':
@ -11068,7 +11003,7 @@ packages:
dev: false
name: '@rush-temp/just-scenario-tests'
resolution:
integrity: sha512-+jnl5KqgUuNsO6XxGjGq5Yg5Os2KYnKRFe4/sbB7L5VQ1CnY7AouYJAvFBihiHffEYagTZhe2lgt9hYyz2oDXg==
integrity: sha512-i2bUzP5lM/WyZN/bvxIEA7r16K5KYzzpam3MBFl+WT7HMwRzWandTPEmHPYLynBE2egTbGT8ApR+SBbBgEYULQ==
tarball: 'file:projects/just-scenario-tests.tgz'
version: 0.0.0
'file:projects/just-scripts-utils.tgz':
@ -11092,11 +11027,11 @@ packages:
jest: 23.6.0
jju: 1.4.0
marked: 0.6.0
marked-terminal: /marked-terminal/3.2.0/marked@0.6.0
marked-terminal: 3.2.0
mock-fs: 4.8.0
semver: 5.6.0
tar: 4.4.8
ts-jest: /ts-jest/23.10.5/jest@23.6.0
ts-jest: 23.10.5
typescript: 3.3.3
yargs: 12.0.5
dev: false
@ -11107,6 +11042,7 @@ packages:
version: 0.0.0
'file:projects/just-scripts.tgz':
dependencies:
'@types/diff-match-patch': 1.0.32
'@types/fs-extra': 5.0.4
'@types/glob': 7.1.1
'@types/jest': 23.3.13
@ -11115,6 +11051,7 @@ packages:
'@types/run-parallel-limit': 1.0.0
'@types/webpack-merge': 4.1.3
chalk: 2.4.2
diff-match-patch: 1.0.4
fs-extra: 7.0.1
glob: 7.1.3
jest: 23.6.0
@ -11130,7 +11067,7 @@ packages:
dev: false
name: '@rush-temp/just-scripts'
resolution:
integrity: sha512-GGkkXH5ycwPhNovTUsVpLqQu21Np5fSzkpvjsRe27GOZgjwGVxOLLMGUDUMwv2MhTYNv2749SjPuWEcTVF44uQ==
integrity: sha512-kXJflYofr4yzOi3coCQ6agNDD3NmjE95Sw70/HLpYbeNLewuCSlaPzqwKqWg3CvodfM76Mvk1SMSnHOU0GgyJw==
tarball: 'file:projects/just-scripts.tgz'
version: 0.0.0
'file:projects/just-stack-monorepo.tgz':
@ -11175,20 +11112,20 @@ packages:
'file:projects/just-task-docs.tgz':
dependencies:
'@babel/core': 7.2.2
'@babel/plugin-proposal-class-properties': /@babel/plugin-proposal-class-properties/7.3.0/@babel!core@7.2.2
'@babel/plugin-proposal-object-rest-spread': /@babel/plugin-proposal-object-rest-spread/7.3.2/@babel!core@7.2.2
'@babel/plugin-proposal-class-properties': 7.3.0
'@babel/plugin-proposal-object-rest-spread': 7.3.2
'@babel/polyfill': 7.2.5
'@babel/preset-env': /@babel/preset-env/7.3.1/@babel!core@7.2.2
'@babel/preset-react': /@babel/preset-react/7.0.0/@babel!core@7.2.2
'@babel/register': /@babel/register/7.0.0/@babel!core@7.2.2
'@babel/preset-env': 7.3.1
'@babel/preset-react': 7.0.0
'@babel/register': 7.0.0
'@babel/traverse': 7.2.3
'@babel/types': 7.3.2
'@uifabric/experiments': /@uifabric/experiments/6.54.2/react-dom@16.7.0+react@16.7.0
'@uifabric/experiments': /@uifabric/experiments/6.54.2/react-dom@16.7.0
cpx: 1.5.0
docusaurus: 1.7.2
office-ui-fabric-react: /office-ui-fabric-react/6.133.0/react-dom@16.7.0+react@16.7.0
office-ui-fabric-react: /office-ui-fabric-react/6.133.0/react-dom@16.7.0
react: 16.7.0
react-dom: /react-dom/16.7.0/react@16.7.0
react-dom: 16.7.0
dev: false
name: '@rush-temp/just-task-docs'
resolution:
@ -11203,7 +11140,7 @@ packages:
chalk: 2.4.2
jest: 23.6.0
mock-fs: 4.8.0
ts-jest: /ts-jest/23.10.5/jest@23.6.0
ts-jest: 23.10.5
yargs: 12.0.5
dev: false
name: '@rush-temp/just-task-logger'
@ -11234,7 +11171,7 @@ packages:
jest: 23.6.0
mock-fs: 4.8.0
resolve: 1.10.0
ts-jest: /ts-jest/23.10.5/jest@23.6.0
ts-jest: 23.10.5
typescript: 3.3.3
undertaker: 1.2.0
undertaker-registry: 1.0.1
@ -11270,6 +11207,7 @@ specifiers:
'@rush-temp/just-task-docs': 'file:./projects/just-task-docs.tgz'
'@rush-temp/just-task-logger': 'file:./projects/just-task-logger.tgz'
'@rush-temp/just-task-scripts': 'file:./projects/just-task-scripts.tgz'
'@types/diff-match-patch': 1.0.32
'@types/glob': ^7.1.1
'@types/handlebars': ^4.0.39
'@types/jest': ^23.3.13
@ -11290,6 +11228,7 @@ specifiers:
'@uifabric/experiments': ^6.41.0
chalk: ^2.4.1
cpx: ^1.5.0
diff-match-patch: 1.0.4
docusaurus: ^1.5.1
fs-extra: ^7.0.1
glob: ^7.1.3

Просмотреть файл

@ -39,13 +39,13 @@ export async function downloadPackage(
pkg: string,
version: string = 'latest'
): Promise<string | null> {
if (_isDevMode(pkg)) {
return path.join(dirname || __dirname, '../..', pkg, 'template');
if (_isDevMode(pkg) && version === 'latest') {
return path.join(dirname || __dirname, '../../', pkg, 'template');
}
const npmCmd = os.platform() === 'win32' ? 'npm.cmd' : 'npm';
const pkgPath = paths.tempPath(pkg);
const pkgPath = paths.tempPath(pkg, version);
if (fse.existsSync(pkgPath)) {
fse.removeSync(pkgPath);

Просмотреть файл

@ -7,6 +7,7 @@ export interface PackageJson {
description?: string;
dependencies?: Dependencies;
devDependencies?: Dependencies;
keywords?: string;
just?: {
/** Stack that the package is tracking */
stack?: string;

Просмотреть файл

@ -13,6 +13,7 @@
"dependencies": {
"@types/node": "^10.12.18",
"chalk": "^2.4.1",
"diff-match-patch": "1.0.4",
"fs-extra": "^7.0.1",
"glob": "^7.1.3",
"just-scripts-utils": ">=0.6.1 <1.0.0",
@ -23,6 +24,7 @@
"webpack-merge": "^4.2.1"
},
"devDependencies": {
"@types/diff-match-patch": "1.0.32",
"@types/fs-extra": "^5.0.4",
"@types/glob": "^7.1.1",
"@types/jest": "^23.3.13",

Просмотреть файл

@ -0,0 +1,7 @@
import { patch_obj } from 'diff-match-patch';
export interface DiffInfo {
patches: { [filename: string]: patch_obj[] };
fromVersion: string;
toVersion: string;
}

Просмотреть файл

@ -0,0 +1,28 @@
import { DiffInfo } from './DiffInfo';
import { diff_match_patch as DiffMatchPatch } from 'diff-match-patch';
import glob from 'glob';
import fs from 'fs';
import path from 'path';
import { logger } from 'just-task';
export function applyStackDiffs(rootPath: string, projectPath: string, diffInfo: DiffInfo) {
const dmp = new DiffMatchPatch();
const globbedFiles = glob.sync('**/*', {
cwd: path.join(rootPath, projectPath),
ignore: 'node_modules/**/*',
nodir: true,
dot: true
});
globbedFiles.forEach(file => {
const filePath = path.join(rootPath, projectPath, file);
if (diffInfo.patches[file]) {
logger.info(`Patching ${file}`);
const content = fs.readFileSync(filePath).toString();
const [newContent] = dmp.patch_apply(diffInfo.patches[file], content);
fs.writeFileSync(filePath, newContent);
}
});
}

Просмотреть файл

@ -1,8 +1,7 @@
import path from 'path';
import fse from 'fs-extra';
import { ScriptsPackageJson } from './ScriptsPackageJson';
import { StackInfo } from './StackInfo';
import { readPackageJson } from 'just-scripts-utils';
import { getAvailableStacks } from '../stack/getAvailableStacks';
// Fetch templates for installation - fetches templates for project generation
// - looks at scripts/package.json just.stacks
@ -10,23 +9,19 @@ import { readPackageJson } from 'just-scripts-utils';
export function findInstalledStacks(rootPath: string) {
const scriptsPath = path.join(rootPath, 'scripts');
const packageJson: ScriptsPackageJson = readPackageJson(scriptsPath)!;
const stacks = Object.keys(getAvailableStacks(rootPath))
.filter(stack => stack.includes('monorepo'))
.map(stack => [stack, path.join(scriptsPath, 'node_modules', stack)]);
if (packageJson && packageJson.just && packageJson.just.stacks) {
const stacks = packageJson.just.stacks
.map(stack => [stack, path.join(scriptsPath, 'node_modules', stack)])
.filter(([, stackPath]) => fse.existsSync(stackPath));
return stacks.map<StackInfo>(([stack, stackPath]) => {
const packageJson = readPackageJson(stackPath)!; // already checked existence above
return {
description: packageJson.description!,
name: stack,
version: packageJson.version,
path: stackPath
};
});
}
return stacks.map<StackInfo>(([stack, stackPath]) => {
const packageJson = readPackageJson(stackPath)!; // already checked existence above
return {
description: packageJson.description!,
name: stack,
version: packageJson.version,
path: stackPath
};
});
return [];
}

Просмотреть файл

@ -1,44 +0,0 @@
import { findInstalledStacks } from './findInstalledStacks';
import path from 'path';
import { spawn } from 'child_process';
export interface OutdatedInfo {
name: string;
current: string;
wanted: string;
latest: string;
location: string;
}
export async function getOutdatedStacks(rootPath: string) {
const scriptsPath = path.join(rootPath, 'scripts');
const installedStacks = findInstalledStacks(rootPath);
const outdatedJson: any = await new Promise((resolve, reject) => {
const cp = spawn('npm', ['outdated', '--json'], { cwd: scriptsPath, stdio: 'pipe' });
let outdatedJsonStr = '';
cp.stdout.on('data', data => {
outdatedJsonStr += data.toString();
});
cp.on('exit', () => {
resolve(JSON.parse(outdatedJsonStr));
});
});
const outdatedStacks: OutdatedInfo[] = [];
Object.keys(outdatedJson).forEach(name => {
const outdated = outdatedJson[name];
const stack = installedStacks.find(stack => stack.name === name);
if (stack) {
if (outdated.current !== outdated.wanted) {
outdatedStacks.push({ ...outdated, name });
}
}
});
return outdatedStacks;
}

Просмотреть файл

@ -0,0 +1,54 @@
import fs from 'fs-extra';
import glob from 'glob';
import { downloadPackage } from 'just-scripts-utils';
import path from 'path';
import { DiffInfo } from './DiffInfo';
import { diff_match_patch as DiffMatchPatch, patch_obj as Patch, Diff } from 'diff-match-patch';
export async function getStackDiffs(
stack: string,
fromVersion: string,
toVersion: string
): Promise<DiffInfo> {
const packagePaths = await Promise.all([
downloadPackage(stack, fromVersion),
downloadPackage(stack, toVersion)
]);
// Concentrates on new and modified files only
const diffInfo: DiffInfo = {
patches: {},
fromVersion,
toVersion
};
const fromPath = packagePaths[0]!;
const toPath = packagePaths[1]!;
const globbedFiles = glob.sync('**/*', { cwd: toPath, nodir: true, dot: true });
const dmp = new DiffMatchPatch();
globbedFiles.forEach(file => {
const toFile = path.join(toPath, file);
const toContent = fs.readFileSync(toFile).toString();
const fromFile = path.join(fromPath, file);
let diffs: Diff[];
let patches: Patch[];
if (fs.existsSync(fromFile)) {
const fromContent = fs.readFileSync(fromFile).toString();
diffs = dmp.diff_main(fromContent, toContent);
patches = dmp.patch_make(fromContent, toContent, diffs);
} else {
diffs = dmp.diff_main('', toContent);
patches = dmp.patch_make('', toContent, diffs);
}
if (patches && patches.length > 0) {
diffInfo.patches[file.replace('.hbs', '')] = patches;
}
});
return diffInfo;
}

Просмотреть файл

@ -0,0 +1,27 @@
import path from 'path';
import { readPackageJson } from 'just-scripts-utils';
export function getAvailableStacks(rootPath: string) {
const scriptsPath = path.join(rootPath, 'scripts');
const packageJson = readPackageJson(path.join(rootPath, 'scripts'));
if (!packageJson) {
throw new Error(`not able to read package.json from ${scriptsPath}`);
}
let stackDeps: { [key: string]: string } = {};
const devDeps = packageJson.devDependencies || {};
Object.keys(devDeps).forEach(dep => {
const depPackageJson = readPackageJson(dep)!;
if (
dep.includes('just-stack') ||
(depPackageJson.keywords && depPackageJson.keywords.includes('just-stack'))
) {
stackDeps[dep] = devDeps[dep];
}
});
return stackDeps;
}

Просмотреть файл

@ -0,0 +1,20 @@
import { getAvailableStacks } from './getAvailableStacks';
import path from 'path';
import fs from 'fs';
export function writeLockFile(rootPath: string) {
const stacks = getAvailableStacks(rootPath);
const lockFile = path.join(rootPath, 'scripts', 'just-stacks.json');
fs.writeFileSync(lockFile, JSON.stringify({ stacks }, null, 2));
}
export function readLockFile(rootPath: string) {
const lockFile = path.join(rootPath, 'scripts', 'just-stacks.json');
if (!fs.existsSync(lockFile)) {
return null;
}
const lockFileObject = JSON.parse(fs.readFileSync(lockFile).toString());
return lockFileObject && lockFileObject.stacks ? lockFileObject.stacks : null;
}

Просмотреть файл

@ -1,5 +1,5 @@
import { task, series, parallel } from 'just-task';
import { cleanTask, tscTask, jestTask, upgradeStackTask } from '../tasks';
import { cleanTask, tscTask, jestTask } from '../tasks';
export function lib() {
task('clean', cleanTask());
@ -16,6 +16,4 @@ export function lib() {
task('test', series('clean', 'jest'));
task('start', series('clean', 'ts:watch'));
task('start-test', series('clean', 'jest:watch'));
task('upgrade-stack', upgradeStackTask());
}

Просмотреть файл

@ -6,5 +6,9 @@ export function monorepo() {
option('name');
option('latest');
task('add-package', 'adds a package to the monorepo', addPackageTask);
task('upgrade-repo', 'upgrades packages inside the monorepo according to the just-stack template', upgradeRepoTask);
task(
'upgrade-repo',
'upgrades packages inside the monorepo according to the just-stack template',
upgradeRepoTask
);
}

Просмотреть файл

@ -1,12 +1,5 @@
import { task, series, parallel } from 'just-task';
import {
cleanTask,
tscTask,
jestTask,
webpackTask,
upgradeStackTask,
webpackDevServerTask
} from '../tasks';
import { cleanTask, tscTask, jestTask, webpackTask, webpackDevServerTask } from '../tasks';
export function webapp() {
task('clean', cleanTask());
@ -26,6 +19,4 @@ export function webapp() {
task('test', series('clean', 'jest'));
task('start', series('clean', 'webpack:watch'));
task('start-test', series('clean', 'jest:watch'));
task('upgrade-stack', upgradeStackTask());
}

Просмотреть файл

@ -46,6 +46,11 @@ export function addPackageTask(): TaskFunction {
const selectedStack = installedStacks.find(stack => stack.name === response.stack)!;
if (!selectedStack) {
logger.warn('Cannot add package if no stack is selected');
return;
}
const packagePath = path.join(rootPath, 'packages', name);
const templatePath = path.join(selectedStack.path, 'template');

Просмотреть файл

@ -8,4 +8,3 @@ export * from './webpackTask';
export * from './apiExtractorTask';
export * from './addPackageTask';
export * from './upgradeRepoTask';
export * from './upgradeStackTask';

Просмотреть файл

@ -1,15 +1,11 @@
import fse from 'fs-extra';
import { findMonoRepoRootPath, readRushJson, readPackageJson, logger } from 'just-scripts-utils';
import path from 'path';
import { upgradeStackPackageJsonFile } from './upgradeStackTask';
import {
findMonoRepoRootPath,
rushUpdate,
readRushJson,
readPackageJson,
logger
} from 'just-scripts-utils';
import { getOutdatedStacks } from '../monorepo/getOutdatedStacks';
import { argv, TaskFunction } from 'just-task';
import { TaskFunction } from 'just-task';
import { getAvailableStacks } from '../stack/getAvailableStacks';
import { readLockFile, writeLockFile } from '../stack/lockfile';
import { getStackDiffs } from '../monorepo/getStackDiffs';
import { DiffInfo } from '../monorepo/DiffInfo';
import { applyStackDiffs } from '../monorepo/applyStackDiffs';
export function upgradeRepoTask(): TaskFunction {
return async function upgradeRepo() {
@ -19,44 +15,75 @@ export function upgradeRepoTask(): TaskFunction {
return;
}
const scriptsPath = path.join(rootPath, 'scripts');
const scriptsPackageJsonPath = path.join(scriptsPath, 'package.json');
const scriptsPackageJson = readPackageJson(scriptsPath);
if (!scriptsPackageJson) {
logger.error(`Could not read ${scriptsPackageJsonPath}. Not upgrading anything.`);
return;
}
const oldStacks = readLockFile(rootPath);
const rushConfig = readRushJson(rootPath);
if (!rushConfig) {
logger.error(`Could not read rush.json under ${rootPath}. Not upgrading anything.`);
return;
}
if (oldStacks) {
let didUpgradeProjects = false;
process.chdir(rootPath);
const outdatedStacks = await getOutdatedStacks(rootPath);
const latest = argv().latest;
// First, gather all the stack diffs
const newStacks = getAvailableStacks(rootPath);
const stackDiffs: { [stack: string]: DiffInfo } = {};
outdatedStacks.forEach(stack => {
const { dependencies = {}, devDependencies = {} } = scriptsPackageJson;
if (devDependencies[stack.name]) {
devDependencies[stack.name] = latest ? `^${stack.latest}` : `^${stack.wanted}`;
} else if (dependencies[stack.name]) {
dependencies[stack.name] = latest ? `^${stack.latest}` : `^${stack.wanted}`;
try {
await Object.keys(oldStacks).reduce(async (currentPromise, stack) => {
await currentPromise;
if (oldStacks[stack] !== newStacks[stack]) {
stackDiffs[stack] = await getStackDiffs(stack, oldStacks[stack], newStacks[stack]);
}
}, Promise.resolve());
} catch (e) {
logger.error('Cannot figure out upgrades needed for the packages in this repo: ', e);
return;
}
});
fse.writeJsonSync(scriptsPackageJsonPath, scriptsPackageJson, { spaces: 2 });
// Second, for each package, look for stacks that match
const rushConfig = readRushJson(rootPath);
if (!rushConfig) {
logger.error(`Could not read rush.json under ${rootPath}. Not upgrading anything.`);
return;
}
rushUpdate(rootPath);
await rushConfig.projects.reduce(async (currentPromise, project) => {
await currentPromise;
let promise = Promise.resolve();
for (const project of rushConfig.projects) {
const projectPath = path.join(rootPath, project.projectFolder);
promise = promise.then(() =>
upgradeStackPackageJsonFile(projectPath, path.join(scriptsPath, 'node_modules'))
);
if (project.projectFolder !== 'scripts') {
const projPackageJson = readPackageJson(path.join(rootPath, project.projectFolder));
if (projPackageJson && projPackageJson.just && projPackageJson.just.stack) {
const diffInfo = stackDiffs[projPackageJson.just.stack];
// no diff info means that there isn't any diffs to apply
if (diffInfo) {
logger.info(
`Upgrading ${project.packageName} from ${projPackageJson.just.stack} v${
diffInfo.fromVersion
} to v${diffInfo.toVersion}`
);
applyStackDiffs(
rootPath,
project.projectFolder,
stackDiffs[projPackageJson.just.stack]
);
didUpgradeProjects = true;
}
}
}
}, Promise.resolve());
if (didUpgradeProjects) {
logger.info(
'Upgrade repo task has finished its work. You might notice some conflicts to be resolved by hand.'
);
logger.info(
'You might also have to perform a `rush update` manually if package.json has been modified by the upgrade'
);
}
}
return promise;
logger.info('Writing just-stacks.json. Please check this file in!');
writeLockFile(rootPath);
};
}

Просмотреть файл

@ -1,83 +0,0 @@
import fse from 'fs-extra';
import path from 'path';
import chalk from 'chalk';
import { logger, TaskFunction } from 'just-task';
import {
paths,
downloadPackage,
applyTemplate,
mergePackageJson,
readPackageJson,
PackageJson
} from 'just-scripts-utils';
export function upgradeStackTask(): TaskFunction {
const { projectPath } = paths;
return function upgradeStack() {
upgradeStackPackageJsonFile(projectPath);
};
}
/**
* Updates the project according to the stack that is specified in the just.stack key in package.json
* - if the templateInstallationPath is provided, use the installed template at that path
* - otherwise, will download the latest and use that to update deps
*
* @param projectPath
* @param templateInstallationPath
*/
export async function upgradeStackPackageJsonFile(
projectPath: string,
templateInstallationPath?: string
): Promise<void> {
const packageJson = readPackageJson(projectPath);
if (packageJson && packageJson.just && packageJson.just.stack) {
const stack = packageJson.just.stack;
let stackPath: string | null = null;
if (!templateInstallationPath) {
stackPath = await downloadPackage(stack);
} else {
stackPath = path.join(templateInstallationPath, stack, 'template');
}
if (stackPath) {
upgradePackageDeps(stackPath, projectPath, packageJson);
} else {
logger.error(`Cannot read or retrieve the stack package.json for ${stack}`);
}
} else if (packageJson) {
logger.info(
`Package ${chalk.cyan(packageJson.name)} does not have a "just" key. Skipping upgrade.`
);
} else {
logger.info(`package.json not found under ${chalk.cyan(projectPath)}. Skipping upgrade.`);
}
}
/**
* Takes the installed or newly downloaded template and merge in the new package deps
*/
function upgradePackageDeps(stackPath: string, projectPath: string, packageJson: PackageJson) {
const templatePath = paths.tempPath(packageJson.name);
applyTemplate(stackPath, templatePath, { name: packageJson.name });
// Update package.json deps
const stackPackageJson = readPackageJson(templatePath);
if (!stackPackageJson) {
logger.error(`Cannot find or read stack's package.json under ${stackPath}`);
return;
}
const newPackageJson = mergePackageJson(packageJson, stackPackageJson);
// If modified, the reference would be different
logger.info(`Checking if package ${packageJson.name} should be upgraded...`);
if (newPackageJson !== packageJson) {
logger.info(`Package ${chalk.cyan(packageJson.name)} is being upgraded.`);
fse.writeJsonSync(path.join(projectPath, 'package.json'), newPackageJson, { spaces: 2 });
} else {
logger.info(`Package ${chalk.cyan(packageJson.name)} upgrade not needed.`);
}
}

Просмотреть файл

@ -1,5 +1,5 @@
module.exports = {
printWidth: 100,
printWidth: 140,
tabWidth: 2,
singleQuote: true
};