diff --git a/package.json b/package.json index 5f8d2796ba..5393ad5639 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "devDependencies": { "@babel/core": "^7.6.2", "@babel/preset-typescript": "^7.3.3", + "@types/cross-spawn": "^6.0.1", "@types/express": "^4.17.0", "@types/fs-extra": "8.0.0", "@types/inquirer": "^6.0.3", diff --git a/packages/docusaurus-plugin-content-docs/package.json b/packages/docusaurus-plugin-content-docs/package.json index d512f49b01..d10e536a06 100644 --- a/packages/docusaurus-plugin-content-docs/package.json +++ b/packages/docusaurus-plugin-content-docs/package.json @@ -16,6 +16,7 @@ "dependencies": { "@docusaurus/mdx-loader": "^2.0.0-alpha.25", "@docusaurus/utils": "^2.0.0-alpha.25", + "cross-spawn": "^7.0.1", "fs-extra": "^8.1.0", "globby": "^10.0.1", "import-fresh": "^3.1.0", diff --git a/packages/docusaurus-plugin-content-docs/src/__tests__/lastUpdate.test.ts b/packages/docusaurus-plugin-content-docs/src/__tests__/lastUpdate.test.ts index 5ca5e87328..bf088ed828 100644 --- a/packages/docusaurus-plugin-content-docs/src/__tests__/lastUpdate.test.ts +++ b/packages/docusaurus-plugin-content-docs/src/__tests__/lastUpdate.test.ts @@ -7,7 +7,6 @@ import fs from 'fs'; import path from 'path'; -import shell from 'shelljs'; import lastUpdate from '../lastUpdate'; @@ -45,43 +44,4 @@ describe('lastUpdate', () => { expect(lastUpdate(tempFilePath)).toBeNull(); fs.unlinkSync(tempFilePath); }); - - test('test renaming and moving file', () => { - const mock = jest.spyOn(shell, 'exec'); - mock - .mockImplementationOnce(() => ({ - stdout: - '1539502055, Yangshun Tay\n' + - '\n' + - ' create mode 100644 v1/lib/core/__tests__/__fixtures__/.temp2\n', - })) - .mockImplementationOnce(() => ({ - stdout: - '1539502056, Joel Marcey\n' + - '\n' + - ' rename v1/lib/core/__tests__/__fixtures__/{.temp2 => test/.temp3} (100%)\n' + - '1539502055, Yangshun Tay\n' + - '\n' + - ' create mode 100644 v1/lib/core/__tests__/__fixtures__/.temp2\n', - })); - const tempFilePath2 = path.join(__dirname, '__fixtures__', '.temp2'); - const tempFilePath3 = path.join( - __dirname, - '__fixtures__', - 'test', - '.temp3', - ); - - // Create new file. - const createData = lastUpdate(tempFilePath2); - expect(createData.timestamp).not.toBeNull(); - - // Rename/move the file. - const updateData = lastUpdate(tempFilePath3); - expect(updateData.timestamp).not.toBeNull(); - // Should only consider file content change. - expect(updateData.timestamp).toEqual(createData.timestamp); - - mock.mockRestore(); - }); }); diff --git a/packages/docusaurus-plugin-content-docs/src/lastUpdate.ts b/packages/docusaurus-plugin-content-docs/src/lastUpdate.ts index a720384b26..c1ac941e34 100644 --- a/packages/docusaurus-plugin-content-docs/src/lastUpdate.ts +++ b/packages/docusaurus-plugin-content-docs/src/lastUpdate.ts @@ -6,6 +6,7 @@ */ import shell from 'shelljs'; +import spawn from 'cross-spawn'; type FileLastUpdateData = {timestamp?: number; author?: string}; @@ -16,10 +17,6 @@ let showedGitRequirementError = false; export default function getFileLastUpdate( filePath: string, ): FileLastUpdateData | null { - function isTimestampAndAuthor(str: string): boolean { - return GIT_COMMIT_TIMESTAMP_AUTHOR_REGEX.test(str); - } - function getTimestampAndAuthor(str: string): FileLastUpdateData | null { if (!str) { return null; @@ -42,36 +39,12 @@ export default function getFileLastUpdate( return null; } - // To differentiate between content change and file renaming/moving, use --summary - // To follow the file history until before it is moved (when we create new version), use - // --follow. - const silentState = shell.config.silent; // Save old silent state. - shell.config.silent = true; - const result = shell - .exec(`git log --follow --summary --format="%ct, %an" ${filePath}`) - .stdout.trim(); - shell.config.silent = silentState; + const result = spawn + .sync('git', ['log', '-1', '--format=%ct, %an', filePath]) + .stdout.toString() + .trim(); - // Format the log results to be - // ['1234567890, Yangshun Tay', 'rename ...', '1234567880, - // 'Joel Marcey', 'move ...', '1234567870', '1234567860'] - const records = result - .replace(/\n\s*\n/g, '\n') - .split('\n') - .filter(String); - const lastContentModifierCommit = records.find((item, index, arr) => { - const currentItemIsTimestampAndAuthor = isTimestampAndAuthor(item); - const isLastTwoItem = index + 2 >= arr.length; - const nextItemIsTimestampAndAuthor = isTimestampAndAuthor(arr[index + 1]); - return ( - currentItemIsTimestampAndAuthor && - (isLastTwoItem || nextItemIsTimestampAndAuthor) - ); - }); - - return lastContentModifierCommit - ? getTimestampAndAuthor(lastContentModifierCommit) - : null; + return getTimestampAndAuthor(result); } catch (error) { console.error(error); } diff --git a/packages/docusaurus-plugin-content-docs/src/metadata.ts b/packages/docusaurus-plugin-content-docs/src/metadata.ts index bd40344d13..718d0e45ae 100644 --- a/packages/docusaurus-plugin-content-docs/src/metadata.ts +++ b/packages/docusaurus-plugin-content-docs/src/metadata.ts @@ -104,7 +104,14 @@ export default async function processMetadata({ } if (showLastUpdateAuthor || showLastUpdateTime) { - const fileLastUpdateData = lastUpdate(filePath); + // Use fake data in dev for faster development + const fileLastUpdateData = + process.env.NODE_ENV === 'production' + ? lastUpdate(filePath) + : { + author: 'Author', + timestamp: '1539502055', + }; if (fileLastUpdateData) { const {author, timestamp} = fileLastUpdateData; diff --git a/yarn.lock b/yarn.lock index 6888fdf51c..1bfe1017ad 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2355,6 +2355,13 @@ dependencies: "@types/node" "*" +"@types/cross-spawn@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/@types/cross-spawn/-/cross-spawn-6.0.1.tgz#60fa0c87046347c17d9735e5289e72b804ca9b63" + integrity sha512-MtN1pDYdI6D6QFDzy39Q+6c9rl2o/xN7aWGe6oZuzqq5N6+YuwFsWiEAv3dNzvzN9YzU+itpN8lBzFpphQKLAw== + dependencies: + "@types/node" "*" + "@types/eslint@*": version "4.16.6" resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-4.16.6.tgz#96d4ecddbea618ab0b55eaf0dffedf387129b06c" @@ -5012,6 +5019,15 @@ cross-spawn@6.0.5, cross-spawn@^6.0.0, cross-spawn@^6.0.5: shebang-command "^1.2.0" which "^1.2.9" +cross-spawn@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.1.tgz#0ab56286e0f7c24e153d04cc2aa027e43a9a5d14" + integrity sha512-u7v4o84SwFpD32Z8IIcPZ6z1/ie24O6RU3RbtL5Y316l3KuHVPx9ItBgWQ6VlfAFnRnTtMUrsQ9MUUTuEZjogg== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + crowdin-cli@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/crowdin-cli/-/crowdin-cli-0.3.0.tgz#eac9989a6fe7feaaf33090397afc187c67b46191" @@ -11705,6 +11721,11 @@ path-key@^2.0.0, path-key@^2.0.1: resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= +path-key@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.0.tgz#99a10d870a803bdd5ee6f0470e58dfcd2f9a54d3" + integrity sha512-8cChqz0RP6SHJkMt48FW0A7+qUOn+OsnOsVtzI59tZ8m+5bCSk7hzwET0pulwOM2YMn9J1efb07KB9l9f30SGg== + path-parse@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" @@ -14181,11 +14202,23 @@ shebang-command@^1.2.0: dependencies: shebang-regex "^1.0.0" +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + shebang-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + shell-quote@1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.6.1.tgz#f4781949cce402697127430ea3b3c5476f481767" @@ -16160,6 +16193,13 @@ which@1, which@^1.2.10, which@^1.2.14, which@^1.2.9, which@^1.3.0, which@^1.3.1: dependencies: isexe "^2.0.0" +which@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.1.tgz#f1cf94d07a8e571b6ff006aeb91d0300c47ef0a4" + integrity sha512-N7GBZOTswtB9lkQBZA4+zAXrjEIWAUOB93AvzUiudRzRxhUdLURQ7D/gAIMY1gatT/LTbmbcv8SiYazy3eYB7w== + dependencies: + isexe "^2.0.0" + wide-align@^1.1.0: version "1.1.3" resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457"