Files snapshot from mithril-server-side-rendering
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
b8a3bb Tucker McKnight
7e40e5 Tucker McKnight
b8a3bb Tucker McKnight
b8a3bb Tucker McKnight
fb82fe Tucker McKnight
fb82fe Tucker McKnight
e2d4fd Tucker McKnight
b8a3bb Tucker McKnight
e2d4fd Tucker McKnight
e2d4fd Tucker McKnight
7e40e5 Tucker McKnight
b8a3bb Tucker McKnight
fb82fe Tucker McKnight
fb82fe Tucker McKnight
fb82fe Tucker McKnight
b8a3bb Tucker McKnight
01b859 Tucker McKnight
e2d4fd Tucker McKnight
01b859 Tucker McKnight
e2d4fd Tucker McKnight
e2d4fd Tucker McKnight
e2d4fd Tucker McKnight
e2d4fd Tucker McKnight
e2d4fd Tucker McKnight
e2d4fd Tucker McKnight
754e1b Tucker McKnight
e2d4fd Tucker McKnight
01b859 Tucker McKnight
01b859 Tucker McKnight
01b859 Tucker McKnight
01b859 Tucker McKnight
01b859 Tucker McKnight
01b859 Tucker McKnight
01b859 Tucker McKnight
01b859 Tucker McKnight
01b859 Tucker McKnight
01b859 Tucker McKnight
01b859 Tucker McKnight
01b859 Tucker McKnight
01b859 Tucker McKnight
7e40e5 Tucker McKnight
01b859 Tucker McKnight
01b859 Tucker McKnight
01b859 Tucker McKnight
01b859 Tucker McKnight
01b859 Tucker McKnight
01b859 Tucker McKnight
01b859 Tucker McKnight
01b859 Tucker McKnight
01b859 Tucker McKnight
01b859 Tucker McKnight
01b859 Tucker McKnight
01b859 Tucker McKnight
01b859 Tucker McKnight
01b859 Tucker McKnight
01b859 Tucker McKnight
01b859 Tucker McKnight
01b859 Tucker McKnight
01b859 Tucker McKnight
01b859 Tucker McKnight
01b859 Tucker McKnight
01b859 Tucker McKnight
01b859 Tucker McKnight
01b859 Tucker McKnight
01b859 Tucker McKnight
7e40e5 Tucker McKnight
7e40e5 Tucker McKnight
e2d4fd Tucker McKnight
01b859 Tucker McKnight
01b859 Tucker McKnight
01b859 Tucker McKnight
01b859 Tucker McKnight
01b859 Tucker McKnight
01b859 Tucker McKnight
01b859 Tucker McKnight
01b859 Tucker McKnight
01b859 Tucker McKnight
01b859 Tucker McKnight
01b859 Tucker McKnight
01b859 Tucker McKnight
e2d4fd Tucker McKnight
e2d4fd Tucker McKnight
01b859 Tucker McKnight
e2d4fd Tucker McKnight
e2d4fd Tucker McKnight
01b859 Tucker McKnight
01b859 Tucker McKnight
01b859 Tucker McKnight
01b859 Tucker McKnight
01b859 Tucker McKnight
b8a3bb Tucker McKnight
b8a3bb Tucker McKnight
4f267d Tucker McKnight
b8a3bb Tucker McKnight
2ecee5 Tucker McKnight
b8a3bb Tucker McKnight
b8a3bb Tucker McKnight
b8a3bb Tucker McKnight
4f267d Tucker McKnight
7e40e5 Tucker McKnight
7e40e5 Tucker McKnight
e2d4fd Tucker McKnight
01b859 Tucker McKnight
7e40e5 Tucker McKnight
01b859 Tucker McKnight
7e40e5 Tucker McKnight
b8a3bb Tucker McKnight
b8a3bb Tucker McKnight
01b859 Tucker McKnight
2ecee5 Tucker McKnight
01b859 Tucker McKnight
fb82fe Tucker McKnight
01b859 Tucker McKnight
01b859 Tucker McKnight
fb82fe Tucker McKnight
01b859 Tucker McKnight
fb82fe Tucker McKnight
01b859 Tucker McKnight
01b859 Tucker McKnight
e07418 Tucker McKnight
01b859 Tucker McKnight
fb82fe Tucker McKnight
fb82fe Tucker McKnight
4eaa3d Tucker McKnight
e07418 Tucker McKnight
e07418 Tucker McKnight
4eaa3d Tucker McKnight
e07418 Tucker McKnight
e07418 Tucker McKnight
e07418 Tucker McKnight
e07418 Tucker McKnight
e07418 Tucker McKnight
e07418 Tucker McKnight
e07418 Tucker McKnight
e07418 Tucker McKnight
e07418 Tucker McKnight
e07418 Tucker McKnight
e07418 Tucker McKnight
e07418 Tucker McKnight
e07418 Tucker McKnight
e07418 Tucker McKnight
e07418 Tucker McKnight
e07418 Tucker McKnight
e07418 Tucker McKnight
4eaa3d Tucker McKnight
4eaa3d Tucker McKnight
4eaa3d Tucker McKnight
4eaa3d Tucker McKnight
4eaa3d Tucker McKnight
4eaa3d Tucker McKnight
4eaa3d Tucker McKnight
4eaa3d Tucker McKnight
4eaa3d Tucker McKnight
4eaa3d Tucker McKnight
e07418 Tucker McKnight
e07418 Tucker McKnight
4f267d Tucker McKnight
7e40e5 Tucker McKnight
4f267d Tucker McKnight
4eaa3d Tucker McKnight
fb82fe Tucker McKnight
95482f Tucker McKnight
fb82fe Tucker McKnight
7e40e5 Tucker McKnight
7e40e5 Tucker McKnight
b8a3bb Tucker McKnight
b8a3bb Tucker McKnight
4f267d Tucker McKnight
b8a3bb Tucker McKnight
b8a3bb Tucker McKnight
e2d4fd Tucker McKnight
import {
type ReposConfiguration,
type GitConfig,
} from './configTypes.ts'
import util from 'util'
import childProcess from 'child_process'
import path from 'path'
import { type Repository} from './dataTypes.ts'
import cloneUrl from './vcses/git/helpers.ts'
import { addBranchToCommitsMap } from './vcses/git/operations.ts'
import { getLocation} from './helpers.ts'
import { getFileList } from './vcses/git/operations.ts'
const exec = util.promisify(childProcess.exec)
const branchesForReposMap: Map<string, Array<{name: string, description?: string, compareTO?: string}>> = new Map()
const getBranches = async (repoConfig: GitConfig, repoName: string): Promise<Array<{name: string, description?: string, compareTo?: string}>> => {
const cachedBranchNames = branchesForReposMap.get(repoName)
if (cachedBranchNames !== undefined) {
return cachedBranchNames
}
// Get all branches available in the repository
const allBranches = (await exec(`git -C ${repoConfig.location} branch --format="%(refname:short)"`)).stdout.split("\n").filter(branch => branch !== '')
// Sort the list of branch descriptions from branchesToPull by the length
// of their patterns.
// Then, for each branch from the repository, see if it matches a pattern.
// If that pattern has rules associated with it (like a description or a max),
// apply those.
type RulesObject = {max?: number, description?: string, compareTo?: string}
let branchRules: Array<{pattern: string, matches: Array<string>, rules: RulesObject}> = repoConfig.branchesToPull.map((branchDescription) => {
const rules: RulesObject = {}
if (typeof branchDescription !== 'string') {
if (branchDescription.max) { rules.max = branchDescription.max }
if (branchDescription.description) { rules.description = branchDescription.description }
if (branchDescription.compareTo) { rules.compareTo = branchDescription.compareTo }
}
return {
pattern: (typeof branchDescription === 'string' ? branchDescription : branchDescription.pattern),
matches: [],
rules,
}
})
branchRules = branchRules.toSorted((a, b) => b.pattern.length - a.pattern.length)
allBranches.forEach((branchName) => {
const matchingPatternIndex = branchRules.findIndex((branchRule) => {
return path.matchesGlob(branchName, branchRule.pattern)
})
if (matchingPatternIndex === -1) { return }
const matchedRule = branchRules[matchingPatternIndex]
matchedRule.matches.push(branchName)
if (
matchedRule.rules?.max
&& matchedRule.rules?.max < matchedRule.matches.length
) {
matchedRule.matches.pop()
}
})
const branches: Array<{
name: string,
description?: string,
compareTo?: string,
}> = branchRules.map((branchRule) => {
return branchRule.matches.map((match) => {
const result = {name: match}
if (branchRule.rules.description) { result['description'] = branchRule.rules.description }
if (branchRule.rules.compareTo) { result['compareTo'] = branchRule.rules.compareTo }
return result
}).flat()
}).flat()
if (branchesForReposMap.get(repoName) === undefined) {
branchesForReposMap.set(repoName, branches)
}
return branches
}
const getBranchNames = async (repoConfig, repoName) => {
return (await getBranches(repoConfig, repoName)).map(branch => branch.name)
}
let cachedRepos: Array<Repository> | null = null
const repos: (reposConfig: ReposConfiguration, outputDir: string) => Promise<Array<Repository>> = async (reposConfig, outputDir) => {
if (cachedRepos !== null) { return cachedRepos }
const repoNames = Object.keys(reposConfig.repos)
cachedRepos = []
for (const repoName of repoNames) {
const repoLocation = getLocation(reposConfig, outputDir, repoName)
const branchesToAdd = await getBranches(reposConfig.repos[repoName], repoName)
const commits: Repository['commits'] = new Map()
for (const branchName of await getBranchNames(reposConfig.repos[repoName], repoName)) {
await addBranchToCommitsMap(branchName, repoLocation, commits)
}
const branches = await Promise.all(branchesToAdd.map(async (branch) => {
const repoLocation = getLocation(reposConfig, outputDir, repoName)
const branchHeadRes = await exec(`git -C ${repoLocation} show-ref refs/heads/${branch.name}`)
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 }
if (branch.compareTo) { result['compareTo'] = branch.compareTo }
return result
}))
const branchesWithCompareToInfo: Repository['branches'] = branches.map((branch) => {
const branchDescription = branchesToAdd.find(branchToAdd => branchToAdd.name === branch.name)
const compareTo = branchDescription.compareTo || reposConfig.repos[repoName].defaultBranch
const compareToBranch = branches.find((test) => test.name === compareTo)
const compareToBranchCommits = new Set()
let currentCommit = commits.get(compareToBranch.head)
while (currentCommit !== undefined) {
compareToBranchCommits.add(currentCommit.hash)
currentCommit = commits.get(currentCommit.parent)
}
const thisBranchCommits = new Set()
currentCommit = commits.get(branch.head)
while (currentCommit !== undefined) {
thisBranchCommits.add(currentCommit.hash)
currentCommit = commits.get(currentCommit.parent)
}
// At this point, we have all commits in the compareTo branch in one set, and
// all commits from this branch in another set.
const onlyInThisBranch = Array.from(thisBranchCommits).filter(thisBranchCommit => !compareToBranchCommits.has(thisBranchCommit)).length
const onlyInCompareToBranch = Array.from(compareToBranchCommits).filter(compareToBranchCommit => !thisBranchCommits.has(compareToBranchCommit)).length
const compareToInfo = {
ahead: onlyInThisBranch,
behind: onlyInCompareToBranch,
compareTo: compareTo,
}
return {...branch, ...compareToInfo}
})
cachedRepos.push({
name: repoName,
description: reposConfig.repos[repoName].description,
branches: branchesWithCompareToInfo,
cloneUrl: cloneUrl.cloneUrl(reposConfig.baseUrl, repoName),
defaultBranch: reposConfig.repos[repoName].defaultBranch,
tags: [], // todo
commits,
})
}
return cachedRepos
}
export {repos, getBranchNames}