Tucker McKnight <tucker@pangolin.lan> | Mon Nov 10 2025
Switching some more things over to the new Repository type Also removed anything that prints out commits in order, as that needs to be re-thought for the new format. So I left some todos in there.
92 93 94 95 96 97
);
eleventyConfig.addFilter("getDirectoryContents", (repo, branch, dirPath) => {
return reposData[repo].branches[branch].files.filter(file => file.startsWith(dirPath) && file !== dirPath)
})
eleventyConfig.addFilter("getRelativePath", (currentDir, fullFilePath) => {92 93 94 95 96 97
);
eleventyConfig.addFilter("getDirectoryContents", (repo, branch, dirPath) => {
return reposData.find(current => current.name === repo).branches[branch].fileList.filter(file => file.startsWith(dirPath) && file !== dirPath)
})
eleventyConfig.addFilter("getRelativePath", (currentDir, fullFilePath) => {109 110 111 112 113 114
return lineNumbers
})
eleventyConfig.addFilter("highlightCode", (code, language) => {
const highlighter = eleventyConfig?.javascript?.functions?.highlight
if (highlighter) {
return highlighter(language, code)109 110 111 112 113 114
return lineNumbers
})
eleventyConfig.addFilter("highlightCode", (code: string, language: string) => {
const highlighter = eleventyConfig?.javascript?.functions?.highlight
if (highlighter) {
return highlighter(language, code)185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
return repoOperations[config._type].getFileLastTouchInfo(repo, branch, filename, location)
})
eleventyConfig.addFilter("isDirectory", (filename, repoName, branchName) => {
const files = reposData[repoName].branches[branchName].files
const isDirectory = files.some((testFile) => {
return testFile.startsWith(filename + '/') && (testFile !== filename)
})
return isDirectory
})
eleventyConfig.addAsyncFilter("getFileContents", async (repo, branch, filename) => {
const location = getLocation(reposConfiguration, branch, repo)
const config = reposConfiguration.repos[repo]
const command = `git show ${branch}:${filename}`
const res = await exec(`(cd ${location} && ${command})`)
return res.stdout185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
return repoOperations[config._type].getFileLastTouchInfo(repo, branch, filename, location)
})
eleventyConfig.addFilter("isDirectory", (filename: string, repoName: string, branchName: string) => {
const repo = reposData.find(repo => repo.name === repoName)
const files = repo.branches.find(branch => branch.name === branchName).fileList
const isDirectory = files.some((testFile) => {
return testFile.startsWith(filename + '/') && (testFile !== filename)
})
return isDirectory
})
eleventyConfig.addAsyncFilter("getFileContents", async (repo: string, branch: string, filename: string) => {
const location = getLocation(reposConfiguration, branch, repo)
const command = `git show ${branch}:${filename}`
const res = await exec(`(cd ${location} && ${command})`)
return res.stdout215 216 217 218 219 220
eleventyConfig.addAsyncFilter("getReadMe", async (repoName, branchName) => {
const location = getLocation(reposConfiguration, branchName, repoName)
const config = reposConfiguration.repos[repoName]
const command = `git show ${branchName}:README.md`
try {
const res = await exec(`(cd ${location} && ${command})`)215 216 217 218 219
eleventyConfig.addAsyncFilter("getReadMe", async (repoName, branchName) => {
const location = getLocation(reposConfiguration, branchName, repoName)
const command = `git show ${branchName}:README.md`
try {
const res = await exec(`(cd ${location} && ${command})`)335 336 337 338 339 340
nav: {
repoName: (data) => data.branchInfo.repoName,
branchName: (data) => data.branchInfo.branchName,
}
},
navTab: "files",
}335 336 337 338 339 340 341 342 343 344 345 346 347 348
nav: {
repoName: (data) => data.branchInfo.repoName,
branchName: (data) => data.branchInfo.branchName,
},
currentRepo: (data) => reposData.find(repo => {
return repo.name === data.branchInfo.repoName
}),
currentBranch: (data) => reposData.find(repo => {
return repo.name === data.branchInfo.repoName
}).branches.find(branch => {
return branch.name === data.branchInfo.branchName
})
},
navTab: "files",
}361 362 363 364 365 366
nav: {
repoName: (data) => data.branch.repoName,
branchName: (data) => data.branch.branchName,
}
},
navTab: "landing",
}361 362 363 364 365 366 367 368 369 370 371 372 373 374
nav: {
repoName: (data) => data.branch.repoName,
branchName: (data) => data.branch.branchName,
},
currentRepo: (data) => reposData.find(repo => {
return repo.name === data.branch.repoName
}),
currentBranch: (data) => reposData.find(repo => {
return repo.name === data.branch.repoName
}).branches.find(branch => {
return branch.name === data.branch.branchName
}),
},
navTab: "landing",
}397 398 399 400 401 402
// PATCH.NJK
const patchTemplate = fsImport.readFileSync(`${import.meta.dirname}/templates/patch.njk`).toString()
const flatPatchesData = await flatPatches(reposConfiguration)
eleventyConfig.addTemplate(
`repos/patch.njk`,
topLayoutPartial + patchTemplate + bottomLayoutPartial,397 398 399 400 401 402
// PATCH.NJK
const patchTemplate = fsImport.readFileSync(`${import.meta.dirname}/templates/patch.njk`).toString()
const flatPatchesData = await flatPatches(reposData)
eleventyConfig.addTemplate(
`repos/patch.njk`,
topLayoutPartial + patchTemplate + bottomLayoutPartial,82 83 84 85 86 87 88 89 90
<div class="input-group input-group-sm">
<span class="input-group-text">Branch</span>
<select class="form-select" onchange="selectBranch(this)" aria-label="Repository branch selector">
{% for branch in branches %}
{% if branch.repoName == nav.repoName %}
<option value="{{branch.repoName | slugify}},{{branch.branchName | slugify}},{{nav.path}}" {% if branch.branchName == nav.branchName %}selected{% endif %}>{{branch.branchName}}</option>
{% endif %}
{% endfor %}
</select>
</div>82 83 84 85 86 87 88
<div class="input-group input-group-sm">
<span class="input-group-text">Branch</span>
<select class="form-select" onchange="selectBranch(this)" aria-label="Repository branch selector">
{% for branch in repos[nav.repoName].branches %}
<option value="{{branch.repoName | slugify}},{{branch.branchName | slugify}},{{nav.path}}" {% if branch.branchName == nav.branchName %}selected{% endif %}>{{branch.branchName}}</option>
{% endfor %}
</select>
</div>33 34 35 36 37 38
},
"branchesToPull": {
"items": {
"type": "string"
},
"type": "array"
},33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
},
"branchesToPull": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"additionalProperties": false,
"properties": {
"max": {
"type": "number"
},
"regex": {
"type": "string"
}
},
"required": [
"regex",
"max"
],
"type": "object"
}
]
},
"type": "array"
},51 52 53 54 55
},
"location": {
"type": "string"
}
},
"required": [51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
},
"location": {
"type": "string"
},
"tags": {
"items": {
"anyOf": [
{
"type": "string"
},
{
"additionalProperties": false,
"properties": {
"max": {
"type": "number"
},
"regex": {
"type": "string"
}
},
"required": [
"regex",
"max"
],
"type": "object"
}
]
},
"type": "array"
}
},
"required": [0 1 2 3 4 5 6 7 8 9 10 11
let cachedBranches = null
export default (repos) => {
if (cachedBranches !== null) { return cachedBranches }
cachedBranches = Object.keys(repos).flatMap((repoName) => {
return Object.keys(repos[repoName].branches).map((branchName) => {
return {
branchName,
repoName,
}
})
})0 1 2 3 4 5 6 7 8 9 10 11 12 13
import { type Repository } from "./dataTypes.ts"
let cachedBranches = null
export default (repos: Array<Repository>) => {
if (cachedBranches !== null) { return cachedBranches }
cachedBranches = repos.flatMap((repo) => {
return repo.branches.map((branch) => {
return {
branchName: branch.name,
repoName: repo.name,
}
})
})50 51 52 53 54 55
location: string,
description?: string,
defaultBranch: string,
branchesToPull: Array<string>,
languageExtensions?: {
[fileExtension: string]: string
},50 51 52 53 54 55 56
location: string,
description?: string,
defaultBranch: string,
branchesToPull: Array<string | {regex: string, max: number}>,
tags?: Array<string | {regex: string, max: number}>,
languageExtensions?: {
[fileExtension: string]: string
},4 5 6 7 8 9 10 11 12 13 14 15 16
defaultBranch: string,
branches: Array<{
name: string,
description?: string,
head: string,
}>,
tags: Array<{
name: string,
sha: string,
}>,
commits: Map<string, {
message: string,
author: string,
date: Date,4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
defaultBranch: string,
branches: Array<{
name: string,
head: string,
fileList: Array<string>,
}>,
tags: Array<{
name: string,
sha: string,
fileList: Array<string>,
}>,
commits: Map<string, {
hash: string,
message: string,
author: string,
date: Date,24 25 26 27 28 29 30
}>
}>,
}
export type BranchInfo = {
files: Array<string>,
patches: Array<any>
}24 25
}>
}>,
}0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
import repos from './repos.ts'
let cachedFlatFiles = null
export default (repos) => {
if (cachedFlatFiles !== null) { return cachedFlatFiles }
cachedFlatFiles = Object.keys(repos).flatMap((repoName) => {
return Object.keys(repos[repoName].branches).flatMap((branchName) => {
return repos[repoName].branches[branchName].files.map((file) => {
return {
file,
branchName,
repoName,
}
})
})0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
import { type Repository } from "./dataTypes.ts"
let cachedFlatFiles = null
export default (repos: Array<Repository>) => {
if (cachedFlatFiles !== null) { return cachedFlatFiles }
cachedFlatFiles = repos.flatMap((repo) => {
return repo.branches.flatMap((branch) => {
return branch.fileList.map((file) => {
return {
file,
branchName: branch.name,
repoName: repo.name,
}
})
})0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
let cachedFlatPatches = null
export default async (repos) => {
if (cachedFlatPatches !== null) { return cachedFlatPatches }
cachedFlatPatches = Object.keys(repos).flatMap((repoName) => {
return Object.keys(repos[repoName].branches).flatMap((branchName) => {
return repos[repoName].branches[branchName].patches.map((patch) => {
return {
patch,
branchName,
repoName,
}
})
})
})
0 1 2 3 4 5 6 7 8 9 10 11
import { type Repository } from "./dataTypes.ts"
let cachedFlatPatches = null
export default async (repos: Array<Repository>) => {
if (cachedFlatPatches !== null) { return cachedFlatPatches }
cachedFlatPatches = repos.flatMap((repo) => {
return repo.branches.flatMap((branch) => {
return [] // todo implement this with new commits format
})
})
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
return Array.from(fileSet)
}
export const getBranchInfo = async (branchName: string, repoLocation: string) => {
const patches: Map<string, {
name: string,
description: string,
author: string,
date: string,
hash: string,
diffs: ReturnType<Repository['commits']['get']>['diffs'],
}> = new Map()
const totalPatchesCountRes = await exec(`(cd ${repoLocation} && git rev-list --count ${branchName})`)
const totalPatchesCount = parseInt(totalPatchesCountRes.stdout)
for (let i = 0; i < totalPatchesCount; i = i + 10) {37 38 39 40 41 42
return Array.from(fileSet)
}
export const addBranchToCommitsMap = async(branchName: string, repoLocation: string, commits: Repository['commits']): Promise<void> => {
const totalPatchesCountRes = await exec(`(cd ${repoLocation} && git rev-list --count ${branchName})`)
const totalPatchesCount = parseInt(totalPatchesCountRes.stdout)
for (let i = 0; i < totalPatchesCount; i = i + 10) {61 62 63 64 65
gitLogSubset = gitLogSubset.slice(nextPatchStart)
const hash = currentPatch[0].replace("commit ", "").trim()
let author: string, date: string
[1, 2, 3].forEach((lineNumber) => {
if (currentPatch[lineNumber].startsWith("Author")) {61 62 63 64 65 66 67 68 69 70 71
gitLogSubset = gitLogSubset.slice(nextPatchStart)
const hash = currentPatch[0].replace("commit ", "").trim()
// exit early if the commits map already includes this hash
if (commits.has(hash)) {
break
}
let author: string, date: string
[1, 2, 3].forEach((lineNumber) => {
if (currentPatch[lineNumber].startsWith("Author")) {1 2 3 4 5 6 7 8 9 10
getFileList as getGitFileList,
getFileLastTouchInfo as getGitFileLastTouchInfo,
} from './git/operations.ts'
import {type BranchInfo} from '../dataTypes.ts'
type RepoOperationsType = {
[vcs: string]: {
getFileList: (repoName: string, branchName: string, repoLocation: string) => Promise<BranchInfo['files']>,
getFileLastTouchInfo: (repoName: string, branchName: string, filename: string, repoLocation: string) => Promise<Array<{sha: string, author: string}>>,
}
}1 2 3 4 5 6 7 8 9
getFileList as getGitFileList,
getFileLastTouchInfo as getGitFileLastTouchInfo,
} from './git/operations.ts'
type RepoOperationsType = {
[vcs: string]: {
getFileList: (repoName: string, branchName: string, repoLocation: string) => Promise<Array<string>>,
getFileLastTouchInfo: (repoName: string, branchName: string, filename: string, repoLocation: string) => Promise<Array<{sha: string, author: string}>>,
}
}0 1 2 3 4 5
<div class="row">
<div class="col">
<ul class="list-group">
{% set files = repos[branchInfo.repoName].branches[branchInfo.branchName].files | topLevelFilesOnly('') %}
{% for file in files %}
<li class="list-group-item">
{% if file.isDirectory %}0 1 2 3 4 5
<div class="row">
<div class="col">
<ul class="list-group">
{% set files = currentBranch.fileList | topLevelFilesOnly('') %}
{% for file in files %}
<li class="list-group-item">
{% if file.isDirectory %}0 1 2 3
<ul>
{% for repoName, options in repos %}
<li><a href="{{reposPath}}/{{repoName | slugify}}/branches/{{reposConfig.repos[repoName].defaultBranch}}">{{repoName}}</a></li>
{% endfor %}
</ul>0 1 2 3
<ul>
{% for repo in repos %}
<li><a href="{{reposPath}}/{{repo.name | slugify}}/branches/{{reposConfig.repos[repo.name].defaultBranch}}">{{repo.name}}</a></li>
{% endfor %}
</ul>