Skip to content

Commit

Permalink
Simplify the logic around git last update
Browse files Browse the repository at this point in the history
  • Loading branch information
mburumaxwell committed Jul 11, 2024
1 parent 3b508ca commit f65ad35
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 195 deletions.
8 changes: 4 additions & 4 deletions packages/markdownlayer/src/core/generation/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { z, type ZodSchema } from 'zod';

import { version } from '../../../package.json';
import { MarkdownlayerError, MarkdownlayerErrorData, errorMap, getYAMLErrorLine } from '../errors';
import { getFileLastUpdate, type LastUpdateData } from '../git';
import { getGitFileLastUpdate, type GitFileLastUpdateResult } from '../git';
import type {
BaseDoc,
DocumentDefinition,
Expand Down Expand Up @@ -290,13 +290,13 @@ async function generateDocuments(options: GenerateDocsOptions): Promise<Generati
const { id, slug } = getDocumentIdAndSlug(file);

// only pull git info if enabled
let lastUpdate: LastUpdateData | null = null;
let lastUpdate: GitFileLastUpdateResult | null = null;
if (gitUpdatedEnabled || gitUpdatedEnabled) {
// in production mode use git, otherwise set default values
if (mode === 'production') {
lastUpdate = await getFileLastUpdate(sourceFilePath);
lastUpdate = await getGitFileLastUpdate(sourceFilePath);
}
lastUpdate ??= { date: new Date(), timestamp: 0, author: 'unknown' };
lastUpdate ??= { date: new Date(), author: 'unknown' };
}

// only calculate read time if enabled
Expand Down
95 changes: 95 additions & 0 deletions packages/markdownlayer/src/core/git.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import { execSync, type ExecException } from 'node:child_process';
import { existsSync } from 'node:fs';
import { basename, dirname } from 'node:path';

/**
* Represents the data for the last update.
*/
export interface GitFileLastUpdateResult {
/** Relevant commit date. */
date: Date;
/** The author's name, as returned from git. */
author: string;
}

export interface GitFileLastUpdateOptions {
/**
* `"oldest"` is the commit that added the file, following renames;
* `"newest"` is the last commit that edited the file.
*
* @default 'newest'
*/
age?: 'oldest' | 'newest';
}

let showedGitRequirementError = false;
let showedFileNotTrackedError = false;

/**
* 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
* can have their dates updated.
*
* @param filePath - Absolute path to the file.
* @param options - Options for the last update.
*/
export async function getGitFileLastUpdate(
filePath: string,
{ age = 'newest' }: GitFileLastUpdateOptions = {},
): Promise<GitFileLastUpdateResult | null> {
// check if git is installed
try {
execSync('git --version', { stdio: 'ignore' });
} catch (error) {
if (!showedGitRequirementError) {
// console.warn(`Failed to retrieve git history for "${filePath}" because git is not installed.`);
console.warn('Sorry, last update options for markdownlayer require Git.');
showedGitRequirementError = true;
}
return null;
}

// check if the file exists
if (!existsSync(filePath)) {
console.warn(`Failed to retrieve git history for "${filePath}" because the file does not exist.`);
return null;
}

const args = [`--format=%ct,%an`, '--max-count=1', age === 'oldest' && '--follow --diff-filter=A']
.filter(Boolean)
.join(' ');

let result: Buffer;
try {
result = execSync(`git log ${args} -- "${basename(filePath)}"`, {
// Setting cwd is important, see: https://github.com/facebook/docusaurus/pull/5048
cwd: dirname(filePath),
stdio: 'pipe', // To capture stdout and stderr
});
} catch (error) {
const err = error as ExecException;
console.warn(`Failed to retrieve the git history for file "${filePath}" with exit code ${err.code}: ${err.stderr}`);
return null;
}

const output = result.toString().trim();
if (!output) {
if (!showedFileNotTrackedError) {
// console.warn(`Failed to retrieve the git history for file "${filePath}" because the file is not tracked by git.`);
console.warn('Cannot infer the update date for some files, as they are not tracked by git.');
showedFileNotTrackedError = true;
}
return null;
}

const match = output.match(/^(?<timestamp>\d+),(?<author>.+)$/);
if (!match) {
console.warn(`Failed to retrieve the git history for file "${filePath}" with unexpected output: ${output}`);
return null;
}

const timestamp = Number(match.groups!.timestamp);
const date = new Date(timestamp * 1000);

return { date, author: match.groups!.author! };
}
48 changes: 0 additions & 48 deletions packages/markdownlayer/src/core/git/index.ts

This file was deleted.

143 changes: 0 additions & 143 deletions packages/markdownlayer/src/core/git/utils.ts

This file was deleted.

0 comments on commit f65ad35

Please sign in to comment.