Compare commits

..

62 Commits

Author SHA1 Message Date
AJ ONeal
35992b4aa4 chore: update version and lockfile 2023-10-12 02:34:41 +00:00
AJ ONeal
ca46158d68 chore: add lint & fmt to ci/cd 2023-10-12 02:34:40 +00:00
AJ ONeal
c78662056d chore: lint & fix shell files 2023-10-12 00:08:28 +00:00
AJ ONeal
4ac9e69f92 chore: lint & fix js files 2023-10-12 00:08:27 +00:00
AJ ONeal
7d49bf1981 chore: update lint config 2023-10-12 00:08:27 +00:00
AJ ONeal
e276bb32a5 chore: use '&&' rather than ';' for 'npm run fmt' on Windows 2023-10-11 23:29:10 +00:00
AJ ONeal
476548cd06 chore: fmt (prettier@3.x) 2023-10-11 23:25:10 +00:00
AJ ONeal
eff21a266c chore: update to prettier@3.x 2023-10-11 23:25:10 +00:00
AJ ONeal
a2e4368da8 chore: fmt (prettier@2.x) 2023-10-11 23:20:36 +00:00
AJ ONeal
22e35e612e chore: update prettier config 2023-10-11 23:19:48 +00:00
AJ ONeal
55a5280057 fix(dashcore-utils): add missing example block 2023-10-11 23:19:01 +00:00
Tristan Engel
f5843b8519 fix(rclone): update install.ps1 (fix #636) 2023-10-11 22:11:15 +00:00
AJ ONeal
9cd869e3bb ref: improve readability of arch sort 2023-10-11 22:06:12 +00:00
AJ ONeal
b882a30659 fix(ppc64le): add ppc64le to arch list for POSIX shell projects 2023-10-11 22:06:03 +00:00
AJ ONeal
489c27ea01 fix(ppc64le): sort by specificity: ppc64le comes BEFORE ppc64 2023-10-11 22:05:22 +00:00
AJ ONeal
456bb61896 fix(vim-ale): show linter code after linter name 2023-10-11 04:09:34 +00:00
AJ ONeal
9fe80496d3 feat: link AtomicParsley to atomicparsley to accommodate real command name 2023-10-09 08:34:29 +00:00
AJ ONeal
fdc6968322 feat: add atomicparsley 2023-10-09 08:34:29 +00:00
AJ ONeal
dcc542d70b feat: add common aliases of vcruntime 2023-10-09 08:34:03 +00:00
AJ ONeal
6b7a78a18a feat: add vcruntime (vcruntime140.dll) 2023-10-09 08:34:03 +00:00
AJ ONeal
b476074f04 ref(hugo): update for latest standard and extended editions 2023-09-16 23:25:11 +00:00
AJ ONeal
cf1c486616 feat: add hugo-extended 2023-09-16 23:05:30 +00:00
AJ ONeal
1d87306129 ref!(go): separate go from go-essentials for 1.21 2023-08-09 23:29:25 +00:00
AJ ONeal
5a92412348 ref: make 'go' canonical installer, not just alias 2023-08-09 23:28:50 +00:00
AJ ONeal
80dace64f3 fix(node): map 'osx' os identifier to 'darwin' filename 2023-07-27 15:45:42 +00:00
AJ ONeal
e6d02f52c7 doc(dashd): add QuickStart, update dash.conf 2023-07-17 18:22:16 +00:00
AJ ONeal
ff015b445a ref(dashcore-utils): add zmqpubhashchainlock and zmqpubrawchainlock to dash.example.conf 2023-07-17 18:22:15 +00:00
jojobyte
005f0fd4f7 doc(ffmpeg): Add DNS resolution note and example 2023-07-15 00:04:32 -06:00
AJ ONeal
0b127b3c6e ref!(node): add officially unofficial musl builds for alpine 2023-07-05 20:03:05 +00:00
AJ ONeal
a3954bad3d ref(alpine): enable musl filtering 2023-07-05 20:03:04 +00:00
AJ ONeal
4ad1d3da4b ref(lsd): enable musl builds, update docs 2023-07-05 17:48:00 +00:00
AJ ONeal
5f96be9593 fix(vim-ale): use ascii rather than utf8 2023-07-05 17:35:28 +00:00
AJ ONeal
2e7f68ef2e feat: add brew-update-service-install 2023-07-05 17:33:49 +00:00
AJ ONeal
36d825a225 ref(ssh-setpass): add usage and helpful checks and messages 2023-07-05 17:31:03 +00:00
AJ ONeal
039280a05f ref(ssh-utils): remove redundant .sh suffix 2023-07-05 17:31:02 +00:00
AJ ONeal
27030f28d2 ref!(cmake): use pkg template rather than exe template 2023-07-03 22:40:56 +00:00
brthngnsh
d00bf9eb12 feat(cmake): Added CMake package
Addon changes:
- Added share directory to install script to fix CMAKE_ROOT not found
  issue.
- Added a simple CPP Hello World program for CMake usage.

Caution:
- Need to test Powershell script.
2023-06-28 07:14:37 +00:00
AJ ONeal
d2980418dc doc(dashcore): note zmq bind behavior 2023-06-25 03:31:41 +00:00
AJ ONeal
af06adb0bb doc(dashcore): note rpcconnect, update indexing times 2023-06-25 02:54:02 +00:00
AJ ONeal
0c877a5516 fix(dashd): turn on indexes 2023-06-21 23:05:37 +00:00
AJ ONeal
cec86d4ebf ref!: move convenience scripts to dashcore-utils 2023-06-21 22:08:58 +00:00
AJ ONeal
ce2f07ef26 feat: add dashd Dash Full Node service 2023-06-21 21:55:18 +00:00
AJ ONeal
731d3c95c1 feat: add Dash Core (dash-qt) 2023-06-12 08:03:20 +00:00
AJ ONeal
b944352e1b ref(ssh-utils): alphabetize, fix typos 2023-06-11 08:40:09 +00:00
AJ ONeal
12de674f54 feat(ssh-utils): add ssh-authorize 2023-06-11 08:27:52 +00:00
AJ ONeal
a3d62393c7 feat: add ssh-authorize 2023-06-11 08:27:13 +00:00
AJ ONeal
aefba90af9 ref!(ssh-adduser): move sshd-prohibit-password to own command 2023-06-10 00:04:56 +00:00
AJ ONeal
3a574392f0 feat: add sshd-prohibit-password 2023-06-09 23:38:50 +00:00
AJ ONeal
6baa78f95d doc(vim-airline): add Files section, update format and wording 2023-06-01 06:13:11 +00:00
Ryan Burnette
54d41336c4 add vim-airline-themes installer 2023-06-01 06:03:04 +00:00
Ryan Burnette
b406af83a6 add vim-airline installer 2023-06-01 06:03:04 +00:00
AJ ONeal
7c717d994f fix(vim-italics): rewrite 2023-06-01 05:59:28 +00:00
Aritra Mallick
3383c1e322 feat: add vim-italics 2023-06-01 05:32:35 +00:00
alexravenna
522ebaddd0 docs(nerdfont): Update Windows Terminal settings to 1.16.10262.0 2023-06-01 05:20:29 +00:00
alexravenna
fd69b0b57a docs(fd): Fix typo in fd readme 2023-06-01 05:20:25 +00:00
AJ ONeal
160e13ccaa ref!: replace 'pathman' with POSIX 'webi_path_add' 2023-05-31 17:36:04 +00:00
AJ ONeal
9e523f0c0e fix(windows): detect Windows ARM64, with AMD64 fallback 2023-05-28 23:46:36 +00:00
AJ ONeal
ffd757edd6 ref(webi): shfmt 2023-05-28 05:02:01 +00:00
AJ ONeal
3ab9eee352 fix(nerdfont): pin version to tag 'v2.3.3' rather than 'master' (now v3.x) 2023-05-25 20:29:09 +00:00
AJ ONeal
efb67109fb ref!: replace pathman with PowerShell [Environment]::SetEnvironmentVariable 2023-05-09 00:04:59 +00:00
AJ ONeal
ba4571ec35 fix(windows): correctly bootstrap pathman install 2023-05-08 20:57:00 +00:00
AJ ONeal
d6757752d5 feat: add beyond-shell (for Workshops) 2023-03-07 12:09:43 +00:00
143 changed files with 5199 additions and 658 deletions

31
.github/workflows/node.js.yml vendored Normal file
View File

@@ -0,0 +1,31 @@
name: Node.js CI
on:
push:
branches: ['main']
pull_request:
jobs:
build:
name: "Fmt, Lint, & Test"
runs-on: ubuntu-latest
strategy:
matrix:
node-version:
- 20.x
- latest
steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- name: "Webi: Install 'shfmt' and 'shellcheck', and update PATH"
run: |
sh ./_scripts/install-ci-deps
echo "${HOME}/.local/bin" >> $GITHUB_PATH
- run: shfmt --version
- run: shellcheck -V
- run: node --version
- run: npm run fmt
- run: npm ci
- run: npm run lint
- run: npm run test

1
.jshintignore Normal file
View File

@@ -0,0 +1 @@
DELETEMEnode_modules/**/*

4
.prettierignore Normal file
View File

@@ -0,0 +1,4 @@
node_modules
jsconfig.json
package.json
package-lock.json

View File

@@ -1,6 +1,9 @@
{
"trailingComma": "all",
"tabWidth": 2,
"bracketSpacing": true,
"printWidth": 80,
"proseWrap": "always",
"singleQuote": true,
"proseWrap": "always"
"tabWidth": 2,
"trailingComma": "all",
"semi": true
}

1
AtomicParsley Symbolic link
View File

@@ -0,0 +1 @@
atomicparsley

View File

@@ -15,11 +15,11 @@ function getAllReleases(request, owner, repo, baseurl) {
if (!baseurl) {
return Promise.reject('missing baseurl');
}
return ghRelease(request, owner, repo, baseurl + '/api/v1').then(function (
all,
) {
return all;
});
return ghRelease(request, owner, repo, baseurl + '/api/v1').then(
function (all) {
return all;
},
);
}
module.exports = getAllReleases;

View File

@@ -1,9 +1,6 @@
'use strict';
var pkg = require('../package.json');
var spawn = require('child_process').spawn;
var os = require('os');
var path = require('path');
function spawner(args) {
return new Promise(function (resolve, reject) {

9
_scripts/install-ci-deps Executable file
View File

@@ -0,0 +1,9 @@
#!/bin/sh
set -e
set -u
# Install 'shfmt 3.7.x'
curl -fsS https://webi.sh/shfmt@3.7 | sh
# Install 'shellcheck v0.9.x'
curl -fsS https://webi.sh/shellcheck@0.9 | sh

View File

@@ -92,35 +92,40 @@ __webi_main() {
export WEBI_WGET="\$(command -v wget)"
set -e
my_libc=''
if ldd /bin/ls 2> /dev/null | grep -q 'musl' 2> /dev/null; then
my_libc=' musl-native'
fi
export WEBI_HOST="\${WEBI_HOST:-https://webinstall.dev}"
export WEBI_UA="\$(uname -s)/\$(uname -r) \$(uname -m)/unknown"
export WEBI_UA="\$(uname -s)/\$(uname -r) \$(uname -m)/unknown\${my_libc}"
webinstall() {
my_package="\${1:-}"
if [ -z "\$my_package" ]; then
>&2 echo "Usage: webi <package>@<version> ..."
>&2 echo "Example: webi node@lts rg"
echo >&2 "Usage: webi <package>@<version> ..."
echo >&2 "Example: webi node@lts rg"
exit 1
fi
export WEBI_BOOT="\$(mktemp -d -t "\$my_package-bootstrap.\$WEBI_TIMESTAMP.XXXXXXXX")"
my_installer_url="\$WEBI_HOST/api/installers/\$my_package.sh?formats=\$my_ext"
set +e
if [ -n "\$WEBI_CURL" ]; then
curl -fsSL "\$my_installer_url" -H "User-Agent: curl \$WEBI_UA" \\
-o "\$WEBI_BOOT/\$my_package-bootstrap.sh"
if ! curl -fsSL "\$my_installer_url" -H "User-Agent: curl \$WEBI_UA" \\
-o "\$WEBI_BOOT/\$my_package-bootstrap.sh"; then
echo >&2 "error fetching '\$my_installer_url'"
exit 1
fi
else
wget -q "\$my_installer_url" --user-agent="wget \$WEBI_UA" \\
-O "\$WEBI_BOOT/\$my_package-bootstrap.sh"
if ! wget -q "\$my_installer_url" --user-agent="wget \$WEBI_UA" \\
-O "\$WEBI_BOOT/\$my_package-bootstrap.sh"; then
echo >&2 "error fetching '\$my_installer_url'"
exit 1
fi
fi
if ! [ \$? -eq 0 ]; then
>&2 echo "error fetching '\$my_installer_url'"
exit 1
fi
set -e
(
cd "\$WEBI_BOOT"
@@ -133,10 +138,10 @@ __webi_main() {
show_path_updates() {
if ! [ -n "\${_WEBI_CHILD}" ]; then
if [ -f "\$_webi_tmp/.PATH.env" ]; then
my_paths=\$(cat "\$_webi_tmp/.PATH.env" | sort -u)
if [ -n "\$my_paths" ]; then
if test -z "\${_WEBI_CHILD}"; then
if test -f "\$_webi_tmp/.PATH.env"; then
my_paths=\$(sort -u < "\$_webi_tmp/.PATH.env")
if test -n "\$my_paths"; then
printf 'PATH.env updated with:\\n'
printf "%s\\n" "\$my_paths"
printf '\\n'
@@ -199,8 +204,7 @@ __webi_main() {
exit 0
fi
for pkgname in "\$@"
do
for pkgname in "\$@"; do
webinstall "\$pkgname"
done

View File

@@ -73,6 +73,7 @@ function normalize(all) {
};
all.releases.forEach(function (rel) {
/* jshint maxcomplexity:25 */
rel.version = rel.version.replace(/^v/i, '');
if (!rel.name) {
rel.name = rel.download.replace(/.*\//, '');
@@ -85,21 +86,24 @@ function normalize(all) {
}
// Hacky-doo for musl
// TODO some sort of glibc vs musl tag?
if (!rel._musl) {
if (/(\b|\.|_|-)(musl)(\b|\.|_|-)/.test(rel.download)) {
rel._musl = true;
if (!rel._musl_native) {
if (!rel._musl) {
if (/(\b|\.|_|-)(musl)(\b|\.|_|-)/.test(rel.download)) {
rel._musl = true;
}
}
}
supported.oses[rel.os] = true;
if (!rel.arch) {
arches.some(function (regKey) {
var arch = (rel.name || rel.download).match(archMap[regKey]) && regKey;
if (arch) {
for (let arch of arches) {
let name = rel.name || rel.download;
let isArch = name.match(archMap[arch]);
if (isArch) {
rel.arch = arch;
return true;
break;
}
});
}
}
if (!rel.arch) {
if ('macos' === rel.os) {

View File

@@ -47,12 +47,14 @@ async function serveInstaller(baseurl, ua, pkg, tag, ext, formats) {
// TODO maybe move package/version/lts/channel detection into getReleases
var myOs = uaDetect.os(ua);
var myArch = uaDetect.arch(ua);
var myLibc = uaDetect.libc(ua);
let cfg = await packages.get(pkg);
let rels = await getReleases({
pkg: cfg.alias || pkg,
ver,
os: myOs,
arch: myArch,
libc: myLibc,
lts,
channel,
formats,

View File

@@ -42,24 +42,87 @@ New-Item -Path .local\opt -ItemType Directory -Force | out-null
# {{ baseurl }}
# {{ version }}
function webi_add_path
function webi_path_add($pathname)
{
Write-Host ''
Write-Host '*****************************' -ForegroundColor red -BackgroundColor white
Write-Host '* IMPORTANT - READ ME *' -ForegroundColor red -BackgroundColor white
Write-Host '*****************************' -ForegroundColor red -BackgroundColor white
Write-Host ''
& "$Env:USERPROFILE\.local\bin\pathman.exe" add "$args[0]"
# Note: not all of these work as expected, so we use the unix-style, which is most consistent
#& "$Env:USERPROFILE\.local\bin\pathman.exe" add ~/.local/bin
#& "$Env:USERPROFILE\.local\bin\pathman.exe" add "$Env:USERPROFILE\.local\bin"
#& "$Env:USERPROFILE\.local\bin\pathman.exe" add %USERPROFILE%\.local\bin
# C:\Users\me => C:/Users/me
$my_home = $Env:UserProfile
$my_home = $my_home.replace('\\', '/')
$my_home_re = [regex]::escape($my_home)
# ~/bin => %USERPROFILE%/bin
$pathname = $pathname.replace('~/', "$Env:UserProfile/")
# C:\Users\me\bin => %USERPROFILE%/bin
$my_pathname = $pathname.replace('\\', '/')
$my_pathname = $my_pathname -ireplace $my_home_re, "%USERPROFILE%"
$all_user_paths = [Environment]::GetEnvironmentVariable("Path", "User")
$user_paths = $all_user_paths -Split(';')
$exists_in_path = $false
foreach ($user_path in $user_paths)
{
# C:\Users\me\bin => %USERPROFILE%/bin
$my_user_path = $user_path.replace('\\', '/')
$my_user_path = $my_user_path -ireplace $my_home_re, "%USERPROFILE%"
if ($my_user_path -ieq $my_pathname)
{
$exists_in_path = $true
}
}
if (-Not $exists_in_path)
{
$all_user_paths = $pathname + ";" + $all_user_paths
[Environment]::SetEnvironmentVariable("Path", $all_user_paths, "User")
}
$session_paths = $Env:Path -Split(';')
$in_session_path = $false
foreach ($session_path in $session_paths)
{
# C:\Users\me\bin => %USERPROFILE%/bin
$my_session_path = $session_path.replace('\\', '/')
$my_session_path = $my_session_path -ireplace $my_home_re, "%USERPROFILE%"
if ($my_session_path -ieq $my_pathname)
{
$in_session_path = $true
}
}
if (-Not $in_session_path)
{
$my_cmd = 'PATH ' + "$pathname" + ';%PATH%'
$my_pwsh = '$Env:Path = "' + "$pathname" + ';$Env:Path"'
Write-Host ''
Write-Host '**********************************' -ForegroundColor red -BackgroundColor white
Write-Host '* IMPORTANT -- READ ME *' -ForegroundColor red -BackgroundColor white
Write-Host '* (run the PATH command below) *' -ForegroundColor red -BackgroundColor white
Write-Host '**********************************' -ForegroundColor red -BackgroundColor white
Write-Host ''
echo ""
echo "Copy, paste, and run the appropriate command to update your PATH:"
echo "(or close and reopen the terminal, or reboot)"
echo ""
echo "cmd.exe:"
echo " $my_cmd"
echo ""
echo "PowerShell:"
echo " $my_pwsh"
echo ""
}
}
# Run pathman to set up the folder
& "$Env:USERPROFILE\.local\bin\pathman.exe" add ~/.local/bin
#$has_local_bin = echo "$Env:PATH" | Select-String -Pattern '\.local.bin'
#if (!$has_local_bin)
#{
webi_path_add ~/.local/bin
#}
{{ installer }}
webi_path_add ~/.local/bin
# Done
popd

View File

@@ -6,6 +6,11 @@ __bootstrap_webi() {
set -u
#set -x
my_libc=''
if ldd /bin/ls 2> /dev/null | grep -q 'musl' 2> /dev/null; then
my_libc=' musl-native'
fi
#WEBI_PKG=
#PKG_NAME=
# TODO should this be BASEURL instead?
@@ -30,7 +35,7 @@ __bootstrap_webi() {
#PKG_OSES=
#PKG_ARCHES=
#PKG_FORMATS=
WEBI_UA="$(uname -s)/$(uname -r) $(uname -m)/unknown"
WEBI_UA="$(uname -s)/$(uname -r) $(uname -m)/unknown${my_libc}"
WEBI_PKG_DOWNLOAD=""
WEBI_DOWNLOAD_DIR="${HOME}/Downloads"
if command -v xdg-user-dir > /dev/null; then
@@ -160,7 +165,7 @@ __bootstrap_webi() {
webi_download() {
# determine the url to download
if [ -n "${1-}" ]; then
my_url="$1"
my_url="${1}"
else
if [ "error" = "$WEBI_CHANNEL" ]; then
# TODO pass back requested OS / Arch / Version
@@ -168,7 +173,11 @@ __bootstrap_webi() {
echo >&2 " '$PKG_NAME' is available for '$PKG_OSES' on '$PKG_ARCHES' as one of '$PKG_FORMATS'"
echo >&2 " (check that the package name and version are correct)"
echo >&2 ""
echo >&2 " Double check at $(echo "$WEBI_RELEASES" | sed 's:\?.*::')"
my_release_url="$(
echo "$WEBI_RELEASES" |
sed 's:\?.*::'
)"
echo >&2 " Double check at ${my_release_url}"
echo >&2 ""
exit 1
fi
@@ -177,11 +186,17 @@ __bootstrap_webi() {
# determine the location to download to
if [ -n "${2-}" ]; then
my_dl="$2"
my_dl="${2}"
else
my_dl="${WEBI_PKG_PATH}/$WEBI_PKG_FILE"
fi
if [ -n "${3-}" ]; then
my_dl_name="${3}"
else
my_dl_name="${PKG_NAME}"
fi
WEBI_PKG_DOWNLOAD="${my_dl}"
export WEBI_PKG_DOWNLOAD
@@ -190,7 +205,7 @@ __bootstrap_webi() {
return 0
fi
echo "Downloading $PKG_NAME from"
echo "Downloading ${my_dl_name} from"
echo "$my_url"
# It's only 2020, we can't expect to have reliable CLI tools
@@ -251,25 +266,179 @@ __bootstrap_webi() {
# use 'pathman' to update $HOME/.config/envman/PATH.env
webi_path_add() {
# make sure that we don't recursively install pathman with webi
my_path="$PATH"
export PATH="$HOME/.local/bin:$PATH"
my_path="${1}"
# install pathman if not already installed
if [ -z "$(command -v pathman)" ]; then
"$HOME/.local/bin/webi" pathman > /dev/null
fn_envman_init
# \v was chosen as it is extremely unlikely for a filename
# \1 could be an even better choice, but needs more testing.
# (currently tested working on: linux & mac)
# "\0001" should also work
my_delim="$(
printf '\v'
)"
my_path_expanded="$(
echo "${my_path}" |
sed -e "s${my_delim}\$HOME${my_delim}$HOME${my_delim}g" \
-e "s${my_delim}\${HOME}${my_delim}$HOME${my_delim}g" \
-e "s${my_delim}^~/${my_delim}$HOME/${my_delim}g"
)"
# A gift for @adamcstephens.
# See https://github.com/webinstall/webi-installers/issues/322
case "${PATH}" in
# matches whether the first, a middle, the last, or the only PATH entry
"${my_path_expanded}":* | \
*:"${my_path_expanded}":* | \
*:"${my_path_expanded}" | \
"${my_path_expanded}")
if fn_is_defined_in_all_shells "${my_path}"; then
return 0
fi
;;
*) ;;
esac
my_path_export="$(
echo "${my_path}" |
sed -e "s${my_delim}${HOME}${my_delim}\$HOME${my_delim}g" \
-e "s${my_delim}\${HOME}${my_delim}\$HOME${my_delim}g" \
-e "s${my_delim}^~/${my_delim}\$HOME/${my_delim}g"
)"
my_export="export PATH=\"$my_path_export:\$PATH\""
if grep -q -F "${my_export}" ~/.config/envman/PATH.env; then
return 0
fi
export PATH="$my_path"
echo "${my_export}" >> ~/.config/envman/PATH.env
# in case pathman was recently installed and the PATH not updated
mkdir -p "$_webi_tmp"
# 'true' to prevent "too few arguments" output
# when there are 0 lines of stdout
"$HOME/.local/bin/pathman" add "$1" |
grep "export" 2> /dev/null \
>> "$_webi_tmp/.PATH.env" ||
true
my_path_tilde="$(
echo "${my_path}" |
sed -e "s${my_delim}${HOME}${my_delim}~${my_delim}g"
)"
if ! test -f "$_webi_tmp/.PATH.env" ||
! grep -q -F "${my_path_tilde}" "$_webi_tmp/.PATH.env"; then
echo "${my_path_tilde}" >> "$_webi_tmp/.PATH.env"
fi
}
fn_envman_init() {
mkdir -p ~/.config/envman/
if ! test -e ~/.config/envman/PATH.env; then
touch ~/.config/envman/PATH.env
fi
if ! test -e ~/.config/envman/load.sh; then
# shellcheck disable=SC2016
{
echo '# Generated for envman. Do not edit.'
echo 'for x in ~/.config/envman/*.env; do'
echo ' my_basename="$(basename "${x}")"'
echo ' if [ "*.env" = "${my_basename}" ]; then'
echo ' continue'
echo ' fi'
echo ''
echo ' # shellcheck source=/dev/null'
echo ' . "${x}"'
echo 'done'
} > ~/.config/envman/load.sh
fi
if command -v sh > /dev/null; then
if test -e ~/.profile; then
if ! grep -q -F '/.config/envman/load.sh' ~/.profile; then
fn_echo_load_sh >> ~/.profile
fi
fi
fi
if command -v bash > /dev/null; then
if test -e ~/.bashrc; then
if ! grep -q -F '/.config/envman/load.sh' ~/.bashrc; then
fn_echo_load_sh >> ~/.bashrc
fi
fi
fi
if command -v zsh > /dev/null; then
if test -e ~/.zshrc; then
if ! grep -q -F '/.config/envman/load.sh' ~/.zshrc; then
fn_echo_load_sh >> ~/.zshrc
fi
fi
fi
if command -v fish > /dev/null; then
if test ! -e ~/.config/envman/load.fish; then
# shellcheck disable=SC2016
{
echo '# Generated for envman. Do not edit.'
echo 'for x in ~/.config/envman/*.env'
echo ' source "$x"'
echo 'end'
} > ~/.config/envman/load.fish
fi
mkdir -p ~/.config/fish
if test -e ~/.config/fish/config.fish; then
touch ~/.config/fish/config.fish
fi
if ! grep -q -F '/.config/envman/load.fish' ~/.config/fish/config.fish; then
fn_echo_load_fish >> ~/.config/fish/config.fish
fi
fi
}
fn_echo_load_fish() {
echo ''
echo '# Generated for envman. Do not edit.'
# shellcheck disable=SC2016
echo 'test -s "$HOME/.config/envman/load.fish"; and source "$HOME/.config/envman/load.fish"'
}
fn_echo_load_sh() {
echo ''
echo '# Generated for envman. Do not edit.'
# shellcheck disable=SC2016
echo '[ -s "$HOME/.config/envman/load.sh" ] && source "$HOME/.config/envman/load.sh"'
}
fn_is_defined_in_all_shells() {
my_path="${1}"
my_path_expanded="$(
echo "${my_path}" |
sed -e "s${my_delim}\$HOME|${my_delim}$HOME${my_delim}g" \
-e "s${my_delim}\${HOME}${my_delim}$HOME${my_delim}g" \
-e "s${my_delim}^~/${my_delim}$HOME/${my_delim}g"
)"
my_paths="$(
echo "${my_path_expanded}"
# $HOME/foo
echo "${my_path_expanded}" |
sed "s${my_delim}${HOME}${my_delim}\$HOME${my_delim}g"
# ${HOME}/foo
echo "${my_path_expanded}" |
sed "s${my_delim}${HOME}${my_delim}\${HOME}${my_delim}g"
echo "${my_path}"
)"
my_confs="$(
echo "${HOME}/.profile"
echo "${HOME}/.bashrc"
echo "${HOME}/.zshrc"
echo "${HOME}/.config/fish/config.fish"
)"
for my_conf in $my_confs; do
if test -e "${my_conf}"; then
if ! grep -q -F "${my_paths}" "${my_conf}"; then
return 1
fi
fi
done
}
# group common pre-install tasks as default
@@ -432,7 +601,9 @@ __bootstrap_webi() {
if [ -z "${_WEBI_CHILD-}" ] && [ -f "$_webi_tmp/.PATH.env" ]; then
if [ -n "$(cat "$_webi_tmp/.PATH.env")" ]; then
printf 'PATH.env updated with:\n'
sort -u "$_webi_tmp/.PATH.env"
sort -u "$_webi_tmp/.PATH.env" | while read -r my_new_path; do
echo " ${my_new_path}"
done
printf "\n"
rm -f "$_webi_tmp/.PATH.env"

View File

@@ -2,6 +2,8 @@
var path = require('path');
var Releases = require('./releases.js');
var uaDetect = require('./ua-detect.js');
var cache = {};
//var staleAge = 5 * 1000;
//var expiredAge = 15 * 1000;
@@ -52,6 +54,14 @@ function createFormatsSorter(formats) {
return 1;
}
// Hacky-doo for musl-native: prefer non-musl
if (a._musl_native && !b._musl_native) {
return 1;
}
if (!a._musl_native && b._musl_native) {
return -1;
}
// Hacky-doo for linux: prefer musl
if (a._musl && !b._musl) {
return -1;
@@ -161,7 +171,7 @@ async function getCachedReleases(pkg) {
async function filterReleases(
all,
{ ver, os, arch, lts, channel, formats, limit },
{ ver, os, arch, libc, lts, channel, formats, limit },
) {
// When multiple formats are downloadable (i.e. .zip and .pkg)
// sort the most compatible format first
@@ -170,27 +180,62 @@ async function filterReleases(
var sortByVerExt = createFormatsSorter(rformats);
var reVer = new RegExp('^' + ver + '\\b');
var sortedRels = all.releases
.filter(function (rel) {
if (
(os && rel.os !== os) ||
// Hacky-doo for linux musl
(arch && rel.arch !== arch) ||
(lts && !rel.lts) ||
(channel && rel.channel !== channel) ||
// to match 'tar.gz' and 'tar.xz' with just 'tar'
(formats.length &&
!formats.some(function (ext) {
return rel.ext.match(ext);
})) ||
(ver && !rel.version.match(reVer))
) {
function selectMatches(rel) {
if (os) {
if (rel.os !== os) {
return false;
}
return true;
})
.sort(sortByVerExt);
}
if (arch) {
if (rel.arch !== arch) {
return false;
}
}
// Hacky-doo for linux musl
if (libc === uaDetect.MUSL_NATIVE) {
if (!rel._musl && !rel._musl_native) {
return false;
}
} else if (rel._musl_native) {
return false;
}
if (lts) {
if (!rel.lts) {
return false;
}
}
if (channel) {
if (rel.channel !== channel) {
return false;
}
}
// to match 'tar.gz' and 'tar.xz' with just 'tar'
function hasExt(ext) {
return rel.ext.match(ext);
}
if (formats.length) {
if (!formats.some(hasExt)) {
return false;
}
}
if (ver) {
if (!rel.version.match(reVer)) {
return false;
}
}
return true;
}
var sortedRels = all.releases.filter(selectMatches).sort(sortByVerExt);
//console.log(sortedRels.slice(0, 4));
return sortedRels.slice(0, limit || 1000);
}
@@ -200,6 +245,7 @@ module.exports = function getReleases({
ver,
os,
arch,
libc,
lts,
channel,
formats,
@@ -213,6 +259,7 @@ module.exports = function getReleases({
ver,
os,
arch,
libc,
lts,
channel,
formats,
@@ -229,13 +276,28 @@ module.exports = function getReleases({
})
.then(function (releases) {
if (!releases.length) {
// Apple Silicon M1 hack-y do workaround fix
// Apple Silicon M1 hacky-do workaround fix
if ('macos' === os && 'arm64' === arch) {
return getReleases({
pkg,
ver,
os,
arch: 'amd64',
libc,
lts,
channel,
formats,
limit,
});
}
// Windows ARM hacky-do workaround fix
if ('windows' === os && 'arm64' === arch) {
return getReleases({
pkg,
ver,
os,
arch: 'amd64',
libc,
lts,
channel,
formats,
@@ -250,6 +312,7 @@ module.exports = function getReleases({
ver,
os,
arch: 'arm64',
libc,
lts,
channel,
formats,
@@ -265,6 +328,7 @@ module.exports = function getReleases({
ver,
os,
arch: 'armv7l',
libc,
lts,
channel,
formats,
@@ -279,6 +343,7 @@ module.exports = function getReleases({
ver,
os,
arch: 'armv6l',
libc,
lts,
channel,
formats,
@@ -295,6 +360,7 @@ module.exports = function getReleases({
os: os || '-',
arch: arch || '-',
_musl: undefined,
_musl_native: undefined,
ext: 'err',
download: 'https://example.com/doesntexist.ext',
comment:
@@ -322,6 +388,7 @@ if (require.main === module) {
os: 'macos',
arch: 'amd64',
lts: true,
libc: '',
channel: 'stable',
formats: ['tar', 'exe', 'zip', 'xz', 'dmg', 'pkg'],
limit: 10,

View File

@@ -2,6 +2,10 @@
var uaDetect = module.exports;
const MUSL_NATIVE = 'musl-native';
uaDetect.MUSL_NATIVE = MUSL_NATIVE;
function getRequest(req) {
var ua = req.headers['user-agent'] || '';
var os = req.query.os;
@@ -56,16 +60,23 @@ function getArch(ua) {
return '-';
}
// quick hack for Apple Silicon M1
// Quick hack for Apple Silicon M1
//
// Note: we now use `uname -srm` which does not have the native arch
// info included with `uname -v` and `uname -a`.
//
// Native: Darwin boomer.local 20.2.0 Darwin Kernel Version 20.2.0: Wed Dec 2 20:40:21 PST 2020; root:xnu-7195.60.75~1/RELEASE_ARM64_T8101 arm64
// Resetta: Darwin boomer.local 20.2.0 Darwin Kernel Version 20.2.0: Wed Dec 2 20:40:21 PST 2020; root:xnu-7195.60.75~1/RELEASE_ARM64_T8101 x86_64
ua = ua.replace(/xnu-.*RELEASE_[^\s]*/, '');
if (/aarch64|arm64|arm8|armv8/i.test(ua)) {
return 'arm64';
} else if (/aarch|arm7|armv7/i.test(ua)) {
return 'armv7l';
} else if (/arm6|armv6/i.test(ua)) {
return 'armv6l';
} else if (/ppc64le/i.test(ua)) {
return 'ppc64le';
} else if (/ppc64/i.test(ua)) {
return 'ppc64';
} else if (/mips64/i.test(ua)) {
@@ -84,6 +95,27 @@ function getArch(ua) {
}
}
function getLibc(ua) {
if ('-' === ua) {
return '-';
}
// Use native 'libc' information, if provided
//
// Generally, we prefer 'musl' builds because they DO work on glibc systems (Ubuntu),
// but 'glibc' builds will NOT work on musl systems (Alpine / Docker).
//
// However, there are a few instances (ex: Node.js), where the 'musl' builds
// DO NOT work on glibc systems.
if (ua.match(MUSL_NATIVE)) {
return MUSL_NATIVE;
}
// TODO handle explicit invalid different
return '';
}
uaDetect.os = getOs;
uaDetect.arch = getArch;
uaDetect.libc = getLibc;
uaDetect.request = getRequest;

View File

@@ -17,7 +17,17 @@ IF ($my_arch -eq $null -or $my_arch -eq "") {
# This is the canonical CPU arch when the process is native
$my_arch = "$Env:PROCESSOR_ARCHITECTURE"
}
# TODO API should know to prefer x86 for windows when arm binary is not available
IF ($my_arch -eq "AMD64") {
# Because PowerShell isn't ARM yet.
# See https://oofhours.com/2020/02/04/powershell-on-windows-10-arm64/
$my_os_arch = wmic os get osarchitecture
# Using -clike because of the trailing newline
IF ($my_os_arch -clike "ARM 64*") {
$my_arch = "ARM64"
}
}
$Env:WEBI_UA = "Windows/10 $my_arch"
$exename = $args[0]
@@ -50,27 +60,6 @@ IF($Env:WEBI_HOST -eq $null -or $Env:WEBI_HOST -eq "")
$Env:WEBI_HOST = "https://webinstall.dev"
}
if (!(Test-Path -Path .local\bin\pathman.exe))
{
& curl.exe -fsSL -A "$Env:WEBI_UA" "$Env:WEBI_HOST/packages/pathman/install.ps1" -o .\.local\tmp\pathman-setup.ps1
powershell .\.local\tmp\pathman-setup.ps1
# TODO del .\.local\tmp\pathman-setup.bat
}
# Run pathman to set up the folder
# (using unix style path because... cmd vs powershell vs whatever)
$has_local_bin = echo "$Env:PATH" | Select-String -Pattern '\.local.bin'
if (!$has_local_bin)
{
Write-Host ''
Write-Host '**********************************' -ForegroundColor red -BackgroundColor white
Write-Host '* IMPORTANT -- READ ME *' -ForegroundColor red -BackgroundColor white
Write-Host '* (run the PATH command below) *' -ForegroundColor red -BackgroundColor white
Write-Host '**********************************' -ForegroundColor red -BackgroundColor white
Write-Host ''
& "$Env:USERPROFILE\.local\bin\pathman.exe" add ~/.local/bin
}
# {{ baseurl }}
# {{ version }}

View File

@@ -10,18 +10,7 @@ pushd "%userprofile%" || goto :error
mkdir .local\opt || goto :error
)
pushd .local\bin || goto :error
if NOT EXIST pathman.exe (
echo updating PATH management
powershell $ProgressPreference = 'SilentlyContinue'; Invoke-WebRequest https://webinstall.dev/packages/pathman/install.bat -OutFile pathman-setup.bat || goto :error
call .\pathman-setup.bat || goto :error
del pathman-setup.bat || goto :error
rem TODO there's rumor of a windows tool called 'pathman' that does the same thing?
)
popd || goto :error
.\.local\bin\pathman add ".local\bin" || goto :error
echo downloading and installing %1
echo Downloading and installing %1
powershell $ProgressPreference = 'SilentlyContinue'; Invoke-WebRequest https://webinstall.dev/packages/%1/install.ps1 -OutFile %1-webinstall.bat || goto :error
rem TODO only add if it's not in there already

View File

@@ -11,6 +11,7 @@ module.exports = function (request) {
'armv6l',
'armv7l',
'ppc64le',
'ppc64',
's390x',
'x86',
];

538
atomicparsley/README.md Normal file
View File

@@ -0,0 +1,538 @@
---
title: atomicparsley
homepage: https://github.com/wez/atomicparsley
tagline: |
AtomicParsley is a lightweight tool for reading, parsing and setting iTunes-style metadata.
---
To update or switch versions, run `webi atomicparsley@stable` (or `@v20221229`,
`@beta`, etc).
### Files
These are the files / directories that are created and/or modified with this
install:
```text
~/.config/envman/PATH.env
~/.local/bin/AtomicParsley
```
**Windows Users**
```text
\Windows\System32\vcruntime140.dll
```
This will also attempt to install the
[Microsoft Visual C++ Redistributable](/vcruntime) via `webi vcruntime`. If it
fails and you get the error _`vcruntime140.dll` was not found_, you'll need to
[install it manually](https://learn.microsoft.com/en-US/cpp/windows/latest-supported-vc-redist?view=msvc-170).
## Cheat Sheet
> `AtomicParsley` is an alternative to `ffmpeg` and `ffprobe` for viewing and
> changing metadata in MPEG-4 files with .3gp, .3g2, .mp4, .m4a, .m4b, .m4p,
> .m4r, and .m4v extensions. Because it's purpose-built for MP4 containers, it
> can do some things `ffmpeg` can't - like adding album artwork.
### How to Change Album Art
1. Save any existing cover art
```sh
AtomicParsley ./my-song.m4a --extractPixToPath ./ 'my-song'
```
2. Remove the artwork
```sh
AtomicParsley ./my-song.m4a --artwork REMOVE_ALL
```
3. Add new artwork at the specified DPI (and other constraints)
```sh
export PIC_OPTIONS="DPI=72"
AtomicParsley ./my-podcast-audiobook.m4b --artwork ./my-season-1-cover.jpg
```
Only JPEG and PNG are supported. See `PIC_OPTIONS` down below for more options.
If you get an error, try exporting your file with a DPI to 72 (or up to 300 with
`PIC_OPTIONS` set) and a smaller resolution - perhaps 600x600 or 1500x1500 (what
old versions iTunes versions used).
### How to Remove Apple Account Info
```sh
AtomicParsley ./my-file.m4a \
--DeepScan \
--manualAtomRemove "moov.trak.mdia.minf.stbl.mp4a.pinf" \
--manualAtomRemove "moov.udta.meta.ilst.apID" \
--manualAtomRemove "moov.udta.meta.ilst.cnID" \
--manualAtomRemove "moov.udta.meta.ilst.purd" \
--manualAtomRemove "moov.udta.meta.ilst.sfID" \
--manualAtomRemove "moov.udta.meta.ilst.soal" \
--manualAtomRemove "moov.udta.meta.ilst.xid"
```
If you wanted to also remove information that indicates which Country or
Language the song was purchased in, or which album it was purchased from, there
are some additional IDs to consider:
| Metadata Tag | Description |
| ---------------------------------------- | -------------------------------------------- |
| moov.udta.meta.ilst.apID | Apple account email address |
| moov.udta.meta.ilst.ownr | Apple account username |
| moov.udta.meta.ilst.atID | Artist-track ID |
| moov.udta.meta.ilst.cnID | iTunes Catalog ID |
| moov.udta.meta.ilst.geID | Genre ID |
| moov.udta.meta.ilst.plID | Playlist ID (identifies album) |
| moov.udta.meta.ilst.sfID | iTunes store identifier (location/number) |
| moov.udta.meta.ilst.cprt | Copyright information |
| moov.udta.meta.ilst.flvr | Bitrate/video size related |
| moov.udta.meta.ilst.purd | Date purchased |
| moov.udta.meta.ilst.rtng | Explicit/Clean information |
| moov.udta.meta.ilst.soal | Album sort name |
| moov.udta.meta.ilst.stik | Media type information |
| moov.udta.meta.ilst.xid | Vendor xID |
| moov.udta.meta.ilst.----.name:[iTunMOVI] | Embedded plist contains filesize and flavor. |
| moov.trak.mdia.minf.stbl.stsd.mp4a.pinf | Purchase information related |
See <https://gist.github.com/riophae/f5694fd2952cb64982689b971ca6ec79>.
### Genre Lists
All values are **case sensitive**.
#### The "stik" List
These values are **case sensitive**:
0. `Home Video`
1. `Normal` (meaning music)
2. `Audiobook` (changes extension to .m4b)
3. `Whacked Bookmark`
4. `Music Video`
5. `Movie`
6. `Short Film`
7. `TV Show`
8. `Booklet`
#### Standard Music Genres
```txt
(1.) Blues
(2.) Classic Rock
(3.) Country
(4.) Dance
(5.) Disco
(6.) Funk
(7.) Grunge
(8.) Hip-Hop
(9.) Jazz
(10.) Metal
(11.) New Age
(12.) Oldies
(13.) Other
(14.) Pop
(15.) R&B
(16.) Rap
(17.) Reggae
(18.) Rock
(19.) Techno
(20.) Industrial
(21.) Alternative
(22.) Ska
(23.) Death Metal
(24.) Pranks
(25.) Soundtrack
(26.) Euro-Techno
(27.) Ambient
(28.) Trip-Hop
(29.) Vocal
(30.) Jazz+Funk
(31.) Fusion
(32.) Trance
(33.) Classical
(34.) Instrumental
(35.) Acid
(36.) House
(37.) Game
(38.) Sound Clip
(39.) Gospel
(40.) Noise
(41.) AlternRock
(42.) Bass
(43.) Soul
(44.) Punk
(45.) Space
(46.) Meditative
(47.) Instrumental Pop
(48.) Instrumental Rock
(49.) Ethnic
(50.) Gothic
(51.) Darkwave
(52.) Techno-Industrial
(53.) Electronic
(54.) Pop-Folk
(55.) Eurodance
(56.) Dream
(57.) Southern Rock
(58.) Comedy
(59.) Cult
(60.) Gangsta
(61.) Top 40
(62.) Christian Rap
(63.) Pop/Funk
(64.) Jungle
(65.) Native American
(66.) Cabaret
(67.) New Wave
(68.) Psychadelic
(69.) Rave
(70.) Showtunes
(71.) Trailer
(72.) Lo-Fi
(73.) Tribal
(74.) Acid Punk
(75.) Acid Jazz
(76.) Polka
(77.) Retro
(78.) Musical
(79.) Rock & Roll
(80.) Hard Rock
(81.) Folk
(82.) Folk/Rock
(83.) National Folk
(84.) Swing
(85.) Fast Fusion
(86.) Bebob
(87.) Latin
(88.) Revival
(89.) Celtic
(90.) Bluegrass
(91.) Avantgarde
(92.) Gothic Rock
(93.) Progressive Rock
(94.) Psychedelic Rock
(95.) Symphonic Rock
(96.) Slow Rock
(97.) Big Band
(98.) Chorus
(99.) Easy Listening
(100.) Acoustic
(101.) Humour
(102.) Speech
(103.) Chanson
(104.) Opera
(105.) Chamber Music
(106.) Sonata
(107.) Symphony
(108.) Booty Bass
(109.) Primus
(110.) Porn Groove
(111.) Satire
(112.) Slow Jam
(113.) Club
(114.) Tango
(115.) Samba
(116.) Folklore
(117.) Ballad
(118.) Power Ballad
(119.) Rhythmic Soul
(120.) Freestyle
(121.) Duet
(122.) Punk Rock
(123.) Drum Solo
(124.) A Capella
(125.) Euro-House
(126.) Dance Hall
```
#### iTunes Movie Genre IDs
```sh
AtomicParsley --genre-movie-id-list
```
```text
(4401) Action & Adventure
(4402) Anime
(4403) Classics
(4404) Comedy
(4405) Documentary
(4406) Drama
(4407) Foreign
(4408) Horror
(4409) Independent
(4410) Kids & Family
(4411) Musicals
(4412) Romance
(4413) Sci-Fi & Fantasy
(4414) Short Films
(4415) Special Interest
(4416) Thriller
(4417) Sports
(4418) Western
(4419) Urban
(4420) Holiday
(4421) Made for TV
(4422) Concert Films
(4423) Music Documentaries
(4424) Music Feature Films
(4425) Japanese Cinema
(4426) Jidaigeki
(4427) Tokusatsu
(4428) Korean Cinema
```
#### iTunes TV Genre IDs
```sh
AtomicParsley --genre-tv-id-list
```
```text
(4000) Comedy
(4001) Drama
(4002) Animation
(4003) Action & Adventure
(4004) Classic
(4005) Kids
(4005) Nonfiction
(4007) Reality TV
(4008) Sci-Fi & Fantasy
(4009) Sports
(4010) Teens
(4011) Latino TV
```
### Help
Note: Normally we don't include full help text, but since AtomicParsley has a
long history across various maintainers and repos, we feel it's appropriate to
do so in this case.
```text
AtomicParsley sets metadata into MPEG-4 files & derivatives supporting 3 tag
schemes: iTunes-style, 3GPP assets & ISO defined copyright notifications.
AtomicParsley quick help for setting iTunes-style metadata into MPEG-4 files.
General usage examples:
AtomicParsley /path/to.mp4 -T 1
AtomicParsley /path/to.mp4 -t +
AtomicParsley /path/to.mp4 --artist "Me" --artwork /path/to/art.jpg
Atomicparsley /path/to.mp4 --albumArtist "You" --podcastFlag true
Atomicparsley /path/to.mp4 --stik "TV Show" --advisory explicit
Getting information about the file & tags:
-T --test Test file for mpeg4-ishness & print atom tree
-t --textdata Prints tags embedded within the file
-E --extractPix Extracts pix to the same folder as the mpeg-4 file
Setting iTunes-style metadata tags
--artist (string) Set the artist tag
--title (string) Set the title tag
--album (string) Set the album tag
--genre (string) Genre tag (see --longhelp for more info)
--tracknum (num)[/tot] Track number (or track number/total tracks)
--disk (num)[/tot] Disk number (or disk number/total disks)
--comment (string) Set the comment tag
--year (num|UTC) Year tag (see --longhelp for "Release Date")
--lyrics (string) Set lyrics (not subject to 256 byte limit)
--lyricsFile (/path) Set lyrics to the content of a file
--composer (string) Set the composer tag
--copyright (string) Set the copyright tag
--grouping (string) Set the grouping tag
--artwork (/path) Set a piece of artwork (jpeg or png only)
--bpm (number) Set the tempo/bpm
--albumArtist (string) Set the album artist tag
--compilation (boolean) Set the compilation flag (true or false)
--hdvideo (number) Set the hdvideo flag to one of:
false or 0 for standard definition
true or 1 for 720p
2 for 1080p
--advisory (string*) Content advisory (*values: 'clean', 'explicit')
--stik (string*) Sets the iTunes "stik" atom (see --longhelp)
--description (string) Set the description tag
--longdesc (string) Set the long description tag
--storedesc (string) Set the store description tag
--TVNetwork (string) Set the TV Network name
--TVShowName (string) Set the TV Show name
--TVEpisode (string) Set the TV episode/production code
--TVSeasonNum (number) Set the TV Season number
--TVEpisodeNum (number) Set the TV Episode number
--podcastFlag (boolean) Set the podcast flag (true or false)
--category (string) Sets the podcast category
--keyword (string) Sets the podcast keyword
--podcastURL (URL) Set the podcast feed URL
--podcastGUID (URL) Set the episode's URL tag
--purchaseDate (UTC) Set time of purchase
--encodingTool (string) Set the name of the encoder
--encodedBy (string) Set the name of the Person/company who encoded the file
--apID (string) Set the Account Name
--cnID (number) Set the iTunes Catalog ID (see --longhelp)
--geID (number) Set the iTunes Genre ID (see --longhelp)
--xID (string) Set the vendor-supplied iTunes xID (see --longhelp)
--gapless (boolean) Set the gapless playback flag
--contentRating (string*) Set tv/mpaa rating (see -rDNS-help)
Deleting tags
Set the value to "": --artist "" --stik "" --bpm ""
To delete (all) artwork: --artwork REMOVE_ALL
manually removal: --manualAtomRemove "moov.udta.meta.ilst.ATOM"
More detailed iTunes help is available with AtomicParsley --longhelp
Setting reverse DNS forms for iTunes files: see --reverseDNS-help
Setting 3gp assets into 3GPP & derivative files: see --3gp-help
Setting copyright notices for all files: see --ISO-help
For file-level options & padding info: see --file-help
Setting custom private tag extensions: see --uuid-help
Setting ID3 tags onto mpeg-4 files: see --ID3-help
----------------------------------------------------------------------
AtomicParsley version: 20221229.172126.0 d813aa6e0304ed3ab6d92f1ae96cd52b586181ec (utf8)
Submit bug fixes to https://github.com/wez/atomicparsley
```
### `--longhelp`
```text
AtomicParsley help page for setting iTunes-style metadata into MPEG-4 files.
(3gp help available with AtomicParsley --3gp-help)
(ISO copyright help available with AtomicParsley --ISO-help)
(reverse DNS form help available with AtomicParsley --reverseDNS-help)
Usage: AtomicParsley [mp4FILE]... [OPTION]... [ARGUMENT]... [ [OPTION2]...[ARGUMENT2]...]
example: AtomicParsley /path/to.mp4 -e ~/Desktop/pix
example: AtomicParsley /path/to.mp4 --podcastURL "http://www.url.net" --tracknum 45/356
example: AtomicParsley /path/to.mp4 --copyright "℗ © 2006"
example: AtomicParsley /path/to.mp4 --year "2006-07-27T14:00:43Z" --purchaseDate timestamp
example: AtomicParsley /path/to.mp4 --sortOrder artist "Mighty Dub Cats, The
------------------------------------------------------------------------------------------------
Extract any pictures in user data "covr" atoms to separate files.
--extractPix , -E Extract to same folder (basename derived from file).
--extractPixToPath , -e (/path/basename) Extract to specific path (numbers added to basename).
example: --e ~/Desktop/SomeText
gives: SomeText_artwork_1.jpg SomeText_artwork_2.png
Note: extension comes from embedded image file format
------------------------------------------------------------------------------------------------
Tag setting options:
--artist , -a (str) Set the artist tag: "moov.udta.meta.ilst.©ART.data"
--title , -s (str) Set the title tag: "moov.udta.meta.ilst.©nam.data"
--album , -b (str) Set the album tag: "moov.udta.meta.ilst.©alb.data"
--genre , -g (str) Set the genre tag: "©gen" (custom) or "gnre" (standard).
see the standard list with "AtomicParsley --genre-list"
--tracknum , -k (num)[/tot] Set the track number (or track number & total tracks).
--disk , -d (num)[/tot] Set the disk number (or disk number & total disks).
--comment , -c (str) Set the comment tag: "moov.udta.meta.ilst.©cmt.data"
--year , -y (num|UTC) Set the year tag: "moov.udta.meta.ilst.©day.data"
set with UTC "2006-09-11T09:00:00Z" for Release Date
--lyrics , -l (str) Set the lyrics tag: "moov.udta.meta.ilst.©lyr.data"
--lyricsFile , (/path) Set the lyrics tag to the content of a file
--composer , -w (str) Set the composer tag: "moov.udta.meta.ilst.©wrt.data"
--copyright , -x (str) Set the copyright tag: "moov.udta.meta.ilst.cprt.data"
--grouping , -G (str) Set the grouping tag: "moov.udta.meta.ilst.©grp.data"
--artwork , -A (/path) Set a piece of artwork (jpeg or png) on "covr.data"
Note: multiple pieces are allowed with more --artwork args
--bpm , -B (num) Set the tempo/bpm tag: "moov.udta.meta.ilst.tmpo.data"
--albumArtist , -A (str) Set the album artist tag: "moov.udta.meta.ilst.aART.data"
--compilation , -C (bool) Sets the "cpil" atom (true or false to delete the atom)
--hdvideo , -V (bool) Sets the "hdvd" atom (true or false to delete the atom)
--advisory , -y (1of3) Sets the iTunes lyrics advisory ('remove', 'clean', 'explicit')
--stik , -S (1of7) Sets the iTunes "stik" atom (--stik "remove" to delete)
"Movie", "Normal", "TV Show" .... others:
see the full list with "AtomicParsley --stik-list"
or set in an integer value with --stik value=(num)
Note: --stik Audiobook will change file extension to '.m4b'
--description , -p (str) Sets the description on the "desc" atom
--Rating , (str) Sets the Rating on the "rate" atom
--longdesc , -j (str) Sets the long description on the "ldes" atom
--storedesc , (str) Sets the iTunes store description on the "sdes" atom
--TVNetwork , -n (str) Sets the TV Network name on the "tvnn" atom
--TVShowName , -H (str) Sets the TV Show name on the "tvsh" atom
--TVEpisode , -I (str) Sets the TV Episode on "tven":"209", but it is a string: "209 Part 1"
--TVSeasonNum , -U (num) Sets the TV Season number on the "tvsn" atom
--TVEpisodeNum , -N (num) Sets the TV Episode number on the "tves" atom
--podcastFlag , -f (bool) Sets the podcast flag (values are "true" or "false")
--category , -q (str) Sets the podcast category; typically a duplicate of its genre
--keyword , -K (str) Sets the podcast keyword; invisible to MacOSX Spotlight
--podcastURL , -L (URL) Set the podcast feed URL on the "purl" atom
--podcastGUID , -J (URL) Set the episode's URL tag on the "egid" atom
--purchaseDate , -D (UTC) Set Universal Coordinated Time of purchase on a "purd" atom
(use "timestamp" to set UTC to now; can be akin to id3v2 TDTG tag)
--encodingTool , (str) Set the name of the encoder on the "©too" atom
--encodedBy , (str) Set the name of the Person/company who encoded the file on the "©enc" atom
--apID , -Y (str) Set the name of the Account Name on the "apID" atom
--cnID , (num) Set iTunes Catalog ID, used for combining SD and HD encodes in iTunes on the "cnID" atom
To combine you must set "hdvd" atom on one file and must have same "stik" on both file
Must not use "stik" of value Home Video(0), use Movie(9)
iTunes Catalog numbers can be obtained by finding the item in the iTunes Store. Once item
is found in the iTunes Store right click on picture of item and select copy link. Paste this link
into a document or web browser to display the catalog number ID.
An example link for the video Street Kings is:
http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewMovie?id=278743714&s=143441
Here you can see the cnID is 278743714
Alternatively you can use iMDB numbers, however these will not match the iTunes catalog.
--geID , (num) Set iTunes Genre ID. This does not necessarily have to match genre.
See --genre-movie-id-list and --genre-tv-id-list
--xID , (str) Set iTunes vendor-supplied xID, used to allow iTunes LPs and iTunes Extras to interact
with other content in your iTunes Library
--gapless , (bool) Sets the gapless playback flag for a track in a gapless album
--sortOrder (type) (str) Sets the sort order string for that type of tag.
(available types are: "name", "artist", "albumartist",
"album", "composer", "show")
NOTE: Except for artwork, only 1 of each tag is allowed; artwork allows multiple pieces.
NOTE: Tags that carry text(str) have a limit of 255 utf8 characters;
however lyrics and long descriptions have no limit.
------------------------------------------------------------------------------------------------
To delete a single atom, set the tag to null (except artwork):
--artist "" --lyrics ""
--artwork REMOVE_ALL
--metaEnema , -P Douches away every atom under "moov.udta.meta.ilst"
--foobar2000Enema , -2 Eliminates foobar2000's non-compliant so-out-o-spec tagging scheme
--manualAtomRemove "some.atom.path" where some.atom.path can be:
keys to using manualAtomRemove:
ilst.ATOM.data or ilst.ATOM target an iTunes-style metadata tag
ATOM:lang=foo target an atom with this language setting; like 3gp assets
ATOM.----.name:[foo] target a reverseDNS metadata tag; like iTunNORM
Note: these atoms show up with 'AP -t' as: Atom "----" [foo]
'foo' is actually carried on the 'name' atom
ATOM[x] target an atom with an index other than 1; like trak[2]
ATOM.uuid=hex-hex-hex-hex targt a uuid atom with the uuid of hex string representation
examples:
moov.udta.meta.ilst.----.name:[iTunNORM] moov.trak[3].cprt:lang=urd
moov.trak[2].uuid=55534d54-21d2-4fce-bb88-695cfac9c740
------------------------------------------------------------------------------------------------
Environmental Variables (affecting picture placement)
set PIC_OPTIONS in your shell to set these flags; preferences are separated by colons (:)
MaxDimensions=num (default: 0; unlimited); sets maximum pixel dimensions
DPI=num (default: 72); sets dpi
MaxKBytes=num (default: 0; unlimited); maximum kilobytes for file (jpeg only)
AddBothPix=bool (default: false); add original & converted pic (for archival purposes)
AllPixJPEG | AllPixPNG =bool (default: false); force conversion to a specific picture format
SquareUp (include to square images to largest dimension, allows an [ugly] 160x1200->1200x1200)
removeTempPix (include to delete temp pic files created when resizing images after tagging)
ForceHeight=num (must also specify width, below) force image pixel height
ForceWidth=num (must also specify height, above) force image pixel width
Examples: (bash-style)
export PIC_OPTIONS="MaxDimensions=400:DPI=72:MaxKBytes=100:AddBothPix=true:AllPixJPEG=true"
export PIC_OPTIONS="SquareUp:removeTempPix"
export PIC_OPTIONS="ForceHeight=999:ForceWidth=333:removeTempPix"
------------------------------------------------------------------------------------------------
```
```
```

60
atomicparsley/install.ps1 Normal file
View File

@@ -0,0 +1,60 @@
#!/usr/bin/env pwsh
#########################
# Install AtomicParsley #
#########################
# Every package should define these variables
$pkg_cmd_name = "AtomicParsley"
$pkg_dst_cmd = "$Env:USERPROFILE\.local\bin\AtomicParsley.exe"
$pkg_dst_bin = "$Env:USERPROFILE\.local\bin"
$pkg_dst = "$pkg_dst_cmd"
$pkg_src_cmd = "$Env:USERPROFILE\.local\opt\AtomicParsley-v$Env:WEBI_VERSION\bin\AtomicParsley.exe"
$pkg_src_bin = "$Env:USERPROFILE\.local\opt\AtomicParsley-v$Env:WEBI_VERSION\bin"
$pkg_src_dir = "$Env:USERPROFILE\.local\opt\AtomicParsley-v$Env:WEBI_VERSION"
$pkg_src = "$pkg_src_cmd"
New-Item "$Env:USERPROFILE\Downloads\webi" -ItemType Directory -Force | out-null
$pkg_download = "$Env:USERPROFILE\Downloads\webi\$Env:WEBI_PKG_FILE"
# Fetch archive
IF (!(Test-Path -Path "$Env:USERPROFILE\Downloads\webi\$Env:WEBI_PKG_FILE")) {
echo "Checking for (or Installing) MSVC Runtime..."
& "$Env:USERPROFILE\.local\bin\webi-pwsh.ps1" vcruntime
echo "Downloading AtomicParsley from $Env:WEBI_PKG_URL to $pkg_download"
& curl.exe -A "$Env:WEBI_UA" -fsSL "$Env:WEBI_PKG_URL" -o "$pkg_download.part"
& move "$pkg_download.part" "$pkg_download"
}
IF (!(Test-Path -Path "$pkg_src_cmd")) {
echo "Installing AtomicParsley"
# TODO: create package-specific temp directory
# Enter tmp
pushd .local\tmp
# Remove any leftover tmp cruft
Remove-Item -Path ".\AtomicParsley-v*" -Recurse -ErrorAction Ignore
Remove-Item -Path ".\AtomicParsley.exe" -Recurse -ErrorAction Ignore
# Unpack archive file into this temporary directory
# Windows BSD-tar handles zip. Imagine that.
echo "Unpacking $pkg_download"
& tar xf "$pkg_download"
# Settle unpacked archive into place
echo "Install Location: $pkg_src_cmd"
New-Item "$pkg_src_bin" -ItemType Directory -Force | out-null
Move-Item -Path ".\AtomicParsley.exe" -Destination "$pkg_src_bin"
# Exit tmp
popd
}
echo "Copying into '$pkg_dst_cmd' from '$pkg_src_cmd'"
Remove-Item -Path "$pkg_dst_cmd" -Recurse -ErrorAction Ignore | out-null
New-Item "$pkg_dst_bin" -ItemType Directory -Force | out-null
Copy-Item -Path "$pkg_src" -Destination "$pkg_dst" -Recurse

41
atomicparsley/install.sh Normal file
View File

@@ -0,0 +1,41 @@
#!/bin/sh
set -e
set -u
__init_atomicparsley() {
#########################
# Install AtomicParsley #
#########################
WEBI_SINGLE=true
# Every package should define these 6 variables
pkg_cmd_name="AtomicParsley"
pkg_dst_cmd="$HOME/.local/bin/AtomicParsley"
pkg_dst="$pkg_dst_cmd"
pkg_src_cmd="$HOME/.local/opt/AtomicParsley-v$WEBI_VERSION/bin/AtomicParsley"
pkg_src_dir="$HOME/.local/opt/AtomicParsley-v$WEBI_VERSION"
pkg_src="$pkg_src_cmd"
# pkg_install must be defined by every package
pkg_install() {
# ~/.local/opt/AtomicParsley-v20221229.172126.0/bin
mkdir -p "$(dirname "$pkg_src_cmd")"
# mv ./AtomicParsley ~/.local/opt/AtomicParsley-v20221229.172126.0/bin/AtomicParsley
mv ./"$pkg_cmd_name" "$pkg_src_cmd"
}
pkg_get_current_version() {
# 'AtomicParsley --version' has output in this format:
# AtomicParsley version: 20221229.172126.0 d813aa6e0304ed3ab6d92f1ae96cd52b586181ec (utf8)
# This trims it down to just the version number:
# 20221229.172126.0
AtomicParsley --version 2> /dev/null | head -n 1 | cut -d' ' -f3
}
}
__init_atomicparsley

74
atomicparsley/releases.js Normal file
View File

@@ -0,0 +1,74 @@
'use strict';
var github = require('../_common/github.js');
var owner = 'wez';
var repo = 'atomicparsley';
let targets = {
x86win: {
os: 'windows',
arch: 'x86',
},
x64win: {
os: 'windows',
arch: 'amd64',
},
x64mac: {
os: 'macos',
arch: 'amd64',
},
x64lin: {
os: 'linux',
arch: 'amd64',
},
x64musl: {
os: 'linux',
arch: 'amd64',
_musl_native: true,
},
};
module.exports = function (request) {
return github(request, owner, repo).then(function (all) {
for (let rel of all.releases) {
let windows32 = rel.name.includes('WindowsX86.');
if (windows32) {
Object.assign(rel, targets.x86win);
continue;
}
let windows64 = rel.name.includes('Windows.');
if (windows64) {
Object.assign(rel, targets.x64win);
continue;
}
let macos64 = rel.name.includes('MacOS');
if (macos64) {
Object.assign(rel, targets.x64mac);
continue;
}
let musl64 = rel.name.includes('Alpine');
if (musl64) {
Object.assign(rel, targets.x64musl);
continue;
}
let lin64 = rel.name.includes('Linux.');
if (lin64) {
Object.assign(rel, targets.x64lin);
continue;
}
}
return all;
});
};
if (module === require.main) {
module.exports(require('@root/request')).then(function (all) {
all = require('../_webi/normalize.js')(all);
console.info(JSON.stringify(all));
//console.info(JSON.stringify(all, null, 2));
});
}

View File

@@ -78,3 +78,6 @@ recommended.
- [iterm2](/iterm2)
- [fish](/fish)
- [NerdFont](/nerdfont)
- git
- vim
- zip

View File

@@ -90,22 +90,85 @@ fn_node_install() { (
fi
); }
fn_git_install() { (
if [ "Darwin" = "$(uname -s)" ]; then
needs_xcode="$(
/usr/bin/xcode-select -p > /dev/null 2> /dev/null || echo "true"
)"
if [ -n "${needs_xcode}" ]; then
echo ""
echo ""
printf "\e[31m[Error]\e[0m: Run this command to install XCode Command Line Tools first:\n"
echo ""
echo " xcode-select --install"
echo ""
echo "After the install, close this terminal, open a new one, and try again."
echo ""
exit 1
else
my_git="$(command -v git)"
echo "[Info] Found ${my_git}"
fi
return 0
fi
if ! command -v git > /dev/null; then
fn_apt_get git git
return 0
fi
my_git="$(command -v git)"
echo "[Info] Found ${my_git}"
); }
fn_apt_get() { (
my_cmd="${1:-}"
my_pkg="${2:-}"
printf "\e[31m[Warning]\e[0m \e[32m%s\e[0m not found\n" "${my_cmd}"
printf "\e[32m[Fixup]\e[0m install \e[34m%s\e[0m (may require password)\n" "${my_pkg}"
sleep 1
echo "sudo apt-get install ${my_pkg}"
# shellcheck disable=SC2030
export DEBIAN_FRONTEND=noninteractive
if ! sudo apt-get install -qq -y -o=Dpkg::Use-Pty=0 "${my_pkg}"; then
echo "failed to install ${my_cmd} on"
cat /etc/issue
fi
); }
fn_vim_install() { (
if command -v vim > /dev/null; then
my_vim="$(command -v vim)"
echo "[Info] Found ${my_vim}"
return 0
fi
fn_apt_get vim vim
); }
fn_zip_install() { (
if command -v zip > /dev/null; then
my_zip="$(command -v zip)"
echo "[Info] Found ${my_zip}"
return 0
fi
fn_apt_get zip zip
); }
fn_fish_install() { (
if ! command -v fish > /dev/null; then
printf "\e[31m[Warning]\e[0m \e[32mfish\e[0m not found\n"
printf "\e[32m[Fixup]\e[0m install \e[34mfish\e[0m (may require password)\n"
sleep 1
if [ "Darwin" = "$(uname -s)" ]; then
"${webi_cmd}" fish
printf "\e[31m[Warning]\e[0m \e[32mfish\e[0m not found\n"
printf "\e[32m[Fixup]\e[0m install \e[34mfish\e[0m\n"
sleep 1
"${webi_cmd}" fish > /dev/null
else
echo sudo apt-get install fish
export DEBIAN_FRONTEND=noninteractive
if ! sudo apt-get install -qq -y -o=Dpkg::Use-Pty=0 fish; then
echo "failed to install fish on"
cat /etc/issue
fi
fn_apt_get fish fish
fi
fi
@@ -276,12 +339,19 @@ __install() {
{
printf "\e[32mwebi\e[0m at \e[32m%s\e[0m\n" '~'/.local/bin/webi
echo ""
echo "[Info] PATH updates in ~/.config/envman/PATH.env"
if [ "Darwin" = "$(uname -s)" ]; then
"${webi_cmd}" iterm2
if test -e /Applications/iTerm.app; then
echo "[Info] Found iTerm.app in /Applications/"
else
printf "\e[32m[Fixup]\e[0m Installing \e[32m%s\e[0m into \e[34m%s\e[0m\n" "iTerm.app" "/Applications/"
"${webi_cmd}" iterm2 > /dev/null
fi
fi
fn_git_install
fn_fish_install
fn_zip_install
if test -e ~/.local/share/fonts/'Droid Sans Mono for Powerline Nerd Font Complete.otf'; then
echo "[Info] Found NerdFont in ~/.local/share/fonts"
@@ -299,13 +369,14 @@ __install() {
fi
echo ""
echo "[Info] PATH updates in ~/.config/envman/PATH.env"
fn_path_bin
fn_touch ~/.vimrc '~'/.vimrc
fn_touch ~/.config/envman/alias.env '~'/.config/envman/alias.env
fn_touch ~/.config/envman/PATH.env '~'/.config/envman/PATH.env
echo ""
fn_node_install
for my_cmd in aliasman bat curlie jq pathman shfmt@3.5 shellcheck ssh-pubkey; do
for my_cmd in aliasman bat curlie jq pathman ssh-pubkey; do
fn_webi_bin "${my_cmd}"
done
@@ -317,6 +388,8 @@ __install() {
# vim config and plugins
echo ""
fn_vim_install
fn_touch ~/.vimrc '~'/.vimrc
for my_plugin in leader shell; do
fn_webi_vimrc "${my_plugin}"
done
@@ -328,6 +401,9 @@ __install() {
for my_plugin in commentary lastplace shfmt prettier; do
fn_webi_vim_plugin "${my_plugin}"
done
for my_cmd in shfmt@3.5 shellcheck; do
fn_webi_bin "${my_cmd}"
done
} | tee -a "${my_log}"

View File

@@ -0,0 +1,47 @@
#!/bin/sh
set -e
set -u
main() { (
sed '1,/^#~\/.local\/bin\/brew-updater/d' "${0}" > ~/.local/bin/brew-update-hourly
chmod a+x ~/.local/bin/brew-update-hourly
env PATH="$PATH" serviceman add --user \
--name sh.brew.updater -- \
~/.local/bin/brew-update-hourly
); }
if main; then
exit 0
fi
#~/.local/bin/brew-updater
#!/bin/sh
#set -e
set -u
if test -e ~/.config/envman/PATH.env; then
# shellcheck disable=SC1090
. ~/.config/envman/PATH.env
fi
while true; do
my_start="$(date '+%s')"
my_date="$(date '+%F %T')"
echo "[$my_date] Updating brew..."
brew update
echo ''
my_end="$(date '+%s')"
my_elapsed="$((my_end - my_start))"
my_date="$(date '+%F %T')"
echo "[$my_date] Updated in ${my_elapsed}s."
echo "[$my_date] Cleaning up..."
brew cleanup
echo "[$my_date] Waiting 24 hours..."
my_wait="$((24 * 60 * 60))"
sleep "$my_wait"
done

View File

@@ -7,9 +7,9 @@ _install_brew() {
# Straight from https://brew.sh
#/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
if [ "Darwin" = "$(uname -s)" ]; then
if test "Darwin" = "$(uname -s)"; then
needs_xcode="$(/usr/bin/xcode-select -p > /dev/null 2> /dev/null || echo "true")"
if [ -n "${needs_xcode}" ]; then
if test -n "${needs_xcode}"; then
echo ""
echo ""
echo "ERROR: Run this command to install XCode Command Line Tools first:"
@@ -20,11 +20,11 @@ _install_brew() {
echo ""
fi
else
if [ -z "$(command -v gcc)" ]; then
if ! command -v gcc > /dev/null; then
echo >&2 "Warning: to install 'gcc' et al on Linux use the built-in package manager."
echo >&2 " For example, try: sudo apt install -y build-essential"
fi
if [ -z "$(command -v git)" ]; then
if ! command -v git > /dev/null; then
echo >&2 "Error: to install 'git' on Linux use the built-in package manager."
echo >&2 " For example, try: sudo apt install -y git"
exit 1
@@ -32,7 +32,7 @@ _install_brew() {
fi
# From Straight from https://brew.sh
if ! [ -d "$HOME/.local/opt/brew" ]; then
if ! test -d "$HOME/.local/opt/brew"; then
echo "Installing to '$HOME/.local/opt/brew'"
echo ""
echo "If you prefer to have brew installed to '/usr/local' cancel now and do the following:"
@@ -44,6 +44,13 @@ _install_brew() {
git clone --depth=1 https://github.com/Homebrew/brew "$HOME/.local/opt/brew"
fi
rm -rf "$HOME/.local/bin/brew-update-service-install"
webi_download \
"$WEBI_HOST/packages/brew/brew-update-service-install" \
"$HOME/.local/bin/brew-update-service-install" \
brew-update-service-install
chmod a+x "$HOME/.local/bin/brew-update-service-install"
webi_path_add "$HOME/.local/opt/brew/bin"
export PATH="$HOME/.local/opt/brew/bin:$PATH"
@@ -60,6 +67,10 @@ _install_brew() {
# shellcheck disable=2016
echo ' /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"'
echo ""
echo "To register 'brew update' as a hourly system service:"
echo " brew-update-service-install"
echo ""
}
_install_brew

83
cmake/README.md Normal file
View File

@@ -0,0 +1,83 @@
---
title: CMake
homepage: https://github.com/Kitware/CMake
tagline: |
CMake is a cross-platform, open-source build system generator
---
To update or switch versions, run `webi cmake@stable` (or `@v2`, `@beta`, etc).
### Files
These are the files / directories that are created and/or modified with this
install:
```text
~/.config/envman/PATH.env
~/.local/bin/cmake
~/.local/opt/cmake
```
## Cheat Sheet
> CMake is a cross-platform alternative to autoconf that works on Windows, Mac,
> and Linux
A project structure looks like this:
```text
my-project/
├── build/
├── CMakeLists.txt
├── hello-world*
└── hello-world.cpp
```
And can be built my running `cmake` from the `build` directory:
```sh
pushd ./build/
cmake ../
make
```
### How to create a Hello World with CMake
Lets create a hello world program in C++ and build it with CMake.
1. Create a project directory
```sh
mkdir ./my-project/
pushd ./my-project/
```
2. Create a Hello World C++ file named `hello-world.cpp` `hello-world.cpp`:
```cpp
#include <iostream>
int main(int argc, char** argv) {
std::cout << "Hello World!" << std::endl;
return 0;
}
```
3. Create a `CMakeLists.txt` to compile our code `CMakeLists.txt`:
```cmake
project{hello-world}
cmake_minimum_required(VERSION 3.10)
add_executable(hello-world hello-world.cpp)
```
4. Create a build directory and build the binary
```sh
mkdir ./build/
pushd ./build/
cmake ../
make
```
5. Test the built binary:
```sh
./hello-world
```

56
cmake/install.ps1 Normal file
View File

@@ -0,0 +1,56 @@
#!/usr/bin/env pwsh
#################
# Install cmake #
#################
# Every package should define these variables
$pkg_cmd_name = "cmake"
$pkg_dst_cmd = "$Env:USERPROFILE\.local\opt\cmake\bin\cmake.exe"
$pkg_dst_dir = "$Env:USERPROFILE\.local\opt\cmake"
$pkg_dst = "$pkg_dst_cmd"
$pkg_src_cmd = "$Env:USERPROFILE\.local\opt\cmake-v$Env:WEBI_VERSION\bin\cmake.exe"
$pkg_src_bin = "$Env:USERPROFILE\.local\opt\cmake-v$Env:WEBI_VERSION\bin"
$pkg_src_dir = "$Env:USERPROFILE\.local\opt\cmake-v$Env:WEBI_VERSION"
$pkg_src = "$pkg_src_cmd"
New-Item "$Env:USERPROFILE\Downloads\webi" -ItemType Directory -Force | out-null
$pkg_download = "$Env:USERPROFILE\Downloads\webi\$Env:WEBI_PKG_FILE"
# Fetch archive
IF (!(Test-Path -Path "$Env:USERPROFILE\Downloads\webi\$Env:WEBI_PKG_FILE"))
{
echo "Downloading cmake from $Env:WEBI_PKG_URL to $pkg_download"
& curl.exe -A "$Env:WEBI_UA" -fsSL "$Env:WEBI_PKG_URL" -o "$pkg_download.part"
& move "$pkg_download.part" "$pkg_download"
}
IF (!(Test-Path -Path "$pkg_src_dir"))
{
echo "Installing cmake"
# TODO: create package-specific temp directory
# Enter tmp
pushd .local\tmp
# Remove any leftover tmp cruft
Remove-Item -Path ".\cmake*" -Recurse -ErrorAction Ignore
# Unpack archive file into this temporary directory
# Windows BSD-tar handles zip. Imagine that.
echo "Unpacking $pkg_download"
& tar xf "$pkg_download"
# Settle unpacked archive into place
echo "Install Location: $pkg_src_cmd"
Move-Item -Path ".\cmake*" -Destination "$pkg_src_dir"
# Exit tmp
popd
}
echo "Copying into '$pkg_dst_cmd' from '$pkg_src_cmd'"
Remove-Item -Path "$pkg_dst_cmd" -Recurse -ErrorAction Ignore | out-null
Copy-Item -Path "$pkg_src" -Destination "$pkg_dst" -Recurse

47
cmake/install.sh Normal file
View File

@@ -0,0 +1,47 @@
#!/bin/sh
# shellcheck disable=SC2034
# "'pkg_cmd_name' appears unused. Verify it or export it."
__init_cmake() {
set -e
set -u
##################
# Install cmake #
##################
# Every package should define these 6 variables
pkg_cmd_name="cmake"
pkg_dst_cmd="$HOME/.local/opt/cmake/bin/cmake"
pkg_dst_dir="$HOME/.local/opt/cmake"
pkg_dst="$pkg_dst_dir"
pkg_src_cmd="$HOME/.local/opt/cmake-v$WEBI_VERSION/bin/cmake"
pkg_src_dir="$HOME/.local/opt/cmake-v$WEBI_VERSION"
pkg_src="$pkg_src_dir"
# pkg_install must be defined by every package
pkg_install() {
# ~/.local/opt/cmake-v3.27.0/
mkdir -p "$(dirname "${pkg_src_dir}")"
# mv ./cmake-*/ ~/.local/opt/cmake-v3.27.0/
mv ./cmake-*/ "${pkg_src_dir}"
}
# pkg_get_current_version is recommended, but not required
pkg_get_current_version() {
# 'cmake --version' has output in this format:
# cmake 3.27.0 (rev abcdef0123)
# This trims it down to just the version number:
# 3.27.0
cmake --version 2> /dev/null |
head -n 1 |
cut -d ' ' -f 3
}
}
__init_cmake

20
cmake/releases.js Normal file
View File

@@ -0,0 +1,20 @@
'use strict';
var github = require('../_common/github.js');
var owner = 'Kitware';
var repo = 'CMake';
module.exports = function (request) {
return github(request, owner, repo).then(function (all) {
return all;
});
};
if (module === require.main) {
module.exports(require('@root/request')).then(function (all) {
all = require('../_webi/normalize.js')(all);
// just select the first 5 for demonstration
all.releases = all.releases.slice(0, 5);
console.info(JSON.stringify(all, null, 2));
});
}

140
dashcore-utils/README.md Normal file
View File

@@ -0,0 +1,140 @@
---
title: Dash Core Desktop Wallet
homepage: https://webinstall.dev/dashcore-utils/
tagline: |
Utilities for Dash Core (DASH / Digital Cash)
---
To update, run `webi dashcore-utils`.
### Files
These are the files / directories that are created and/or modified with this
install:
```txt
~/.config/envman/PATH.env
~/.local/opt/dashcore/
~/.local/bin/dash-qt-hd
~/.local/bin/dashd-hd
~/.local/bin/dashd-hd-service-install
```
[`dashcore`](../dashcore/) will also be installed if not present.
## Cheat Sheet
> Convenience scripts for running the Dash Daemon or the Dash Core Desktop
> Wallet.
- `dash-qt-hd`
- `dash-qt-testnet`
- `dashd-hd`
- `dashd-hd-service-install`
- `dashd-testnet`
- `dashd-testnet-service-install`
For historical reasons [`dashd`](../dashd/) (System Daemon) and
[`dash-qt`](../dashcore/) (Desktop Wallet) use _lossy_ keys (non-HD wallets) by
default, and the storage options options are not intuitive.
These scripts run them with safer options that are easier to configure for
server and desktop deployment, respectively.
### How to run the DASH System Daemon
1. Mount or otherwise designate a user-owned folder on a storage volume with
60g+ free space, such as
```sh
/mnt/slc1_vol_100g/dashcore/
```
2. Generally you'll want to install the Dash Daemon as a system service
```sh
dashd-hd-install-service /mnt/vol_slc1_100g/dashcore/
```
To accomplish the same manually you would:
1. Create `~/.dashcore/dash.conf` with
[reasonable defaults](../packages/dashcore-utils/dash.example.conf)
```ini
txindex=1
addressindex=1
timestampindex=1
spentindex=1
[main]
rpcuser=RPCUSER_MAIN
rpcpassword=RPCPASS_MAIN
# to run on multiple interfaces, use multiple config lines
# ex: bind=127.0.0.1:9999 and bind=10.0.0.100:9999)
bind=127.0.0.1:9999
rpcbind=127.0.0.1:9998
rpcconnect=127.0.0.1:9998
rpcallowip=127.0.0.1/16
# zmq* can only be bound to a single interface
# See https://github.com/dashpay/dash/issues/5461
zmqpubrawtx=tcp://127.0.0.1:28332
zmqpubrawtxlock=tcp://127.0.0.1:28332
zmqpubrawchainlock=tcp://127.0.0.1:28332
zmqpubhashchainlock=tcp://127.0.0.1:28332
[test]
# ...
[regtest]
# ...
```
Which is essentially the same as:
```sh
my_user="$(id -u -n)"
sudo mkdir /mnt/slc1_vol_100g/dashcore/
chown -R "$my_user" /mnt/slc1_vol_100g/dashcore/
mkdir -p ~/.dashcore/wallets/
mkdir -p /mnt/slc1_vol_100g/dashcore/_data
mkdir -p /mnt/slc1_vol_100g/dashcore/_caches
sudo env PATH="$PATH" serviceman add \
--system --user "$my_user" --path "$PATH" --name dashd --force -- \
dashd \
-usehd \
-conf="$HOME/.dashcore/dash.conf" \
-walletdir="$HOME/.dashcore/wallets/" \
-datadir=/mnt/slc1_vol_100g/dashcore/_data \
-blocksdir=/mnt/slc1_vol_100g/dashcore/_caches
```
See also:
- [The `dashd` Cheat Sheet](../dashd/).
### How to run the DASH Desktop Wallet
To open an existing (or create a new) Dash Desktop Wallet:
```sh
dash-qt-hd
```
Which is essentially the same as:
```sh
dash-qt \
-usehd \
-walletdir="$HOME/.config/dashcore/wallets/" \
-settings="$HOME/.config/dashcore/settings.json" \
-datadir="$HOME/.dashcore/_data/" \
-blocksdir="$HOME/.dashcore/_caches/"
```
Or pass `-testnet` to use with _TestNet_.
See also:
- [The `dash-qt` Cheat Sheet](../dashcore/).

21
dashcore-utils/dash-qt-hd Normal file
View File

@@ -0,0 +1,21 @@
#!/bin/sh
set -e
set -u
# I don't have the gall to change the defaults (Webi values),
# but I would *strongly* recommend that you do!
#
# Instance-specific data should be separate from global caches:
#
# -settings="$HOME/.config/dashcore/settings.json" \
# -walletdir="$HOME/.config/dashcore/wallets/" \
# -datadir="$HOME/.dashcore/_data/" \
# -blocksdir="$HOME/.dashcore/_caches/" \
dash-qt \
-usehd \
-enablecoinjoin=1 \
-coinjoinautostart=1 \
-coinjoinrounds=16 \
-coinjoindenomsgoal=10 \
-coinjoindenomshardcap=25

View File

@@ -0,0 +1,22 @@
#!/bin/sh
set -e
set -u
# I don't have the gall to change the defaults (Webi values),
# but I would *strongly* recommend that you do!
#
# Instance-specific data should be separate from global caches:
#
# -settings="$HOME/.config/dashcore/settings.json" \
# -walletdir="$HOME/.config/dashcore/wallets/" \
# -datadir="$HOME/.dashcore/_data/" \
# -blocksdir="$HOME/.dashcore/_caches/" \
dash-qt \
-testnet \
-usehd \
-enablecoinjoin=1 \
-coinjoinautostart=1 \
-coinjoinrounds=16 \
-coinjoindenomsgoal=10 \
-coinjoindenomshardcap=25

View File

@@ -0,0 +1,44 @@
txindex=1
addressindex=1
timestampindex=1
spentindex=1
[main]
rpcuser=RPCUSER_MAIN
rpcpassword=RPCPASS_MAIN
# to run on multiple interfaces, use multiple config lines
# ex: bind=127.0.0.1:9999 and bind=10.0.0.100:9999)
bind=127.0.0.1:9999
rpcbind=127.0.0.1:9998
rpcconnect=127.0.0.1:9998
rpcallowip=127.0.0.1/16
# zmq* can only be bound to a single interface
# See https://github.com/dashpay/dash/issues/5461
zmqpubrawtx=tcp://127.0.0.1:28332
zmqpubrawtxlock=tcp://127.0.0.1:28332
zmqpubrawchainlock=tcp://127.0.0.1:28332
zmqpubhashchainlock=tcp://127.0.0.1:28332
[test]
rpcuser=RPCUSER_TEST
rpcpassword=RPCPASS_TEST
bind=127.0.0.1:19999
rpcbind=127.0.0.1:19998
rpcconnect=127.0.0.1:19998
rpcallowip=127.0.0.1/16
zmqpubrawtx=tcp://127.0.0.1:18009
zmqpubrawtxlock=tcp://127.0.0.1:18009
zmqpubrawchainlock=tcp://127.0.0.1:18009
zmqpubhashchainlock=tcp://127.0.0.1:18009
[regtest]
rpcuser=RPCUSER_REGTEST
rpcpassword=RPCPASS_REGTEST
bind=127.0.0.1:19899
rpcbind=127.0.0.1:19898
rpcconnect=127.0.0.1:19898
rpcallowip=127.0.0.1/16
zmqpubrawtx=tcp://127.0.0.1:18809
zmqpubrawtxlock=tcp://127.0.0.1:18809
zmqpubrawchainlock=tcp://127.0.0.1:18809
zmqpubhashchainlock=tcp://127.0.0.1:18809

46
dashcore-utils/dashd-hd Normal file
View File

@@ -0,0 +1,46 @@
#!/bin/sh
set -e
set -u
# Unfortunately we can't know that datadir won't be used
# for other non-cache files, but we can at least protect
# the ones we're aware of.
my_netname="${1:-}"
if test -n "${my_netname}"; then
if test "${my_netname}" != mainnet &&
test "${my_netname}" != testnet &&
test "${my_netname}" != regnet &&
test "${my_netname}" != devnet; then
echo ""
echo "ERROR"
echo " '${my_netname}' is not one of 'testnet', 'regnet', 'devnet'"
echo ""
echo ""
fi
if test "${my_netname}" != mainnet; then
my_netname=''
fi
fi
my_net_arg=''
if test -n "${my_netname}"; then
my_net_arg="-${my_netname}"
fi
# shellcheck disable=2086
dashd \
-usehd \
${my_net_arg} \
-conf="$HOME/.dashcore/dash.conf" \
-settings="$HOME/.dashcore/settings.json" \
-walletdir="$HOME/.dashcore/wallets/" \
-datadir="$HOME/.dashcore/_data/" \
-blocksdir="$HOME/.dashcore/_data/"
# -enablecoinjoin=1 \
# -coinjoinautostart=1 \
# -coinjoinrounds=16 \
# -coinjoindenomsgoal=10 \
# -coinjoindenomshardcap=25

View File

@@ -0,0 +1,176 @@
#!/bin/sh
set -e
set -u
fn_usage() { (
echo >&2 ""
echo >&2 "USAGE"
echo >&2 " dashd-hd-service-install [datadir] ['testnet']"
echo >&2 ""
echo >&2 "EXAMPLE"
echo >&2 " dashd-hd-service-install /mnt/vol_slc1_100g/dashcore/"
echo >&2 ""
echo >&2 "NOTE"
echo >&2 " If a directory matching '/mnt/*/dashcore/' is found,"
echo >&2 " it will be used automatically."
echo >&2 ""
); }
fn_datadir_help() { (
my_vol="${1:-}"
my_user="$(
id -n -u
)"
my_group="$(
id -n -g
)"
echo >&2 ""
echo >&2 "ERROR"
echo >&2 " '${my_vol}' is not writable"
echo >&2 ""
echo >&2 "SOLUTION"
echo >&2 " 1. Mount a large (50gb+) volume"
echo >&2 ""
echo >&2 " sudo mkdir -p /mnt/EXAMPLE"
echo >&2 " sudo mount /dev/sdx1 /mnt/EXAMPLE"
echo >&2 ""
echo >&2 " 2. Create a 'dashcore' inside of it"
echo >&2 ""
echo >&2 " sudo mkdir -p '${my_vol}'"
echo >&2 ""
echo >&2 " 3. Make it writable to this user"
echo >&2 ""
echo >&2 " sudo chown -R '${my_user}':'${my_group}' '${my_vol}'"
echo >&2 ""
echo >&2 ""
); }
fn_srv_install() { (
my_vol="${1:-}"
my_netname="${2:-}"
my_name='dashd'
# both of these will get '/testnet3' suffixes with -testnet
my_datadir="${my_vol}/_data"
my_blocksdir="${my_vol}/_caches"
if test -n "${my_netname}"; then
if test "mainnet" = "${my_netname}"; then
my_netname=""
elif test "testnet" != "${my_netname}"; then
fn_usage
return 1
fi
fi
if ! test -d "${my_datadir}"; then
mkdir "${my_datadir}"
chmod 0700 "${my_datadir}"
fi
if ! test -d "${my_blocksdir}"; then
mkdir -p "${my_blocksdir}"
chmod 0700 "${my_blocksdir}"
fi
my_net_flag=''
if test -n "${my_netname}"; then
# ex: -testnet
my_net_flag="-${my_netname}"
# ex: dashd-testnet
my_name="dashd-${my_netname}"
fi
my_system_args=""
my_kernel="$(
uname -s
)"
if test "Darwin" != "${my_kernel}"; then
my_user="$(
id -u -n
)"
my_system_args="--system --username ${my_user}"
fi
# shellcheck disable=SC2016,SC1090
echo 'sudo env PATH="$PATH"' \
"serviceman add ${my_system_args} --path \"\$PATH\" --name \"${my_name}\" --force --" \
"dashd " \
"${my_net_flag}" \
-usehd \
'-conf="$HOME/.dashcore/dash.conf"' \
'-settings="$HOME/.dashcore/settings.json"' \
'-walletdir="$HOME/.dashcore/wallets/"' \
"-datadir=\"${my_datadir}\"" \
"-blocksdir=\"${my_blocksdir}\""
if ! command -v serviceman > /dev/null; then
echo ""
echo "Installing 'serviceman'..."
echo ""
{
curl -fsSL "${WEBI_HOST}/serviceman" | sh
} > /dev/null
# shellcheck disable=SC1090
. ~/.config/envman/PATH.env || true
fi
mkdir -p "$HOME/.dashcore/wallets/"
chmod 0700 "$HOME/.dashcore/wallets/"
mkdir -p "${my_datadir}"
chmod 0700 "${my_datadir}"
mkdir -p "${my_blocksdir}"
chmod 0700 "${my_blocksdir}"
cd "${my_vol}" || return 1
# leave options unquoted so they're interpreted separately
# shellcheck disable=SC2086
sudo env PATH="${PATH}" \
serviceman add ${my_system_args} --path "${PATH}" --name "${my_name}" --force -- \
dashd \
${my_net_flag} \
-usehd \
-conf="${HOME}/.dashcore/dash.conf" \
-settings="${HOME}/.dashcore/settings.json" \
-walletdir="${HOME}/.dashcore/wallets/" \
-datadir="${my_datadir}" \
-blocksdir="${my_blocksdir}"
); }
main() { (
my_vol="${1:-}"
my_netname="${2:-}"
if test -z "${my_vol}"; then
my_vol="$(
ls -d /mnt/*/dashcore/ 2> /dev/null || true
)"
fi
if test "help" = "${my_vol}" ||
test "--help" = "${my_vol}"; then
fn_usage
return 0
fi
if test -z "${my_vol}"; then
fn_usage
return 1
fi
if ! test -d "${my_vol}" ||
! test -w "${my_vol}"; then
fn_datadir_help "${my_vol}"
return 1
fi
fn_srv_install "${my_vol}" "${my_netname}"
); }
main "${@:-}"

View File

@@ -0,0 +1,13 @@
#!/bin/sh
set -e
set -u
# NOTE:
# The '-testnet' flag will always cause a './testnet3/' folder
# to be created under '-datadir' (it won't the 'datadir' directly)
#
# Example:
# dashd -testnet -datadir="$HOME/.dashcore/"
# will save to ~/.dashcore/testnet3/, NOT ~/.dashcore/
dashd-hd testnet

View File

@@ -0,0 +1,5 @@
#!/bin/sh
set -e
set -u
dashd-hd-service-install "${1:-}" "testnet"

91
dashcore-utils/install.sh Normal file
View File

@@ -0,0 +1,91 @@
#!/bin/sh
set -e
set -u
__install_dashcore_utils() {
webi_download \
"$WEBI_HOST/packages/dashcore-utils/dash-qt-hd" \
"$HOME/.local/bin/dash-qt-hd"
chmod a+x "$HOME/.local/bin/dash-qt-hd"
webi_download \
"$WEBI_HOST/packages/dashcore-utils/dash-qt-testnet" \
"$HOME/.local/bin/dash-qt-testnet"
chmod a+x "$HOME/.local/bin/dash-qt-testnet"
webi_download \
"$WEBI_HOST/packages/dashcore-utils/dashd-hd" \
"$HOME/.local/bin/dashd-hd"
chmod a+x "$HOME/.local/bin/dashd-hd"
webi_download \
"$WEBI_HOST/packages/dashcore-utils/dashd-testnet" \
"$HOME/.local/bin/dashd-testnet"
chmod a+x "$HOME/.local/bin/dashd-testnet"
webi_download \
"$WEBI_HOST/packages/dashcore-utils/dashd-hd-service-install" \
"$HOME/.local/bin/dashd-hd-service-install"
chmod a+x "$HOME/.local/bin/dashd-hd-service-install"
webi_download \
"$WEBI_HOST/packages/dashcore-utils/dashd-testnet-service-install" \
"$HOME/.local/bin/dashd-testnet-service-install"
chmod a+x "$HOME/.local/bin/dashd-testnet-service-install"
if ! test -e "${HOME}/.dashcore"; then
mkdir -p "${HOME}/.dashcore"
chmod 0700 "${HOME}/.dashcore"
fi
if ! test -e "${HOME}/.dashcore/dash.conf"; then
touch "${HOME}/.dashcore/dash.conf"
chmod 0600 "${HOME}/.dashcore/dash.conf"
fi
webi_download \
"$WEBI_HOST/packages/dashcore-utils/dash.example.conf" \
"$HOME/.dashcore/dash.example.conf"
if ! grep -q rpcuser ~/.dashcore/dash.conf; then
cat ~/.dashcore/dash.example.conf >> ~/.dashcore/dash.conf
cmd_sed="sed -i -E"
my_bsd_sed=''
if ! sed -V 2>&1 | grep -q 'GNU'; then
cmd_sed="sed -i .dascore-utils-bak -E"
my_bsd_sed='true'
fi
my_user="$(
id -u -n
)"
my_main_pass="$(xxd -l16 -ps /dev/urandom)"
my_test_pass="$(xxd -l16 -ps /dev/urandom)"
my_regtest_pass="$(xxd -l16 -ps /dev/urandom)"
$cmd_sed "s/RPCUSER_MAIN/${my_user}/" ~/.dashcore/dash.conf
$cmd_sed "s/RPCPASS_MAIN/${my_main_pass}/" ~/.dashcore/dash.conf
$cmd_sed "s/RPCUSER_TEST/${my_user}-test/" ~/.dashcore/dash.conf
$cmd_sed "s/RPCPASS_TEST/${my_test_pass}/" ~/.dashcore/dash.conf
$cmd_sed "s/RPCUSER_REGTEST/${my_user}-regtest/" ~/.dashcore/dash.conf
$cmd_sed "s/RPCPASS_REGTEST/${my_regtest_pass}/" ~/.dashcore/dash.conf
if test -n "${my_bsd_sed}"; then
rm -f ~/.dashcore/dash.conf.dascore-utils-bak
fi
fi
export PATH="$HOME/.local/opt/dashcore/bin:$PATH"
if ! command -v dashd > /dev/null ||
! command -v dash-qt > /dev/null; then
"$HOME/.local/bin/webi" dashcore
fi
# Always try to correct the permissions due to
# https://github.com/dashpay/dash/issues/5420
chmod -R og-rwx "${HOME}/.dashcore/" || true
}
__install_dashcore_utils

189
dashcore/README.md Normal file
View File

@@ -0,0 +1,189 @@
---
title: Dash Core Desktop Wallet
homepage: https://github.com/dashpay/dash
tagline: |
Dash Core is the Desktop Wallet for Digital Cash (DASH)
---
To update or switch versions, run `webi dashcore@stable` (or `@v19`, `@beta`,
etc).
### System Requirements
- 50GB Free Storage (100GB recommended)
- 4GB RAM (8GB recommended)
- 4 hours for initial sync
### Files
These are the files / directories that are created and/or modified with this
install:
```txt
~/.config/envman/PATH.env
~/.local/opt/dashcore/
# For convenience
~/.local/bin/dash-qt-hd
~/.local/bin/dash-qt-testnet
# Linux
~/.dashcore/settings.json
~/.dashcore/testnet3/
# macOS
~/Library/Application Support/DashCore/settings.json
~/Library/Application Support/DashCore/testnet3/
~/Library/Saved Application State/org.dash.Dash-Qt.savedState
~/Library/Preferences/org.dash.Dash-Qt.plist
```
[`dashcore-utils`](../dashcore-utils/) will also be installed if not present.
## Cheat Sheet
> _DASH_ (portmanteau of _Digital Cash_) is an international currency. _Dash
> Core_ is the original suite of tools for _Dash_, maintained by DCG.
The original tools include:
- `dash-qt` - a _Desktop Wallet_ for sending and receiving money
- [`dashd`](../dashd/) - the [_Full Node_](../dashd/) server daemon \
(for APIs, servers, and such)
- `dash-cli` - send RPC commands (same as the dash-qt command console)
- `dash-tx` - create and debug raw (hex) transactions
- `dash-wallet` - interact with wallet files offline
The webi installer also includes two convenience wrapper scripts:
- `dash-qt-hd`
- `dash-qt-testnet`
To open an existing (or create a new) Dash Desktop Wallet:
```sh
dash-qt \
-usehd \
-walletdir="$HOME/.config/dashcore/wallets/" \
-settings="$HOME/.config/dashcore/settings.json" \
-datadir="$HOME/.dashcore/_data/" \
-blocksdir="$HOME/.dashcore/_caches/"
```
Or pass `-testnet` to use with _TestNet_:
```sh
dash-qt \
-testnet \
-usehd \
-walletdir="$HOME/.config/dashcore/wallets/" \
-settings="$HOME/.config/dashcore/settings.json" \
-datadir="$HOME/.dashcore/_data/" \
-blocksdir="$HOME/.dashcore/_caches/"
```
### IMPORTANT: How to NOT Lose Money!
`dash-qt-hd` should be preferred to `dash-qt`.
For historical reasons, `dash-qt` uses **lossy keys** by default!
This is very dangerous - without a Wallet Phrase to recover HD Keys, file
corruption (or losing the device) can lead to losing money permanently.
To avoid this you may use `dash-qt-hd`, or create your wallet with `-usehd`
(optionally with `-mnemonic=<wallet phrase>` if you'd like to recover an
existing wallet), or `upgradetohd`.
### How to Convert from Lossy to HD
If you used `dash-qt` without `-usehd` and already created a wallet, you can fix
it from the command console, which can be found in _Window => Console_.
```text
# Usage
# upgradetohd [wallet phrase] [legacy salt] <wallet encryption phrase>
# Example
upgradetohd "" "" "correct horse battery staple"
# Example with the "zoomonic" and a legacy salt
upgradetohd "zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo wrong" \
"TREZOR" "correct horse battery staple"
```
It's a good idea to back up your wallet before running the conversion.
For more detail see:
<https://docs.dash.org/en/stable/docs/user/wallets/dashcore/advanced.html>
### How to Separate Caches from Data
You can make your data much safer by separating it from the caches you may need
to delete by setting:
- `-walletdir=` your money!!
- `-settings=` desktop app settings!
- `-conf=` server settings
- `-datadir=` miscellaneous
- `-blocksdir=` generic caches
```sh
dash-qt \
-usehd \
-settings="$HOME/.config/dashcore/settings.json" \
-walletdir="$HOME/.config/dashcore/wallets/" \
-datadir="$HOME/.dashcore/_data/" \
-blocksdir="$HOME/.dashcore/_caches/" \
-enablecoinjoin=1 \
-coinjoinautostart=1 \
-coinjoinrounds=16 \
-coinjoindenomsgoal=10 \
-coinjoindenomshardcap=25
```
### How to Mix with CoinJoin
CoinJoin aids in preventing some bad actors and malicious observers being able
to easily reconstruct details about your transactions from the publicly
available data by creating many excess transactions. \
(be aware, however, that dedicated bad actors can use sophisticated software that
will reveal much of the same information over time)
`dash-qt` does not enable CoinJoin mixing by default.
`dash-qt-hd` does. It runs the following:
```sh
dash-qt \
-usehd \
-enablecoinjoin=1 \
-coinjoinautostart=1 \
-coinjoinrounds=16 \
-coinjoindenomsgoal=10 \
-coinjoindenomshardcap=25
```
The `coinjoindenomsgoal` and `coinjoindenomshardcap` prevent CoinJoin from
splitting coins down into hundreds of small, unusable coins.
### Other Tools
- [`dashphrase`](https://github.com/dashhive/dashphrase-cli) for generating
secure Wallet Phrases
- [`dashsight`](https://github.com/dashhive/dashphrase-cli) for inspecting
balances, transactions, etc via API (without downloading the indexes)
### More Documentation
All of the **command line flags and options** for the Dash Core Desktop Wallet
are documented between these two pages:
- https://docs.dash.org/projects/core/en/stable/docs/dashcore/wallet-arguments-and-commands-dash-qt.html
- https://docs.dash.org/projects/core/en/stable/docs/dashcore/wallet-arguments-and-commands-dashd.html
The **config files** `dash.conf` (mainly for _Full Nodes_) and `settings.json`
(mainly for Desktop Wallets) are documented at:
- <https://github.com/dashpay/dash/blob/master/contrib/debian/examples/dash.conf>
- <https://docs.dash.org/projects/core/en/stable/docs/dashcore/wallet-configuration-file.html>

56
dashcore/install.ps1 Normal file
View File

@@ -0,0 +1,56 @@
#!/usr/bin/env pwsh
####################
# Install dashcore #
####################
# Every package should define these variables
$pkg_cmd_name = "dash-qt"
$pkg_dst_cmd = "$Env:USERPROFILE\.local\opt\dashcore\bin\dash-qt.exe"
$pkg_dst_dir = "$Env:USERPROFILE\.local\opt\dashcore"
$pkg_dst = "$pkg_dst_cmd"
$pkg_src_cmd = "$Env:USERPROFILE\.local\opt\dashcore-v$Env:WEBI_VERSION\bin\dash-qt.exe"
$pkg_src_bin = "$Env:USERPROFILE\.local\opt\dashcore-v$Env:WEBI_VERSION\bin"
$pkg_src_dir = "$Env:USERPROFILE\.local\opt\dashcore-v$Env:WEBI_VERSION"
$pkg_src = "$pkg_src_cmd"
New-Item "$Env:USERPROFILE\Downloads\webi" -ItemType Directory -Force | out-null
$pkg_download = "$Env:USERPROFILE\Downloads\webi\$Env:WEBI_PKG_FILE"
# Fetch archive
IF (!(Test-Path -Path "$Env:USERPROFILE\Downloads\webi\$Env:WEBI_PKG_FILE"))
{
echo "Downloading dashcore from $Env:WEBI_PKG_URL to $pkg_download"
& curl.exe -A "$Env:WEBI_UA" -fsSL "$Env:WEBI_PKG_URL" -o "$pkg_download.part"
& move "$pkg_download.part" "$pkg_download"
}
IF (!(Test-Path -Path "$pkg_src_dir"))
{
echo "Installing dashcore"
# TODO: create package-specific temp directory
# Enter tmp
pushd .local\tmp
# Remove any leftover tmp cruft
Remove-Item -Path ".\dashcore*" -Recurse -ErrorAction Ignore
# Unpack archive file into this temporary directory
# Windows BSD-tar handles zip. Imagine that.
echo "Unpacking $pkg_download"
& tar xf "$pkg_download"
# Settle unpacked archive into place
echo "Install Location: $pkg_src_cmd"
Move-Item -Path ".\dashcore*" -Destination "$pkg_src_dir"
# Exit tmp
popd
}
echo "Copying into '$pkg_dst_cmd' from '$pkg_src_cmd'"
Remove-Item -Path "$pkg_dst_cmd" -Recurse -ErrorAction Ignore | out-null
Copy-Item -Path "$pkg_src" -Destination "$pkg_dst" -Recurse

81
dashcore/install.sh Normal file
View File

@@ -0,0 +1,81 @@
#!/bin/sh
# shellcheck disable=SC2034
# "'pkg_cmd_name' appears unused. Verify it or export it."
__init_dashcore() {
set -e
set -u
####################
# Install dashcore #
####################
# Every package should define these 6 variables
pkg_cmd_name="dash-qt"
pkg_dst_cmd="$HOME/.local/opt/dashcore/bin/dash-qt"
pkg_dst_dir="$HOME/.local/opt/dashcore"
pkg_dst="$pkg_dst_dir"
pkg_src_cmd="$HOME/.local/opt/dashcore-v$WEBI_VERSION/bin/dash-qt"
pkg_src_dir="$HOME/.local/opt/dashcore-v$WEBI_VERSION"
pkg_src="$pkg_src_dir"
# pkg_install must be defined by every package
pkg_install() {
# mv ./dashcore-* ~/.local/opt/dashcore-v0.19.1
mv ./dashcore-* "${pkg_src_dir}"
if ! test -e "${HOME}/.dashcore"; then
mkdir -p "${HOME}/.dashcore"
chmod 0700 "${HOME}/.dashcore" || true
fi
# if ! test -e "${HOME}/.dashcore/dash.conf"; then
# my_main_pass="$(xxd -l16 -ps /dev/urandom)"
# my_test_pass="$(xxd -l16 -ps /dev/urandom)"
# {
# echo '[main]'
# echo "rpcuser=$(id -u -n)"
# echo "rpcpassword=${my_main_pass}"
# echo ''
# echo '[test]'
# echo "rpcuser=$(id -u -n)-test"
# echo "rpcpassword=${my_test_pass}"
# echo ''
# } >> "${HOME}/.dashcore/dash.conf"
# chmod 0600 "${HOME}/.dashcore/dash.conf" || true
# fi
# if ! test -e "${HOME}/.dashcore/settings.json"; then
# echo '{}' >> "${HOME}/.dashcore/settings.json"
# chmod 0600 "${HOME}/.dashcore/settings.json" || true
# fi
if ! test -e "$HOME/.local/bin/dash-qt-hd" ||
! test -e "$HOME/.local/bin/dash-qt-testnet"; then
"$HOME/.local/bin/webi" dashcore-utils
fi
# Always try to correct the permissions due to
# https://github.com/dashpay/dash/issues/5420
chmod -R og-rwx "${HOME}/.dashcore/" || true
}
# pkg_get_current_version is recommended, but not required
pkg_get_current_version() {
# 'dash-qt' doesn't have version info, so we use 'dashd'
# 'dashd --version' has output in this format:
# Dash Core Daemon version v19.1.0
# This trims it down to just the version number:
# 19.1.0
dashd --version 2> /dev/null |
head -n 1 |
cut -d ' ' -f 5 |
sed 's:^v::'
}
}
__init_dashcore

28
dashcore/releases.js Normal file
View File

@@ -0,0 +1,28 @@
'use strict';
var github = require('../_common/github.js');
var owner = 'dashpay';
var repo = 'dash';
module.exports = function (request) {
return github(request, owner, repo).then(function (all) {
all.releases = all.releases.filter(function (rel) {
return !rel.name.endsWith('.asc');
});
all.releases.forEach(function (rel) {
if (rel.name.includes('osx64')) {
rel.os = 'macos';
}
});
return all;
});
};
if (module === require.main) {
module.exports(require('@root/request')).then(function (all) {
all = require('../_webi/normalize.js')(all);
// just select the first 5 for demonstration
all.releases = all.releases.slice(0, 5);
console.info(JSON.stringify(all, null, 2));
});
}

310
dashd/README.md Normal file
View File

@@ -0,0 +1,310 @@
---
title: Dash Core Full Node Daemon
homepage: https://github.com/dashpay/dash
tagline: |
dashd is the Full Node service for Digital Cash (DASH)
---
To update or switch versions, run `webi dashd@stable` (or `@v0.19`, `@beta`,
etc).
### Recommended Hardware
- 100GB+ Block Storage
- 8GB RAM
- 4 vCPUs
- **30 hours** for initial indexing
### Files
These are the files / directories that are created and/or modified with this
install:
```txt
~/.config/envman/PATH.env
~/.dashcore/dash.conf
~/.dashcore/wallets/
~/.local/bin/bin/dashd-hd-service-install
~/.local/opt/dashcore/
/mnt/<BLK_VOL>/dashcore/
```
[`dashcore-utils`](../dashcore-utils/) will also be installed if not present.
## Cheat Sheet
> A DASH _Full Node_ syncs and indexes the DASH blockchain and can be used to
> broadcast transactions (sending money) and retrieve information about
> transactions, balances, etc. This "Dash Core" implementation is maintained by
> DCG.
To install as **a system service** with reasonable defaults, \
you can use these convenience scripts provided by Webi:
```sh
# USAGE
# dashd-hd-service-install [storage-volume] [testnet]
#
# EXAMPLE
dashd-hd-service-install
```
### QuickStart
0. Check that you have enough Storage and RAM
- mainnet: 100GB+ Storage, 8GB RAM
- testnet: 20GB+ Storage, 2GB RAM
1. Create a mount for your storage volume
```sh
sudo mkdir -p /mnt/100gb-vol/
sudo mount /dev/vda1 /mnt/100gb-vol/
```
2. Create a correctly permissioned `dashcore` directory
```sh
sudo mkdir -p /mnt/100g-vol/dashcore/
sudo chown -R "$(id -u -n):$(id -g -n)" /mnt/100gb-vol/dashcore/
```
3. Register `dashd` with the system launcher
```sh
dashd-hd-service-install
```
4. Wait **about 30 hours** for initial sync and indexing to complete
5. Test with the DashCore CLI
```sh
dash-cli getaddresstxids '{
"addresses": ["XchrTJFPGFiror4zjXQRR7XTSN25YtLYhC"],
"start": 0,
"end":1000000000
}'
```
### How to use DashCore CLI
After it completes the initial sync (about 4 hours), \
you can query address information:
```sh
# Balances
dash-cli getaddressbalance '{"addresses": ["XchrTJFPGFiror4zjXQRR7XTSN25YtLYhC"]}'
# UTXOs
dash-cli getaddressutxos '{"addresses": ["XpLVjhDd6vNJamtcJXcrpQYA1sE6fmxVDa"]}'
# TXes
dash-cli getaddresstxids '{
"addresses": ["XchrTJFPGFiror4zjXQRR7XTSN25YtLYhC"],
"start": 0,
"end":1000000000
}'
# Broadcast TX
dash-cli -testnet sendrawtransaction 01000000...0c0226b428a488ac00000000
```
### How to Run dashd Manually
To run **in the foreground**: \
(add `-testnet` to run on testnet)
```sh
dashd \
-usehd \
-conf="$HOME/.dashcore/dash.conf" \
-settings="$HOME/.dashcore/settings.json" \
-walletdir="$HOME/.dashcore/wallets/" \
-datadir="/mnt/100gb/dashcore/_data/" \
-blocksdir="/mnt/100gb/dashcore/_caches/" \
-addressindex=1 \
-timestampindex=1 \
-txindex=1 \
-spentindex=1
```
**Warning**: killing the process with ctrl+c before the first full sync may
corrupt the data and require starting over (see below)
### Server Requirements
150MB for Applications on OS Storage
For **mainnet**:
- 100GB Block Storage Volume \
- minimum of 40GB (blockchain) + 50GB (indexes) as of 2023
- plus 4-8GB per year
- 8GB RAM \
(min 4GB RAM + 4GB swap, otherwise it crashes during indexing)
- 4 vCPUs \
(min 2x 2.0GHz vCPUs, higher clock speed is better than more cors)
- 100 megabit network
- 28-30 hours to sync and index in ideal conditions
- minimum of 4 hours to sync
- approximately 28 hours to index regardless of sync time
For **testnet**:
- 20GB Block Storage Volume \
- min 4GB (blockchain) + 5 GB (indexes) as of 2022
- plus 0.5-1GB/year
- 2GB RAM
- 1 vCPU
- 4 hours to sync and index in ideal conditions
- 1 hour to sync
- about 4 hours to index regardless of sync time
### How to configure `dash.conf`
You can set options for `main`, `test`, and `regtest`.
If you intend to use the various RPCs you must enable indexes.
```ini
txindex=1
addressindex=1
timestampindex=1
spentindex=1
[main]
rpcuser=alice
rpcpassword=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
bind=127.0.0.1:9999
rpcbind=127.0.0.1:9998
rpcconnect=127.0.0.1:9998
rpcallowip=127.0.0.1/16
zmqpubrawtx=tcp://127.0.0.1:28332
zmqpubrawtxlock=tcp://127.0.0.1:28332
zmqpubrawchainlock=tcp://127.0.0.1:28332
zmqpubhashchainlock=tcp://127.0.0.1:28332
[test]
rpcuser=alice-test
rpcpassword=yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
bind=127.0.0.1:19999
rpcbind=127.0.0.1:19998
rpcconnect=127.0.0.1:19998
rpcallowip=127.0.0.1/16
zmqpubrawtx=tcp://127.0.0.1:18009
zmqpubrawtxlock=tcp://127.0.0.1:18009
zmqpubrawchainlock=tcp://127.0.0.1:18009
zmqpubhashchainlock=tcp://127.0.0.1:18009
```
See also:
- [dash: examples/dash.conf](https://github.com/dashpay/dash/blob/549e347b742cb4dc63807a292729e658218d7d0f/contrib/debian/examples/dash.conf#L2)
- [dashd: Indexing Options](https://docs.dash.org/projects/core/en/19.0.0/docs/dashcore/wallet-arguments-and-commands-dashd.html#indexing-options)
### How to Separate Caches from Data
You can make your data much safer by separating it from the caches you may need
to delete by setting:
- `-walletdir=` your money!!
- `-settings=` desktop app settings!
- `-conf=` server settings
- `-datadir=` generic caches
```sh
dashd \
-usehd \
-conf="$HOME/.config/dashcore/dash.conf" \
-walletdir="$HOME/.config/dashcore/wallets/" \
-datadir="/mnt/dashcore/dashcore/"
```
### How to Run as a System Service
You can use [`serviceman`](../serviceman/):
**Linux**
```sh
sudo env PATH="$PATH" \
serviceman add \
--system \
--username "$(id -n -u)" \
--path "$PATH" \
--name dashd \
--force \
-- \
dashd \
-usehd \
-conf="$HOME/.dashcore/dash.conf" \
-settings="$HOME/.dashcore/settings.json" \
-walletdir="$HOME/.dashcore/wallets/" \
-datadir="/mnt/100gb/dashcore/_data/" \
-blocksdir="/mnt/100gb/dashcore/_caches/"
```
**Mac**
```sh
serviceman add \
--path "$PATH" \
--name dashd \
--force \
-- \
dashd \
-usehd \
-conf="$HOME/.dashcore/dash.conf" \
-settings="$HOME/.dashcore/settings.json" \
-walletdir="$HOME/.dashcore/wallets/" \
-datadir="/Volumes/100gb/dashcore/_data/" \
-blocksdir="/Volumes/100gb/dashcore/_caches/"
```
**Windows**
(be sure modify variables appropriately for `cmd.exe` or `powershell`)
```sh
& serviceman add \
--name dashd \
--force \
-- \
dashd \
-usehd \
-conf="$Env:UserProfile/.dashcore/dash.conf" \
-settings="$Env:UserProfile/.dashcore/settings.json" \
-walletdir="$Env:UserProfile/.dashcore/wallets/" \
-datadir="D:/100gb/dashcore/_data/" \
-blocksdir="D:/100gb/dashcore/_caches/"
```
### How to Trim Excessive Storage
If the service **crashes** during the initial syncing and indexing (such as when
using less than 4GB RAM + 4GB Swap) it **will not resume** (typically).
Instead it will create duplicate new data, and not clean up the old data.
You may need to **delete /mnt/<BLK_VOL>/dashcore/** and start from scratch
(being careful not to delete any wallet information, if you have any).
Generally I wouldn't recommend storing money on a Full Node -since it's
primarily used for creating APIs for transactions and validations - but if you
do, please always make sure to use `-usehd` and print out your Wallet Phrase as
a failsafe.
### More Tools
In particular, you may find these useful:
- [`dashphrase`](https://github.com/dashhive/dashphrase-cli) for generating
secure Wallet Phrases
- [`dashsight`](https://github.com/dashhive/dashphrase-cli) for inspecting
balances, transactions, etc via API (without downloading the indexes)
### More Documentation
All of the **command line flags and options** for the Dash Core Desktop Wallet
are documented between these two pages:
- https://docs.dash.org/projects/core/en/stable/docs/dashcore/wallet-arguments-and-commands-dash-qt.html
- https://docs.dash.org/projects/core/en/stable/docs/dashcore/wallet-arguments-and-commands-dashd.html
The **config files** `dash.conf` (mainly for _Full Nodes_) and `settings.json`
(mainly for Desktop Wallets) are documented at:
- <https://github.com/dashpay/dash/blob/master/contrib/debian/examples/dash.conf>
- <https://docs.dash.org/projects/core/en/stable/docs/dashcore/wallet-configuration-file.html>

56
dashd/install.ps1 Normal file
View File

@@ -0,0 +1,56 @@
#!/usr/bin/env pwsh
#################
# Install dashd #
#################
# Every package should define these variables
$pkg_cmd_name = "dashd"
$pkg_dst_cmd = "$Env:USERPROFILE\.local\opt\dashcore\bin\dashd.exe"
$pkg_dst_dir = "$Env:USERPROFILE\.local\opt\dashcore"
$pkg_dst = "$pkg_dst_cmd"
$pkg_src_cmd = "$Env:USERPROFILE\.local\opt\dashcore-v$Env:WEBI_VERSION\bin\dashd.exe"
$pkg_src_bin = "$Env:USERPROFILE\.local\opt\dashcore-v$Env:WEBI_VERSION\bin"
$pkg_src_dir = "$Env:USERPROFILE\.local\opt\dashcore-v$Env:WEBI_VERSION"
$pkg_src = "$pkg_src_cmd"
New-Item "$Env:USERPROFILE\Downloads\webi" -ItemType Directory -Force | out-null
$pkg_download = "$Env:USERPROFILE\Downloads\webi\$Env:WEBI_PKG_FILE"
# Fetch archive
IF (!(Test-Path -Path "$Env:USERPROFILE\Downloads\webi\$Env:WEBI_PKG_FILE"))
{
echo "Downloading dashd from $Env:WEBI_PKG_URL to $pkg_download"
& curl.exe -A "$Env:WEBI_UA" -fsSL "$Env:WEBI_PKG_URL" -o "$pkg_download.part"
& move "$pkg_download.part" "$pkg_download"
}
IF (!(Test-Path -Path "$pkg_src_dir"))
{
echo "Installing dashd"
# TODO: create package-specific temp directory
# Enter tmp
pushd .local\tmp
# Remove any leftover tmp cruft
Remove-Item -Path ".\dashcore*" -Recurse -ErrorAction Ignore
# Unpack archive file into this temporary directory
# Windows BSD-tar handles zip. Imagine that.
echo "Unpacking $pkg_download"
& tar xf "$pkg_download"
# Settle unpacked archive into place
echo "Install Location: $pkg_src_cmd"
Move-Item -Path ".\dashcore*" -Destination "$pkg_src_dir"
# Exit tmp
popd
}
echo "Copying into '$pkg_dst_cmd' from '$pkg_src_cmd'"
Remove-Item -Path "$pkg_dst_cmd" -Recurse -ErrorAction Ignore | out-null
Copy-Item -Path "$pkg_src" -Destination "$pkg_dst" -Recurse

74
dashd/install.sh Normal file
View File

@@ -0,0 +1,74 @@
#!/bin/sh
# shellcheck disable=SC2034,2317
# "'pkg_cmd_name' appears unused. Verify it or export it."
# "Command appears to be unreachable."
__init_dashd() {
set -e
set -u
#################
# Install dashd #
#################
# Every package should define these 6 variables
pkg_cmd_name="dashd"
pkg_dst_cmd="$HOME/.local/opt/dashcore/bin/dashd"
pkg_dst_dir="$HOME/.local/opt/dashcore"
pkg_dst="$pkg_dst_dir"
pkg_src_cmd="$HOME/.local/opt/dashcore-v$WEBI_VERSION/bin/dashd"
pkg_src_dir="$HOME/.local/opt/dashcore-v$WEBI_VERSION"
pkg_src="$pkg_src_dir"
# pkg_install must be defined by every package
pkg_install() {
# mv ./dashcore-* ~/.local/opt/dashcore-v0.19.1
mv ./dashcore-* "${pkg_src_dir}"
if ! test -e "${HOME}/.dashcore"; then
mkdir -p "${HOME}/.dashcore"
chmod 0700 "${HOME}/.dashcore"
fi
if ! test -e "$HOME/.local/bin/dashd-hd-service-install" ||
! test -e "$HOME/.local/bin/dashd-testnet-service-install"; then
"$HOME/.local/bin/webi" dashcore-utils
fi
# Always try to correct the permissions due to
# https://github.com/dashpay/dash/issues/5420
chmod -R og-rwx "${HOME}/.dashcore/" || true
}
pkg_done_message() {
echo "Installed 'dashd@v$WEBI_VERSION' to ~/.local/opt/dashcore/"
echo ""
echo "TO START THE DAEMON"
echo ""
echo " # mainnet"
echo " dashd-hd-service-install"
echo ""
echo ""
echo " # testnet"
echo " dashd-testnet-service-install"
echo ""
}
# pkg_get_current_version is recommended, but not required
pkg_get_current_version() {
# 'dashd --version' has output in this format:
# Dash Core Daemon version v19.1.0
# This trims it down to just the version number:
# 19.1.0
dashd --version 2> /dev/null |
head -n 1 |
cut -d ' ' -f 5 |
sed 's:^v::'
}
}
__init_dashd

3
dashd/releases.js Normal file
View File

@@ -0,0 +1,3 @@
'use strict';
module.exports = require('../dashcore/releases.js');

View File

@@ -38,6 +38,3 @@ IF (!(Test-Path -Path "$Env:USERPROFILE\.local\opt\$Env:PKG_NAME-v$Env:WEBI_VERS
echo "Copying into '$Env:USERPROFILE\.local\bin\$Env:PKG_NAME.exe' from '$Env:USERPROFILE\.local\opt\$Env:PKG_NAME-v$Env:WEBI_VERSION.exe'"
Remove-Item -Path "$Env:USERPROFILE\.local\bin\$Env:PKG_NAME.exe" -Recurse -ErrorAction Ignore
Copy-Item -Path "$Env:USERPROFILE\.local\opt\$Env:PKG_NAME-v$Env:WEBI_VERSION.exe" -Destination "$Env:USERPROFILE\.local\bin\$Env:PKG_NAME.exe" -Recurse
# Add to path
& "$Env:USERPROFILE\.local\bin\pathman.exe" add ~/.local/bin

View File

@@ -11,6 +11,7 @@ module.exports = function (request) {
'armv6l',
'armv7l',
'ppc64le',
'ppc64',
's390x',
'x86',
];

View File

@@ -49,5 +49,5 @@ fd -e md -e mkdn -e js -e mjs
For options see:
```sh
hexyl --help
fd --help
```

View File

@@ -19,3 +19,16 @@ that produce the most similar quality by default.
```sh
ffmpeg -i input.m4a output.mp3
```
Important information per https://johnvansickle.com/ffmpeg/release-readme.txt
> Notes: A limitation of statically linking `glibc` is the loss of DNS
> resolution. Installing `nscd` through your package manager will fix this.
_This is relevant if using ffmpeg to relay to an RTMP server via domain name._
```sh
# for example, this will not work without `nscd` installed.
ffmpeg -re -stream_loop -1 -i "FooBar.m4v" -c copy -f flv rtmp://stream.example.com/foo/bar
```

View File

@@ -53,6 +53,4 @@ Remove-Item -Path "$pkg_dst" -Recurse -ErrorAction Ignore
Copy-Item -Path "$pkg_src" -Destination "$pkg_dst" -Recurse
# Add to path
& "$Env:USERPROFILE\.local\bin\pathman.exe" add ~/.local/opt/git/cmd
#& "$Env:USERPROFILE\.local\bin\pathman.exe" add "$Env:USERPROFILE\.local\opt\git\cmd"
#& "$Env:USERPROFILE\.local\bin\pathman.exe" add %USERPROFILE%\.local\opt\git\cmd
webi_path_add ~/.local/opt/git/cmd

View File

@@ -1,5 +1,66 @@
#!/bin/pwsh
#!/usr/bin/env pwsh
echo "'go@$Env:WEBI_TAG' is an alias for 'golang@$Env:WEBI_VERSION'"
IF ($Env:WEBI_HOST -eq $null -or $Env:WEBI_HOST -eq "") { $Env:WEBI_HOST = "https://webinstall.dev" }
curl.exe -fsSL "$Env:WEBI_HOST/golang@$Env:WEBI_VERSION" | powershell
if (!(Get-Command "go.exe" -ErrorAction SilentlyContinue))
{
& "$Env:USERPROFILE\.local\bin\webi-pwsh.ps1" go
# because we need git.exe to be available to golang immediately
$Env:PATH = "$Env:USERPROFILE\go\bin;$Env:USERPROFILE\.local\opt\go\bin;$Env:PATH"
}
# Special to go: re-run all go tooling builds
echo "Building go language tools..."
echo ""
echo godoc
& go install golang.org/x/tools/cmd/godoc@latest
echo ""
echo gopls
& go install golang.org/x/tools/gopls@latest
echo ""
echo guru
& go install golang.org/x/tools/guru@latest
echo ""
echo golint
& go install golang.org/x/lint/golint@latest
#echo ""
#echo errcheck
#& go install github.com/kisielk/errcheck
#echo ""
#echo gotags
#& go install github.com/jstemmer/gotags
echo ""
echo goimports
& go install golang.org/x/tools/cmd/goimports@latest
echo ""
echo gomvpkg
& go install golang.org/x/tools/cmd/gomvpkg@latest
echo ""
echo gorename
& go install golang.org/x/tools/cmd/gorename
echo ""
echo gotype
& go install golang.org/x/tools/cmd/gotype
echo ""
echo stringer
& go install golang.org/x/tools/cmd/stringer
echo ""
# literal %USERPROFILE% on purpose
echo 'Installed go "x" tools to GOBIN=%USERPROFILE%/go/bin'
echo ""
echo "Suggestion: Also check out these great productivity multipliers:"
echo ""
echo " - vim-essentials (sensible defaults for vim)"
echo " - vim-go (golang linting, etc)"
echo ""

View File

@@ -3,10 +3,8 @@ set -e
set -u
__run_go_essentials() {
WEBI__GO_ESSENTIALS='true'
export WEBI__GO_ESSENTIALS
if [ -z "${WEBI__GO_INSTALL-}" ]; then
"$HOME/.local/bin/webi" "golang@${WEBI_TAG}"
if ! command -v go 2> /dev/null; then
"$HOME/.local/bin/webi" "go@${WEBI_TAG}"
fi
export PATH="$HOME/.local/opt/go/bin:$PATH"
@@ -75,6 +73,9 @@ __run_go_essentials() {
go "${my_install}" golang.org/x/tools/cmd/stringer@latest > /dev/null #2>/dev/null
echo ""
# literal $HOME on purpose
# shellcheck disable=SC2016
echo 'Installed go "x" tools to GOBIN=$HOME/go/bin'
printf '\n'
printf 'Suggestion: Also check out these great productivity multipliers:\n'

View File

@@ -1,11 +1,89 @@
---
title: Go (golang alias)
homepage: https://webinstall.dev/golang
title: Go
homepage: https://golang.org
tagline: |
Alias for https://webinstall.dev/golang
alias: golang
description: |
See https://webinstall.dev/golang
Go makes it easy to build simple, reliable, and efficient software.
---
Alias for https://webinstall.dev/golang
To update or switch versions, run `webi go@stable` (or `@v1.21`, `@beta`, etc).
### Files
```text
~/.config/envman/PATH.env
~/.local/opt/go/
~/go/
```
## Cheat Sheet
> Go is designed, through and through, to make Software Engineering easy. It's
> fast, efficient, reliable, and something you can learn in a weekend.
>
> If you subscribe to
> [_The Zen of Python_](https://www.python.org/dev/peps/pep-0020/), you'll
> [love](https://go-proverbs.github.io/) >
> [Go](https://www.youtube.com/watch?v=PAAkCSZUG1c).
You may also want to install the Go IDE tooling:
[go-essentials](/go-essentials).
### Hello World
1. Make and enter your project directory
```sh
mkdir -p ./hello/cmd/hello
pushd ./hello/
```
2. Initialize your `go.mod` to your _git repository_ url:
```sh
go mod init github.com/example/hello
```
3. Create a `hello.go`
```sh
cat << EOF >> ./cmd/hello/hello.go
package main
import (
"fmt"
)
func main () {
fmt.Println("Hello, World!")
}
EOF
```
4. Format, build, and run your `./hello`
```sh
go fmt ./...
go build -o hello ./cmd/hello/
./hello
```
You should see your output:
```text
> Hello, World!
```
### How to run a Go program as a service
On Linux:
```sh
# Install serviceman (compatible with systemd)
webi serviceman
```
```sh
# go into your programs 'opt' directory
pushd ./hello/
# swap 'hello' and './hello' for the name of your project and binary
sudo env PATH="$PATH" \
serviceman add --system --username "$(whoami)" --name hello -- \
./hello
# Restart the logging service
sudo systemctl restart systemd-journald
```

View File

@@ -1,5 +1,63 @@
#!/bin/pwsh
#!/usr/bin/env pwsh
echo "'go@$Env:WEBI_TAG' is an alias for 'golang@$Env:WEBI_VERSION'"
IF ($Env:WEBI_HOST -eq $null -or $Env:WEBI_HOST -eq "") { $Env:WEBI_HOST = "https://webinstall.dev" }
curl.exe -fsSL "$Env:WEBI_HOST/golang@$Env:WEBI_VERSION" | powershell
$pkg_cmd_name = "go"
New-Item "$Env:USERPROFILE\Downloads\webi" -ItemType Directory -Force | out-null
$pkg_download = "$Env:USERPROFILE\Downloads\webi\$Env:WEBI_PKG_FILE"
$pkg_src = "$Env:USERPROFILE\.local\opt\$pkg_cmd_name-v$Env:WEBI_VERSION"
$pkg_dst = "$Env:USERPROFILE\.local\opt\$pkg_cmd_name"
$pkg_dst_cmd = "$pkg_dst\bin\$pkg_cmd_name"
$pkg_dst_bin = "$pkg_dst\bin"
if (!(Get-Command "git.exe" -ErrorAction SilentlyContinue))
{
& "$Env:USERPROFILE\.local\bin\webi-pwsh.ps1" git
# because we need git.exe to be available to golang immediately
$Env:PATH = "$Env:USERPROFILE\.local\opt\git\cmd;$Env:PATH"
}
# Fetch archive
IF (!(Test-Path -Path "$pkg_download"))
{
echo "Downloading $Env:PKG_NAME from $Env:WEBI_PKG_URL to $pkg_download"
& curl.exe -A "$Env:WEBI_UA" -fsSL "$Env:WEBI_PKG_URL" -o "$pkg_download.part"
& move "$pkg_download.part" "$pkg_download"
}
IF (!(Test-Path -Path "$pkg_src"))
{
echo "Installing $pkg_cmd_name"
# TODO: temp directory
# Enter opt
pushd .local\tmp
# Remove any leftover tmp cruft
Remove-Item -Path "$pkg_cmd_name*" -Recurse -ErrorAction Ignore
# Unpack archive
# Windows BSD-tar handles zip. Imagine that.
echo "Unpacking $pkg_download"
& tar xf "$pkg_download"
# Settle unpacked archive into place
echo "New Name: $pkg_cmd_name-v$Env:WEBI_VERSION"
Get-ChildItem "$pkg_cmd_name*" | Select -f 1 | Rename-Item -NewName "$pkg_cmd_name-v$Env:WEBI_VERSION"
echo "New Location: $pkg_src"
Move-Item -Path "$pkg_cmd_name-v$Env:WEBI_VERSION" -Destination "$Env:USERPROFILE\.local\opt"
# Exit tmp
popd
}
echo "Copying into '$pkg_dst' from '$pkg_src'"
Remove-Item -Path "$pkg_dst" -Recurse -ErrorAction Ignore
Copy-Item -Path "$pkg_src" -Destination "$pkg_dst" -Recurse
IF (!(Test-Path -Path go\bin)) { New-Item -Path go\bin -ItemType Directory -Force | out-null }
# Add to path
webi_path_add ~/.local/opt/go/bin
# Special to go: add default GOBIN to PATH
webi_path_add ~/go/bin

View File

@@ -2,10 +2,60 @@
set -e
set -u
__redirect_alias_golang() {
echo "'go@${WEBI_TAG:-stable}' is an alias for 'golang@${WEBI_VERSION-}'"
WEBI_HOST=${WEBI_HOST:-"https://webinstall.dev"}
curl -fsSL "$WEBI_HOST/golang@${WEBI_VERSION-}" | sh
GOBIN="${HOME}/go"
GOBIN_REAL="${HOME}/.local/opt/go-bin-v${WEBI_VERSION}"
pkg_cmd_name="go"
# NOTE: pkg_* variables can be defined here
# pkg_cmd_name
# pkg_src, pkg_src_bin, pkg_src_cmd
# pkg_dst, pkg_dst_bin, pkg_dst_cmd
#
# Their defaults are defined in _webi/template.sh at https://github.com/webinstall/packages
pkg_get_current_version() {
# 'go version' has output in this format:
# go version go1.14.2 darwin/amd64
# This trims it down to just the version number:
# 1.14.2
go version 2> /dev/null |
head -n 1 |
cut -d' ' -f3 |
sed 's:go::'
}
__redirect_alias_golang
pkg_format_cmd_version() {
# 'go v1.14.0' will be 'go1.14'
my_version=$(echo "$1" | sed 's:\.0::g')
echo "${pkg_cmd_name}${my_version}"
}
pkg_link() {
# 'pkg_dst' will default to $HOME/.local/opt/go
# 'pkg_src' will be the installed version, such as to $HOME/.local/opt/go-v1.14.2
rm -rf "$pkg_dst"
ln -s "$pkg_src" "$pkg_dst"
# Go has a special $GOBIN
# 'GOBIN' is set above to "${HOME}/go"
# 'GOBIN_REAL' will be "${HOME}/.local/opt/go-bin-v${WEBI_VERSION}"
rm -rf "$GOBIN"
mkdir -p "$GOBIN_REAL/bin"
ln -s "$GOBIN_REAL" "$GOBIN"
}
pkg_post_install() {
pkg_link
# web_path_add is defined in _webi/template.sh at https://github.com/webinstall/packages
# Updates PATH with
# "$HOME/.local/opt/go"
webi_path_add "$pkg_dst_bin"
webi_path_add "$GOBIN/bin"
}
pkg_done_message() {
echo "Installed 'go v$WEBI_VERSION' to ~/.local/opt/go"
}

78
go/releases.js Normal file
View File

@@ -0,0 +1,78 @@
'use strict';
var osMap = {
darwin: 'macos',
};
var archMap = {
386: 'x86',
};
function getAllReleases(request) {
/*
{
version: 'go1.13.8',
stable: true,
files: [
{
filename: 'go1.13.8.src.tar.gz',
os: '',
arch: '',
version: 'go1.13.8',
sha256:
'b13bf04633d4d8cf53226ebeaace8d4d2fd07ae6fa676d0844a688339debec34',
size: 21631178,
kind: 'source'
}
]
};
*/
return request({
url: 'https://golang.org/dl/?mode=json&include=all',
json: true,
}).then((resp) => {
var goReleases = resp.body;
var all = {
releases: [],
download: 'https://dl.google.com/go/{{ download }}',
};
goReleases.forEach((release) => {
// strip 'go' prefix, standardize version
var parts = release.version.slice(2).split('.');
while (parts.length < 3) {
parts.push('0');
}
var version = parts.join('.');
release.files.forEach((asset) => {
var filename = asset.filename;
var os = osMap[asset.os] || asset.os || '-';
var arch = archMap[asset.arch] || asset.arch || '-';
all.releases.push({
version: version,
// all go versions >= 1.0.0 are effectively LTS
lts: (parts[0] > 0 && release.stable) || false,
channel: (release.stable && 'stable') || 'beta',
date: '1970-01-01', // the world may never know
os: os,
arch: arch,
ext: '', // let normalize run the split/test/join
hash: '-', // not ready to standardize this yet
download: filename,
});
});
});
return all;
});
}
module.exports = getAllReleases;
if (module === require.main) {
getAllReleases(require('@root/request')).then(function (all) {
all = require('../_webi/normalize.js')(all);
all.releases = all.releases.slice(0, 10);
console.info(JSON.stringify(all, null, 2));
});
}

View File

@@ -3,10 +3,14 @@ title: Go
homepage: https://golang.org
tagline: |
Go makes it easy to build simple, reliable, and efficient software.
alias: go
description: |
See https://webinstall.dev/go
---
To update or switch versions, run `webi golang@stable` (or `@v1.19`, `@beta`,
etc).
Alias for <https://webinstall.dev/go>.
To update or switch versions, run `webi go@stable` (or `@v1.21`, `@beta`, etc).
### Files

View File

@@ -17,15 +17,6 @@ if (!(Get-Command "git.exe" -ErrorAction SilentlyContinue))
$Env:PATH = "$Env:USERPROFILE\.local\opt\git\cmd;$Env:PATH"
}
Write-Host '' -ForegroundColor red -BackgroundColor white
Write-Host '*********************' -ForegroundColor red -BackgroundColor white
Write-Host '* BREAKING CHANGE *' -ForegroundColor red -BackgroundColor white
Write-Host '*********************' -ForegroundColor red -BackgroundColor white
Write-Host '' -ForegroundColor red -BackgroundColor white
Write-Host ' ''webi golang'' will NOT install go tooling starting with go1.21+' -ForegroundColor red -BackgroundColor white
Write-Host ' use ''webi go-essentials'' to preserve the previous behavior' -ForegroundColor red -BackgroundColor white
Write-Host '' -ForegroundColor red -BackgroundColor white
# Fetch archive
IF (!(Test-Path -Path "$pkg_download"))
{
@@ -65,31 +56,8 @@ Remove-Item -Path "$pkg_dst" -Recurse -ErrorAction Ignore
Copy-Item -Path "$pkg_src" -Destination "$pkg_dst" -Recurse
IF (!(Test-Path -Path go\bin)) { New-Item -Path go\bin -ItemType Directory -Force | out-null }
# Special to go: re-run all go tooling builds
echo "Building go language tools..."
echo gopls
& "$pkg_dst_cmd" install golang.org/x/tools/gopls
echo golint
& "$pkg_dst_cmd" install golang.org/x/lint/golint
echo errcheck
& "$pkg_dst_cmd" install github.com/kisielk/errcheck
echo gotags
& "$pkg_dst_cmd" install github.com/jstemmer/gotags
echo goimports
& "$pkg_dst_cmd" install golang.org/x/tools/cmd/goimports
echo gorename
& "$pkg_dst_cmd" install golang.org/x/tools/cmd/gorename
echo gotype
& "$pkg_dst_cmd" install golang.org/x/tools/cmd/gotype
echo stringer
& "$pkg_dst_cmd" install golang.org/x/tools/cmd/stringer
# Add to path
& "$Env:USERPROFILE\.local\bin\pathman.exe" add ~/.local/opt/go/bin
#& "$Env:USERPROFILE\.local\bin\pathman.exe" add "$Env:USERPROFILE\.local\opt\go\bin"
#& "$Env:USERPROFILE\.local\bin\pathman.exe" add %USERPROFILE%\.local\opt\go\bin
webi_path_add ~/.local/opt/go/bin
# Special to go: add default GOBIN to PATH
& "$Env:USERPROFILE\.local\bin\pathman.exe" add ~/go/bin
#& "$Env:USERPROFILE\.local\bin\pathman.exe" add "$Env:USERPROFILE\go\bin"
#& "$Env:USERPROFILE\.local\bin\pathman.exe" add %USERPROFILE%\go\bin
webi_path_add ~/go/bin

View File

@@ -5,7 +5,6 @@ set -u
GOBIN="${HOME}/go"
GOBIN_REAL="${HOME}/.local/opt/go-bin-v${WEBI_VERSION}"
# The package is 'golang', but the command is 'go'
pkg_cmd_name="go"
# NOTE: pkg_* variables can be defined here
@@ -15,19 +14,6 @@ pkg_cmd_name="go"
#
# Their defaults are defined in _webi/template.sh at https://github.com/webinstall/packages
if [ -z "${WEBI__GO_ESSENTIALS-}" ]; then
# TODO nix for go1.21+
echo >&2 ""
printf >&2 '\e[31m%s:\e[0m\n' '#####################'
printf >&2 '\e[31m%s:\e[0m\n' '# BREAKING CHANGE #'
printf >&2 '\e[31m%s:\e[0m\n' '#####################'
echo >&2 ""
printf >&2 "\e[31m 'webi golang' will NOT install go tooling starting with go1.21+\e[0m\n"
printf >&2 "\e[31m use 'webi go-essentials' to preserve the previous behavior\e[0m\n"
echo >&2 ""
sleep 4
fi
pkg_get_current_version() {
# 'go version' has output in this format:
# go version go1.14.2 darwin/amd64
@@ -68,18 +54,8 @@ pkg_post_install() {
# "$HOME/.local/opt/go"
webi_path_add "$pkg_dst_bin"
webi_path_add "$GOBIN/bin"
if [ -z "${WEBI__GO_ESSENTIALS-}" ]; then
# TODO nix for go1.21+
WEBI__GO_INSTALL='true'
export WEBI__GO_INSTALL
"$HOME/.local/bin/webi" "go-essentials@${WEBI_TAG}"
fi
}
pkg_done_message() {
echo "Installed 'go v$WEBI_VERSION' to ~/.local/opt/go"
# note: literal $HOME on purpose
#shellcheck disable=SC2016
echo 'Installed go "x" tools to GOBIN=$HOME/go/bin'
}

View File

@@ -1,78 +1,3 @@
'use strict';
var osMap = {
darwin: 'macos',
};
var archMap = {
386: 'x86',
};
function getAllReleases(request) {
/*
{
version: 'go1.13.8',
stable: true,
files: [
{
filename: 'go1.13.8.src.tar.gz',
os: '',
arch: '',
version: 'go1.13.8',
sha256:
'b13bf04633d4d8cf53226ebeaace8d4d2fd07ae6fa676d0844a688339debec34',
size: 21631178,
kind: 'source'
}
]
};
*/
return request({
url: 'https://golang.org/dl/?mode=json&include=all',
json: true,
}).then((resp) => {
var goReleases = resp.body;
var all = {
releases: [],
download: 'https://dl.google.com/go/{{ download }}',
};
goReleases.forEach((release) => {
// strip 'go' prefix, standardize version
var parts = release.version.slice(2).split('.');
while (parts.length < 3) {
parts.push('0');
}
var version = parts.join('.');
release.files.forEach((asset) => {
var filename = asset.filename;
var os = osMap[asset.os] || asset.os || '-';
var arch = archMap[asset.arch] || asset.arch || '-';
all.releases.push({
version: version,
// all go versions >= 1.0.0 are effectively LTS
lts: (parts[0] > 0 && release.stable) || false,
channel: (release.stable && 'stable') || 'beta',
date: '1970-01-01', // the world may never know
os: os,
arch: arch,
ext: '', // let normalize run the split/test/join
hash: '-', // not ready to standardize this yet
download: filename,
});
});
});
return all;
});
}
module.exports = getAllReleases;
if (module === require.main) {
getAllReleases(require('@root/request')).then(function (all) {
all = require('../_webi/normalize.js')(all);
all.releases = all.releases.slice(0, 10);
console.info(JSON.stringify(all, null, 2));
});
}
module.exports = require('../go/releases.js');

64
hugo-extended/README.md Normal file
View File

@@ -0,0 +1,64 @@
---
title: Hugo Extended Edition
homepage: https://github.com/gohugoio/hugo
tagline: |
Hugo, but with libsass and WebP support.
---
To update or switch versions, run `webi hugo-extended@stable` (or `@v0.118.2`,
`@beta`, etc).
### Files
These are the files / directories that are created and/or modified with this
install:
```text
~/.config/envman/PATH.env
~/.local/opt/hugo-extended/
~/.local/bin/hugo
```
## Cheat Sheet
> Hugo Extended Edition sacrifices some of the portability and memory-safety of
> Go in order to include libsass and WebP support.
- **libsass** (as opposed to ["dartsass"](../sass/) - a.k.a. [sass](../sass/))
- **WebP** encoding
If you DON'T need those, check out [Hugo](../hugo/) (Standard Edition).
### How to Switch Between Editions
If you've installed `hugo` and `hugo-extended` with Webi, you can switch easily:
```sh
webi hugo
```
```text
switched to 'hugo v0.118.2':
/Users/aj/.local/bin/hugo => /Users/aj/.local/opt/hugo-v0.118.2/bin/hugo
```
```sh
webi hugo-extended
```
```text
switched to 'hugo v0.118.2':
/home/me/.local/bin/hugo => /home/me/.local/opt/hugo-extended-v0.118.2/bin/hugo
```
### Why NOT Use Extended Edition?
The Standard Edition is written and compiled with Go, which means it's binaries:
- work on all OSes and architectures Go supports (musl, arm, BSD, etc)
- are more secure against attacks (Go is memory-safe, C languages are not)
- _slightly_ smaller file size (but... it doesn't really matter)
### [Hugo](../hugo/) Quick Start & Tips
See the [Hugo Cheat Sheet](../hugo/). See the [Hugo Cheat Sheet](../hugo/).

57
hugo-extended/install.ps1 Normal file
View File

@@ -0,0 +1,57 @@
#!/usr/bin/env pwsh
#########################
# Install hugo-extended #
#########################
# Every package should define these variables
$pkg_cmd_name = "hugo"
$pkg_dst_cmd = "$Env:USERPROFILE\.local\bin\hugo.exe"
$pkg_dst_bin = "$Env:USERPROFILE\.local\bin"
$pkg_dst = "$pkg_dst_cmd"
$pkg_src_cmd = "$Env:USERPROFILE\.local\opt\hugo-extended-v$Env:WEBI_VERSION\bin\hugo.exe"
$pkg_src_bin = "$Env:USERPROFILE\.local\opt\hugo-extended-v$Env:WEBI_VERSION\bin"
$pkg_src_dir = "$Env:USERPROFILE\.local\opt\hugo-extended-v$Env:WEBI_VERSION"
$pkg_src = "$pkg_src_cmd"
New-Item "$Env:USERPROFILE\Downloads\webi" -ItemType Directory -Force | out-null
$pkg_download = "$Env:USERPROFILE\Downloads\webi\$Env:WEBI_PKG_FILE"
# Fetch archive
IF (!(Test-Path -Path "$Env:USERPROFILE\Downloads\webi\$Env:WEBI_PKG_FILE")) {
echo "Downloading hugo-extended from $Env:WEBI_PKG_URL to $pkg_download"
& curl.exe -A "$Env:WEBI_UA" -fsSL "$Env:WEBI_PKG_URL" -o "$pkg_download.part"
& move "$pkg_download.part" "$pkg_download"
}
IF (!(Test-Path -Path "$pkg_src_cmd")) {
echo "Installing hugo-extended"
# TODO: create package-specific temp directory
# Enter tmp
pushd .local\tmp
# Remove any leftover tmp cruft
Remove-Item -Path ".\hugo-extended-v*" -Recurse -ErrorAction Ignore
Remove-Item -Path ".\hugo.exe" -Recurse -ErrorAction Ignore
# Unpack archive file into this temporary directory
# Windows BSD-tar handles zip. Imagine that.
echo "Unpacking $pkg_download"
& tar xf "$pkg_download"
# Settle unpacked archive into place
echo "Install Location: $pkg_src_cmd"
New-Item "$pkg_src_bin" -ItemType Directory -Force | out-null
Move-Item -Path ".\hugo.exe" -Destination "$pkg_src_bin"
# Exit tmp
popd
}
echo "Copying into '$pkg_dst_cmd' from '$pkg_src_cmd'"
Remove-Item -Path "$pkg_dst_cmd" -Recurse -ErrorAction Ignore | out-null
New-Item "$pkg_dst_bin" -ItemType Directory -Force | out-null
Copy-Item -Path "$pkg_src" -Destination "$pkg_dst" -Recurse

40
hugo-extended/install.sh Normal file
View File

@@ -0,0 +1,40 @@
#!/bin/sh
# shellcheck disable=SC2034
# "'pkg_cmd_name' appears unused. Verify it or export it."
__init_hugoextended() {
set -e
set -u
WEBI_SINGLE=true
# Every package should define these 6 variables
pkg_cmd_name="hugo"
pkg_dst_cmd="$HOME/.local/bin/hugo"
pkg_dst="$pkg_dst_cmd"
pkg_src_cmd="$HOME/.local/opt/hugo-extended-v$WEBI_VERSION/bin/hugo"
pkg_src_dir="$HOME/.local/opt/hugo-extended-v$WEBI_VERSION/bin"
pkg_src="$pkg_src_dir"
# pkg_install must be defined by every package
pkg_install() {
# ~/.local/opt/hugo-extended-v0.118.2/bin
mkdir -p "$(dirname "${pkg_src_cmd}")"
# mv ./hugo ~/.local/opt/hugo-extended-v0.118.2/bin/
mv ./hugo "${pkg_src_cmd}"
}
pkg_get_current_version() {
# 'hugo version' has output in this format:
# hugo v0.118.2-da7983ac4b94d97d776d7c2405040de97e95c03d darwin/arm64 BuildDate=2023-08-31T11:23:51Z VendorInfo=gohugoio
# This trims it down to just the version number:
# 0.118.2
hugo version 2> /dev/null | head -n 1 | cut -d' ' -f2 | cut -d '-' -f1 | sed 's:^v::'
}
}
__init_hugoextended

35
hugo-extended/releases.js Normal file
View File

@@ -0,0 +1,35 @@
'use strict';
var github = require('../_common/github.js');
var owner = 'gohugoio';
var repo = 'hugo';
module.exports = async function (request) {
let all = await github(request, owner, repo);
all.releases = all.releases.filter(function (rel) {
let isExtended = rel.name.includes('_extended_');
if (!isExtended) {
return false;
}
// remove checksums and .deb
for (let ignorableExt of ['.txt', '.deb']) {
let isIgnorable = rel.name.endsWith(ignorableExt);
if (isIgnorable) {
return false;
}
}
return true;
});
return all;
};
if (module === require.main) {
module.exports(require('@root/request')).then(function (all) {
all = require('../_webi/normalize.js')(all);
console.info(JSON.stringify(all));
});
}

View File

@@ -1,5 +1,5 @@
---
title: Hugo
title: Hugo (Standard & Extended Editions)
homepage: https://github.com/gohugoio/hugo
tagline: |
Hugo: The worlds fastest framework for building websites.
@@ -8,11 +8,45 @@ tagline: |
To update or switch versions, run `webi hugo@stable` (or `@v0.87`, `@beta`,
etc).
### Files
These are the files / directories that are created and/or modified with this
install:
```text
~/.config/envman/PATH.env
~/.local/opt/hugo/
~/.local/bin/hugo
```
## Cheat Sheet
> Hugo is one of the most popular open-source static site generators. It makes
> building websites fun again.
Hugo is a simple and fast Jamstack / Static Site Generator (SSG) tool, which
comes in two flavors:
**Hugo Standard Edition**: Fast, Safe, & Runs Almost Everywhere
**Hugo Extended Edition**: Supports _libsass_ transpilation and _WebP_ encoding,
but mixed with unsafe C code and available for fewer OSes and CPU architectures
### How to Pick & Switch Editions
You'll need [Hugo Extended Edition](../hugo-extended/) for:
- legacy `libsass` support - if you use templates that require it \
(["dartsass"](../sass/), also known as just "sass", is supported in both)
- **WebP** encoding
Use `webi hugo-extended` and `webi hugo` to switch between editions.
Use `hugo env` to determine which edition you're running (Extended Edition
references _libsass_ and _WebP_ in the output).
See [hugo-extended](../hugo-extended/) tips specific to Hugo Extended Edition.
### Create a new site
```sh

View File

@@ -1,14 +1,27 @@
#!/bin/sh
set -e
set -u
pkg_cmd_name="hugo"
WEBI_SINGLE=true
# shellcheck disable=SC2034
# "'pkg_cmd_name' appears unused. Verify it or export it."
__init_hugo() {
set -e
set -u
################
# Install hugo #
################
pkg_cmd_name="hugo"
WEBI_SINGLE=true
pkg_get_current_version() {
# 'hugo version' has output in this format:
# hugo v0.118.2-da7983ac4b94d97d776d7c2405040de97e95c03d darwin/arm64 BuildDate=2023-08-31T11:23:51Z VendorInfo=gohugoio
# This trims it down to just the version number:
# 0.118.2
hugo version 2> /dev/null | head -n 1 | cut -d' ' -f2 | cut -d '-' -f1 | sed 's:^v::'
}
pkg_get_current_version() {
# 'hugo version' has output in this format:
# Hugo Static Site Generator v0.72.0-8A7EF3CF darwin/amd64 BuildDate: 2020-05-31T12:07:44Z
# This trims it down to just the version number:
# 0.72.0
hugo version 2> /dev/null | head -n 1 | cut -d' ' -f5 | cut -d '-' -f1 | sed 's:^v::'
}
__init_hugo

View File

@@ -4,14 +4,27 @@ var github = require('../_common/github.js');
var owner = 'gohugoio';
var repo = 'hugo';
module.exports = function (request) {
return github(request, owner, repo).then(function (all) {
module.exports = async function (request) {
let all = await github(request, owner, repo);
all.releases = all.releases.filter(function (rel) {
let isExtended = rel.name.includes('_extended_');
if (isExtended) {
return false;
}
// remove checksums and .deb
all.releases = all.releases.filter(function (rel) {
return !/(\.txt)|(\.deb)$/i.test(rel.name);
});
return all;
for (let ignorableExt of ['.txt', '.deb']) {
let isIgnorable = rel.name.endsWith(ignorableExt);
if (isIgnorable) {
return false;
}
}
return true;
});
return all;
};
if (module === require.main) {

View File

@@ -1,20 +1,22 @@
'use strict';
function getRawReleases(request) {
return request({ url: 'https://iterm2.com/downloads.html' }).then(function (
resp,
) {
var links = resp.body
.split(/[<>]+/g)
.map(function (str) {
var m = str.match(/href="(https:\/\/iterm2\.com\/downloads\/.*\.zip)"/);
if (m && /iTerm2-[34]/.test(m[1])) {
return m[1];
}
})
.filter(Boolean);
return links;
});
return request({ url: 'https://iterm2.com/downloads.html' }).then(
function (resp) {
var links = resp.body
.split(/[<>]+/g)
.map(function (str) {
var m = str.match(
/href="(https:\/\/iterm2\.com\/downloads\/.*\.zip)"/,
);
if (m && /iTerm2-[34]/.test(m[1])) {
return m[1];
}
})
.filter(Boolean);
return links;
},
);
}
function transformReleases(links) {

View File

@@ -1,15 +1,23 @@
---
title: LSDeluxe
homepage: https://github.com/Peltoche/lsd
homepage: https://github.com/lsd-rs/lsd
tagline: |
LSDeluxe: next gen ls command
---
To update or switch versions, run `webi lsd@stable` (or `@v0.20`, `@beta`, etc).
### Files
```text
~/.config/envman/PATH.env
~/.config/lsd/config.yaml
~/.local/bin/lsd
```
## Cheat Sheet
![](https://raw.githubusercontent.com/Peltoche/lsd/assets/screen_lsd.png)
![](https://raw.githubusercontent.com/lsd-rs/lsd/assets/screen_lsd.png)
> `lsd` is a modern, cross-platform, drop-in replacement for `ls`. It does
> everything that you expect it to, plus modern extras that you can check out
@@ -46,6 +54,16 @@ alias lsd=lsd --icon=never --color=never
lsd
```
(you may also enjoy [`aliasman`](../aliasman/))
Or update the config file:
`~/.config/lsd/config.yaml`
```yaml
classic: true
```
### How to alias as `ls`, `ll`, `la`, etc
This will affect the interactive shell, but not scripts.
@@ -92,8 +110,14 @@ Or manually update your `.bashrc`, `.zshrc`, or `.profile`
alias tree="lsd -AF --tree"
```
And when you want to use GNU `tree`, just escape the alias:
And when you want to use GNU `tree` you can escape the alias in some shells:
```sh
\tree
```
Or use the full path:
```sh
/bin/tree
```

View File

@@ -1,13 +1,13 @@
'use strict';
var github = require('../_common/github.js');
var owner = 'Peltoche';
var owner = 'lsd-rs';
var repo = 'lsd';
module.exports = function (request) {
return github(request, owner, repo).then(function (all) {
all.releases = all.releases.filter(function (rel) {
return !/(-musl\.)|(-msvc\.)|(\.deb$)/.test(rel.name);
return !/(-msvc\.)|(\.deb$)/.test(rel.name);
});
return all;
});

1
msvc-runtime Symbolic link
View File

@@ -0,0 +1 @@
vcruntime

1
msvcruntime Symbolic link
View File

@@ -0,0 +1 @@
vcruntime

View File

@@ -10,7 +10,7 @@ tagline: |
> A font with a high number of extra glyphs from popular 'iconic fonts' such as
> Font Awesome ➶, Devicons ➶, Octicons ➶, and others.
![](https://github.com/ryanoasis/nerd-fonts/raw/master/images/sankey-glyphs-combined-diagram.svg)
![](https://github.com/ryanoasis/nerd-fonts/raw/v2.3.3/images/sankey-glyphs-combined-diagram.svg)
This installs just "Droid Sans Mono for Powerline Nerd Font Complete.otf".
@@ -21,57 +21,57 @@ See [All Nerd Fonts](https://www.nerdfonts.com/font-downloads)
view list
</summary>
- [3270 Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/master/patched-fonts/3270)
- [Agave](https://github.com/ryanoasis/nerd-fonts/blob/master/patched-fonts/Agave)
- [Anonymice Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/master/patched-fonts/AnonymousPro)
- [Arimo](https://github.com/ryanoasis/nerd-fonts/blob/master/patched-fonts/Arimo)
- [Aurulent Sans Mono Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/master/patched-fonts/AurulentSansMono)
- [BigBlueTerminal](https://github.com/ryanoasis/nerd-fonts/blob/master/patched-fonts/BigBlueTerminal)
- [Bitstream Vera Sans Mono Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/master/patched-fonts/BitstreamVeraSansMono)
- [Blex\*](https://github.com/ryanoasis/nerd-fonts/blob/master/patched-fonts/IBMPlexMono)
- [Caskaydia Cove Nerd Font\*](https://github.com/ryanoasis/nerd-fonts/blob/master/patched-fonts/CascadiaCode)
- [Code New Roman Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/master/patched-fonts/CodeNewRoman)
- [Cousine Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/master/patched-fonts/Cousine)
- [DaddyTimeMono](https://github.com/ryanoasis/nerd-fonts/blob/master/patched-fonts/DaddyTimeMono)
- [DejaVu Sans Mono Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/master/patched-fonts/DejaVuSansMono)
- [Droid Sans Mono Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/master/patched-fonts/DroidSansMono)
- [Fantasque Sans Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/master/patched-fonts/FantasqueSansMono)
- [Fira Code Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/master/patched-fonts/FiraCode)
- [Fira Mono Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/master/patched-fonts/FiraMono)
- [Go Mono Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/master/patched-fonts/Go-Mono)
- [Gohu Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/master/patched-fonts/Gohu)
- [Hack Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/master/patched-fonts/Hack)
- [Hasklug Nerd Font\*](https://github.com/ryanoasis/nerd-fonts/blob/master/patched-fonts/Hasklig)
- [Heavy Data Mono Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/master/patched-fonts/HeavyData)
- [Hermut Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/master/patched-fonts/Hermit)
- [iM-Writing\*](https://github.com/ryanoasis/nerd-fonts/blob/master/patched-fonts/iA-Writer)
- [Inconsolata Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/master/patched-fonts/Inconsolata)
- [Inconsolata Go Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/master/patched-fonts/InconsolataGo)
- [Inconsolata LGC Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/master/patched-fonts/InconsolataLGC)
- [Iosevka Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/master/patched-fonts/Iosevka)
- [JetBrains Mono](https://github.com/ryanoasis/nerd-fonts/blob/master/patched-fonts/JetBrainsMono)
- [Lekton Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/master/patched-fonts/Lekton)
- [Literation Mono Nerd Font\*](https://github.com/ryanoasis/nerd-fonts/blob/master/patched-fonts/LiberationMono)
- [Meslo Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/master/patched-fonts/Meslo)
- [Monofur Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/master/patched-fonts/Monofur)
- [Monoid Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/master/patched-fonts/Monoid)
- [Mononoki Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/master/patched-fonts/Mononoki)
- [M+ (MPlus) Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/master/patched-fonts/MPlus)
- [Noto](https://github.com/ryanoasis/nerd-fonts/blob/master/patched-fonts/Noto)
- [OpenDyslexic](https://github.com/ryanoasis/nerd-fonts/blob/master/patched-fonts/OpenDyslexic)
- [Overpass](https://github.com/ryanoasis/nerd-fonts/blob/master/patched-fonts/Overpass)
- [ProFont (Windows tweaked) Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/master/patched-fonts/ProFont)
- [ProFont (x11) Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/master/patched-fonts/ProFont)
- [ProggyClean Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/master/patched-fonts/ProggyClean)
- [Roboto Mono](https://github.com/ryanoasis/nerd-fonts/blob/master/patched-fonts/RobotoMono)
- [Sauce Code Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/master/patched-fonts/SourceCodePro)
- [Shure Tech Mono Nerd Font\*](https://github.com/ryanoasis/nerd-fonts/blob/master/patched-fonts/ShareTechMono)
- [Space Mono Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/master/patched-fonts/SpaceMono)
- [Terminess Nerd Font\*](https://github.com/ryanoasis/nerd-fonts/blob/master/patched-fonts/Terminus)
- [Tinos](https://github.com/ryanoasis/nerd-fonts/blob/master/patched-fonts/Tinos)
- [Ubuntu Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/master/patched-fonts/Ubuntu)
- [Ubuntu Mono Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/master/patched-fonts/UbuntuMono)
- [Victor Mono](https://github.com/ryanoasis/nerd-fonts/blob/master/patched-fonts/VictorMono)
- [3270 Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/v2.3.3/patched-fonts/3270)
- [Agave](https://github.com/ryanoasis/nerd-fonts/blob/v2.3.3/patched-fonts/Agave)
- [Anonymice Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/v2.3.3/patched-fonts/AnonymousPro)
- [Arimo](https://github.com/ryanoasis/nerd-fonts/blob/v2.3.3/patched-fonts/Arimo)
- [Aurulent Sans Mono Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/v2.3.3/patched-fonts/AurulentSansMono)
- [BigBlueTerminal](https://github.com/ryanoasis/nerd-fonts/blob/v2.3.3/patched-fonts/BigBlueTerminal)
- [Bitstream Vera Sans Mono Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/v2.3.3/patched-fonts/BitstreamVeraSansMono)
- [Blex\*](https://github.com/ryanoasis/nerd-fonts/blob/v2.3.3/patched-fonts/IBMPlexMono)
- [Caskaydia Cove Nerd Font\*](https://github.com/ryanoasis/nerd-fonts/blob/v2.3.3/patched-fonts/CascadiaCode)
- [Code New Roman Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/v2.3.3/patched-fonts/CodeNewRoman)
- [Cousine Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/v2.3.3/patched-fonts/Cousine)
- [DaddyTimeMono](https://github.com/ryanoasis/nerd-fonts/blob/v2.3.3/patched-fonts/DaddyTimeMono)
- [DejaVu Sans Mono Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/v2.3.3/patched-fonts/DejaVuSansMono)
- [Droid Sans Mono Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/v2.3.3/patched-fonts/DroidSansMono)
- [Fantasque Sans Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/v2.3.3/patched-fonts/FantasqueSansMono)
- [Fira Code Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/v2.3.3/patched-fonts/FiraCode)
- [Fira Mono Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/v2.3.3/patched-fonts/FiraMono)
- [Go Mono Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/v2.3.3/patched-fonts/Go-Mono)
- [Gohu Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/v2.3.3/patched-fonts/Gohu)
- [Hack Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/v2.3.3/patched-fonts/Hack)
- [Hasklug Nerd Font\*](https://github.com/ryanoasis/nerd-fonts/blob/v2.3.3/patched-fonts/Hasklig)
- [Heavy Data Mono Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/v2.3.3/patched-fonts/HeavyData)
- [Hermut Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/v2.3.3/patched-fonts/Hermit)
- [iM-Writing\*](https://github.com/ryanoasis/nerd-fonts/blob/v2.3.3/patched-fonts/iA-Writer)
- [Inconsolata Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/v2.3.3/patched-fonts/Inconsolata)
- [Inconsolata Go Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/v2.3.3/patched-fonts/InconsolataGo)
- [Inconsolata LGC Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/v2.3.3/patched-fonts/InconsolataLGC)
- [Iosevka Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/v2.3.3/patched-fonts/Iosevka)
- [JetBrains Mono](https://github.com/ryanoasis/nerd-fonts/blob/v2.3.3/patched-fonts/JetBrainsMono)
- [Lekton Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/v2.3.3/patched-fonts/Lekton)
- [Literation Mono Nerd Font\*](https://github.com/ryanoasis/nerd-fonts/blob/v2.3.3/patched-fonts/LiberationMono)
- [Meslo Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/v2.3.3/patched-fonts/Meslo)
- [Monofur Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/v2.3.3/patched-fonts/Monofur)
- [Monoid Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/v2.3.3/patched-fonts/Monoid)
- [Mononoki Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/v2.3.3/patched-fonts/Mononoki)
- [M+ (MPlus) Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/v2.3.3/patched-fonts/MPlus)
- [Noto](https://github.com/ryanoasis/nerd-fonts/blob/v2.3.3/patched-fonts/Noto)
- [OpenDyslexic](https://github.com/ryanoasis/nerd-fonts/blob/v2.3.3/patched-fonts/OpenDyslexic)
- [Overpass](https://github.com/ryanoasis/nerd-fonts/blob/v2.3.3/patched-fonts/Overpass)
- [ProFont (Windows tweaked) Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/v2.3.3/patched-fonts/ProFont)
- [ProFont (x11) Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/v2.3.3/patched-fonts/ProFont)
- [ProggyClean Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/v2.3.3/patched-fonts/ProggyClean)
- [Roboto Mono](https://github.com/ryanoasis/nerd-fonts/blob/v2.3.3/patched-fonts/RobotoMono)
- [Sauce Code Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/v2.3.3/patched-fonts/SourceCodePro)
- [Shure Tech Mono Nerd Font\*](https://github.com/ryanoasis/nerd-fonts/blob/v2.3.3/patched-fonts/ShareTechMono)
- [Space Mono Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/v2.3.3/patched-fonts/SpaceMono)
- [Terminess Nerd Font\*](https://github.com/ryanoasis/nerd-fonts/blob/v2.3.3/patched-fonts/Terminus)
- [Tinos](https://github.com/ryanoasis/nerd-fonts/blob/v2.3.3/patched-fonts/Tinos)
- [Ubuntu Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/v2.3.3/patched-fonts/Ubuntu)
- [Ubuntu Mono Nerd Font](https://github.com/ryanoasis/nerd-fonts/blob/v2.3.3/patched-fonts/UbuntuMono)
- [Victor Mono](https://github.com/ryanoasis/nerd-fonts/blob/v2.3.3/patched-fonts/VictorMono)
<!--
// https://github.com/ryanoasis/nerd-fonts
@@ -91,20 +91,30 @@ console.log(list.join('\n -'));
Note: This will _NOT_ work in Command.exe. You must get _Windows Terminal_ from
the Microsoft Store.
Select `Settings` from the drop down and update `profiles.defaults.fontFace`:
You can update the font in the Windows Terminal settings either for the
"Defaults" profile (which applies to all profiles unless overwritten) or
individually for different profiles under
`Settings -> <profile_name> -> Appearance -> Font face`:
![Windows Terminal Settings](windows-terminal-settings-01.png 'Opening Settings in Windows Terminal')
![Windows Terminal Settings](windows-terminal-settings-02.png 'Setting Nerd Font in Windows Terminal Defaults profile')
(Screenshots taken with Windows Terminal version 1.16.10262.0)
Additionally, you can update `profiles.defaults.font.face` in the Windows
Terminal settings.json directly:
```json
{
"profiles": {
"defaults": {
"fontFace": "DroidSansMono NF"
"font": {
"face": "DroidSansMono NF"
}
}
}
}
```
![Windows Terminal Settings](https://i.imgur.com/4RgK6s9.png 'lsd using The Nerd Font in Windows Terminal')
### Nerd Fonts for iTerm2
Find `iTerm2` in the top Mac menu, then...

View File

@@ -6,7 +6,7 @@ $my_fontdir = "$Env:UserProfile\AppData\Local\Microsoft\Windows\Fonts"
New-Item -Path "$my_fontdir" -ItemType Directory -Force | out-null
IF (!(Test-Path -Path "$my_fontdir\$my_nerdfont_otf"))
{
& curl.exe -fsSLo "$my_nerdfont_otf" 'https://github.com/ryanoasis/nerd-fonts/raw/master/patched-fonts/DroidSansMono/complete/Droid%20Sans%20Mono%20Nerd%20Font%20Complete%20Windows%20Compatible.otf'
& curl.exe -fsSLo "$my_nerdfont_otf" 'https://github.com/ryanoasis/nerd-fonts/raw/v2.3.3/patched-fonts/DroidSansMono/complete/Droid%20Sans%20Mono%20Nerd%20Font%20Complete%20Windows%20Compatible.otf'
& move "$my_nerdfont_otf" "$my_fontdir"
}

View File

@@ -6,7 +6,7 @@ __init_nerdfont() {
my_nerdfont="Droid Sans Mono for Powerline Nerd Font Complete.otf"
curl -fsSLo "$my_nerdfont" \
'https://github.com/ryanoasis/nerd-fonts/raw/master/patched-fonts/DroidSansMono/complete/Droid%20Sans%20Mono%20Nerd%20Font%20Complete.otf'
'https://github.com/ryanoasis/nerd-fonts/raw/v2.3.3/patched-fonts/DroidSansMono/complete/Droid%20Sans%20Mono%20Nerd%20Font%20Complete.otf'
my_fontdir=""
if [ -e "$HOME/Library/Fonts" ]; then

Binary file not shown.

After

Width:  |  Height:  |  Size: 252 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 117 KiB

View File

@@ -41,4 +41,4 @@ Remove-Item -Path "$Env:USERPROFILE\.local\opt\$Env:PKG_NAME" -Recurse -ErrorAct
Copy-Item -Path "$Env:USERPROFILE\.local\opt\$Env:PKG_NAME-v$Env:WEBI_VERSION" -Destination "$Env:USERPROFILE\.local\opt\$Env:PKG_NAME" -Recurse
# Add to path
& "$Env:USERPROFILE\.local\bin\pathman.exe" add ~/.local/opt/node
webi_path_add ~/.local/opt/node

View File

@@ -1,14 +1,22 @@
'use strict';
// Map from node conventions to webinstall conventions
var map = {
// OSes
osx: 'macos',
// https://blog.risingstack.com/update-nodejs-8-end-of-life-no-support/
// 6 mos "current" + 18 mos LTS "active" + 12 mos LTS "maintenance"
//var endOfLife = 3 * 366 * 24 * 60 * 60 * 1000;
// If there have been no updates in 12 months, it's almost certainly end-of-life
const END_OF_LIFE = 366 * 24 * 60 * 60 * 1000;
// OSes
let osMap = {
osx: 'macos', // NOTE: filename is 'darwin'
linux: 'linux',
win: 'windows', // windows
sunos: 'sunos',
aix: 'aix',
// CPU architectures
};
// CPU architectures
let archMap = {
x64: 'amd64',
x86: 'x86',
ppc64: 'ppc64',
@@ -17,124 +25,150 @@ var map = {
armv7l: 'armv7l',
armv6l: 'armv6l',
s390x: 's390x',
// file extensions
pkg: 'pkg',
exe: 'exe',
msi: 'msi',
'7z': '7z',
zip: 'zip',
tar: 'tar.gz',
};
function getAllReleases(request) {
return request({
url: 'https://nodejs.org/dist/index.json',
// file extensions
let pkgMap = {
pkg: ['pkg'],
//exe: ['exe'], // disable
'7z': ['7z'],
zip: ['zip'],
tar: ['tar.gz', 'tar.xz'],
// oddity - no os in download
msi: ['msi'],
// oddity - no pkg info
musl: ['tar.gz', 'tar.xz'],
};
async function getAllReleases(request) {
let all = {
releases: [],
download: '',
};
/*
[
{
"version":"v20.3.1",
"date":"2023-06-20",
"files":["headers","linux-armv6l","linux-x64-musl","linux-x64-pointer-compression"],
"npm":"9.6.7",
"v8":"11.3.244.8",
"uv":"1.45.0",
"zlib":"1.2.13.1-motley",
"openssl":"3.0.9+quic",
"modules":"115",
"lts":false,
"security":true
},
]
*/
// Alternate: 'https://nodejs.org/dist/index.json',
let baseUrl = `https://nodejs.org/download/release`;
let officialP = request({
url: `${baseUrl}/index.json`,
json: true,
}).then(function (resp) {
var rels = resp.body;
var all = {
releases: [],
download: '', // node's download URLs are unpredictable
};
transform(baseUrl, resp.body);
return;
});
// https://blog.risingstack.com/update-nodejs-8-end-of-life-no-support/
// 6 mos "current" + 18 mos LTS "active" + 12 mos LTS "maintenance"
//var endOfLife = 3 * 366 * 24 * 60 * 60 * 1000;
// If there have been no updates in 12 months, it's almost certainly end-of-life
var endOfLife = 366 * 24 * 60 * 60 * 1000;
let unofficialBaseUrl = `https://unofficial-builds.nodejs.org/download/release`;
let unofficialP = request({
url: `${unofficialBaseUrl}/index.json`,
json: true,
})
.then(function (resp) {
transform(unofficialBaseUrl, resp.body);
return;
})
.catch(function (err) {
console.error('failed to fetch unofficial-builds');
console.error(err);
});
rels.forEach(function (rel) {
if (Date.now() - new Date(rel.date).valueOf() > endOfLife) {
function transform(baseUrl, builds) {
builds.forEach(function (build) {
let buildDate = new Date(build.date).valueOf();
let age = Date.now() - buildDate;
let maintained = age < END_OF_LIFE;
if (!maintained) {
return;
}
rel.files.forEach(function (file) {
let lts = false !== build.lts;
// skip 'v'
let vparts = build.version.slice(1).split('.');
let major = parseInt(vparts[0], 10);
let channel = 'stable';
let isEven = 0 === major % 2;
if (!isEven) {
channel = 'beta';
}
build.files.forEach(function (file) {
if ('src' === file || 'headers' === file) {
return;
}
var parts = file.split(/-/);
var os = map[parts[0]];
if (!os) {
console.warn('node versions: unknown os "%s"', parts[0]);
let fileParts = file.split('-');
let osPart = fileParts[0];
let os = osMap[osPart];
let archPart = fileParts[1];
let arch = archMap[archPart];
let pkgPart = fileParts[2];
let pkgs = pkgMap[pkgPart];
if (!pkgPart) {
pkgs = pkgMap.tar;
}
var arch = map[parts[1]];
if (!arch) {
console.warn('node versions: unknown arch "%s"', parts[1]);
}
var ext = map[parts[2] || 'tar'];
if (!ext) {
console.warn('node versions: unknown ext "%s"', parts[2]);
}
if ('exe' === ext) {
// node exe files are not self-extracting installers
if (!pkgs?.length) {
return;
}
var even = 0 === rel.version.slice(1).split('.')[0] % 2;
var r = {
// nix leading 'v'
version: rel.version.slice(1),
date: rel.date,
lts: !!rel.lts,
// historically odd releases have been beta and even have been stable
channel: even ? 'stable' : 'beta',
os: os,
arch: arch,
ext: ext,
//sha1: '',
// See https://nodejs.org/dist/v14.0.0/
// usually like https://nodejs.org/dist/v14.0.0/node-{version}-{plat}-{arch}.{ext}
download:
'https://nodejs.org/dist/' + rel.version + '/node-' + rel.version,
};
all.releases.push(r);
// handle all the special cases (which there are many)
if ('pkg' === ext) {
r.download += '.pkg';
return;
let extra = '';
let muslNative;
if (fileParts[2] === 'musl') {
extra = '-musl';
muslNative = true;
}
if ('msi' === ext) {
if ('amd64' === arch) {
r.download += '-x64.msi';
} else {
r.download += '-x86.msi';
pkgs.forEach(function (pkg) {
if (osPart === 'osx') {
osPart = 'darwin';
}
return;
}
if ('macos' === os) {
r.download += '-darwin';
} else if ('windows' === os) {
r.download += '-win';
} else {
r.download += '-' + os;
}
let filename = `node-${build.version}-${osPart}-${archPart}${extra}.${pkg}`;
if ('msi' === pkg) {
filename = `node-${build.version}-${archPart}${extra}.${pkg}`;
}
let downloadUrl = `${baseUrl}/${build.version}/${filename}`;
if ('amd64' === arch) {
r.download += '-x64';
} else {
r.download += '-' + arch;
}
let release = {
name: filename,
version: build.version,
lts: lts,
channel: channel,
date: build.date,
os: os,
arch: arch,
ext: pkg,
download: downloadUrl,
_musl_native: muslNative,
};
if ('aix' === os) {
r.download += '.tar.gz';
return;
}
r.download += '.' + ext;
if ('tar.gz' === ext) {
r.download = r.download.replace(/\.tar\.gz$/, '.tar.xz');
r.ext = 'tar.xz';
all.releases.push(JSON.parse(JSON.stringify(r)));
r.download = r.download.replace(/\.tar\.xz$/, '.tar.gz');
r.ext = 'tar.gz';
}
all.releases.push(release);
});
});
});
}
return all;
});
await officialP;
await unofficialP;
return all;
}
module.exports = getAllReleases;

33
package-lock.json generated
View File

@@ -1,23 +1,42 @@
{
"name": "@webinstall/webi-installers",
"version": "1.0.0",
"lockfileVersion": 1,
"lockfileVersion": 3,
"requires": true,
"dependencies": {
"@root/request": {
"packages": {
"": {
"name": "@webinstall/webi-installers",
"version": "1.0.0",
"license": "MPL-2.0",
"dependencies": {
"@root/request": "^1.9.2",
"dotenv": "^8.2.0",
"marked": "^4.1.1"
}
},
"node_modules/@root/request": {
"version": "1.9.2",
"resolved": "https://registry.npmjs.org/@root/request/-/request-1.9.2.tgz",
"integrity": "sha512-wVaL9yVV9oDR9UNbPZa20qgY+4Ch6YN8JUkaE4el/uuS5dmhD8Lusm/ku8qJVNtmQA56XLzEDCRS6/vfpiHK2A=="
},
"dotenv": {
"node_modules/dotenv": {
"version": "8.2.0",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz",
"integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw=="
"integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==",
"engines": {
"node": ">=8"
}
},
"marked": {
"node_modules/marked": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/marked/-/marked-4.1.1.tgz",
"integrity": "sha512-0cNMnTcUJPxbA6uWmCmjWz4NJRe/0Xfk2NhXCUHjew9qJzFN20krFnsUe7QynwqOwa5m1fZ4UDg0ycKFVC0ccw=="
"integrity": "sha512-0cNMnTcUJPxbA6uWmCmjWz4NJRe/0Xfk2NhXCUHjew9qJzFN20krFnsUe7QynwqOwa5m1fZ4UDg0ycKFVC0ccw==",
"bin": {
"marked": "bin/marked.js"
},
"engines": {
"node": ">= 12"
}
}
}
}

View File

@@ -1,15 +1,18 @@
{
"name": "@webinstall/webi-installers",
"private": true,
"version": "1.0.0",
"version": "1.0.1",
"description": "webinstall script repository",
"main": "_webi/",
"scripts": {
"fmt": "npm run prettier; npm run shfmt",
"lint": "npx jshint@2.x -c ./.jshintrc */*.js",
"prettier": "npx prettier@2.x -w '**/*.{js,md,html}'",
"shfmt": "shfmt -w -i 4 -sr -ci -s ./",
"test": "node _webi/test.js ./node/"
"fmt": "npm run prettier && npm run shfmt",
"lint": "npm run shellcheck && npm run jshint",
"test": "node _webi/test.js ./node/",
"----": "------------------------------------",
"jshint": "npx -p jshint@2.x -- jshint -c ./.jshintrc --exclude 'node_modules/**/*' */*.js */*/*.js",
"prettier": "npx -p prettier@3.x -- prettier -w '**/*.{js,md,html}'",
"shellcheck": "shellcheck -s sh -S style --exclude=SC2154,SC2034 */*.sh",
"shfmt": "shfmt -w -i 4 -sr -ci -s ./"
},
"repository": {
"type": "git",

3
package.json.extra Normal file
View File

@@ -0,0 +1,3 @@
"tsc": "npx -p typescript@5 -- tsc -p ./jsconfig.json"
"lint": "npm run jshint && npm run tsc",

View File

@@ -1,19 +0,0 @@
pushd "%userprofile%" || goto :error
IF NOT EXIST .local (
mkdir .local || goto :error
)
IF NOT EXIST .local\bin (
mkdir .local\bin || goto :error
)
pushd .local\bin || goto :error
rem TODO %PROCESSOR_ARCH%
powershell $ProgressPreference = 'SilentlyContinue'; Invoke-WebRequest "https://rootprojects.org/pathman/dist/windows/amd64/pathman.exe" -OutFile pathman.exe || goto :error
popd || goto :error
popd
goto :EOF
:error
echo Failed with error #%errorlevel%.
exit /b %errorlevel%

View File

@@ -1,3 +1,57 @@
#!/usr/bin/env pwsh
curl.exe -fsSL -A "$Env:WEBI_UA" "https://rootprojects.org/pathman/dist/windows/amd64/pathman.exe" -o "$Env:USERPROFILE\.local\bin\pathman.exe"
###################
# Install pathman #
###################
# Every package should define these variables
$pkg_cmd_name = "pathman"
$pkg_dst_cmd = "$Env:USERPROFILE\.local\bin\pathman.exe"
$pkg_dst = "$pkg_dst_cmd"
$pkg_src_cmd = "$Env:USERPROFILE\.local\opt\pathman-v$Env:WEBI_VERSION\bin\pathman.exe"
$pkg_src_bin = "$Env:USERPROFILE\.local\opt\pathman-v$Env:WEBI_VERSION\bin"
$pkg_src_dir = "$Env:USERPROFILE\.local\opt\pathman-v$Env:WEBI_VERSION"
$pkg_src = "$pkg_src_cmd"
New-Item "$Env:USERPROFILE\Downloads\webi" -ItemType Directory -Force | out-null
$pkg_download = "$Env:USERPROFILE\Downloads\webi\$Env:WEBI_PKG_FILE"
# Fetch archive
IF (!(Test-Path -Path "$Env:USERPROFILE\Downloads\webi\$Env:WEBI_PKG_FILE"))
{
echo "Downloading pathman from $Env:WEBI_PKG_URL to $pkg_download"
& curl.exe -A "$Env:WEBI_UA" -fsSL "$Env:WEBI_PKG_URL" -o "$pkg_download.part"
& move "$pkg_download.part" "$pkg_download"
}
IF (!(Test-Path -Path "$pkg_src_cmd"))
{
echo "Installing pathman"
# TODO: create package-specific temp directory
# Enter tmp
pushd .local\tmp
# Remove any leftover tmp cruft
Remove-Item -Path ".\pathman-v*" -Recurse -ErrorAction Ignore
Remove-Item -Path ".\pathman.exe" -Recurse -ErrorAction Ignore
# Unpack archive file into this temporary directory
# Windows BSD-tar handles zip. Imagine that.
echo "Unpacking $pkg_download"
& tar xf "$pkg_download"
# Settle unpacked archive into place
echo "Install Location: $pkg_src_cmd"
New-Item "$pkg_src_bin" -ItemType Directory -Force | out-null
Move-Item -Path ".\pathman-v*"-Destination "$pkg_src_cmd"
# Exit tmp
popd
}
echo "Copying into '$pkg_dst_cmd' from '$pkg_src_cmd'"
Remove-Item -Path "$pkg_dst_cmd" -Recurse -ErrorAction Ignore | out-null
Copy-Item -Path "$pkg_src" -Destination "$pkg_dst" -Recurse

View File

@@ -7,6 +7,9 @@ var baseurl = 'https://git.rootprojects.org';
module.exports = function (request) {
return github(request, owner, repo, baseurl).then(function (all) {
all.releases = all.releases.filter(function (release) {
return !/debug/.test(release.name);
});
return all;
});
};

View File

@@ -46,7 +46,7 @@ IF (!(Test-Path -Path "$pkg_src_cmd"))
# Settle unpacked archive into place
echo "Install Location: $pkg_src_cmd"
New-Item "$pkg_src_bin" -ItemType Directory -Force | out-null
Move-Item -Path ".\rclone.exe" -Destination "$pkg_src_bin"
Move-Item -Path ".\rclone-v*\rclone.exe" -Destination "$pkg_src_bin"
# Exit tmp
popd

View File

@@ -52,4 +52,4 @@ echo "Linking '$pkg_dst_dir' from '$pkg_src_dir'"
New-Item -ItemType Junction -Path "$pkg_dst_dir" -Target "$pkg_src_dir" > $null
# Add to path
& "$Env:USERPROFILE\.local\bin\pathman.exe" add ~/.local/opt/dart-sass
webi_path_add ~/.local/opt/dart-sass

View File

@@ -28,7 +28,7 @@ curl -H "Host: example.com" http://localhost:3000
```
```html
<!DOCTYPE html>
<!doctype html>
<html>
<body>
<h1>Example Domain</h1>

View File

@@ -3,18 +3,26 @@ set -e
set -u
__install_ssh_adduser() {
my_cmd="ssh-adduser"
rm -f "$HOME/.local/bin/${my_cmd}"
# ssh-adduser
rm -f "$HOME/.local/bin/ssh-adduser"
webi_download \
"$WEBI_HOST/packages/${my_cmd}/${my_cmd}.sh" \
"$HOME/.local/bin/${my_cmd}"
"$WEBI_HOST/packages/ssh-adduser/ssh-adduser" \
"$HOME/.local/bin/ssh-adduser"
chmod a+x "$HOME/.local/bin/ssh-adduser"
chmod a+x "$HOME/.local/bin/${my_cmd}"
# sshd-prohibit-password
rm -f "$HOME/.local/bin/sshd-prohibit-password"
webi_download \
"$WEBI_HOST/packages/sshd-prohibit-password/sshd-prohibit-password" \
"$HOME/.local/bin/sshd-prohibit-password"
chmod a+x "$HOME/.local/bin/sshd-prohibit-password"
# run the command
"$HOME/.local/bin/${my_cmd}"
# run the commands
export SSH_ADDUSER_AUTO=true
"$HOME/.local/bin/ssh-adduser"
# TODO create vps-init or the like to do both
"$HOME/.local/bin/sshd-prohibit-password"
}
__install_ssh_adduser

80
ssh-adduser/ssh-adduser Normal file
View File

@@ -0,0 +1,80 @@
#!/bin/sh
set -e
set -u
main() {
# Add User 'app'
# Picking 'app' by common convention (what Docker & Vagrant use).
my_new_user="${1:-"app"}"
my_key_url="${2:-}"
my_keys=""
if [ "root" != "$(whoami)" ]; then
echo "webi adduser: running user is already a non-root user"
exit 0
fi
if [ -n "${my_key_url}" ]; then
my_keys="$(
curl -fsS "${my_key_url}"
)"
elif [ -e ~/.ssh/authorized_keys ] && grep -q -v '#' ~/.ssh/authorized_keys; then
my_keys="$(
cat "${HOME}/.ssh/authorized_keys"
)"
else
echo ""
echo "Error:"
echo " You must add a key to ~/.ssh/authorized_keys before adding a new ssh user."
echo ""
echo "To fix:"
echo " Run 'curl https://webinstall.dev/ssh-pubkey | sh' on your local system, "
echo " then add that key to ~/.ssh/authorized_keys on this (the remote) system. "
echo ""
exit 1
fi
adduser --disabled-password --gecos '' "$my_new_user"
my_password=$(openssl rand -hex 16)
printf '%s\n%s' "${my_password}" "${my_password}" | passwd "${my_new_user}"
# make 'app' a sudo-er (admin)
adduser "$my_new_user" sudo
echo "$my_new_user ALL=(ALL:ALL) NOPASSWD: ALL" | tee "/etc/sudoers.d/$my_new_user"
# allow users who can already login as 'root' to login as 'app'
mkdir -p "/home/$my_new_user/.ssh/"
chmod 0700 "/home/$my_new_user/.ssh/"
echo "${my_keys}" >> "/home/$my_new_user/.ssh/authorized_keys"
chmod 0600 "/home/$my_new_user/.ssh/authorized_keys"
touch "/home/$my_new_user/.ssh/config"
chmod 0644 "/home/$my_new_user/.ssh/config"
chown -R "$my_new_user":"$my_new_user" "/home/$my_new_user/.ssh/"
chown -R "$my_new_user":"$my_new_user" "/home/$my_new_user/.ssh/"
# ensure that 'app' has an SSH Keypair
# sudo -i -u "$my_new_user" sh -c \
# "ssh-keygen -b 2048 -t rsa -f '/home/$my_new_user/.ssh/id_rsa' -q -N ''"
WEBI_HOST=${WEBI_HOST:-"https://webinstall.dev"}
sudo -i -u "$my_new_user" sh -c "curl -fsSL '$WEBI_HOST/ssh-pubkey' | sh > /dev/null" ||
sudo -i -u "$my_new_user" sh -c "wget -q -O - '$WEBI_HOST/ssh-pubkey' | sh > /dev/null"
if test -z "${SSH_ADDUSER_AUTO}"; then
echo ""
echo "!! BREAKING CHANGE !!"
echo ""
echo " 'ssh-adduser' no longer checks or hardens /etc/ssh/sshd_config"
echo ""
echo " Run 'sshd-probihit-password' to secure /etc/ssh/sshd_config"
echo ""
fi
echo "Created user '${my_new_user}' as sudoer with a random password."
echo "(set a new password with 'password ${my_new_user}')"
echo ""
echo "note: you can add an ssh key passphrase with 'webi ssh-setpass'"
}
main "${1:-app}" "${2:-}"

61
ssh-authorize/README.md Normal file
View File

@@ -0,0 +1,61 @@
---
title: SSH Authorize
homepage: https://webinstall.dev/ssh-authorize
tagline: |
Add to your SSH Authorized Keys from a string, file, or url.
---
## Cheat Sheet
> Does the tedious work of making sure your `.ssh/authorized_keys` exists with
> the proper permissions, and that only valid keys from a given string, file, or
> URL go into it!
Use `ssh-authorize` to add trusted public keys to allow others to login to your
servers / systems / local computers;
```sh
# ssh-authorize <ssh-pubkey-or-file-or-url> [comment]
ssh-authorize https://github.com/jonny.keys 'My GitHub Keys'
```
```text
USAGE
ssh-authorize <ssh-pubkey-or-file-or-url> [comment]
EXAMPLES
ssh-authorize https://github.com/you.keys 'My GH Keys'
ssh-authorize ./id_rsa.you@example.co.pub
ssh-authorize 'ssh-rsa AAAA...example.co'
LOCAL IDENTIFY FILES
/home/app/.ssh/id_rsa.pub
```
### How to Add Manually
For the simplest case it seems almost silly to even have a utility for this:
```sh
mkdir -p ~/.ssh/
chmod 0700 ~/.ssh/
touch ~/.ssh/authorized_keys
chmod 0600 ~/.ssh/
curl https://github.com/me.keys >> ~/.ssh/authorized_keys
```
but... tedium, error checking... things are never as simple as they seem.
### But really, why?
- handles arbitrary files and URLs, failing bad key lines
- sets permissions correctly, even if they were incorrect
- works `curl` (macOS, Ubuntu) or `wget` (Docker, Alpine)
- enforces `https`

17
ssh-authorize/install.sh Normal file
View File

@@ -0,0 +1,17 @@
#!/bin/sh
set -e
set -u
__install_ssh_authorize() {
my_cmd="ssh-authorize"
rm -f "$HOME/.local/bin/${my_cmd}"
webi_download \
"$WEBI_HOST/packages/${my_cmd}/${my_cmd}" \
"$HOME/.local/bin/${my_cmd}"
chmod a+x "$HOME/.local/bin/${my_cmd}"
}
__install_ssh_authorize

164
ssh-authorize/ssh-authorize Normal file
View File

@@ -0,0 +1,164 @@
#!/bin/sh
set -e
set -u
cmd_http_get="curl ${CURL_OPTS:-} --max-time 15 --proto =https --tlsv1.2 -fsS"
if ! command -v curl > /dev/null; then
cmd_http_get="wget ${WGET_OPTS:-} --secure-protocol=TLSv1_2 --secure-protocol=TLSv1_3 --timeout=15 -o /dev/null -O -"
fi
fn_init_authorized_keys() { (
if ! test -e ~/.ssh/; then
mkdir -p ~/.ssh/
fi
chmod 0700 ~/.ssh/
if ! test -e ~/.ssh/authorized_keys; then
touch ~/.ssh/authorized_keys
fi
chmod 0600 ~/.ssh/authorized_keys
); }
fn_ssh_keys() { (
my_key_uri="${1:-}"
# Handle keys as a URL, a file, or string
my_keys="${my_key_uri}"
case "${my_key_uri}" in
http:*)
echo "please use 'https://' for ssh public key urls"
return 1
;;
https:*)
my_keys="$(
${cmd_http_get} "${my_key_uri}"
)"
;;
*)
if test -e "${my_key_uri}"; then
my_keys="$(
cat "${my_key_uri}"
)"
fi
;;
esac
# printf for proper whitespace handling
printf '%s' "${my_keys}"
); }
main() { (
my_keything="${1:-}"
my_comment="${2:-}"
fn_init_authorized_keys
if test -z "${my_keything:-}"; then
echo ""
echo "USAGE"
echo ""
echo " ssh-authorize <ssh-pubkey-or-file-or-url> [comment]"
echo ""
echo "EXAMPLES"
echo ""
echo " ssh-authorize https://github.com/you.keys 'My GH Keys'"
echo ""
echo " ssh-authorize ./id_rsa.you@example.co.pub"
echo ""
echo " ssh-authorize 'ssh-rsa AAAA...example.co'"
echo ""
echo "LOCAL IDENTIFY FILES"
echo ""
for my_file in ~/.ssh/*.pub; do
if test "${my_file}" = "$HOME/.ssh/*.pub"; then
echo " (no files match ~/.ssh/*.pub)"
break
fi
printf ' %s\n' "${my_file}"
done
echo ""
return 1
fi
my_pubkeys=""
if test -n "${my_keything}"; then
my_pubkeys="$(
fn_ssh_keys "${my_keything}"
)"
else
# if ! command -v ssh-pubkey > /dev/null; then
# {
# echo ""
# echo "ERROR"
# echo " no key string, file, or url was given,"
# echo " and 'ssh-pubkey' is not installed."
# echo ""
# echo "SOLUTION"
# echo " provide a valid key string, file or url,"
# echo " or 'curl https://webi.sh/ssh-pubkey | sh'"
# echo " to install 'ssh-pubkey'"
# echo ""
# } >&2
#
# return 1
# fi
# Get the default key (for authorizing self)
my_pubkeys="$(
ssh-pubkey 2> /dev/null
)"
fi
# Clean up non-key lines, preserving comments and newlines
my_pubkeys_safe="$(
printf '%s' "${my_pubkeys}" | grep -E '^(#|\s*$|(ssh|ecdsa)-[a-zA-Z0-9-]+ AAA)'
)"
my_pubkeys_trimmed="$(
printf '%s' "${my_pubkeys}" | grep -E '^(ssh|ecdsa)-[a-zA-Z0-9-]+ AAA'
)"
my_pubkeys_excluded="$(
printf '%s' "${my_pubkeys}" | grep -v -E '^(#|\s*$|(ssh|ecdsa)-[a-zA-Z0-9-]+ AAA)' || true
)"
if test -z "${my_pubkeys_trimmed}"; then
{
echo ""
echo "ERROR"
echo " not a valid key string, file, or url:"
echo " '${my_keything}'"
echo ""
echo "SOLUTION"
echo " inspect the file / url / string, double"
echo " check that you copied correctly, etc"
echo ""
} >&2
return 1
fi
{
if test -n "${my_comment}"; then
printf '# %s\n' "${my_comment}"
fi
printf '%s\n' "${my_pubkeys_safe}"
} | tee -a ~/.ssh/authorized_keys
echo ""
echo "Successfully copied the above ssh keys to ~/.ssh/authorized_keys"
if test -n "${my_pubkeys_excluded}"; then
{
echo ""
echo "WARNING: the following (invalid) lines were excluded:"
echo ""
echo "${my_pubkeys_excluded}"
echo ""
} >&2
fi
); }
if test -z "${SSH_AUTHORIZE_UNIT_TEST:-}"; then
main "${@:-}"
fi

97
ssh-harden/README.md Normal file
View File

@@ -0,0 +1,97 @@
---
title: SSH Prohibit Password
homepage: https://webinstall.dev/ssh-prohibit-password
tagline: |
SSH Prohibit Password: Because friends don't let friends ssh with passwords
linux: true
---
## Cheat Sheet
> Will check if your system This will check if your Modern SSH deployments are
> key-only and don't allow root login. However, there's a lot of legacy systems
> out there.
`ssh-harden` will
1. Check that some `/home/*/.ssh/authorized_keys` is non-empty
2. Check that `/etc/sudoers.d` is not empty
3. Optionally create a `sudoer` for a given user and group
4. Disable `root` login
5. Disable Password and Challenge login
```sh
USAGE
ssh-harden [username] [sudo-group]
EXAMPLES
sudo ssh-harden
sudo ssh-harden app
sudo ssh-harden "$(id -n -u)" wheel
```
### How to check for sudoers
```sh
sudo sh -c 'grep "^\w\+ ALL=" /etc/sudoers.d/*'
```
### How to check for authorized ssh users
**Quick 'n' Easy**
```sh
sudo sh -c "grep -E '^(ssh|ec)' /home/*/.ssh/authorized_keys" |
cut -d' ' -f3 |
sort -u
```
**Detailed**
```sh
my_authorized=''
for my_file in /home/*/.ssh/authorized_keys; do
# if no files match the glob becomes a literal string
if test "${my_file}" = '/home/*/.ssh/authorized_keys'; then
break
fi
echo "${my_file} authorizes:"
if ! grep -q -E '^(ssh|ec)' "${my_file}"; then
echo " (none, empty file)"
continue
fi
grep '^(ssh|ec)' "${my_file}" | cut -d' ' -f3 | while read -r my_comment; do
echo " ${my_comment}"
done
my_authorized='true'
done
if test -z "${my_authorized}"; then
echo >&2 ""
echo >&2 "ERROR"
echo >&2 " No authorized remote users found."
echo >&2 ""
exit 1
fi
```
### How to add passwordless sudoer
```sh
echo "app ALL=(ALL:ALL) NOPASSWD: ALL" | sudo tee /etc/sudoers.d/app
```
How to copy allowed keys from root to the new user:
```sh
mkdir -p /home/app/.ssh/
chmod 0700 /home/app/.ssh/
cat "$HOME/.ssh/authorized_keys" >> /home/app/.ssh/authorized_keys
chmod 0600 /home/app/.ssh/authorized_keys
chown -R app:app /home/app/.ssh/
```

View File

@@ -2,46 +2,116 @@
set -e
set -u
main() {
# There are two important use cases:
# 1. Run as 'root', for the 'app' (or specified) user
# 2. Run as a sudoer, for self
# Add User 'app'
# Picking 'app' by common convention (what Docker & Vagrant use).
my_new_user="${1:-"app"}"
my_key_url="${2:-}"
my_keys=""
fn_check_as_root() { (
my_admin="${1:-}"
# TODO would $EUID be better?
if [ "root" != "$(whoami)" ]; then
echo "webi adduser: running user is already a non-root user"
exit 0
fi
if [ -n "${my_key_url}" ]; then
my_keys="$(
curl -fsS "${my_key_url}"
)"
elif [ -e ~/.ssh/authorized_keys ] && grep -q -v '#' ~/.ssh/authorized_keys; then
my_keys="$(
cat "${HOME}/.ssh/authorized_keys"
)"
if ! command -v sudo > /dev/null; then
echo ""
echo "WARNING"
echo " 'sudo' is not installed."
echo " '${my_admin}' MUST be able to login via the 'root' password."
echo ""
else
my_admin_is_sudoer=''
if grep -q "^${my_admin} ALL=" /etc/sudoers; then
my_admin_is_sudoer='true'
elif test -e /etc/sudoers.d; then
if grep -q "^${my_admin} ALL=" /etc/sudoers.d/*; then
my_admin_is_sudoer='true'
fi
fi
echo ""
echo "Error:"
echo " You must add a key to ~/.ssh/authorized_keys before adding a new ssh user."
echo "ERROR"
echo " '${my_admin}' is NOT a sudoer"
echo ""
echo "To fix:"
echo " Run 'curl https://webinstall.dev/ssh-pubkey | sh' on your local system, "
echo " then add that key to ~/.ssh/authorized_keys on this (the remote) system. "
echo "SOLUTION"
echo " mkdir -p /etc/sudoers.d"
echo " chmod 0700 /etc/sudoers.d"
echo " echo '${my_admin} ALL=(ALL:ALL) NOPASSWD: ALL' | "
echo " tee '/etc/sudoers.d/${my_admin}'"
echo ""
exit 1
fi
); }
fn_check_as_sudoer() { (
echo
); }
main() {
echo ""
echo "IMPORTANT"
echo ""
echo "READ CAREFULLY (or get LOCKED OUT)"
echo ""
my_user_id="$(id -u)"
if test "0" = "${my_user_id}"; then
fn_check_as_root ${1:-app}
else
fn_check_as_sudoer
fi
adduser --disabled-password --gecos '' "$my_new_user"
my_password=$(openssl rand -hex 16)
printf '%s\n%s' "${my_password}" "${my_password}" | passwd "${my_new_user}"
my_username="$(id -u -n)"
my_sudo_user="${1:-${my_username}}"
# make 'app' a sudo-er (admin)
adduser "$my_new_user" sudo
my_sudo_exists=''
my_sudo=''
if command -v sudo > /dev/null; then
my_sudo_exists='true'
my_sudo="sudo"
fi
my_root=''
if test "$(id -u)" = "0"; then
my_root='true'
my_sudo=''
fi
my_authorized_exists=''
echo ''
echo "All authorized users:"
if ! $my_sudo sh -c 'ls /home/*/.ssh/authorized_keys' > /devl/null 2>&1; then
echo " (none)"
else
$my_sudo sh -c "grep -E '^(ssh|ec)' /home/*/.ssh/authorized_keys" |
cut -d' ' -f3 |
sort -u |
while read -r my_comment; do
echo " ${my_comment}"
my_authorized_exists='true'
done
fi
my_sudoer_exists=''
echo ''
echo "All sudoers:"
if test -z "${my_sudo_exists}"; then
echo ' (sudo not installed)'
else
{
$my_sudo sh -c "grep -E '(sudo|wheel):' /etc/gshadow" |
cut -d':' -f4 |
tr ',' '\n'
#$my_sudo sh -c "grep '^%\?\w\+ ALL=' /etc/sudoers /etc/sudoers.d/*" |
$my_sudo sh -c "grep '^\w\+ ALL=' /etc/sudoers /etc/sudoers.d/*" |
cut -d':' -f2 |
cut -d' ' -f1
} |
grep -v root |
sort -u |
while read -r my_sudoer; do
my_sudoer_exists='true'
echo " ${my_sudoer}"
done
fi
#adduser "$my_new_user" sudo || adduser "$my_new_user" wheel
echo "$my_new_user ALL=(ALL:ALL) NOPASSWD: ALL" | tee "/etc/sudoers.d/$my_new_user"
# allow users who can already login as 'root' to login as 'app'

View File

@@ -0,0 +1,11 @@
---
title: SSH Prohibit Password
homepage: https://webinstall.dev/sshd-prohibit-password
tagline: |
Alias for https://webinstall.dev/sshd-prohibit-password
alias: sshd-prohibit-password
description: |
See https://webinstall.dev/sshd-prohibit-password
---
Alias for https://webinstall.dev/sshd-prohibit-password

View File

@@ -0,0 +1,13 @@
#!/bin/sh
set -e
set -u
# shellcheck disable=SC2016
__alias_sshd_prohibit_password() {
echo "'ssh-prohibit-password@${WEBI_TAG:-stable}' is an alias for 'sshd-prohibit-password@${WEBI_VERSION-}'"
WEBI_HOST=${WEBI_HOST:-"https://webinstall.dev"}
curl -fsSL "$WEBI_HOST/sshd-prohibit-password@${WEBI_VERSION-}" | sh
}
__alias_sshd_prohibit_password

Some files were not shown because too many files have changed in this diff Show More