Tucker McKnight <tucker@pangolin.lan> | Sun Mar 01 2026
Change references of "branches" to "rels", allow for tags, too "rels" refers to a branch _or_ a tag. Flattened data lists (flatPatches, flatFiles, and branches.ts (now flatRels.ts)) should specify which type of rel each of their entries is. Pages now have the rel type (branch or tag) in their permalink instead of always being hard-coded to /branches/.
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
eleventyConfig: any,
data: any,
) => {
const pagesJustForBranch = eleventyConfig.getFilter("pagesJustForBranch")
const slugify = eleventyConfig.getFilter("slugify")
const date = eleventyConfig.getFilter("date")
const nav = NavHelper(reposConfig, slugify, data.patchPage.repoName, data.patchPage.branchName)
const pageContent = [
m('div', {class: "row mt-3 mb-1"},
m('div', {class: "col"},
m('p', {class: "d-inline-block"}, [
'Showing commits from ',
m('span', {class: "font-monospace me-2"}, data.patchPage.branchName),
m('a', {
class: "btn btn-outline-primary badge shadow-none",
href: nav.repoCurrentBranchRssFeed()6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
eleventyConfig: any,
data: any,
) => {
const pagesJustForRel = eleventyConfig.getFilter("pagesJustForRel")
const slugify = eleventyConfig.getFilter("slugify")
const date = eleventyConfig.getFilter("date")
const nav = NavHelper(reposConfig, slugify, data.patchPage.repoName, data.patchPage.relName)
const pageContent = [
m('div', {class: "row mt-3 mb-1"},
m('div', {class: "col"},
m('p', {class: "d-inline-block"}, [
'Showing commits from ',
m('span', {class: "font-monospace me-2"}, data.patchPage.relName),
m('a', {
class: "btn btn-outline-primary badge shadow-none",
href: nav.repoCurrentBranchRssFeed()33 34 35 36 37 38 39 40 41 42 43 44 45 46
),
m('nav',
m('ul', {class: "pagination"},
pagesJustForBranch(
data.paginatedPatches,
data.patchPage.repoName,
data.patchPage.branchName
).map((pageObj) => {
return m('li', {class: "page-item"},
m('a', {
class: `page-link ${pageObj.pageNumber === data.patchPage.pageNumber ? 'active' : ''}`,
href: `${data.reposPath}/${slugify(data.patchPage.repoName)}/branches/${data.patchPage.branchName}/commits/page${pageObj.pageNumber}`
}, pageObj.pageNumber)
)
})33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
),
m('nav',
m('ul', {class: "pagination"},
pagesJustForRel(
data.paginatedPatches,
data.patchPage.repoName,
data.patchPage.relName,
data.patchPage.type,
).map((pageObj) => {
return m('li', {class: "page-item"},
m('a', {
class: `page-link ${pageObj.pageNumber === data.patchPage.pageNumber ? 'active' : ''}`,
href: `${data.reposPath}/${slugify(data.patchPage.repoName)}/${data.patchPage.type}/${data.patchPage.relName}/commits/page${pageObj.pageNumber}`
}, pageObj.pageNumber)
)
})55 56 57 58 59 60
commit.isMerge ? m('span', {class: 'badge rounded-pill bg-primary me-1'}, 'merge') : null,
m('a', {
class: "fs-5",
href: `${data.reposPath}/${slugify(data.patchPage.repoName)}/branches/${slugify(data.patchPage.branchName)}/commits/${commit.hash}`,
}, commit.message.split('\n').slice(0, 1)),
m('br'),
m('span', date(commit.date)),55 56 57 58 59 60
commit.isMerge ? m('span', {class: 'badge rounded-pill bg-primary me-1'}, 'merge') : null,
m('a', {
class: "fs-5",
href: `${data.reposPath}/${slugify(data.patchPage.repoName)}/${data.patchPage.type}/${slugify(data.patchPage.relName)}/commits/${commit.hash}`,
}, commit.message.split('\n').slice(0, 1)),
m('br'),
m('span', date(commit.date)),66 67 68 69 70 71 72 73 74 75 76 77 78 79
})),
m('nav',
m('ul', {class: "pagination"},
pagesJustForBranch(
data.paginatedPatches,
data.patchPage.repoName,
data.patchPage.branchName
).map((pageObj) => {
return m('li', {class: "page-item"},
m('a', {
class: `page-link ${pageObj.pageNumber === data.patchPage.pageNumber ? 'active' : ''}`,
href: `${data.reposPath}/${slugify(data.patchPage.repoName)}/branches/${data.patchPage.branchName}/commits/page${pageObj.pageNumber}`
}, pageObj.pageNumber)
)
})66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
})),
m('nav',
m('ul', {class: "pagination"},
pagesJustForRel(
data.paginatedPatches,
data.patchPage.repoName,
data.patchPage.relName,
data.patchPage.type,
).map((pageObj) => {
return m('li', {class: "page-item"},
m('a', {
class: `page-link ${pageObj.pageNumber === data.patchPage.pageNumber ? 'active' : ''}`,
href: `${data.reposPath}/${slugify(data.patchPage.repoName)}/${data.patchPage.type}/${data.patchPage.relName}/commits/page${pageObj.pageNumber}`
}, pageObj.pageNumber)
)
})10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
}
const repo: Repository = data.currentRepo
const branch: Repository['branches'][0] = data.currentBranch
const slugify = eleventyConfig.getFilter("slugify")
const nav = NavHelper(reposConfig, slugify, repo.name, branch.name)
const branchesWithHrefs = repo.branches.map((branch) => {
return {
name: branch.name,
href: nav.repoBranchHome(branch.name) + '/' + data.nav.path,
date: repo.commits.get(branch.head).date.toISOString(),
}
}).concat(repo.tags.map((tag) => {
return {10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
}
const repo: Repository = data.currentRepo
const rel: Repository['branches'][0] = data.currentRel
const slugify = eleventyConfig.getFilter("slugify")
const nav = NavHelper(reposConfig, slugify, repo.name, rel.name)
const branchesWithHrefs = repo.branches.map((branch) => {
return {
name: branch.name,
href: nav.repoBranchHome(branch.name) + '/' + data.nav.path,
date: repo.commits.get(branch.sha).date.toISOString(),
}
}).concat(repo.tags.map((tag) => {
return {38 39 40 41 42 43
m('script', m.trust(`
window.branchesWithHrefs = ${JSON.stringify(branchesWithHrefs)};
window.defaultBranch = "${repo.defaultBranch}";
window.currentBranch = "${branch.name}";
window.cloneUrl = "${repo.cloneUrl}";
`)),
m('link', {38 39 40 41 42 43
m('script', m.trust(`
window.branchesWithHrefs = ${JSON.stringify(branchesWithHrefs)};
window.defaultBranch = "${repo.defaultBranch}";
window.currentBranch = "${rel.name}";
window.cloneUrl = "${repo.cloneUrl}";
`)),
m('link', {70 71 72 73 74 75
'data-bs-toggle': "dropdown",
'data-bs-auto-close': "outside",
'aria-expanded': "false"
}, branch.name),
m('div', {class: "dropdown-menu"}, [
m('form', {class: "mx-3 my-1"}, [
m('input', {type: "text", class: "form-control", id: "dropdownBranchSearch", placeholder: "Search branches..."}),70 71 72 73 74 75
'data-bs-toggle': "dropdown",
'data-bs-auto-close': "outside",
'aria-expanded': "false"
}, rel.name),
m('div', {class: "dropdown-menu"}, [
m('form', {class: "mx-3 my-1"}, [
m('input', {type: "text", class: "form-control", id: "dropdownBranchSearch", placeholder: "Search branches..."}),94 95 96 97 98 99
]),
m('div', {class: "dropdown-divider"}),
m('div', {id: "dropdown-branches-results", class: "dropdown-branches"},
branchesListItems(branchesWithHrefs, repo.defaultBranch, branch.name, 'date')
)
])
])94 95 96 97 98 99
]),
m('div', {class: "dropdown-divider"}),
m('div', {id: "dropdown-branches-results", class: "dropdown-branches"},
branchesListItems(branchesWithHrefs, repo.defaultBranch, rel.name, 'date')
)
])
])0 1 2 3 4 5
import m from 'mithril'
import render from 'mithril-node-render'
import { type Repository } from '../src/dataTypes.ts'
import branches from '../src/branches.ts'
import { dateToRfc3339 } from '@11ty/eleventy-plugin-rss'
import flatPatches from '../src/flatPatches.ts'
0 1 2 3 4 5
import m from 'mithril'
import render from 'mithril-node-render'
import { type Repository } from '../src/dataTypes.ts'
import getFlatRels from '../src/flatRels.ts'
import { dateToRfc3339 } from '@11ty/eleventy-plugin-rss'
import flatPatches from '../src/flatPatches.ts'
14 15 16 17 18 19
const languageExtension = eleventyConfig.getFilter("languageExtension")
const renderContentIfAvailable = eleventyConfig.getFilter("renderContentIfAvailable")
const currentBranch: Branch = data.currentBranch
const fileInfo: FlatFileEntry = data.fileInfo
const pageContent = [ 14 15 16 17 18 19
const languageExtension = eleventyConfig.getFilter("languageExtension")
const renderContentIfAvailable = eleventyConfig.getFilter("renderContentIfAvailable")
const currentRel: Branch = data.currentRel
const fileInfo: FlatFileEntry = data.fileInfo
const pageContent = [ 95 96 97 98 99 100
m('div', {class: "row rendered-content"},
m('div', {class: "col"},
m.trust(await renderContentIfAvailable(
currentBranch.fileList.get(fileInfo.file).fileInfo.contents
))
)
)95 96 97 98 99 100
m('div', {class: "row rendered-content"},
m('div', {class: "col"},
m.trust(await renderContentIfAvailable(
currentRel.fileList.get(fileInfo.file).fileInfo.contents
))
)
)115 116 117 118 119 120
m('div', {class: "col-auto p-0"},
m('code', {style: "white-space: pre;"},
m('pre', {class: "language-text"},
lineNumbers(currentBranch.fileList.get(fileInfo.file).fileInfo.contents).map((lineNumber) => {
return lineNumber
}).join('\n')
)115 116 117 118 119 120
m('div', {class: "col-auto p-0"},
m('code', {style: "white-space: pre;"},
m('pre', {class: "language-text"},
lineNumbers(currentRel.fileList.get(fileInfo.file).fileInfo.contents).map((lineNumber) => {
return lineNumber
}).join('\n')
)124 125 126 127 128 129 130 131 132 133 134 135 136
m('div', {id: "annotations", class: "col-auto d-none p-0"},
m('code', {style: "white-space: pre;"}, [
m('pre', {class: "language-text"}, m.trust(
currentBranch.fileList.get(fileInfo.file).fileInfo.blameLines.map((annotation) => {
return `<a href="${data.reposPath}/${slugify(fileInfo.repoName)}/branches/${slugify(fileInfo.branchName)}/commits/${annotation.sha}">${annotation.sha.substr(0, 6)}</a> ${annotation.author}`
}).join('\n')))
])
),
m('div', {class: "col overflow-scroll p-0"},
m('code', m.trust(highlightCode(
currentBranch.fileList.get(fileInfo.file).fileInfo.contents,
languageExtension(
fileInfo.file,
fileInfo.repoName124 125 126 127 128 129 130 131 132 133 134 135 136
m('div', {id: "annotations", class: "col-auto d-none p-0"},
m('code', {style: "white-space: pre;"}, [
m('pre', {class: "language-text"}, m.trust(
currentRel.fileList.get(fileInfo.file).fileInfo.blameLines.map((annotation) => {
return `<a href="${data.reposPath}/${slugify(fileInfo.repoName)}/branches/${slugify(fileInfo.branchName)}/commits/${annotation.sha}">${annotation.sha.substr(0, 6)}</a> ${annotation.author}`
}).join('\n')))
])
),
m('div', {class: "col overflow-scroll p-0"},
m('code', m.trust(highlightCode(
currentRel.fileList.get(fileInfo.file).fileInfo.contents,
languageExtension(
fileInfo.file,
fileInfo.repoName2 3 4 5 6 7
import htmlPage from './common/htmlPage.ts'
export default async (reposConfig: any, eleventyConfig: any, data: any) => {
const branch: Repository['branches'][0] = data.currentBranch
const topLevelFilesOnly = eleventyConfig.getFilter("topLevelFilesOnly")
const slugify = eleventyConfig.getFilter("slugify")
2 3 4 5 6 7
import htmlPage from './common/htmlPage.ts'
export default async (reposConfig: any, eleventyConfig: any, data: any) => {
const branch: Repository['branches'][0] = data.currentRel
const topLevelFilesOnly = eleventyConfig.getFilter("topLevelFilesOnly")
const slugify = eleventyConfig.getFilter("slugify")
13 14 15 16 17 18
m('div', {class: "col"},
m('p', [
'Files snapshot from ',
m('span', {class: "font-monospace"}, data.branchInfo.branchName)
])
)
]),13 14 15 16 17 18
m('div', {class: "col"},
m('p', [
'Files snapshot from ',
m('span', {class: "font-monospace"}, data.flatRel.relName)
])
)
]),26 27 28 29 30 31
return m('li', {class: 'list-group-item'}, [
file.isDirectory ? m.trust('<span>📁 </span>') : null,
m('a', {
href: `${data.reposPath}/${slugify(data.branchInfo.repoName)}/branches/${slugify(data.branchInfo.branchName)}/files/${
file.fullPath.split('/')
.map((pathPart) => {
return pathPart.split('.').map((subPart) => {26 27 28 29 30 31
return m('li', {class: 'list-group-item'}, [
file.isDirectory ? m.trust('<span>📁 </span>') : null,
m('a', {
href: `${data.reposPath}/${slugify(data.flatRel.repoName)}/branches/${slugify(data.flatRel.relName)}/files/${
file.fullPath.split('/')
.map((pathPart) => {
return pathPart.split('.').map((subPart) => {2 3 4 5 6 7
export default async (eleventyConfig: any) => {
return async (data) => {
const branch: Branch = data.currentBranch
return branch.fileList.get(data.fileInfo.file).fileInfo.contents
}2 3 4 5 6 7
export default async (eleventyConfig: any) => {
return async (data) => {
const branch: Branch = data.currentRel
return branch.fileList.get(data.fileInfo.file).fileInfo.contents
}4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
export default async (reposConfig: any, eleventyConfig: any, data: any) => {
const repo: Repository = data.currentRepo
const branch: Repository['branches'][0] = data.currentBranch
const renderContentIfAvailable = eleventyConfig.getFilter("renderContentIfAvailable")
const slugify = eleventyConfig.getFilter("slugify")
const getReadMe = eleventyConfig.getFilter("getReadMe")
const latestCommit = repo.commits.get(branch.head)
const latestCommitMessage = latestCommit.message.length > 72
? latestCommit.message.split('\n')[0].substr(0, 72) + '...'
: latestCommit.message
const nav = NavHelper(reposConfig, slugify, repo.name, branch.name)
const languageCounts = Array.from(branch.fileList.keys()).reduce((counts, currentFile) => {
const fileParts = currentFile.split(".")
const fileExtension = fileParts[fileParts.length - 1]
// todo: add more ignoreable extensions or specific files4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
export default async (reposConfig: any, eleventyConfig: any, data: any) => {
const repo: Repository = data.currentRepo
const rel: Repository['branches'][0] | Repository['tags'][0] = data.currentRel
const renderContentIfAvailable = eleventyConfig.getFilter("renderContentIfAvailable")
const slugify = eleventyConfig.getFilter("slugify")
const getReadMe = eleventyConfig.getFilter("getReadMe")
const latestCommit = repo.commits.get(rel.sha)
const latestCommitMessage = latestCommit.message.length > 72
? latestCommit.message.split('\n')[0].substr(0, 72) + '...'
: latestCommit.message
const nav = NavHelper(reposConfig, slugify, repo.name, rel.name)
const languageCounts = Array.from(rel.fileList.keys()).reduce((counts, currentFile) => {
const fileParts = currentFile.split(".")
const fileExtension = fileParts[fileParts.length - 1]
// todo: add more ignoreable extensions or specific files30 31 32 33 34 35
// todo: this is probably broken for repos that use fewer than 6 languages
let languagePercentages: Array<[string, number]> = []
const total = Array.from(branch.fileList.keys()).length
for (const entry of languageCounts) {
languagePercentages.push([entry[0], entry[1] / total])30 31 32 33 34 35
// todo: this is probably broken for repos that use fewer than 6 languages
let languagePercentages: Array<[string, number]> = []
const total = Array.from(rel.fileList.keys()).length
for (const entry of languageCounts) {
languagePercentages.push([entry[0], entry[1] / total])45 46 47 48 49 50
const largestPercent = Math.max(...topLanguagePercentages.map(tuple => tuple[1]), otherLanguagePercent)
const readmeContent = await renderContentIfAvailable(await getReadMe(repo.name, branch.name), branch.name)
const pageContent = [
m('div', {class: "row"}, [45 46 47 48 49 50
const largestPercent = Math.max(...topLanguagePercentages.map(tuple => tuple[1]), otherLanguagePercent)
const readmeContent = await renderContentIfAvailable(await getReadMe(repo.name, rel.name), rel.name)
const pageContent = [
m('div', {class: "row"}, [1 2 3 4 5 6
import util from 'util'
import childProcess from 'child_process'
import {repos, getBranchesAndTags} from './src/repos.ts'
import branches from './src/branches.ts'
import flatFiles from './src/flatFiles.ts'
import flatPatches from './src/flatPatches.ts'
import paginatedPatches, {type PatchPage} from './src/paginatedPatches.ts'1 2 3 4 5 6
import util from 'util'
import childProcess from 'child_process'
import {repos, getBranchesAndTags} from './src/repos.ts'
import getFlatRels from './src/flatRels.ts'
import flatFiles from './src/flatFiles.ts'
import flatPatches from './src/flatPatches.ts'
import paginatedPatches, {type PatchPage} from './src/paginatedPatches.ts'87 88 89 90 91 92 93
eleventyConfig.addGlobalData("reposConfig", reposConfiguration)
eleventyConfig.addGlobalData("reposPath", reposPath)
const branchesData = branches(reposData)
eleventyConfig.addGlobalData("branches", branchesData)
eleventyConfig.addFilter("getFileName", (filePath: string) => {
const pathParts = filePath.split("/")87 88 89 90 91 92 93
eleventyConfig.addGlobalData("reposConfig", reposConfiguration)
eleventyConfig.addGlobalData("reposPath", reposPath)
const flatRels = getFlatRels(reposData)
eleventyConfig.addGlobalData("flatRels", flatRels)
eleventyConfig.addFilter("getFileName", (filePath: string) => {
const pathParts = filePath.split("/")252 253 254 255 256 257 258
return isDirectory
})
eleventyConfig.addFilter("pagesJustForBranch", (pages: Array<PatchPage>, repoName: string, branchName: string) => {
return pages.filter(page => page.repoName === repoName && page.branchName === branchName)
})
eleventyConfig.addFilter("date", (dateString: string) => {252 253 254 255 256 257 258
return isDirectory
})
eleventyConfig.addFilter("pagesJustForRel", (pages: Array<PatchPage>, repoName: string, relName: string, relType: "branch" | "tag") => {
return pages.filter(page => page.repoName === repoName && page.relName === relName && page.type === relType)
})
eleventyConfig.addFilter("date", (dateString: string) => {337 338 339 340 341 342
permalink: (data) => {
const repoName = data.fileInfo.repoName
const branchName = data.fileInfo.branchName
return `${reposPath}/${eleventyConfig.getFilter("slugify")(repoName)}/branches/${eleventyConfig.getFilter("slugify")(branchName)}/files/${data.fileInfo.file.split('/').map((filePart) => filePart.split('.').map((subPart) => eleventyConfig.getFilter("slugify")(subPart)).join('.')).join('/')}.html`
},
eleventyComputed: {
nav: {337 338 339 340 341 342 343
permalink: (data) => {
const repoName = data.fileInfo.repoName
const branchName = data.fileInfo.branchName
const relType = data.fileInfo.type
return `${reposPath}/${eleventyConfig.getFilter("slugify")(repoName)}/${relType}/${eleventyConfig.getFilter("slugify")(branchName)}/files/${data.fileInfo.file.split('/').map((filePart) => filePart.split('.').map((subPart) => eleventyConfig.getFilter("slugify")(subPart)).join('.')).join('/')}.html`
},
eleventyComputed: {
nav: {348 349 350 351 352 353
currentRepo: (data) => reposData.find(repo => {
return repo.name === data.fileInfo.repoName
}),
currentBranch: (data) => reposData.find(repo => {
return repo.name === data.fileInfo.repoName
}).branches.find(branch => {
return branch.name === data.fileInfo.branchName348 349 350 351 352 353
currentRepo: (data) => reposData.find(repo => {
return repo.name === data.fileInfo.repoName
}),
currentRel: (data) => reposData.find(repo => {
return repo.name === data.fileInfo.repoName
}).branches.find(branch => {
return branch.name === data.fileInfo.branchName373 374 375 376 377 378 379 380 381
permalink: (data) => {
const repoName = data.fileInfo.repoName
const branchName = data.fileInfo.branchName
return `${reposPath}/${eleventyConfig.getFilter("slugify")(repoName)}/branches/${eleventyConfig.getFilter("slugify")(branchName)}/raw/${data.fileInfo.file.split('.').map(filePart => eleventyConfig.getFilter("slugify")(filePart)).join('.')}`
},
eleventyComputed: {
currentBranch: (data) => reposData.find(repo => {
return repo.name === data.fileInfo.repoName
}).branches.find(branch => {
return branch.name === data.fileInfo.branchName373 374 375 376 377 378 379 380 381 382
permalink: (data) => {
const repoName = data.fileInfo.repoName
const branchName = data.fileInfo.branchName
const relType = data.fileInfo.type
return `${reposPath}/${eleventyConfig.getFilter("slugify")(repoName)}/${relType}/${eleventyConfig.getFilter("slugify")(branchName)}/raw/${data.fileInfo.file.split('.').map(filePart => eleventyConfig.getFilter("slugify")(filePart)).join('.')}`
},
eleventyComputed: {
currentRel: (data) => reposData.find(repo => {
return repo.name === data.fileInfo.repoName
}).branches.find(branch => {
return branch.name === data.fileInfo.branchName456 457 458 459 460 461
// COMMITS.TS
const paginatedPatchesData = await paginatedPatches(reposData)
eleventyConfig.addTemplate(
`repos/patches.11ty.js`,
commonPage(commitsJsTemplate, reposConfiguration, eleventyConfig),
{
pagination: {456 457 458 459 460 461
// COMMITS.TS
const paginatedPatchesData = await paginatedPatches(reposData)
eleventyConfig.addTemplate(
`repos/commits.11ty.js`,
commonPage(commitsJsTemplate, reposConfiguration, eleventyConfig),
{
pagination: {0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
import { type Repository } from "./dataTypes.ts"
let cachedBranches: Array<{
branchName: string,
repoName: string,
}> | null = null
export default (repos: Array<Repository>) => {
if (cachedBranches !== null) { return cachedBranches }
cachedBranches = repos.flatMap((repo) => {
return repo.branches.map((branch) => {
const result = {
branchName: branch.name,
repoName: repo.name,
compareTo: branch.compareTo,
ahead: branch.ahead,
behind: branch.behind,
}
if (branch.description) { result['description'] = branch.description }
return result
})
})
return cachedBranches
}
16 17 18 19 20 21
ahead: number,
behind: number,
compareTo: string,
head: string,
// instead of strings, make it point to a function that returns
// the file contents. The first time, search in both directions for a commit
// that has already cached this file before a diff in that commit mentions16 17 18 19 20 21
ahead: number,
behind: number,
compareTo: string,
sha: string,
// instead of strings, make it point to a function that returns
// the file contents. The first time, search in both directions for a commit
// that has already cached this file before a diff in that commit mentions2 3 4 5 6 7
type FlatPatchRecord = {
commit: ReturnType<Repository['commits']['get']>,
repoName: string,
branchName: string,
}
let cachedFlatPatches: Array<FlatPatchRecord> | null = null2 3 4 5 6 7 8
type FlatPatchRecord = {
commit: ReturnType<Repository['commits']['get']>,
repoName: string,
relName: string,
type: "branch" | "tag",
}
let cachedFlatPatches: Array<FlatPatchRecord> | null = null12 13 14 15 16 17 18 19 20 21 22 23 24 25
if (cachedFlatPatches !== null) { return cachedFlatPatches }
cachedFlatPatches = repos.flatMap((repo) => {
return repo.branches.flatMap((branch) => {
const flatPatches: Array<FlatPatchRecord> = []
let currentCommit: ReturnType<Repository['commits']['get']> | undefined = repo.commits.get(branch.head)
while (currentCommit !== undefined) {
flatPatches.push({
commit: currentCommit,
repoName: repo.name,
branchName: branch.name
})
currentCommit = repo.commits.get(currentCommit.parent)12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
if (cachedFlatPatches !== null) { return cachedFlatPatches }
cachedFlatPatches = repos.flatMap((repo) => {
const branches = repo.branches.flatMap((branch) => {
const flatPatches: Array<FlatPatchRecord> = []
let currentCommit: ReturnType<Repository['commits']['get']> | undefined = repo.commits.get(branch.sha)
while (currentCommit !== undefined) {
flatPatches.push({
type: "branch",
commit: currentCommit,
repoName: repo.name,
relName: branch.name
})
currentCommit = repo.commits.get(currentCommit.parent)28 29 30 31 32
return flatPatches
})
})
return cachedFlatPatches28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
return flatPatches
})
const tags = repo.tags.flatMap((tag) => {
const flatPatches: Array<FlatPatchRecord> = []
let currentCommit: ReturnType<Repository['commits']['get']> = repo.commits.get(tag.sha)
while (currentCommit !== undefined) {
flatPatches.push({
type: "tag",
commit: currentCommit,
repoName: repo.name,
relName: tag.name,
})
currentCommit = repo.commits.get(currentCommit.parent)
}
return flatPatches
})
return [...branches, ...tags]
})
return cachedFlatPatches2 3 4 5 6 7
export type PatchPage = {
repoName: string,
branchName: string,
commits: Array<ReturnType<Repository['commits']['get']>>,
pageNumber: number,
}2 3 4 5 6 7 8
export type PatchPage = {
repoName: string,
relName: string,
type: "branch" | "tag",
commits: Array<ReturnType<Repository['commits']['get']>>,
pageNumber: number,
}20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
const index = paginatedPatches.findIndex((page) => {
return (
page.repoName === patch.repoName
&& page.branchName == patch.branchName
&& page.commits.length <= patchesPerPage
)
})
if (index === -1) {
const pageNumber = paginatedPatches.filter(page => (page.repoName === patch.repoName && page.branchName === patch.branchName)).length + 1
paginatedPatches.push({
repoName: patch.repoName,
branchName: patch.branchName,
commits: [patch.commit],
// current page number is one more than "how many items in paginatedPatches already
// have repoName as their repo name.
pageNumber,20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
const index = paginatedPatches.findIndex((page) => {
return (
page.repoName === patch.repoName
&& page.relName == patch.relName
&& page.type == patch.type
&& page.commits.length <= patchesPerPage
)
})
if (index === -1) {
const pageNumber = paginatedPatches.filter(page => (
page.repoName === patch.repoName
&& page.relName === patch.relName
&& page.type === patch.type
)).length + 1
paginatedPatches.push({
repoName: patch.repoName,
relName: patch.relName,
commits: [patch.commit],
type: patch.type,
// current page number is one more than "how many items in paginatedPatches already
// have repoName as their repo name.
pageNumber,161 162 163 164 165 166
const branchHead = branchHeadRes.stdout.split(" ")[0]
const result = {
name: branch.name,
head: branchHead,
fileList: await getFileList(branch.name, repoLocation)
}
if (branch.description) { result['description'] = branch.description }161 162 163 164 165 166
const branchHead = branchHeadRes.stdout.split(" ")[0]
const result = {
name: branch.name,
sha: branchHead,
fileList: await getFileList(branch.name, repoLocation)
}
if (branch.description) { result['description'] = branch.description }189 190 191 192 193 194 195 196 197 198 199 200 201
const compareToBranch = branches.find((test) => test.name === compareTo)
const compareToBranchCommits = new Set<string>()
let currentCommit = commits.get(compareToBranch.head)
while (currentCommit !== undefined) {
compareToBranchCommits.add(currentCommit.hash)
currentCommit = commits.get(currentCommit.parent)
}
const thisBranchCommits = new Set<string>()
currentCommit = commits.get(branch.head)
while (currentCommit !== undefined) {
thisBranchCommits.add(currentCommit.hash)
currentCommit = commits.get(currentCommit.parent)189 190 191 192 193 194 195 196 197 198 199 200 201
const compareToBranch = branches.find((test) => test.name === compareTo)
const compareToBranchCommits = new Set<string>()
let currentCommit = commits.get(compareToBranch.sha)
while (currentCommit !== undefined) {
compareToBranchCommits.add(currentCommit.hash)
currentCommit = commits.get(currentCommit.parent)
}
const thisBranchCommits = new Set<string>()
currentCommit = commits.get(branch.sha)
while (currentCommit !== undefined) {
thisBranchCommits.add(currentCommit.hash)
currentCommit = commits.get(currentCommit.parent)