Tucker McKnight
Change the before hook to an exported function Also pass in the site output directory to the getLocation function, since all calls to git now check in the cloned copy of the repo in the _site dir (or whatever the output dir is) instead of checking the user's original, local copy of the repo. This also means that remote URLs can be used in your eleventy config. An explanation for the before hook change is in wiki/projects/clone-early.md. Basically, it seems like a plugin can't actually have a before hook run before the site generation happens. So instead, I'm exporting the before hook function so that the user can manually add it as a before hook in the eleventy config for their main site.
26
26
// TODO document how people need to do this and why. And maybe file 11ty bug?
export function beforeHook(eleventyConfig, reposConfiguration) {
return async ({directories}) => {
const cwd = process.cwd()
const reposPath = reposConfiguration.path || ""
// Check to see if there is already a repo in all of the locations
// that should have one.
for (let repoName in reposConfiguration.repos) {
const repoConfig = reposConfiguration.repos[repoName]
const repoPath = directories.output + reposPath + "/" + eleventyConfig.getFilter("slugify")(repoName)
const gitRepoName = eleventyConfig.getFilter("slugify")(repoName) + ".git"
// If it is there, do git pull
if (fsImport.existsSync(repoPath + ".git")) {
// git repos are just in the repos folder, not in their subdir
// create string of commands saying 'git fetch origin branch:branch' for each branch
const location = directories.output + reposPath + "/" + gitRepoName
const fetchCommands = repoConfig.branchesToPull.map(branch => `git -C ${location} fetch origin ${branch}:${branch}`).join('; ')
await exec(`${fetchCommands} && git -C ${location} update-server-info`)
} else {
// If it is not there, do git clone
// todo: does this work if the latest branch is not checked
// out locally?
let originalLocation = cwd + "/" + repoConfig.location
if (repoConfig.location.startsWith("https://") || repoConfig.location.startsWith("ssh://")) {
originalLocation = repoConfig.location
}
await exec(`git clone ${originalLocation} ${directories.output + reposPath + "/" + gitRepoName} --bare`)
await exec(`git -C ${directories.output + reposPath + "/" + gitRepoName} update-server-info`)
}
const location = directories.output + reposPath + "/" + gitRepoName
await exec(`git -C ${location} symbolic-ref HEAD refs/heads/${repoConfig.defaultBranch}`)
}
}
}
35
const reposData = await repos(reposConfiguration)
35
const reposData = await repos(reposConfiguration, eleventyConfig.dir.output)
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
eleventyConfig.on(
"eleventy.before",
async ({ directories }) => {
const cwd = process.cwd()
// Check to see if there is already a repo in all of the locations
// that should have one.
for (let repoName in reposConfiguration.repos) {
const repoConfig = reposConfiguration.repos[repoName]
const repoPath = eleventyConfig.dir.output + reposPath + "/" + eleventyConfig.getFilter("slugify")(repoName)
const gitRepoName = eleventyConfig.getFilter("slugify")(repoName) + ".git"
// If it is there, do git pull
if (fsImport.existsSync(repoPath + ".git")) {
// git repos are just in the repos folder, not in their subdir
// create string of commands saying 'git fetch origin branch:branch' for each branch
const location = eleventyConfig.dir.output + reposPath + "/" + gitRepoName
const fetchCommands = repoConfig.branchesToPull.map(branch => `git -C ${location} fetch origin ${branch}:${branch}`).join('; ')
await exec(`${fetchCommands} && git -C ${location} update-server-info`)
} else {
// If it is not there, do git clone
// todo: does this work if the latest branch is not checked
// out locally?
const originalLocation = cwd + "/" + repoConfig.location
await exec(`git clone ${originalLocation} ${eleventyConfig.dir.output + reposPath + "/" + gitRepoName} --bare`)
await exec(`git -C ${eleventyConfig.dir.output + reposPath + "/" + gitRepoName} update-server-info`)
}
const location = eleventyConfig.dir.output + reposPath + "/" + gitRepoName
await exec(`git -C ${location} symbolic-ref HEAD refs/heads/${repoConfig.defaultBranch}`)
}
}
)
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
222
const location = getLocation(reposConfiguration, repo)
222
const location = getLocation(reposConfiguration, eleventyConfig.dir.output, repo)
236
const location = getLocation(reposConfiguration, repo)
236
const location = getLocation(reposConfiguration, eleventyConfig.dir.output, repo)
255
const location = getLocation(reposConfiguration, repoName)
255
const location = getLocation(reposConfiguration, eleventyConfig.dir.output, repoName)
70 71 72
const getLocation = (reposConfig: ReposConfiguration, repoName: string): string => {
const config = reposConfig.repos[repoName]
return config.location
70 71 72
const getLocation = (reposConfig: ReposConfiguration, outputDir: string, repoName: string): string => {
return outputDir + (reposConfig.path || "") + "/" + repoName + ".git"
26
const repos: (reposConfig: ReposConfiguration) => Promise<Array<Repository>> = async (reposConfig) => {
26
const repos: (reposConfig: ReposConfiguration, outputDir: string) => Promise<Array<Repository>> = async (reposConfig, outputDir) => {
36 37
const repoLocation = getLocation(reposConfig, repoName)
const repoLocation = getLocation(reposConfig, repoName)
36 37
const repoLocation = getLocation(reposConfig, outputDir, repoName)
const repoLocation = getLocation(reposConfig, outputDir, repoName)
13
13
- this was surprisingly easy; just changing eleventy.before to eleventy.after
seems to have worked for doing the clone before the site generation.
- the build steps happen in their own, separate eleventy.after callback
now. Which also works, and might have fixed a race condition where it was
sometimes running the build steps before the cloned repo was available.
- Next step: do not reference the original repository after the clone happens.
Always reference the cloned repo instead.
Places that mention `git -C`. Check if these need to be replaced:
- [x] main.ts: const fetchCommands = repoConfig.branchesToPull.map(branch => `git -C ${location} fetch origin ${branch}:${branch}`).join('; ')
- [x] main.ts: await exec(`${fetchCommands} && git -C ${location} update-server-info`)
- [x] main.ts: await exec(`git -C ${eleventyConfig.dir.output + reposPath + "/" + gitRepoName} update-server-info`)
- [x] main.ts: await exec(`git -C ${location} symbolic-ref HEAD refs/heads/${repoConfig.defaultBranch}`)
- [x] main.ts: await exec(`git -C ${tempDirRepoPath} checkout ${branch}`)
- [x] main.ts: const command = `git -C ${location} show ${branch}:${filename}`
- [x] main.ts: const command = `git -C ${location} show ${branchName}:README.md`
- [x] src/repos.ts: const branchHeadRes = await exec(`git -C ${repoLocation} show-ref refs/heads/${branchName}`)
- [x] src/vcses/git/operations.ts: const command = `git -C ${repoLocation} ls-tree -r --name-only ${branchName}`
- [x] src/vcses/git/operations.ts: const totalPatchesCountRes = await exec(`git -C ${repoLocation} rev-list --count ${branchName}`)
- [x] src/vcses/git/operations.ts: const gitLogSubsetRes = await exec(`git -C ${repoLocation} log ${branchName} -p -n 10 --skip ${i}`)
- [x] src/vcses/git/operations.ts: const command = `git -C ${repoLocation} blame --porcelain ${branch} ${filename}`
^ Most of those were fixed by changing what repo location is found in
`getLocation`.
### Before hook issue
Seems like a plugin actually can't make its before hook get triggered before the site generation happens.
Because the plugin is now exclusively reading things from the _cloned_ repository, and not the source repo
on the computer, the before hook really does need to happen before the site generation happens. Apparently
it wasn't happening before, but this wasn't an issue because the plugin was just reading directly from the
source repo.
I've worked around this by not calling the `eleventyConfig.on("eleventy.before")` _in_ the plugin, but rather,
exporting a function that the user will need to call as a before hook in their own eleventy config. Also, it needs
to be `"beforeConfig"` instead of just `"before"` -- seems like plugins are executed as part of the config step.