Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions scripts/generate-last-updated.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import fs from 'fs'
import path from 'path'
import { fileURLToPath } from 'url'
import { getGitLastModified } from './git-dates.mjs'
import { buildGitDateMap } from './git-dates.mjs'

const __dirname = path.dirname(fileURLToPath(import.meta.url))
const ROOT = path.join(__dirname, '..')
Expand Down Expand Up @@ -45,9 +45,10 @@ const entries = findMdxRoutes(PAGES_DIR)
.filter((r) => r.route !== '/' && r.route !== '')
.sort((a, b) => a.route.localeCompare(b.route))

const gitDates = buildGitDateMap()
const map = {}
for (const { route, filePath } of entries) {
const date = getGitLastModified(filePath)
const date = gitDates.get(path.relative(ROOT, filePath))
if (date) map[route] = date
}

Expand Down
5 changes: 3 additions & 2 deletions scripts/generate-sitemap.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import fs from 'fs'
import path from 'path'
import { fileURLToPath } from 'url'
import { getGitLastModified } from './git-dates.mjs'
import { buildGitDateMap } from './git-dates.mjs'

const __dirname = path.dirname(fileURLToPath(import.meta.url))
const ROOT = path.join(__dirname, '..')
Expand Down Expand Up @@ -56,10 +56,11 @@ function escapeXml(s) {
.replace(/'/g, ''')
}

const gitDates = buildGitDateMap()
const entries = findMdxFiles(PAGES_DIR)
.map(({ route, filePath }) => ({
url: toPublicUrl(route),
lastmod: getGitLastModified(filePath),
lastmod: gitDates.get(path.relative(ROOT, filePath)) ?? null,
}))
.sort((a, b) => a.url.localeCompare(b.url))

Expand Down
47 changes: 47 additions & 0 deletions scripts/git-dates.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ import { execSync } from 'child_process'
/**
* Get the last modified date for a file from git history.
* Returns YYYY-MM-DD or null if the file is not tracked / git is unavailable.
*
* Prefer buildGitDateMap() when you need dates for many files — this spawns a
* git process per call, which is ~300x slower across a full page tree.
*/
export function getGitLastModified(filePath) {
try {
Expand All @@ -16,3 +19,47 @@ export function getGitLastModified(filePath) {
return null
}
}

let _dateMapCache

/**
* Build a map of repo-relative path -> last commit date (YYYY-MM-DD) for every
* file in history, in a SINGLE git process, instead of one `git log` per file.
* Memoised for the lifetime of the process.
*
* git log is reverse-chronological, so the first date seen for a path is its
* most recent commit — the same value `git log -1 -- <path>` returns. Paths are
* repo-relative with forward slashes, matching path.relative(repoRoot, file).
*
* Returns an empty map if git is unavailable (e.g. inside the Docker image,
* which has no git binary); callers then fall back to no date, exactly as the
* per-file getGitLastModified() did.
*/
export function buildGitDateMap() {
if (_dateMapCache) return _dateMapCache
const map = new Map()
try {
// core.quotePath=false keeps non-ASCII paths unquoted so line parsing is safe.
const out = execSync(
'git -c core.quotePath=false log --format=%cI --name-only',
{
encoding: 'utf-8',
maxBuffer: 128 * 1024 * 1024,
stdio: ['pipe', 'pipe', 'ignore'],
}
)
let currentDate = null
for (const line of out.split('\n')) {
if (line === '') continue
if (/^\d{4}-\d{2}-\d{2}T/.test(line)) {
currentDate = line.slice(0, 10)
continue
}
if (currentDate && !map.has(line)) map.set(line, currentDate)
}
} catch {
// git unavailable — return the empty map, callers fall back to null.
}
_dateMapCache = map
return map
}
Loading