1
mirror of https://github.com/jakejarvis/hugo-extended.git synced 2025-11-17 08:30:51 -05:00
Files
hugo-extended/install.js

157 lines
4.9 KiB
JavaScript

"use strict";
const fs = require("fs");
const stream = require("stream");
const { promisify } = require("util");
const path = require("path");
const execa = require("execa");
const chalk = require("chalk");
const got = require("got");
const decompress = require("decompress");
const sumchecker = require("sumchecker");
installHugo()
.then((bin) => {
// print output of `hugo version` to console
const { stdout } = execa.sync(bin, ["version"]);
return stdout;
})
.then((version) => {
console.log(chalk.green("✔ Hugo installed successfully!"));
console.log(version);
})
.catch((error) => {
// pass whatever error occured along the way along to console
console.error(chalk.red("✖ Hugo installation failed. :("));
throw error;
});
async function installHugo() {
// this package's version number (should) always match the Hugo release we want
const { version } = require("./package.json");
const downloadBaseUrl = `https://github.com/gohugoio/hugo/releases/download/v${version}/`;
const releaseFile = getArchiveFilename(version, process.platform, process.arch);
const checksumFile = `hugo_${version}_checksums.txt`;
// stop here if there's nothing we can download
if (!releaseFile) {
throw "Are you sure this platform is supported?";
}
const releaseUrl = downloadBaseUrl + releaseFile;
const checksumUrl = downloadBaseUrl + checksumFile;
const vendorDir = path.join(__dirname, "vendor");
const archivePath = path.join(vendorDir, releaseFile);
const checksumPath = path.join(vendorDir, checksumFile);
const binName = process.platform === "win32" ? "hugo.exe" : "hugo";
const binPath = path.join(vendorDir, binName);
try {
// ensure the target directory exists
await fs.promises.mkdir(vendorDir, { recursive: true });
await Promise.all([
// fetch the archive file from GitHub
downloadFile(releaseUrl, archivePath),
// fetch the checksum file from GitHub
downloadFile(checksumUrl, checksumPath),
]);
// validate the checksum of the download
await checkChecksum(vendorDir, checksumPath, releaseFile);
// extract the downloaded file
await decompress(archivePath, vendorDir);
} finally {
await Promise.all([
// delete the downloaded archive when finished
deleteFile(archivePath),
// ...and the checksum file
deleteFile(checksumPath),
]);
}
// return the full path to our Hugo binary
return binPath;
}
async function downloadFile(url, dest) {
const pipeline = promisify(stream.pipeline);
return await pipeline(
got.stream(url, { followRedirect: true }), // GitHub releases redirect to unpredictable URLs
fs.createWriteStream(dest),
);
}
async function deleteFile(path) {
if (fs.existsSync(path)) {
return await fs.promises.unlink(path);
} else {
return;
}
}
async function checkChecksum(baseDir, checksumFile, binFile) {
const checker = new sumchecker.ChecksumValidator("sha256", checksumFile, {
// returns a completely different hash without this for some reason
defaultTextEncoding: "binary",
});
return await checker.validate(baseDir, binFile);
}
// Hugo Extended supports: macOS x64, macOS ARM64, Linux x64, Windows x64.
// all other combos fall back to vanilla Hugo. there are surely much better ways
// to do this but this is easy to read/update. :)
function getArchiveFilename(version, os, arch) {
const filename =
// macOS
os === "darwin" && arch === "x64" ?
`hugo_extended_${version}_macOS-64bit.tar.gz` :
os === "darwin" && arch === "arm64" ?
`hugo_extended_${version}_macOS-ARM64.tar.gz` :
// Windows
os === "win32" && arch === "x64" ?
`hugo_extended_${version}_Windows-64bit.zip` :
os === "win32" && arch.endsWith("32") ?
`hugo_${version}_Windows-32bit.zip` :
// Linux
os === "linux" && arch === "x64" ?
`hugo_extended_${version}_Linux-64bit.tar.gz` :
os === "linux" && arch.endsWith("32") ?
`hugo_${version}_Linux-32bit.tar.gz` :
os === "linux" && arch === "arm" ?
`hugo_${version}_Linux-ARM.tar.gz` :
os === "linux" && arch === "arm64" ?
`hugo_${version}_Linux-ARM64.tar.gz` :
// FreeBSD
os === "freebsd" && arch === "x64" ?
`hugo_${version}_FreeBSD-64bit.tar.gz` :
os === "freebsd" && arch.endsWith("32") ?
`hugo_${version}_FreeBSD-32bit.tar.gz` :
os === "freebsd" && arch === "arm" ?
`hugo_${version}_FreeBSD-ARM.tar.gz` :
os === "freebsd" && arch === "arm64" ?
`hugo_${version}_FreeBSD-ARM64.tar.gz` :
// OpenBSD
os === "openbsd" && arch === "x64" ?
`hugo_${version}_OpenBSD-64bit.tar.gz` :
os === "openbsd" && arch.endsWith("32") ?
`hugo_${version}_OpenBSD-32bit.tar.gz` :
os === "openbsd" && arch === "arm" ?
`hugo_${version}_OpenBSD-ARM.tar.gz` :
os === "openbsd" && arch === "arm64" ?
`hugo_${version}_OpenBSD-ARM64.tar.gz` :
// not gonna work :(
null;
return filename;
}
module.exports.installHugo = installHugo;