mirror of
https://github.com/webinstall/webi-installers.git
synced 2026-08-23 22:16:48 +00:00
ref!: release info from git tags
This commit is contained in:
@@ -0,0 +1,145 @@
|
||||
'use strict';
|
||||
|
||||
require('dotenv').config({ path: '.env' });
|
||||
if (!process.env.REPO_BASE_DIR) {
|
||||
// for stderr
|
||||
console.error('[Warn] REPO_BASE_DIR= not set, using ./repos/');
|
||||
}
|
||||
// ../ because this script is one directory deep
|
||||
let repoBaseDir = process.env.REPO_BASE_DIR || '../repos';
|
||||
|
||||
var Crypto = require('crypto');
|
||||
var util = require('util');
|
||||
var exec = util.promisify(require('child_process').exec);
|
||||
var Fs = require('node:fs/promises');
|
||||
|
||||
var Repos = {};
|
||||
|
||||
Repos.clone = async function (gitUrl, repoPath) {
|
||||
let uuid = Crypto.randomUUID();
|
||||
let tmpPath = `${repoPath}.${uuid}.tmp`;
|
||||
await exec(`git clone --bare --filter=tree:0 ${gitUrl} ${tmpPath}`);
|
||||
await Fs.rename(tmpPath, repoPath);
|
||||
};
|
||||
|
||||
Repos.checkExists = async function (repoPath) {
|
||||
let err = await Fs.access(repoPath).catch(Object);
|
||||
if (!err) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (err.code !== 'ENOENT') {
|
||||
throw err;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
Repos.getTags = async function (repoPath) {
|
||||
var { stdout } = await exec(`git --git-dir=${repoPath} tag`);
|
||||
var rawTags = stdout.trim().split('\n');
|
||||
|
||||
let tags = [];
|
||||
for (let tag of rawTags) {
|
||||
// ex: v1, v2, v1.1, 1.1.0-rc
|
||||
let maybeVersionRe = /^(v\d+|v?\d+\.\d+)/;
|
||||
let maybeVersion = maybeVersionRe.test(tag);
|
||||
if (maybeVersion) {
|
||||
tags.push(tag);
|
||||
}
|
||||
|
||||
// TODO date versions
|
||||
// let maybeVersionDate = /^v?\d{4}[._-]\d{2}[._-]\d{2}[._-]\D/.test(tag);
|
||||
}
|
||||
|
||||
tags = tags.reverse();
|
||||
return tags;
|
||||
};
|
||||
|
||||
Repos.getCommitInfo = async function (repoPath, commitish) {
|
||||
var { stdout } = await exec(
|
||||
`git --git-dir=${repoPath} log -1 --format="%h %H %ad %cd" --date=iso-strict ${commitish}`,
|
||||
);
|
||||
stdout = stdout.trim();
|
||||
var commitParts = stdout.split(/\s+/g);
|
||||
return {
|
||||
commit_id: `${commitParts[0]}`,
|
||||
commit: `${commitParts[1]}`,
|
||||
date: commitParts[2],
|
||||
date_authored: commitParts[3],
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Lists GitHub Releases (w/ uploaded assets)
|
||||
*
|
||||
* @param request
|
||||
* @param {string} owner
|
||||
* @param {string} gitUrl
|
||||
* @returns {PromiseLike<any> | Promise<any>}
|
||||
*/
|
||||
async function getAllReleases(gitUrl) {
|
||||
let all = {
|
||||
releases: [],
|
||||
download: '',
|
||||
};
|
||||
|
||||
let repoName = gitUrl.split('/').pop();
|
||||
repoName = repoName.replace(/\.git$/, '');
|
||||
|
||||
let repoPath = `${repoBaseDir}/${repoName}.git`;
|
||||
|
||||
let isCloned = await Repos.checkExists(repoPath);
|
||||
if (!isCloned) {
|
||||
await Repos.clone(gitUrl, repoPath);
|
||||
}
|
||||
|
||||
let releases = [];
|
||||
let tags = await Repos.getTags(repoPath);
|
||||
for (let tag of tags) {
|
||||
let commitInfo = await Repos.getCommitInfo(repoPath, tag);
|
||||
let date = new Date(commitInfo.date);
|
||||
let version = tag.replace(/^v/, '');
|
||||
|
||||
let rel = {
|
||||
name: `${repoName}-v${version}`,
|
||||
version: tag,
|
||||
git_tag: tag,
|
||||
git_commit_hash: commitInfo.commit_id,
|
||||
//git_long_commit_hash: commitInfo.commit,
|
||||
lts: false,
|
||||
channel: '',
|
||||
date: date.toISOString(),
|
||||
os: '*',
|
||||
arch: '*',
|
||||
ext: 'git',
|
||||
//command: `git clone --depth=1 --single-branch --branch ${tag} ${gitUrl}`,
|
||||
download: gitUrl,
|
||||
};
|
||||
|
||||
releases.push(rel);
|
||||
}
|
||||
all.releases = releases;
|
||||
|
||||
return all;
|
||||
}
|
||||
|
||||
module.exports = getAllReleases;
|
||||
|
||||
if (module === require.main) {
|
||||
(async function main() {
|
||||
let all = await getAllReleases('https://github.com/dense-analysis/ale.git');
|
||||
// for stderr
|
||||
let sample = JSON.stringify(all.releases[0], null, 2);
|
||||
console.error('Sample:');
|
||||
console.error(sample);
|
||||
|
||||
all = require('../_webi/normalize.js')(all);
|
||||
console.info(JSON.stringify(all, null, 2));
|
||||
})()
|
||||
.then(function () {
|
||||
process.exit(0);
|
||||
})
|
||||
.catch(function (err) {
|
||||
console.error(err);
|
||||
});
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
require('dotenv').config({ path: '.env' });
|
||||
if (!process.env.REPO_BASE_DIR) {
|
||||
console.warn('[Warn] REPO_BASE_DIR= not set, using ./repos/');
|
||||
}
|
||||
// ../ because this script is one directory deep
|
||||
let repoBaseDir = process.env.REPO_BASE_DIR || '../repos';
|
||||
|
||||
const util = require('util');
|
||||
const exec = util.promisify(require('child_process').exec);
|
||||
const fs = require('fs').promises;
|
||||
|
||||
/**
|
||||
* Lists GitHub Releases (w/ uploaded assets)
|
||||
*
|
||||
* @param request
|
||||
* @param {string} owner
|
||||
* @param {string} gitUrl
|
||||
* @returns {PromiseLike<any> | Promise<any>}
|
||||
*/
|
||||
async function getAllReleases(gitUrl) {
|
||||
const all = {
|
||||
releases: [],
|
||||
download: ''
|
||||
};
|
||||
|
||||
const repoName = gitUrl.split('/').pop();
|
||||
const repoPath = `${repoBaseDir}/${repoName}`;
|
||||
|
||||
// Function to clone the repository if it doesn't exist
|
||||
async function cloneRepository() {
|
||||
if (!(await repoExists())) {
|
||||
await exec(`git clone --bare ${gitUrl} ${repoPath}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Function to check if the repository already exists
|
||||
async function repoExists() {
|
||||
try {
|
||||
await fs.access(repoPath);
|
||||
return true;
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Function to list all version tags
|
||||
async function listVersionTags() {
|
||||
await cloneRepository();
|
||||
const { stdout } = await exec(`git --git-dir=${repoPath} tag`);
|
||||
const tags = stdout.trim().split('\n');
|
||||
return tags;
|
||||
}
|
||||
|
||||
// Function to create an array of release info objects
|
||||
async function createReleaseInfo() {
|
||||
const tags = await listVersionTags();
|
||||
const releaseInfo = [];
|
||||
|
||||
for (const tag of tags) {
|
||||
const { stdout: tagDate } = await exec(
|
||||
`git --git-dir=${repoPath} log -1 --format=%ad --date=iso ${tag}`
|
||||
);
|
||||
const tagObject = {
|
||||
name: `${repoName}-v${tag}`,
|
||||
version: tag,
|
||||
date: tagDate.trim(),
|
||||
ext: 'git',
|
||||
command: `git clone --depth=1 --single-branch --branch ${tag} ${gitUrl}`
|
||||
};
|
||||
releaseInfo.push(tagObject);
|
||||
}
|
||||
|
||||
return releaseInfo;
|
||||
}
|
||||
|
||||
all.releases = await createReleaseInfo();
|
||||
|
||||
return all;
|
||||
}
|
||||
module.exports = getAllReleases;
|
||||
|
||||
if (module === require.main) {
|
||||
(async function main() {
|
||||
let all = await getAllReleases('https://github.com/jshint/jshint');
|
||||
console.log(all.releases[0]);
|
||||
all = require('../_webi/normalize.js')(all);
|
||||
console.info(JSON.stringify(all, null, 2));
|
||||
})()
|
||||
.then(function () {
|
||||
process.exit(0);
|
||||
})
|
||||
.catch(function (err) {
|
||||
console.error(err);
|
||||
});
|
||||
}
|
||||
+1
-1
@@ -20,7 +20,7 @@ Object.keys(osMap).forEach(function (name) {
|
||||
maps.oses[name] = true;
|
||||
});
|
||||
|
||||
var formats = ['zip', 'xz', 'tar', 'pkg', 'msi', 'git', 'exe', 'dmg'];
|
||||
var formats = ['zip', 'xz', 'tar', 'pkg', 'msi', 'git', 'exe', 'dmg', 'git'];
|
||||
formats.forEach(function (name) {
|
||||
maps.formats[name] = true;
|
||||
});
|
||||
|
||||
+42
-26
@@ -114,6 +114,10 @@ Releases.renderBash = async function (
|
||||
.replace(/^\s*#?WEBI_MINOR=.*/m, 'WEBI_MINOR=' + v.minor)
|
||||
.replace(/^\s*#?WEBI_PATCH=.*/m, 'WEBI_PATCH=' + v.patch)
|
||||
.replace(/^\s*#?WEBI_BUILD=.*/m, 'WEBI_BUILD=' + v.build)
|
||||
.replace(
|
||||
/^\s*#?WEBI_GIT_TAG=.*/m,
|
||||
"WEBI_GIT_TAG='" + rel.git_tag + "'",
|
||||
)
|
||||
.replace(/^\s*#?WEBI_LTS=.*/m, 'WEBI_LTS=' + rel.lts)
|
||||
.replace(/^\s*#?WEBI_CHANNEL=.*/m, 'WEBI_CHANNEL=' + rel.channel)
|
||||
.replace(
|
||||
@@ -187,32 +191,44 @@ Releases.renderPowerShell = async function (
|
||||
.readFile(path.join(__dirname, 'template.ps1'), 'utf8')
|
||||
.then(function (tplTxt) {
|
||||
var pkgver = pkg + '@' + ver;
|
||||
return tplTxt
|
||||
.replace(
|
||||
/^(#)?\$Env:WEBI_HOST\s*=.*/im,
|
||||
"$Env:WEBI_HOST = '" + baseurl + "'",
|
||||
)
|
||||
.replace(
|
||||
/^(#)?\$Env:WEBI_PKG\s*=.*/im,
|
||||
"$Env:WEBI_PKG = '" + pkgver + "'",
|
||||
)
|
||||
.replace(
|
||||
/^(#)?\$Env:PKG_NAME\s*=.*/im,
|
||||
"$Env:PKG_NAME = '" + pkg + "'",
|
||||
)
|
||||
.replace(
|
||||
/^(#)?\$Env:WEBI_VERSION\s*=.*/im,
|
||||
"$Env:WEBI_VERSION = '" + rel.version + "'",
|
||||
)
|
||||
.replace(
|
||||
/^(#)?\$Env:WEBI_PKG_URL\s*=.*/im,
|
||||
"$Env:WEBI_PKG_URL = '" + rel.download + "'",
|
||||
)
|
||||
.replace(
|
||||
/^(#)?\$Env:WEBI_PKG_FILE\s*=.*/im,
|
||||
"$Env:WEBI_PKG_FILE = '" + rel.name + "'",
|
||||
)
|
||||
.replace(reInstallTpl, '\n' + installTxt);
|
||||
return (
|
||||
tplTxt
|
||||
.replace(
|
||||
/^(#)?\$Env:WEBI_HOST\s*=.*/im,
|
||||
"$Env:WEBI_HOST = '" + baseurl + "'",
|
||||
)
|
||||
.replace(
|
||||
/^(#)?\$Env:WEBI_PKG\s*=.*/im,
|
||||
"$Env:WEBI_PKG = '" + pkgver + "'",
|
||||
)
|
||||
.replace(
|
||||
/^(#)?\$Env:PKG_NAME\s*=.*/im,
|
||||
"$Env:PKG_NAME = '" + pkg + "'",
|
||||
)
|
||||
.replace(
|
||||
/^(#)?\$Env:WEBI_VERSION\s*=.*/im,
|
||||
"$Env:WEBI_VERSION = '" + rel.version + "'",
|
||||
)
|
||||
.replace(
|
||||
/^(#)?\$Env:WEBI_GIT_TAG\s*=.*/im,
|
||||
"$Env:WEBI_GIT_TAG = '" + rel.git_tag + "'",
|
||||
)
|
||||
.replace(
|
||||
/^(#)?\$Env:WEBI_PKG_URL\s*=.*/im,
|
||||
"$Env:WEBI_PKG_URL = '" + rel.download + "'",
|
||||
)
|
||||
// TODO replace WEBI_PKG_FILE (which is sometimes a dir)
|
||||
.replace(
|
||||
/^(#)?\$Env:WEBI_PKG_PATHNAME\s*=.*/im,
|
||||
"$Env:WEBI_PKG_PATHNAME = '" + rel.name + "'",
|
||||
)
|
||||
// TODO deprecate
|
||||
.replace(
|
||||
/^(#)?\$Env:WEBI_PKG_FILE\s*=.*/im,
|
||||
"$Env:WEBI_PKG_FILE = '" + rel.name + "'",
|
||||
)
|
||||
.replace(reInstallTpl, '\n' + installTxt)
|
||||
);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
@@ -25,6 +25,7 @@ __bootstrap_webi() {
|
||||
#WEBI_PATCH=
|
||||
# TODO not sure if BUILD is the best name for this
|
||||
#WEBI_BUILD=
|
||||
#WEBI_GIT_TAG=
|
||||
#WEBI_LTS=
|
||||
#WEBI_CHANNEL=
|
||||
#WEBI_EXT=
|
||||
@@ -248,6 +249,32 @@ __bootstrap_webi() {
|
||||
echo "Saved as ${my_dl_rel}"
|
||||
}
|
||||
|
||||
webi_git_clone() { (
|
||||
my_url="${1}"
|
||||
my_dl="${2}"
|
||||
|
||||
my_dl_rel="$(
|
||||
webi_sub_home "${my_dl}"
|
||||
)"
|
||||
if [ -e "${my_dl}" ]; then
|
||||
echo "Found ${my_dl_rel}"
|
||||
|
||||
cp -RPp "${my_dl}" "${WEBI_TMP}/${WEBI_PKG_FILE}/"
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo "Cloning ${my_url}"
|
||||
cmd_git="git clone --config advice.detachedHead=false --quiet --depth=1 --single-branch"
|
||||
rm -rf "${my_dl}.part"
|
||||
if ! $cmd_git "${my_url}" --branch "${WEBI_GIT_TAG}" "${my_dl}.part"; then
|
||||
echo >&2 "failed to git clone ${WEBI_PKG_URL}"
|
||||
exit 1
|
||||
fi
|
||||
mv "${my_dl}.part" "${my_dl}"
|
||||
|
||||
cp -RPp "${my_dl}" "${WEBI_TMP}/${WEBI_PKG_FILE}/"
|
||||
); }
|
||||
|
||||
# detect which archives can be used
|
||||
webi_extract() {
|
||||
(
|
||||
@@ -265,6 +292,9 @@ __bootstrap_webi() {
|
||||
elif [ "exe" = "$WEBI_EXT" ]; then
|
||||
echo "Moving ${my_dl_rel}"
|
||||
mv "${WEBI_PKG_PATH}/$WEBI_PKG_FILE" .
|
||||
elif [ "git" = "$WEBI_EXT" ]; then
|
||||
echo "Moving ${my_dl_rel}"
|
||||
mv "${WEBI_PKG_PATH}/$WEBI_PKG_FILE" .
|
||||
elif [ "xz" = "$WEBI_EXT" ]; then
|
||||
echo "Inflating ${my_dl_rel}"
|
||||
unxz -c "${WEBI_PKG_PATH}/$WEBI_PKG_FILE" > "$(basename "$WEBI_PKG_FILE")"
|
||||
@@ -456,6 +486,12 @@ __bootstrap_webi() {
|
||||
webi_pre_install() {
|
||||
webi_check_installed
|
||||
webi_check_available
|
||||
if test "git" = "${WEBI_EXT}"; then
|
||||
webi_git_clone \
|
||||
"${WEBI_PKG_URL}" \
|
||||
"${WEBI_PKG_PATH}/${WEBI_PKG_FILE}"
|
||||
return 0
|
||||
fi
|
||||
webi_download \
|
||||
"${WEBI_PKG_URL}" \
|
||||
"${WEBI_PKG_PATH}/${WEBI_PKG_FILE}"
|
||||
|
||||
@@ -182,14 +182,18 @@ async function filterReleases(
|
||||
|
||||
function selectMatches(rel) {
|
||||
if (os) {
|
||||
if (rel.os !== os) {
|
||||
return false;
|
||||
if (rel.os !== '*') {
|
||||
if (rel.os !== os) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (arch) {
|
||||
if (rel.arch !== arch) {
|
||||
return false;
|
||||
if (rel.arch !== '*') {
|
||||
if (rel.arch !== arch) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -100,7 +100,7 @@ if ($exename -eq "-V" -or $exename -eq "--version" -or $exename -eq "version" -o
|
||||
|
||||
# Fetch <whatever>.ps1
|
||||
# TODO detect formats
|
||||
$PKG_URL = "$Env:WEBI_HOST/api/installers/$exename.ps1?formats=zip,exe,tar"
|
||||
$PKG_URL = "$Env:WEBI_HOST/api/installers/$exename.ps1?formats=zip,exe,tar,git"
|
||||
Write-Output "Downloading $PKG_URL"
|
||||
# Invoke-WebRequest -UserAgent "Windows amd64" "$PKG_URL" -OutFile ".\.local\tmp\$exename.install.ps1"
|
||||
& curl.exe -fsSL -A "$Env:WEBI_UA" "$PKG_URL" -o .\.local\tmp\$exename.install.ps1
|
||||
|
||||
Reference in New Issue
Block a user