Tucker McKnight <tmcknight@instructure.com> | Sat Jun 20 2026
Only read from locally-cloned repo for operations that require local repos Commands called with `git -C` would fail if the location in the repo config was a remote URL. This is because `git -C` only works on local repos. For git commands that require a local repo, we need to only call then on the already-cloned, local repository. (This is what we should be doing all the time anyway.) Some functions now have to know the slugify function and output directory, then, in order to find the path to the cloned repo. This should be done more cleanly in the future, like with a globally-available "localRepoPath" function.
129 130 131 132 133 134
// Run the command for each step in each branch
await exec(`(cd ${tempDirRepoPath} && ${buildStep.command})`)
// Copy the specified folders from the "from" to the "to" dir
await exec(`cp -r ${tempDirRepoPath}/${buildStep.copyFrom} ${directories.output}${eleventyConfig.getFilter("slugify")(repoName)}/branches/${eleventyConfig.getFilter("slugify")(branch)}/${buildStep.copyTo}`)
}
}
for (let tag of tagNames) {129 130 131 132 133 134
// Run the command for each step in each branch
await exec(`(cd ${tempDirRepoPath} && ${buildStep.command})`)
// Copy the specified folders from the "from" to the "to" dir
await exec(`cp -r ${tempDirRepoPath}/${buildStep.copyFrom} ${directories.output}${slugify(repoName)}/branches/${slugify(branch)}/${buildStep.copyTo}`)
}
}
for (let tag of tagNames) {138 139 140 141 142 143
// Run the command for each step in each branch
await exec(`(cd ${tempDirRepoPath} && ${buildStep.command})`)
// Copy the specified folders from the "from" to the "to" dir
await exec(`cp -r ${tempDirRepoPath}/${buildStep.copyFrom} ${directories.output}${eleventyConfig.getFilter("slugify")(repoName)}/tags/${eleventyConfig.getFilter("slugify")(tag)}/${buildStep.copyTo}`)
}
}
// delete the temp dirs138 139 140 141 142 143
// Run the command for each step in each branch
await exec(`(cd ${tempDirRepoPath} && ${buildStep.command})`)
// Copy the specified folders from the "from" to the "to" dir
await exec(`cp -r ${tempDirRepoPath}/${buildStep.copyFrom} ${directories.output}${slugify(repoName)}/tags/${slugify(tag)}/${buildStep.copyTo}`)
}
}
// delete the temp dirs17 18 19 20 21 22 23 24 25 26 27
const tagsForReposMap: Map<string, Array<{name: string}>> = new Map()
const getBranchesAndTags = async (
repoConfig: GitConfig,
repoName: string
): Promise<{
branches: Array<{name: string, description?: string, compareTo?: string}>,
tags: Array<{name: string}>,
}> => {
const cachedBranchNames = branchesForReposMap.get(repoName)
const cachedTagNames = tagsForReposMap.get(repoName)
if (cachedBranchNames !== undefined) {17 18 19 20 21 22 23 24 25 26 27 28 29 30
const tagsForReposMap: Map<string, Array<{name: string}>> = new Map()
const getBranchesAndTags = async (
reposConfig: ReposConfiguration,
repoName: string,
outputDir: string,
slugify: Function,
): Promise<{
branches: Array<{name: string, description?: string, compareTo?: string}>,
tags: Array<{name: string}>,
}> => {
const repoConfig = reposConfig.repos[repoName]
const cachedBranchNames = branchesForReposMap.get(repoName)
const cachedTagNames = tagsForReposMap.get(repoName)
if (cachedBranchNames !== undefined) {30 31 32 33 34 35 36
}
// Get all branches and tags available in the repository
const allBranches = (await exec(`git -C ${repoConfig.location} branch --format="%(refname:short)"`)).stdout.split("\n").filter(branch => branch !== '')
const allTags = (await exec(`git -C ${repoConfig.location} tag`)).stdout.split("\n").filter(tag => tag !== '')
// Sort the list of branch descriptions from `branches` by the length
// of their patterns.30 31 32 33 34 35 36 37 38 39
}
// Get all branches and tags available in the repository
// Get it from the local, cloned location, instead of the remote, since `git -C` commands
// don't work on remote locations.
const clonedLocation = getLocation(reposConfig, outputDir, repoName, slugify)
const allBranches = (await exec(`git -C ${clonedLocation} branch --format="%(refname:short)"`)).stdout.split("\n").filter(branch => branch !== '')
const allTags = (await exec(`git -C ${clonedLocation} tag`)).stdout.split("\n").filter(tag => tag !== '')
// Sort the list of branch descriptions from `branches` by the length
// of their patterns.150 151 152 153 154 155
for (const repoName of repoNames) {
const repoLocation = getLocation(reposConfig, outputDir, repoName, slugify)
const commits: Repository['commits'] = new Map()
const branchesAndTags = await getBranchesAndTags(reposConfig.repos[repoName], repoName)
const branchNames = branchesAndTags.branches.map(branch => branch.name)
for (const branchName of branchNames) {
await addBranchToCommitsMap(branchName, repoLocation, commits)150 151 152 153 154 155
for (const repoName of repoNames) {
const repoLocation = getLocation(reposConfig, outputDir, repoName, slugify)
const commits: Repository['commits'] = new Map()
const branchesAndTags = await getBranchesAndTags(reposConfig, repoName, outputDir, slugify)
const branchNames = branchesAndTags.branches.map(branch => branch.name)
for (const branchName of branchNames) {
await addBranchToCommitsMap(branchName, repoLocation, commits)242 243 244 245 246
break
}
if (fileMap.has(`${filename}-${currentCommit.hash}`)) {
return fileMap.get(`${filename}-${currentCommit.hash}`)
}
242 243 244 245 246 247 248
break
}
if (fileMap.has(`${filename}-${currentCommit.hash}`)) {
// TODO: maybe cache here as well, so that we don't have to loop as many
// times next time?
return fileMap.get(`${filename}-${currentCommit.hash}`)
}
256 257 258 259 260
blameLines,
}
fileMap.set(key, commit)
return commit
},256 257 258 259 260 261 262
blameLines,
}
// TODO: cache it as deeply in the git history as it can be, so that as many other commits
// benefit from this as possible.
fileMap.set(key, commit)
return commit
},