Files
awesome-copilot/eng/utils/git-dates.mjs
Aaron Powell 46256b3a50 feat(website): Add last updated dates for agents, prompts, instructions, and skills
- Add git-dates.mjs utility to extract file modification dates from git history
- Include lastUpdated field in JSON data for all resource types
- Display relative time (e.g., '3 days ago') with full date on hover
- Add 'Recently Updated' sort option to agents, prompts, instructions, and skills pages
- Update deploy-website.yml to use fetch-depth: 0 for full git history

CI overhead: ~20-30s additional for full git checkout
2026-02-03 12:14:45 +11:00

104 lines
2.7 KiB
JavaScript

#!/usr/bin/env node
/**
* Utility to extract last modification dates from git history.
* Uses a single git log command for efficiency.
*/
import { execSync } from "child_process";
import path from "path";
/**
* Get the last modification date for all tracked files in specified directories.
* Returns a Map of file path -> ISO date string.
*
* @param {string[]} directories - Array of directory paths to scan
* @param {string} rootDir - Root directory for relative paths
* @returns {Map<string, string>} Map of relative file path to ISO date string
*/
export function getGitFileDates(directories, rootDir) {
const fileDates = new Map();
try {
// Get git log with file names for all specified directories
// Format: ISO date, then file names that were modified in that commit
const gitArgs = [
"--no-pager",
"log",
"--format=%aI", // Author date in ISO 8601 format
"--name-only",
"--diff-filter=ACMR", // Added, Copied, Modified, Renamed
"--",
...directories,
];
const output = execSync(`git ${gitArgs.join(" ")}`, {
encoding: "utf8",
cwd: rootDir,
stdio: ["pipe", "pipe", "pipe"],
});
// Parse the output: alternating date lines and file name lines
// Format is:
// 2026-01-15T10:30:00+00:00
//
// file1.md
// file2.md
//
// 2026-01-14T09:00:00+00:00
// ...
let currentDate = null;
const lines = output.split("\n");
for (const line of lines) {
const trimmed = line.trim();
if (!trimmed) {
continue;
}
// Check if this is a date line (ISO 8601 format)
if (/^\d{4}-\d{2}-\d{2}T/.test(trimmed)) {
currentDate = trimmed;
} else if (currentDate && trimmed) {
// This is a file path - only set if we haven't seen this file yet
// (first occurrence is the most recent modification)
if (!fileDates.has(trimmed)) {
fileDates.set(trimmed, currentDate);
}
}
}
} catch (error) {
// Git command failed - might not be a git repo or no history
console.warn("Warning: Could not get git dates:", error.message);
}
return fileDates;
}
/**
* Get the last modification date for a single file.
*
* @param {string} filePath - Path to the file (relative to git root)
* @param {string} rootDir - Root directory
* @returns {string|null} ISO date string or null if not found
*/
export function getGitFileDate(filePath, rootDir) {
try {
const output = execSync(
`git --no-pager log -1 --format="%aI" -- "${filePath}"`,
{
encoding: "utf8",
cwd: rootDir,
stdio: ["pipe", "pipe", "pipe"],
}
);
const date = output.trim();
return date || null;
} catch (error) {
return null;
}
}