1
mirror of https://github.com/jakejarvis/hugo-extended.git synced 2025-04-27 11:18:29 -04:00

clean up & speed up install.js

This commit is contained in:
Jake Jarvis 2021-06-02 00:10:18 -04:00
parent e8f5de5e96
commit 2fc3b6fc3b
Signed by: jake
GPG Key ID: 2B0C9CF251E69A39

View File

@ -1,131 +1,152 @@
'use strict'; 'use strict';
const fs = require("fs"); const fs = require('fs');
const path = require("path"); const path = require('path');
const { https } = require("follow-redirects"); const { https } = require('follow-redirects'); // Node's https module doesn't follow redirects, needed for GitHub releases
const decompress = require('decompress'); const decompress = require('decompress');
const sumchecker = require('sumchecker'); const sumchecker = require('sumchecker');
(async () => { installHugo()
install()
.then(() => { .then(() => {
console.log('✔ Hugo installed successfully!'); console.log('✔ Hugo installed successfully!');
}) })
.catch((error) => { .catch((error) => {
console.error('✖ ERROR: Hugo installation failed. :(\n', error); console.error('✖ ERROR: Hugo installation failed. :(\n', error);
}); });
})();
async function install() { async function installHugo() {
// this package's version number (should) always matches the Hugo version we want // this package's version number (should) always match the Hugo release we want
const { version } = require('./package.json'); const { version } = require('./package.json');
const downloadBaseUrl = `https://github.com/gohugoio/hugo/releases/download/v${version}/`; const downloadBaseUrl = `https://github.com/gohugoio/hugo/releases/download/v${version}/`;
const downloadFile = getArchiveFilename(version, process.platform, process.arch);
// Hugo Extended supports: macOS x64, macOS ARM64, Linux x64, Windows x64. const checksumFile = `hugo_${version}_checksums.txt`;
// all other combos fall back to vanilla Hugo.
const checksumFile = `hugo_${version}_checksums.txt`
const downloadFile =
process.platform === 'darwin' && process.arch === 'x64'
? `hugo_extended_${version}_macOS-64bit.tar.gz` :
process.platform === 'darwin' && process.arch === 'arm64'
? `hugo_extended_${version}_macOS-ARM64.tar.gz` :
process.platform === 'win32' && process.arch === 'x64'
? `hugo_extended_${version}_Windows-64bit.zip` :
process.platform === 'win32' && process.arch.endsWith('32')
? `hugo_${version}_Windows-32bit.zip` :
process.platform === 'linux' && process.arch === 'x64'
? `hugo_extended_${version}_Linux-64bit.tar.gz` :
process.platform === 'linux' && process.arch.endsWith('32')
? `hugo_${version}_Linux-32bit.tar.gz` :
process.platform === 'linux' && process.arch === 'arm'
? `hugo_${version}_Linux-ARM.tar.gz` :
process.platform === 'linux' && process.arch === 'arm64'
? `hugo_${version}_Linux-ARM64.tar.gz` :
process.platform === 'freebsd' && process.arch === 'x64'
? `hugo_${version}_FreeBSD-64bit.tar.gz` :
process.platform === 'freebsd' && process.arch.endsWith('32')
? `hugo_${version}_FreeBSD-32bit.tar.gz` :
process.platform === 'freebsd' && process.arch === 'arm'
? `hugo_${version}_FreeBSD-ARM.tar.gz` :
process.platform === 'freebsd' && process.arch === 'arm64'
? `hugo_${version}_FreeBSD-ARM64.tar.gz` :
process.platform === 'openbsd' && process.arch === 'x64'
? `hugo_${version}_OpenBSD-64bit.tar.gz` :
process.platform === 'openbsd' && process.arch.endsWith('32')
? `hugo_${version}_OpenBSD-32bit.tar.gz` :
process.platform === 'openbsd' && process.arch === 'arm'
? `hugo_${version}_OpenBSD-ARM.tar.gz` :
process.platform === 'openbsd' && process.arch === 'arm64'
? `hugo_${version}_OpenBSD-ARM64.tar.gz` :
null;
// stop here if there's nothing we can download // stop here if there's nothing we can download
if (!downloadFile) throw "Are you sure this platform is supported?"; if (!downloadFile) throw 'Are you sure this platform is supported?';
let downloadUrl = downloadBaseUrl + downloadFile; const downloadUrl = downloadBaseUrl + downloadFile;
let checksumUrl = downloadBaseUrl + checksumFile; const checksumUrl = downloadBaseUrl + checksumFile;
let vendorDir = path.join(__dirname, 'vendor'); const vendorDir = path.join(__dirname, 'vendor');
let archivePath = path.join(vendorDir, downloadFile); const archivePath = path.join(vendorDir, downloadFile);
let checksumPath = path.join(vendorDir, checksumFile); const checksumPath = path.join(vendorDir, checksumFile);
let binName = process.platform === 'win32' ? 'hugo.exe' : 'hugo'; const binName = process.platform === 'win32' ? 'hugo.exe' : 'hugo';
let binPath = path.join(vendorDir, binName); const binPath = path.join(vendorDir, binName);
try { try {
// ensure the target directory exists // ensure the target directory exists
await fs.promises.mkdir(vendorDir, { recursive: true }); await fs.promises.mkdir(vendorDir, { recursive: true });
await Promise.all([
// fetch the archive file from GitHub // fetch the archive file from GitHub
await new Promise((resolve, reject) => https.get(downloadUrl, response => { downloadToFile(downloadUrl, archivePath),
// throw an error immediately if the download failed
if (response.statusCode !== 200) {
response.resume();
reject(new Error(`Download failed: status code ${response.statusCode} from ${downloadUrl}`));
return;
}
// pipe the response directly to a file
response.pipe(
fs.createWriteStream(archivePath)
.on('finish', resolve)
.on('error', reject)
);
}).on('error', reject));
// fetch the checksum file from GitHub // fetch the checksum file from GitHub
await new Promise((resolve, reject) => https.get(checksumUrl, response => { downloadToFile(checksumUrl, checksumPath),
// throw an error immediately if the download failed ]);
if (response.statusCode !== 200) {
response.resume();
reject(new Error(`Download failed: status code ${response.statusCode} from ${checksumUrl}`));
return;
}
// pipe the response directly to a file
response.pipe(
fs.createWriteStream(checksumPath)
.on('finish', resolve)
.on('error', reject)
);
}).on('error', reject));
// validate the checksum of the download // validate the checksum of the download
const checker = new sumchecker.ChecksumValidator('sha256', checksumPath, { await checkChecksum(vendorDir, checksumPath, downloadFile);
defaultTextEncoding: 'binary'
});
await checker.validate(vendorDir, downloadFile);
// extract the downloaded file // extract the downloaded file
await decompress(archivePath, vendorDir); await decompress(archivePath, vendorDir);
} finally { } finally {
await Promise.all([
// delete the downloaded archive when finished // delete the downloaded archive when finished
if (fs.existsSync(archivePath)) deleteFile(archivePath),
await fs.promises.unlink(archivePath);
// ...and the checksum file // ...and the checksum file
if (fs.existsSync(checksumPath)) deleteFile(checksumPath),
await fs.promises.unlink(checksumPath); ]);
} }
// return the full path to our Hugo binary // return the full path to our Hugo binary
return binPath; return binPath;
} }
async function downloadToFile(url, dest) {
return new Promise((resolve, reject) => https.get(url, response => {
// throw an error immediately if the download failed
if (response.statusCode !== 200) {
response.resume();
reject(new Error(`Download failed: status code ${response.statusCode} from ${url}`));
return;
}
// pipe the response directly to a file
response.pipe(
fs.createWriteStream(dest)
.on('finish', resolve)
.on('error', reject)
);
}).on('error', reject));
}
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;