From 0da5877726cccbabd8fe6686ae31aa9517d818a6 Mon Sep 17 00:00:00 2001 From: sebastien Date: Sat, 24 Feb 2024 19:51:34 +0100 Subject: [PATCH] Optimize synchronous getFileCommitDate code --- .../src/__tests__/index.test.ts | 2 +- .../src/blogUtils.ts | 3 +- .../src/lastUpdate.ts | 3 +- .../src/__tests__/gitUtils.test.ts | 40 ++++++++++--------- packages/docusaurus-utils/src/gitUtils.ts | 40 +++++++++++++------ 5 files changed, 54 insertions(+), 34 deletions(-) diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/index.test.ts b/packages/docusaurus-plugin-content-blog/src/__tests__/index.test.ts index 0c922aea8675..7ffb8862518d 100644 --- a/packages/docusaurus-plugin-content-blog/src/__tests__/index.test.ts +++ b/packages/docusaurus-plugin-content-blog/src/__tests__/index.test.ts @@ -437,7 +437,7 @@ describe('blog plugin', () => { const noDateSource = path.posix.join('@site', PluginPath, 'no date.md'); const noDateSourceFile = path.posix.join(siteDir, PluginPath, 'no date.md'); // We know the file exists and we know we have git - const result = getFileCommitDate(noDateSourceFile, {age: 'oldest'}); + const result = await getFileCommitDate(noDateSourceFile, {age: 'oldest'}); const noDateSourceTime = result.date; expect({ diff --git a/packages/docusaurus-plugin-content-blog/src/blogUtils.ts b/packages/docusaurus-plugin-content-blog/src/blogUtils.ts index 82494a641cee..e0c6de3b06fc 100644 --- a/packages/docusaurus-plugin-content-blog/src/blogUtils.ts +++ b/packages/docusaurus-plugin-content-blog/src/blogUtils.ts @@ -258,10 +258,11 @@ async function processBlogSourceFile( } try { - const result = getFileCommitDate(blogSourceAbsolute, { + const result = await getFileCommitDate(blogSourceAbsolute, { age: 'oldest', includeAuthor: false, }); + return result.date; } catch (err) { logger.warn(err); diff --git a/packages/docusaurus-plugin-content-docs/src/lastUpdate.ts b/packages/docusaurus-plugin-content-docs/src/lastUpdate.ts index 110dff5ab7a1..2a0fefd5b6fa 100644 --- a/packages/docusaurus-plugin-content-docs/src/lastUpdate.ts +++ b/packages/docusaurus-plugin-content-docs/src/lastUpdate.ts @@ -25,10 +25,11 @@ export async function getFileLastUpdate( // Wrap in try/catch in case the shell commands fail // (e.g. project doesn't use Git, etc). try { - const result = getFileCommitDate(filePath, { + const result = await getFileCommitDate(filePath, { age: 'newest', includeAuthor: true, }); + return {timestamp: result.timestamp, author: result.author}; } catch (err) { if (err instanceof GitNotFoundError) { diff --git a/packages/docusaurus-utils/src/__tests__/gitUtils.test.ts b/packages/docusaurus-utils/src/__tests__/gitUtils.test.ts index 914b795445f4..f99d3ea3df55 100644 --- a/packages/docusaurus-utils/src/__tests__/gitUtils.test.ts +++ b/packages/docusaurus-utils/src/__tests__/gitUtils.test.ts @@ -47,88 +47,92 @@ function initializeTempRepo() { describe('getFileCommitDate', () => { const repoDir = initializeTempRepo(); it('returns earliest commit date', async () => { - expect(getFileCommitDate(path.join(repoDir, 'test.txt'), {})).toEqual({ + await expect( + getFileCommitDate(path.join(repoDir, 'test.txt'), {}), + ).resolves.toEqual({ date: new Date('2020-06-19'), timestamp: new Date('2020-06-19').getTime() / 1000, }); - expect(getFileCommitDate(path.join(repoDir, 'dest.txt'), {})).toEqual({ + await expect( + getFileCommitDate(path.join(repoDir, 'dest.txt'), {}), + ).resolves.toEqual({ date: new Date('2020-09-13'), timestamp: new Date('2020-09-13').getTime() / 1000, }); }); it('returns latest commit date', async () => { - expect( + await expect( getFileCommitDate(path.join(repoDir, 'test.txt'), {age: 'newest'}), - ).toEqual({ + ).resolves.toEqual({ date: new Date('2020-09-13'), timestamp: new Date('2020-09-13').getTime() / 1000, }); - expect( + await expect( getFileCommitDate(path.join(repoDir, 'dest.txt'), {age: 'newest'}), - ).toEqual({ + ).resolves.toEqual({ date: new Date('2020-11-13'), timestamp: new Date('2020-11-13').getTime() / 1000, }); }); it('returns latest commit date with author', async () => { - expect( + await expect( getFileCommitDate(path.join(repoDir, 'test.txt'), { age: 'oldest', includeAuthor: true, }), - ).toEqual({ + ).resolves.toEqual({ date: new Date('2020-06-19'), timestamp: new Date('2020-06-19').getTime() / 1000, author: 'Caroline', }); - expect( + await expect( getFileCommitDate(path.join(repoDir, 'dest.txt'), { age: 'oldest', includeAuthor: true, }), - ).toEqual({ + ).resolves.toEqual({ date: new Date('2020-09-13'), timestamp: new Date('2020-09-13').getTime() / 1000, author: 'Caroline', }); }); it('returns earliest commit date with author', async () => { - expect( + await expect( getFileCommitDate(path.join(repoDir, 'test.txt'), { age: 'newest', includeAuthor: true, }), - ).toEqual({ + ).resolves.toEqual({ date: new Date('2020-09-13'), timestamp: new Date('2020-09-13').getTime() / 1000, author: 'Caroline', }); - expect( + await expect( getFileCommitDate(path.join(repoDir, 'dest.txt'), { age: 'newest', includeAuthor: true, }), - ).toEqual({ + ).resolves.toEqual({ date: new Date('2020-11-13'), timestamp: new Date('2020-11-13').getTime() / 1000, author: 'Josh-Cena', }); }); it('throws custom error when file is not tracked', async () => { - expect(() => + await expect(() => getFileCommitDate(path.join(repoDir, 'untracked.txt'), { age: 'newest', includeAuthor: true, }), - ).toThrow(FileNotTrackedError); + ).rejects.toThrow(FileNotTrackedError); }); it('throws when file not found', async () => { - expect(() => + await expect(() => getFileCommitDate(path.join(repoDir, 'nonexistent.txt'), { age: 'newest', includeAuthor: true, }), - ).toThrow( + ).rejects.toThrow( /Failed to retrieve git history for ".*nonexistent.txt" because the file does not exist./, ); }); diff --git a/packages/docusaurus-utils/src/gitUtils.ts b/packages/docusaurus-utils/src/gitUtils.ts index 00e15658c9a4..807bc5c17d97 100644 --- a/packages/docusaurus-utils/src/gitUtils.ts +++ b/packages/docusaurus-utils/src/gitUtils.ts @@ -24,7 +24,7 @@ export class FileNotTrackedError extends Error {} * @throws Also throws when `git log` exited with non-zero, or when it outputs * unexpected text. */ -export function getFileCommitDate( +export async function getFileCommitDate( /** Absolute path to the file. */ file: string, args: { @@ -36,12 +36,12 @@ export function getFileCommitDate( /** Use `includeAuthor: true` to get the author information as well. */ includeAuthor?: false; }, -): { +): Promise<{ /** Relevant commit date. */ date: Date; /** Timestamp in **seconds**, as returned from git. */ timestamp: number; -}; +}>; /** * Fetches the git history of a file and returns a relevant commit date. * It gets the commit date instead of author date so that amended commits @@ -52,7 +52,7 @@ export function getFileCommitDate( * @throws Also throws when `git log` exited with non-zero, or when it outputs * unexpected text. */ -export function getFileCommitDate( +export async function getFileCommitDate( /** Absolute path to the file. */ file: string, args: { @@ -63,15 +63,16 @@ export function getFileCommitDate( age?: 'oldest' | 'newest'; includeAuthor: true; }, -): { +): Promise<{ /** Relevant commit date. */ date: Date; /** Timestamp in **seconds**, as returned from git. */ timestamp: number; /** The author's name, as returned from git. */ author: string; -}; -export function getFileCommitDate( +}>; + +export async function getFileCommitDate( file: string, { age = 'oldest', @@ -80,11 +81,11 @@ export function getFileCommitDate( age?: 'oldest' | 'newest'; includeAuthor?: boolean; }, -): { +): Promise<{ date: Date; timestamp: number; author?: string; -} { +}> { if (!shell.which('git')) { throw new GitNotFoundError( `Failed to retrieve git history for "${file}" because git is not installed.`, @@ -105,11 +106,24 @@ export function getFileCommitDate( .filter(Boolean) .join(' '); - const result = shell.exec(`git log ${args} -- "${path.basename(file)}"`, { - // Setting cwd is important, see: https://github.com/facebook/docusaurus/pull/5048 - cwd: path.dirname(file), - silent: true, + const result = await new Promise<{ + code: number; + stdout: string; + stderr: string; + }>((resolve) => { + shell.exec( + `git log ${args} -- "${path.basename(file)}"`, + { + // Setting cwd is important, see: https://github.com/facebook/docusaurus/pull/5048 + cwd: path.dirname(file), + silent: true, + }, + (code, stdout, stderr) => { + resolve({code, stdout, stderr}); + }, + ); }); + if (result.code !== 0) { throw new Error( `Failed to retrieve the git history for file "${file}" with exit code ${result.code}: ${result.stderr}`,