@docusaurus/utils
Version:
Node utility functions for Docusaurus packages.
79 lines • 3.71 kB
JavaScript
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.FileNotTrackedError = exports.GitNotFoundError = void 0;
exports.getFileCommitDate = getFileCommitDate;
const tslib_1 = require("tslib");
const path_1 = tslib_1.__importDefault(require("path"));
const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
const lodash_1 = tslib_1.__importDefault(require("lodash"));
const shelljs_1 = tslib_1.__importDefault(require("shelljs")); // TODO replace with async-first version
const realHasGitFn = () => !!shelljs_1.default.which('git');
// The hasGit call is synchronous IO so we memoize it
// The user won't install Git in the middle of a build anyway...
const hasGit = process.env.NODE_ENV === 'test' ? realHasGitFn : lodash_1.default.memoize(realHasGitFn);
/** Custom error thrown when git is not found in `PATH`. */
class GitNotFoundError extends Error {
}
exports.GitNotFoundError = GitNotFoundError;
/** Custom error thrown when the current file is not tracked by git. */
class FileNotTrackedError extends Error {
}
exports.FileNotTrackedError = FileNotTrackedError;
async function getFileCommitDate(file, { age = 'oldest', includeAuthor = false, }) {
if (!hasGit()) {
throw new GitNotFoundError(`Failed to retrieve git history for "${file}" because git is not installed.`);
}
if (!(await fs_extra_1.default.pathExists(file))) {
throw new Error(`Failed to retrieve git history for "${file}" because the file does not exist.`);
}
// 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}`,
'--max-count=1',
age === 'oldest' ? '--follow --diff-filter=A' : undefined,
]
.filter(Boolean)
.join(' ');
const command = `git -c log.showSignature=false log ${args} -- "${path_1.default.basename(file)}"`;
const result = await new Promise((resolve) => {
shelljs_1.default.exec(command, {
// Setting cwd is important, see: https://github.com/facebook/docusaurus/pull/5048
cwd: path_1.default.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}`);
}
// 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)/;
const output = result.stdout.trim();
if (!output) {
throw new FileNotTrackedError(`Failed to retrieve the git history for file "${file}" because the file is not tracked by git.`);
}
const match = output.match(regex);
if (!match) {
throw new Error(`Failed to retrieve the git history for file "${file}" with unexpected output: ${output}`);
}
const timestampInSeconds = Number(match.groups.timestamp);
const timestamp = timestampInSeconds * 1000;
const date = new Date(timestamp);
if (includeAuthor) {
return { date, timestamp, author: match.groups.author };
}
return { date, timestamp };
}
//# sourceMappingURL=gitUtils.js.map
;