Switching some more things over to the new Repository type

7e40e5b6c81b4a222015b3d5586bc53eebd258c5

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.
main.ts:93
Before
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) => {
After
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) => {
main.ts:110
Before
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)
After
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)
main.ts:186
Before
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.stdout
After
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: 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.stdout
main.ts:216
Before
215
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})`)
After
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})`)
main.ts:336
Before
335
336
337
338








339
340
        nav: {
          repoName: (data) => data.branchInfo.repoName,
          branchName: (data) => data.branchInfo.branchName,
        }
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
      },
      navTab: "files",
    }
After
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",
    }
main.ts:362
Before
361
362
363
364








365
366
        nav: {
          repoName: (data) => data.branch.repoName,
          branchName: (data) => data.branch.branchName,
        }
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
      },
      navTab: "landing",
    }
After
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",
    }
main.ts:398
Before
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,
After
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,
main.ts:429
Before
After
partial_templates/main_top.njk:83
Before
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>
After
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>
schemas/ReposConfiguration.json:34
Before
33
34
35


36


















37
38
        },
        "branchesToPull": {
          "items": {
⁣
⁣
            "type": "string"
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
          },
          "type": "array"
        },
After
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"
        },
schemas/ReposConfiguration.json:52
Before
51
52
53
54


























55
        },
        "location": {
          "type": "string"
        }
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
⁣
      },
      "required": [
After
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": [
src/branches.ts:1
Before

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,
      }
    })
  })
After
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,
      }
    })
  })
src/configTypes.ts:51
Before
50
51
52
53

54
55
  location: string,
  description?: string,
  defaultBranch: string,
  branchesToPull: Array<string>,
⁣
  languageExtensions?: {
    [fileExtension: string]: string
  },
After
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
  },
src/dataTypes.ts:5
Before
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,
After
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,
src/dataTypes.ts:25
Before
24
25
26
27
28
29
30
    }>
  }>,
}

export type BranchInfo = {
  files: Array<string>,
  patches: Array<any>
}
After
24
25




    }>
  }>,
⁣
⁣
⁣
⁣
⁣
}
src/flatFiles.ts:1
Before
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,
        }
      })
    })
After
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,
        }
      })
    })
src/flatPatches.ts:1
Before

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,
        }
      })
    })
  })
After
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
⁣
⁣
⁣
⁣
⁣
    })
  })
src/repos.ts:1
Before
After
src/vcses/git/operations.ts:38
Before
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) {
After
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) {
src/vcses/git/operations.ts:62
Before
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")) {
After
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")) {
src/vcses/operations.ts:2
Before
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}>>,
  }
}
After
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}>>,
  }
}
templates/files.njk:1
Before
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 %}
After
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 %}
templates/index.njk:1
Before
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>
After
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>