Last active
May 26, 2022 19:22
-
-
Save zpao/7bbb58f2d44b553cf37581d338c826a4 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/packages/create-docusaurus/package.json b/packages/create-docusaurus/package.json | |
index 8c715fc339..5fba51f11b 100755 | |
--- a/packages/create-docusaurus/package.json | |
+++ b/packages/create-docusaurus/package.json | |
@@ -24,11 +24,11 @@ | |
"dependencies": { | |
"@docusaurus/logger": "2.0.0-beta.20", | |
"commander": "^5.1.0", | |
+ "execa": "^6.1.0", | |
"fs-extra": "^10.1.0", | |
"lodash": "^4.17.21", | |
"prompts": "^2.4.2", | |
"semver": "^7.3.7", | |
- "shelljs": "^0.8.5", | |
"supports-color": "^9.2.2", | |
"tslib": "^2.4.0" | |
}, | |
diff --git a/packages/create-docusaurus/src/index.ts b/packages/create-docusaurus/src/index.ts | |
index b35e653b0a..99f31126bd 100755 | |
--- a/packages/create-docusaurus/src/index.ts | |
+++ b/packages/create-docusaurus/src/index.ts | |
@@ -10,7 +10,7 @@ import fs from 'fs-extra'; | |
import {fileURLToPath} from 'url'; | |
import prompts, {type Choice} from 'prompts'; | |
import path from 'path'; | |
-import shell from 'shelljs'; | |
+import {execa} from 'execa'; | |
import _ from 'lodash'; | |
import supportsColor from 'supports-color'; | |
@@ -35,6 +35,24 @@ type PackageManager = keyof typeof lockfileNames; | |
const packageManagers = Object.keys(lockfileNames) as PackageManager[]; | |
+async function hasYarnInPath(): Promise<boolean> { | |
+ try { | |
+ const {exitCode} = await execa('yarn', ['--version']); | |
+ return exitCode === 0; | |
+ } catch { | |
+ return false; | |
+ } | |
+} | |
+ | |
+async function hasPnpmInPath(): Promise<boolean> { | |
+ try { | |
+ const {exitCode} = await execa('pnpm', ['--version']); | |
+ return exitCode === 0; | |
+ } catch { | |
+ return false; | |
+ } | |
+} | |
+ | |
async function findPackageManagerFromLockFile( | |
rootDir: string, | |
): Promise<PackageManager | undefined> { | |
@@ -54,8 +72,8 @@ function findPackageManagerFromUserAgent(): PackageManager | undefined { | |
} | |
async function askForPackageManagerChoice(): Promise<PackageManager> { | |
- const hasYarn = shell.exec('yarn --version', {silent: true}).code === 0; | |
- const hasPnpm = shell.exec('pnpm --version', {silent: true}).code === 0; | |
+ const hasYarn = await hasYarnInPath(); | |
+ const hasPnpm = await hasPnpmInPath(); | |
if (!hasYarn && !hasPnpm) { | |
return 'npm'; | |
@@ -464,7 +482,9 @@ export default async function init( | |
if (source.type === 'git') { | |
logger.info`Cloning Git template url=${source.url}...`; | |
const command = await getGitCommand(source.strategy); | |
- if (shell.exec(`${command} ${source.url} ${dest}`).code !== 0) { | |
+ try { | |
+ await execa(command, [source.url, dest]); | |
+ } catch { | |
logger.error`Cloning Git template failed!`; | |
process.exit(1); | |
} | |
@@ -514,26 +534,24 @@ export default async function init( | |
const cdpath = path.relative('.', dest); | |
const pkgManager = await getPackageManager(dest, cliOptions); | |
if (!cliOptions.skipInstall) { | |
- shell.cd(dest); | |
logger.info`Installing dependencies with name=${pkgManager}...`; | |
- if ( | |
- shell.exec( | |
- pkgManager === 'yarn' ? 'yarn' : `${pkgManager} install --color always`, | |
- { | |
- env: { | |
- ...process.env, | |
- // Force coloring the output, since the command is invoked by | |
- // shelljs, which is not an interactive shell | |
- ...(supportsColor.stdout ? {FORCE_COLOR: '1'} : {}), | |
- }, | |
+ try { | |
+ const args = | |
+ pkgManager === 'yarn' ? [] : ['install', '--color', 'always']; | |
+ await execa(pkgManager, args, { | |
+ cwd: dest, | |
+ env: { | |
+ // Force coloring the output, since the command is invoked by | |
+ // execa, which is not an interactive shell | |
+ ...(supportsColor.stdout ? {FORCE_COLOR: '1'} : {}), | |
}, | |
- ).code !== 0 | |
- ) { | |
+ }).stdout?.pipe(process.stdout); | |
+ } catch { | |
logger.error('Dependency installation failed.'); | |
logger.info`The site directory has already been created, and you can retry by typing: | |
- code=${`cd ${cdpath}`} | |
- code=${`${pkgManager} install`}`; | |
+ code=${`cd ${cdpath}`} | |
+ code=${`${pkgManager} install`}`; | |
process.exit(0); | |
} | |
} | |
diff --git a/packages/docusaurus-utils/package.json b/packages/docusaurus-utils/package.json | |
index cdddacda8d..d76472ea9d 100644 | |
--- a/packages/docusaurus-utils/package.json | |
+++ b/packages/docusaurus-utils/package.json | |
@@ -20,6 +20,7 @@ | |
"dependencies": { | |
"@docusaurus/logger": "2.0.0-beta.20", | |
"@svgr/webpack": "^6.2.1", | |
+ "execa": "^6.1.0", | |
"file-loader": "^6.2.0", | |
"fs-extra": "^10.1.0", | |
"github-slugger": "^1.4.0", | |
@@ -29,10 +30,10 @@ | |
"lodash": "^4.17.21", | |
"micromatch": "^4.0.5", | |
"resolve-pathname": "^3.0.0", | |
- "shelljs": "^0.8.5", | |
"tslib": "^2.4.0", | |
"url-loader": "^4.1.1", | |
- "webpack": "^5.72.1" | |
+ "webpack": "^5.72.1", | |
+ "which": "^2.0.2" | |
}, | |
"engines": { | |
"node": ">=14" | |
@@ -43,6 +44,7 @@ | |
"@types/github-slugger": "^1.3.0", | |
"@types/micromatch": "^4.0.2", | |
"@types/react-dom": "^18.0.3", | |
+ "@types/which": "^2.0.1", | |
"dedent": "^0.7.0" | |
} | |
} | |
diff --git a/packages/docusaurus-utils/src/gitUtils.ts b/packages/docusaurus-utils/src/gitUtils.ts | |
index 4d7ffde633..20a6b2a866 100644 | |
--- a/packages/docusaurus-utils/src/gitUtils.ts | |
+++ b/packages/docusaurus-utils/src/gitUtils.ts | |
@@ -6,7 +6,11 @@ | |
*/ | |
import path from 'path'; | |
-import shell from 'shelljs'; | |
+import fs from 'fs-extra'; | |
+import {execaSync} from 'execa'; | |
+import which from 'which'; | |
+ | |
+import type {ExecaSyncError} from 'execa'; | |
/** Custom error thrown when git is not found in `PATH`. */ | |
export class GitNotFoundError extends Error {} | |
@@ -85,49 +89,52 @@ export function getFileCommitDate( | |
timestamp: number; | |
author?: string; | |
} { | |
- if (!shell.which('git')) { | |
+ if (!which.sync('git', {nothrow: true})) { | |
throw new GitNotFoundError( | |
`Failed to retrieve git history for "${file}" because git is not installed.`, | |
); | |
} | |
- if (!shell.test('-f', file)) { | |
+ // eslint-disable-next-line no-restricted-properties | |
+ if (!fs.existsSync(file)) { | |
throw new Error( | |
`Failed to retrieve git history for "${file}" because the file does not exist.`, | |
); | |
} | |
+ const args = ['log', '--max-count=1']; | |
+ if (age === 'oldest') { | |
+ // --follow is necessary to follow file renames | |
+ // --diff-filter=A ensures we only get the commit which (A)dded the file | |
+ args.push(' --follow --diff-filter=A'); | |
+ } | |
+ | |
let formatArg = '--format=%ct'; | |
if (includeAuthor) { | |
formatArg += ',%an'; | |
} | |
+ args.push(formatArg); | |
- let extraArgs = '--max-count=1'; | |
- if (age === 'oldest') { | |
- // --follow is necessary to follow file renames | |
- // --diff-filter=A ensures we only get the commit which (A)dded the file | |
- extraArgs += ' --follow --diff-filter=A'; | |
- } | |
+ args.push('--', path.basename(file)); | |
- const result = shell.exec( | |
- `git log ${extraArgs} ${formatArg} -- "${path.basename(file)}"`, | |
- { | |
- // Setting cwd is important, see: https://github.com/facebook/docusaurus/pull/5048 | |
+ let result; | |
+ try { | |
+ result = execaSync('git', args, { | |
cwd: path.dirname(file), | |
- silent: true, | |
- }, | |
- ); | |
- if (result.code !== 0) { | |
+ }); | |
+ } catch (_e) { | |
+ const error = _e as ExecaSyncError; | |
throw new Error( | |
- `Failed to retrieve the git history for file "${file}" with exit code ${result.code}: ${result.stderr}`, | |
+ `Failed to retrieve the git history for file "${file}" with exit code ${error.exitCode}: ${error.stderr}`, | |
); | |
} | |
+ | |
let regex = /^(?<timestamp>\d+)$/; | |
if (includeAuthor) { | |
regex = /^(?<timestamp>\d+),(?<author>.+)$/; | |
} | |
- const output = result.stdout.trim(); | |
+ const output = result.stdout; | |
if (!output) { | |
throw new FileNotTrackedError( | |
diff --git a/yarn.lock b/yarn.lock | |
index 5374e67cd0..1ccc21ec01 100644 | |
--- a/yarn.lock | |
+++ b/yarn.lock | |
@@ -3817,6 +3817,11 @@ | |
anymatch "^3.0.0" | |
source-map "^0.6.0" | |
+"@types/which@^2.0.1": | |
+ version "2.0.1" | |
+ resolved "https://registry.yarnpkg.com/@types/which/-/which-2.0.1.tgz#27ecd67f915b7c3d6ba552135bb1eecd66e63501" | |
+ integrity sha512-Jjakcv8Roqtio6w1gr0D7y6twbhx6gGgFGF5BLwajPpnOIOxFkakFhCq+LmyyeAz7BX6ULrjBOxdKaCDy+4+dQ== | |
+ | |
"@types/ws@^8.5.1": | |
version "8.5.3" | |
resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.3.tgz#7d25a1ffbecd3c4f2d35068d0b283c037003274d" | |
@@ -7139,6 +7144,21 @@ execa@^5.0.0, execa@^5.1.1: | |
signal-exit "^3.0.3" | |
strip-final-newline "^2.0.0" | |
+execa@^6.1.0: | |
+ version "6.1.0" | |
+ resolved "https://registry.yarnpkg.com/execa/-/execa-6.1.0.tgz#cea16dee211ff011246556388effa0818394fb20" | |
+ integrity sha512-QVWlX2e50heYJcCPG0iWtf8r0xjEYfz/OYLGDYH+IyjWezzPNxz63qNFOu0l4YftGWuizFVZHHs8PrLU5p2IDA== | |
+ dependencies: | |
+ cross-spawn "^7.0.3" | |
+ get-stream "^6.0.1" | |
+ human-signals "^3.0.1" | |
+ is-stream "^3.0.0" | |
+ merge-stream "^2.0.0" | |
+ npm-run-path "^5.1.0" | |
+ onetime "^6.0.0" | |
+ signal-exit "^3.0.7" | |
+ strip-final-newline "^3.0.0" | |
+ | |
execall@^2.0.0: | |
version "2.0.0" | |
resolved "https://registry.yarnpkg.com/execall/-/execall-2.0.0.tgz#16a06b5fe5099df7d00be5d9c06eecded1663b45" | |
@@ -7787,7 +7807,7 @@ get-stream@^5.1.0: | |
dependencies: | |
pump "^3.0.0" | |
-get-stream@^6.0.0: | |
+get-stream@^6.0.0, get-stream@^6.0.1: | |
version "6.0.1" | |
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" | |
integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== | |
@@ -8525,6 +8545,11 @@ human-signals@^2.1.0: | |
resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" | |
integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== | |
+human-signals@^3.0.1: | |
+ version "3.0.1" | |
+ resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-3.0.1.tgz#c740920859dafa50e5a3222da9d3bf4bb0e5eef5" | |
+ integrity sha512-rQLskxnM/5OCldHo+wNXbpVgDn5A17CUoKX+7Sokwaknlq7CdSnphy0W39GU8dw59XiCXmFXDg4fRuckQRKewQ== | |
+ | |
humanize-ms@^1.2.1: | |
version "1.2.1" | |
resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed" | |
@@ -9093,6 +9118,11 @@ is-stream@^2.0.0: | |
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" | |
integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== | |
+is-stream@^3.0.0: | |
+ version "3.0.0" | |
+ resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-3.0.0.tgz#e6bfd7aa6bef69f4f472ce9bb681e3e57b4319ac" | |
+ integrity sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA== | |
+ | |
is-string@^1.0.5, is-string@^1.0.7: | |
version "1.0.7" | |
resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" | |
@@ -10599,6 +10629,11 @@ mimic-fn@^2.1.0: | |
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" | |
integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== | |
+mimic-fn@^4.0.0: | |
+ version "4.0.0" | |
+ resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-4.0.0.tgz#60a90550d5cb0b239cca65d893b1a53b29871ecc" | |
+ integrity sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw== | |
+ | |
mimic-response@^1.0.0, mimic-response@^1.0.1: | |
version "1.0.1" | |
resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" | |
@@ -11153,6 +11188,13 @@ npm-run-path@^4.0.1: | |
dependencies: | |
path-key "^3.0.0" | |
+npm-run-path@^5.1.0: | |
+ version "5.1.0" | |
+ resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-5.1.0.tgz#bc62f7f3f6952d9894bd08944ba011a6ee7b7e00" | |
+ integrity sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q== | |
+ dependencies: | |
+ path-key "^4.0.0" | |
+ | |
npm-to-yarn@^1.0.1: | |
version "1.0.1" | |
resolved "https://registry.yarnpkg.com/npm-to-yarn/-/npm-to-yarn-1.0.1.tgz#6cdb95114c4ff0be50a7a2381d4d16131a5f52df" | |
@@ -11325,6 +11367,13 @@ onetime@^5.1.0, onetime@^5.1.2: | |
dependencies: | |
mimic-fn "^2.1.0" | |
+onetime@^6.0.0: | |
+ version "6.0.0" | |
+ resolved "https://registry.yarnpkg.com/onetime/-/onetime-6.0.0.tgz#7c24c18ed1fd2e9bca4bd26806a33613c77d34b4" | |
+ integrity sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ== | |
+ dependencies: | |
+ mimic-fn "^4.0.0" | |
+ | |
open@^8.0.9, open@^8.4.0: | |
version "8.4.0" | |
resolved "https://registry.yarnpkg.com/open/-/open-8.4.0.tgz#345321ae18f8138f82565a910fdc6b39e8c244f8" | |
@@ -11681,6 +11730,11 @@ path-key@^3.0.0, path-key@^3.1.0: | |
resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" | |
integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== | |
+path-key@^4.0.0: | |
+ version "4.0.0" | |
+ resolved "https://registry.yarnpkg.com/path-key/-/path-key-4.0.0.tgz#295588dc3aee64154f877adb9d780b81c554bf18" | |
+ integrity sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ== | |
+ | |
path-parse@^1.0.6, path-parse@^1.0.7: | |
version "1.0.7" | |
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" | |
@@ -14297,6 +14351,11 @@ strip-final-newline@^2.0.0: | |
resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" | |
integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== | |
+strip-final-newline@^3.0.0: | |
+ version "3.0.0" | |
+ resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-3.0.0.tgz#52894c313fbff318835280aed60ff71ebf12b8fd" | |
+ integrity sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw== | |
+ | |
strip-indent@^3.0.0: | |
version "3.0.0" | |
resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment