NitWikit/patches/@docusaurus__utils@3.5.1.patch
minimouse0 e25ca26cef ?
2024-08-13 23:22:50 +08:00

229 lines
7.8 KiB
Diff

diff --git a/@docusaurus__utils@3.5.1.patch b/@docusaurus__utils@3.5.1.patch
new file mode 100644
index 0000000000000000000000000000000000000000..5f35778fe477fa1cfca7e791c7902c70965ad609
--- /dev/null
+++ b/@docusaurus__utils@3.5.1.patch
@@ -0,0 +1,111 @@
+diff --git a/src/gitUtils.ts b/src/gitUtils.ts
+index 39a3ad754a0c5ab27cfb78c7b44a9f0be3785a62..c3116d7a725d4a5420286baac8147f4e821e5631 100755
+--- a/src/gitUtils.ts
++++ b/src/gitUtils.ts
+@@ -95,6 +95,13 @@ export async function getFileCommitDate(
+ timestamp: number;
+ author?: string;
+ }> {
++ await throwGitErrors(file);
++ const regex = retrieveCorrectRegex(includeAuthor);
++ const result = await runGitCommandOnFile(file, createArgs('', includeAuthor, age));
++ const match = matchFromRegex(file, regex, result);
++ return matchDateAndTimestamp(match, includeAuthor);
++}
++async function throwGitErrors(file: string) {
+ if (!hasGit()) {
+ throw new GitNotFoundError(
+ `Failed to retrieve git history for "${file}" because git is not installed.`,
+@@ -106,19 +113,28 @@ export async function getFileCommitDate(
+ `Failed to retrieve git history for "${file}" because the file does not exist.`,
+ );
+ }
++}
+
++function createArgs(format: string, includeAuthor?: boolean, age: 'oldest' | 'newest' = 'oldest') {
+ // We add a "RESULT:" prefix to make parsing easier
+ // See why: https://mirror.yizhan.wiki/https://github.com/facebook/docusaurus/pull/10022
+ const resultFormat = includeAuthor ? 'RESULT:%ct,%an' : 'RESULT:%ct';
+
+ const args = [
+- `--format=${resultFormat}`,
++ `--format=${includeAuthor === undefined ? format : resultFormat}`,
+ '--max-count=1',
+ age === 'oldest' ? '--follow --diff-filter=A' : undefined,
+ ]
+ .filter(Boolean)
+ .join(' ');
+
++ return args;
++}
++async function runGitCommandOnFile(file: string, args: string): Promise<{
++ code: number;
++ stdout: string;
++ stderr: string;
++}> {
+ const command = `git -c log.showSignature=false log ${args} -- "${path.basename(
+ file,
+ )}"`;
+@@ -147,12 +163,18 @@ export async function getFileCommitDate(
+ );
+ }
+
++ return result;
++}
++function retrieveCorrectRegex(includeAuthor: boolean) {
+ // We only parse the output line starting with our "RESULT:" prefix
+ // See why https://mirror.yizhan.wiki/https://github.com/facebook/docusaurus/pull/10022
+ const regex = includeAuthor
+ ? /(?:^|\n)RESULT:(?<timestamp>\d+),(?<author>.+)(?:$|\n)/
+ : /(?:^|\n)RESULT:(?<timestamp>\d+)(?:$|\n)/;
+
++ return regex;
++}
++function matchFromRegex(file: string, regex: RegExp, result: { code: number; stdout: string; stderr: string; }): RegExpMatchArray {
+ const output = result.stdout.trim();
+
+ if (!output) {
+@@ -169,6 +191,13 @@ export async function getFileCommitDate(
+ );
+ }
+
++ return match;
++}
++function matchDateAndTimestamp(match: RegExpMatchArray, includeAuthor: boolean): {
++ date: Date;
++ timestamp: number;
++ author?: string;
++} {
+ const timestampInSeconds = Number(match.groups!.timestamp);
+ const timestamp = timestampInSeconds * 1_000;
+ const date = new Date(timestamp);
+@@ -178,3 +207,29 @@ export async function getFileCommitDate(
+ }
+ return {date, timestamp};
+ }
++
++/**
++ * Fetches the git history of a file and returns a relevant commit hash.
++ *
++ * @throws {@link GitNotFoundError} If git is not found in `PATH`.
++ * @throws {@link FileNotTrackedError} If the current file is not tracked by git.
++ * @throws Also throws when `git log` exited with non-zero, or when it outputs
++ * unexpected text.
++ */
++export async function getFileCommitHash(
++ /** Absolute path to the file. */
++ file: string,
++): Promise<{
++ /** The author's commit hash, as returned from git. */
++ commit: string;
++}>;
++
++export async function getFileCommitHash(file: string): Promise<{
++ commit: string;
++}> {
++ throwGitErrors(file);
++ const result = await runGitCommandOnFile(file, createArgs('RESULT:%h', undefined, 'newest'))
++ const regex = /(?:^|\n)RESULT:(?<commit>\w+)(?:$|\n)/;
++ const match = matchFromRegex(file, regex, result);
++ return {commit: match.groups!.commit!};
++}
diff --git a/src/gitUtils.ts b/src/gitUtils.ts
index 39a3ad754a0c5ab27cfb78c7b44a9f0be3785a62..c3116d7a725d4a5420286baac8147f4e821e5631 100644
--- a/src/gitUtils.ts
+++ b/src/gitUtils.ts
@@ -95,6 +95,13 @@ export async function getFileCommitDate(
timestamp: number;
author?: string;
}> {
+ await throwGitErrors(file);
+ const regex = retrieveCorrectRegex(includeAuthor);
+ const result = await runGitCommandOnFile(file, createArgs('', includeAuthor, age));
+ const match = matchFromRegex(file, regex, result);
+ return matchDateAndTimestamp(match, includeAuthor);
+}
+async function throwGitErrors(file: string) {
if (!hasGit()) {
throw new GitNotFoundError(
`Failed to retrieve git history for "${file}" because git is not installed.`,
@@ -106,19 +113,28 @@ export async function getFileCommitDate(
`Failed to retrieve git history for "${file}" because the file does not exist.`,
);
}
+}
+function createArgs(format: string, includeAuthor?: boolean, age: 'oldest' | 'newest' = 'oldest') {
// We add a "RESULT:" prefix to make parsing easier
// See why: https://github.com/facebook/docusaurus/pull/10022
const resultFormat = includeAuthor ? 'RESULT:%ct,%an' : 'RESULT:%ct';
const args = [
- `--format=${resultFormat}`,
+ `--format=${includeAuthor === undefined ? format : resultFormat}`,
'--max-count=1',
age === 'oldest' ? '--follow --diff-filter=A' : undefined,
]
.filter(Boolean)
.join(' ');
+ return args;
+}
+async function runGitCommandOnFile(file: string, args: string): Promise<{
+ code: number;
+ stdout: string;
+ stderr: string;
+}> {
const command = `git -c log.showSignature=false log ${args} -- "${path.basename(
file,
)}"`;
@@ -147,12 +163,18 @@ export async function getFileCommitDate(
);
}
+ return result;
+}
+function retrieveCorrectRegex(includeAuthor: boolean) {
// We only parse the output line starting with our "RESULT:" prefix
// See why https://github.com/facebook/docusaurus/pull/10022
const regex = includeAuthor
? /(?:^|\n)RESULT:(?<timestamp>\d+),(?<author>.+)(?:$|\n)/
: /(?:^|\n)RESULT:(?<timestamp>\d+)(?:$|\n)/;
+ return regex;
+}
+function matchFromRegex(file: string, regex: RegExp, result: { code: number; stdout: string; stderr: string; }): RegExpMatchArray {
const output = result.stdout.trim();
if (!output) {
@@ -169,6 +191,13 @@ export async function getFileCommitDate(
);
}
+ return match;
+}
+function matchDateAndTimestamp(match: RegExpMatchArray, includeAuthor: boolean): {
+ date: Date;
+ timestamp: number;
+ author?: string;
+} {
const timestampInSeconds = Number(match.groups!.timestamp);
const timestamp = timestampInSeconds * 1_000;
const date = new Date(timestamp);
@@ -178,3 +207,29 @@ export async function getFileCommitDate(
}
return {date, timestamp};
}
+
+/**
+ * Fetches the git history of a file and returns a relevant commit hash.
+ *
+ * @throws {@link GitNotFoundError} If git is not found in `PATH`.
+ * @throws {@link FileNotTrackedError} If the current file is not tracked by git.
+ * @throws Also throws when `git log` exited with non-zero, or when it outputs
+ * unexpected text.
+ */
+export async function getFileCommitHash(
+ /** Absolute path to the file. */
+ file: string,
+): Promise<{
+ /** The author's commit hash, as returned from git. */
+ commit: string;
+}>;
+
+export async function getFileCommitHash(file: string): Promise<{
+ commit: string;
+}> {
+ throwGitErrors(file);
+ const result = await runGitCommandOnFile(file, createArgs('RESULT:%h', undefined, 'newest'))
+ const regex = /(?:^|\n)RESULT:(?<commit>\w+)(?:$|\n)/;
+ const match = matchFromRegex(file, regex, result);
+ return {commit: match.groups!.commit!};
+}