diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6363d51b8..20d485837 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,18 @@
# Unreleased
+## `github-build-setup` Job Customization
+
+It's now possible to specify to which jobs `github-build-setup` steps are added.
+
+```toml
+github-build-setup = "build-steps.yml"
+github-build-setup-jobs = ["plan", "build-local-artifacts", "build-global-artifacts", "host"]
+```
+
+If not configured, this defaults to `["build-local-artifacts"]`.
+
+- impl @arusahni [feat: optionally apply `github-build-setup` steps to additional jobs](https://github.com/axodotdev/cargo-dist/pull/2070)
+
# Version 0.30.0 (2025-09-07)
This release contains several improvements to ZIP archives, the installers and additional build workflow customization options.
diff --git a/book/src/reference/config.md b/book/src/reference/config.md
index 7690e38b1..292a05f07 100644
--- a/book/src/reference/config.md
+++ b/book/src/reference/config.md
@@ -95,6 +95,7 @@ We're currently in the middle of [a major config migration](https://github.com/a
* [`github-custom-job-permissions`](#github-custom-job-permissions)
* [`github-custom-runners`](#github-custom-runners)
* [`github-build-setup`](#github-build-setup)
+ * [`github-build-setup-jobs`](#github-build-setup-jobs)
* [`github-action-commits`](#github-action-commits)
* [custom ci jobs](#custom-ci-jobs)
* [`plan-jobs`](#plan-jobs)
@@ -1382,8 +1383,28 @@ These settings are specific to [your dist GitHub CI][github-ci].
This configuration value should be a path relative to the repository your `.github/workflows` directory.
The file located at that path should contain a yaml array of [steps][github-workflow-step] which will be
-performed before we call `dist build`.
+performed before we call `dist build` in the `build-local-artifacts` job. These
+steps can be added to additional jobs by defining
+[`github-build-setup-jobs`](#github-build-setup-jobs).
+#### `github-build-setup-jobs`
+
+> since 1.0.0
[global-only][]
+> š§ this is an experimental feature! \
+> [š read the ci customization guide!][github-ci] \
+> default = ``
+>
+> *in your dist-workspace.toml or dist.toml:*
+> ```toml
+> [dist]
+> # Defaults to "build-local-artifacts"
+> github-build-setup-jobs = ["plan", "build-local-artifacts"]
+> ```
+
+This configuration value should accompany
+[`github-build-setup`](#github-build-setup). When not specified, it defaults to
+`["build-local-artifacts"]`. Otherwise, the listed jobs will have the steps
+defined in `github-build-setup` added.
#### `github-custom-job-permissions`
diff --git a/cargo-dist/src/backend/ci/github.rs b/cargo-dist/src/backend/ci/github.rs
index 426cf5170..4794a6403 100644
--- a/cargo-dist/src/backend/ci/github.rs
+++ b/cargo-dist/src/backend/ci/github.rs
@@ -100,6 +100,8 @@ pub struct GithubCiInfo {
pub root_permissions: Option,
/// Extra build steps
pub github_build_setup: Vec,
+ /// The jobs to which the [`GithubCiInfo::github_build_setup`] steps should be prepended
+ pub github_build_setup_jobs: Vec,
/// Info about making a GitHub Release (if we're making one)
#[serde(flatten)]
pub github_release: Option,
@@ -372,6 +374,7 @@ impl GithubCiInfo {
})
.transpose()?
.unwrap_or_default();
+ let github_build_setup_jobs = ci_config.build_setup_jobs.clone();
let default_action_versions = [
("actions/checkout", "v4"),
@@ -420,6 +423,7 @@ impl GithubCiInfo {
hosting_providers,
root_permissions,
github_build_setup,
+ github_build_setup_jobs,
github_release,
actions,
need_cargo_auditable,
diff --git a/cargo-dist/src/config/v0.rs b/cargo-dist/src/config/v0.rs
index 9863a45b0..3758465d3 100644
--- a/cargo-dist/src/config/v0.rs
+++ b/cargo-dist/src/config/v0.rs
@@ -539,10 +539,14 @@ pub struct DistMetadata {
#[serde(default, with = "opt_string_or_vec")]
pub install_libraries: Option>,
- /// Any additional steps that need to be performed before building local artifacts
+ /// Any additional steps that need to be performed before executing certain job steps
#[serde(default)]
pub github_build_setup: Option,
+ /// The jobs to which the [`DistMetadata::github_build_setup`] steps should be prepended
+ #[serde(default)]
+ pub github_build_setup_jobs: Option>,
+
/// Configuration specific to Mac .pkg installers
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(default)]
@@ -645,6 +649,7 @@ impl DistMetadata {
package_libraries: _,
install_libraries: _,
github_build_setup: _,
+ github_build_setup_jobs: _,
mac_pkg_config: _,
min_glibc_version: _,
binaries: _,
@@ -752,6 +757,7 @@ impl DistMetadata {
package_libraries,
install_libraries,
github_build_setup,
+ github_build_setup_jobs,
mac_pkg_config,
min_glibc_version,
binaries,
@@ -880,6 +886,9 @@ impl DistMetadata {
if github_build_setup.is_some() {
warn!("package.metadata.dist.github-build-setup is set, but this is only accepted in workspace.metadata (value is being ignored): {}", package_manifest_path);
}
+ if github_build_setup_jobs.is_some() {
+ warn!("package.metadata.dist.github-build-setup-jobs is set, but this is only accepted in workspace.metadata (value is being ignored): {}", package_manifest_path);
+ }
// Merge non-global settings
if installers.is_none() {
diff --git a/cargo-dist/src/config/v0_to_v1.rs b/cargo-dist/src/config/v0_to_v1.rs
index 73e9f58f7..ee486363c 100644
--- a/cargo-dist/src/config/v0_to_v1.rs
+++ b/cargo-dist/src/config/v0_to_v1.rs
@@ -88,6 +88,7 @@ impl DistMetadata {
package_libraries,
install_libraries,
github_build_setup,
+ github_build_setup_jobs,
min_glibc_version,
binaries,
cargo_auditable,
@@ -165,6 +166,7 @@ impl DistMetadata {
if github_custom_runners.is_some()
|| github_custom_job_permissions.is_some()
|| github_build_setup.is_some()
+ || github_build_setup_jobs.is_some()
|| github_action_commits.is_some()
{
Some(GithubCiLayer {
@@ -172,6 +174,7 @@ impl DistMetadata {
runners: github_custom_runners,
permissions: github_custom_job_permissions,
build_setup: github_build_setup,
+ build_setup_jobs: github_build_setup_jobs,
action_commits: github_action_commits,
})
} else {
diff --git a/cargo-dist/src/config/v1/ci/github.rs b/cargo-dist/src/config/v1/ci/github.rs
index 52ef18912..e4c3c0a05 100644
--- a/cargo-dist/src/config/v1/ci/github.rs
+++ b/cargo-dist/src/config/v1/ci/github.rs
@@ -25,10 +25,14 @@ pub struct GithubCiLayer {
#[serde(skip_serializing_if = "Option::is_none")]
pub permissions: Option>,
- /// Custom permissions for jobs
+ /// Custom steps for jobs
#[serde(skip_serializing_if = "Option::is_none")]
pub build_setup: Option,
+ /// What jobs to which the [`GithubCiLayer::build_setup`] steps should be prepended
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub build_setup_jobs: Option>,
+
/// Use these commits for actions
#[serde(skip_serializing_if = "Option::is_none")]
pub action_commits: Option>,
@@ -46,9 +50,12 @@ pub struct GithubCiConfig {
/// Custom permissions for jobs
pub permissions: SortedMap,
- /// Custom permissions for jobs
+ /// Custom steps for jobs
pub build_setup: Option,
+ /// What jobs to which the [`GithubCiConfig::build_setup`] steps should be prepended
+ pub build_setup_jobs: Vec,
+
/// Use these commits for github actions
pub action_commits: SortedMap,
}
@@ -62,6 +69,7 @@ impl GithubCiConfig {
permissions: Default::default(),
action_commits: Default::default(),
build_setup: None,
+ build_setup_jobs: vec!["build-local-artifacts".to_string()],
}
}
}
@@ -75,6 +83,7 @@ impl ApplyLayer for GithubCiConfig {
runners,
permissions,
build_setup,
+ build_setup_jobs,
action_commits,
}: Self::Layer,
) {
@@ -143,6 +152,7 @@ impl ApplyLayer for GithubCiConfig {
}));
self.permissions.apply_val(permissions);
self.build_setup.apply_opt(build_setup);
+ self.build_setup_jobs.apply_val(build_setup_jobs);
self.action_commits.apply_val(action_commits);
}
}
@@ -155,6 +165,7 @@ impl ApplyLayer for GithubCiLayer {
runners,
permissions,
build_setup,
+ build_setup_jobs,
action_commits,
}: Self::Layer,
) {
@@ -162,6 +173,7 @@ impl ApplyLayer for GithubCiLayer {
self.runners.apply_opt(runners);
self.permissions.apply_opt(permissions);
self.build_setup.apply_opt(build_setup);
+ self.build_setup_jobs.apply_opt(build_setup_jobs);
self.action_commits.apply_opt(action_commits);
}
}
diff --git a/cargo-dist/src/init/v0.rs b/cargo-dist/src/init/v0.rs
index 2b2527376..e8fffd343 100644
--- a/cargo-dist/src/init/v0.rs
+++ b/cargo-dist/src/init/v0.rs
@@ -252,6 +252,7 @@ fn get_new_dist_metadata(
package_libraries: None,
install_libraries: None,
github_build_setup: None,
+ github_build_setup_jobs: None,
mac_pkg_config: None,
min_glibc_version: None,
binaries: None,
@@ -765,6 +766,7 @@ fn apply_dist_to_metadata(metadata: &mut toml_edit::Item, meta: &DistMetadata) {
bin_aliases: _,
system_dependencies: _,
github_build_setup: _,
+ github_build_setup_jobs: _,
binaries: _,
} = &meta;
diff --git a/cargo-dist/templates/ci/github/release.yml.j2 b/cargo-dist/templates/ci/github/release.yml.j2
index 1e01a0023..258d9ac0a 100644
--- a/cargo-dist/templates/ci/github/release.yml.j2
+++ b/cargo-dist/templates/ci/github/release.yml.j2
@@ -128,6 +128,53 @@ jobs:
with:
name: cargo-dist-cache
path: ~/.cargo/bin/dist
+ {{%- if "plan" in github_build_setup_jobs %}}
+ {{%- for step in github_build_setup %}}
+ - name: {{{ step.name }}}
+ {{%- if step.id is not undefined %}}
+ id: {{{ step.id }}}
+ {{%- endif %}}
+ {{%- if step.uses is not undefined %}}
+ uses: {{{ step.uses }}}
+ {{%- endif %}}
+ {{%- if step.if is not undefined %}}
+ if: {{{ step.if }}}
+ {{%- endif %}}
+ {{%- if step.run is not undefined %}}
+ {{%- if step.run is multiline %}}
+ run: |
+ {{{ step.run|indent(10) }}}
+ {{%- else %}}
+ run: {{{ step.run }}}
+ {{%- endif %}}
+ {{%- endif %}}
+ {{%- if step.working_directory is not undefined %}}
+ working-directory: {{{ step.working_directory }}}
+ {{%- endif %}}
+ {{%- if step.shell is not undefined %}}
+ shell: {{{ step.shell }}}
+ {{%- endif %}}
+ {{%- if not step.with is empty %}}
+ with:
+ {{%- for (var,value) in step.with|items %}}
+ {{%- if value is mapping %}}
+ {{{ var }}}:
+ {{%- for (var,value) in value|items %}}
+ {{{ var }}}: {{{ value }}}
+ {{%- endfor %}}
+ {{%- else %}}
+ {{{ var }}}: {{{ value }}}
+ {{%- endif %}}
+ {{%- endfor %}}
+ {{%- endif %}}
+ {{%- if not step.env is empty %}}
+ env:
+ {{%- for (var,value) in step.env|items %}}
+ {{{ var }}}: {{{ value }}}
+ {{%- endfor %}}
+ {{%- endif %}}
+ {{%- endfor %}}
+ {{%- endif %}}
# sure would be cool if github gave us proper conditionals...
# so here's a doubly-nested ternary-via-truthiness to try to provide the best possible
# functionality based on whether this is a pull_request, and whether it's from a fork.
@@ -229,6 +276,7 @@ jobs:
- name: Use rustup to set correct Rust version
run: rustup update {{{ rust_version }}} --no-self-update && rustup default {{{ rust_version }}}
{{%- endif %}}
+ {{%- if "build-local-artifacts" in github_build_setup_jobs %}}
{{%- for step in github_build_setup %}}
- name: {{{ step.name }}}
{{%- if step.id is not undefined %}}
@@ -280,6 +328,7 @@ jobs:
timeout-minutes: {{{ step.timeout_minutes }}}
{{%- endif %}}
{{%- endfor %}}
+ {{%- endif %}}
{{%- if cache_builds %}}
- uses: {{{actions["swatinem/rust-cache"] | safe }}}
with:
@@ -415,6 +464,53 @@ jobs:
pattern: artifacts-*
path: target/distrib/
merge-multiple: true
+ {{%- if "build-global-artifacts" in github_build_setup_jobs %}}
+ {{%- for step in github_build_setup %}}
+ - name: {{{ step.name }}}
+ {{%- if step.id is not undefined %}}
+ id: {{{ step.id }}}
+ {{%- endif %}}
+ {{%- if step.uses is not undefined %}}
+ uses: {{{ step.uses }}}
+ {{%- endif %}}
+ {{%- if step.if is not undefined %}}
+ if: {{{ step.if }}}
+ {{%- endif %}}
+ {{%- if step.run is not undefined %}}
+ {{%- if step.run is multiline %}}
+ run: |
+ {{{ step.run|indent(10) }}}
+ {{%- else %}}
+ run: {{{ step.run }}}
+ {{%- endif %}}
+ {{%- endif %}}
+ {{%- if step.working_directory is not undefined %}}
+ working-directory: {{{ step.working_directory }}}
+ {{%- endif %}}
+ {{%- if step.shell is not undefined %}}
+ shell: {{{ step.shell }}}
+ {{%- endif %}}
+ {{%- if not step.with is empty %}}
+ with:
+ {{%- for (var,value) in step.with|items %}}
+ {{%- if value is mapping %}}
+ {{{ var }}}:
+ {{%- for (var,value) in value|items %}}
+ {{{ var }}}: {{{ value }}}
+ {{%- endfor %}}
+ {{%- else %}}
+ {{{ var }}}: {{{ value }}}
+ {{%- endif %}}
+ {{%- endfor %}}
+ {{%- endif %}}
+ {{%- if not step.env is empty %}}
+ env:
+ {{%- for (var,value) in step.env|items %}}
+ {{{ var }}}: {{{ value }}}
+ {{%- endfor %}}
+ {{%- endif %}}
+ {{%- endfor %}}
+ {{%- endif %}}
- id: cargo-dist
shell: bash
run: |
@@ -524,6 +620,53 @@ jobs:
merge-multiple: true
{{%- if "github" in hosting_providers and release_phase == "announce" %}}
# This is a harmless no-op for GitHub Releases, hosting for that happens in "announce"
+ {{%- endif %}}
+ {{%- if "host" in github_build_setup_jobs %}}
+ {{%- for step in github_build_setup %}}
+ - name: {{{ step.name }}}
+ {{%- if step.id is not undefined %}}
+ id: {{{ step.id }}}
+ {{%- endif %}}
+ {{%- if step.uses is not undefined %}}
+ uses: {{{ step.uses }}}
+ {{%- endif %}}
+ {{%- if step.if is not undefined %}}
+ if: {{{ step.if }}}
+ {{%- endif %}}
+ {{%- if step.run is not undefined %}}
+ {{%- if step.run is multiline %}}
+ run: |
+ {{{ step.run|indent(10) }}}
+ {{%- else %}}
+ run: {{{ step.run }}}
+ {{%- endif %}}
+ {{%- endif %}}
+ {{%- if step.working_directory is not undefined %}}
+ working-directory: {{{ step.working_directory }}}
+ {{%- endif %}}
+ {{%- if step.shell is not undefined %}}
+ shell: {{{ step.shell }}}
+ {{%- endif %}}
+ {{%- if not step.with is empty %}}
+ with:
+ {{%- for (var,value) in step.with|items %}}
+ {{%- if value is mapping %}}
+ {{{ var }}}:
+ {{%- for (var,value) in value|items %}}
+ {{{ var }}}: {{{ value }}}
+ {{%- endfor %}}
+ {{%- else %}}
+ {{{ var }}}: {{{ value }}}
+ {{%- endif %}}
+ {{%- endfor %}}
+ {{%- endif %}}
+ {{%- if not step.env is empty %}}
+ env:
+ {{%- for (var,value) in step.env|items %}}
+ {{{ var }}}: {{{ value }}}
+ {{%- endfor %}}
+ {{%- endif %}}
+ {{%- endfor %}}
{{%- endif %}}
- id: host
shell: bash
diff --git a/cargo-dist/tests/integration-tests.rs b/cargo-dist/tests/integration-tests.rs
index 43b472522..d708c212c 100644
--- a/cargo-dist/tests/integration-tests.rs
+++ b/cargo-dist/tests/integration-tests.rs
@@ -1905,6 +1905,52 @@ identifier = "dev.axo.axolotsay"
})
}
+
+#[test]
+fn axolotlsay_custom_job_build_setup_steps() -> Result<(), miette::Report> {
+ let test_name = _function_name!();
+ AXOLOTLSAY
+ .run_test(|ctx| {
+ ctx.workspace_write_file(".github/workflows/build_setup.yml",
+ include_str!("../../cargo-dist/tests/build_setup.yml"))?;
+ let dist_version = ctx.tools.cargo_dist.version().unwrap();
+ ctx.patch_cargo_toml(format!(r#"
+[workspace.metadata.dist]
+cargo-dist-version = "{dist_version}"
+installers = ["shell", "powershell", "homebrew", "npm", "msi", "pkg"]
+tap = "axodotdev/homebrew-packages"
+publish-jobs = ["homebrew", "npm"]
+targets = ["x86_64-unknown-linux-gnu", "x86_64-apple-darwin", "x86_64-pc-windows-msvc", "aarch64-apple-darwin"]
+install-success-msg = ">o_o< everything's installed!"
+ci = ["github"]
+unix-archive = ".tar.gz"
+windows-archive = ".tar.gz"
+npm-scope ="@axodotdev"
+github-build-setup = "build_setup.yml"
+github-build-setup-jobs = ["plan", "build-local-artifacts", "host"]
+
+[package.metadata.wix]
+upgrade-guid = "B36177BE-EA4D-44FB-B05C-EDDABDAA95CA"
+path-guid = "BFD25009-65A4-4D1E-97F1-0030465D90D6"
+
+[package.metadata.dist.mac-pkg-config]
+identifier = "dev.axo.axolotsay"
+
+"#
+ ))?;
+
+ // Run generate to make sure stuff is up to date before running other commands
+ let ci_result = ctx.cargo_dist_generate(test_name)?;
+ let ci_snap = ci_result.check_all()?;
+ // Do usual build+plan checks
+ let main_result = ctx.cargo_dist_build_and_plan(test_name)?;
+ let main_snap = main_result.check_all(&ctx, ".cargo/bin/")?;
+ // snapshot all
+ main_snap.join(ci_snap).snap();
+ Ok(())
+ })
+}
+
#[test]
fn axolotlsay_dist_url_override() -> Result<(), miette::Report> {
let test_name = _function_name!();
diff --git a/cargo-dist/tests/snapshots/axolotlsay_custom_job_build_setup_steps.snap b/cargo-dist/tests/snapshots/axolotlsay_custom_job_build_setup_steps.snap
new file mode 100644
index 000000000..aaafc1794
--- /dev/null
+++ b/cargo-dist/tests/snapshots/axolotlsay_custom_job_build_setup_steps.snap
@@ -0,0 +1,4928 @@
+---
+source: cargo-dist/tests/gallery/dist/snapshot.rs
+expression: self.payload
+---
+================ axolotlsay-installer.sh ================
+#!/bin/sh
+# shellcheck shell=dash
+# shellcheck disable=SC2039 # local is non-POSIX
+#
+# Licensed under the MIT license
+# , at your
+# option. This file may not be copied, modified, or distributed
+# except according to those terms.
+
+# This runs on Unix shells like bash/dash/ksh/zsh. It uses the common `local`
+# extension. Note: Most shells limit `local` to 1 var per line, contra bash.
+
+# Some versions of ksh have no `local` keyword. Alias it to `typeset`, but
+# beware this makes variables global with f()-style function syntax in ksh93.
+# mksh has this alias by default.
+has_local() {
+ # shellcheck disable=SC2034 # deliberately unused
+ local _has_local
+}
+
+has_local 2>/dev/null || alias local=typeset
+
+set -u
+
+APP_NAME="axolotlsay"
+APP_VERSION="0.2.2"
+# Look for GitHub Enterprise-style base URL first
+if [ -n "${AXOLOTLSAY_INSTALLER_GHE_BASE_URL:-}" ]; then
+ INSTALLER_BASE_URL="$AXOLOTLSAY_INSTALLER_GHE_BASE_URL"
+else
+ INSTALLER_BASE_URL="${AXOLOTLSAY_INSTALLER_GITHUB_BASE_URL:-https://github.com}"
+fi
+if [ -n "${AXOLOTLSAY_DOWNLOAD_URL:-}" ]; then
+ ARTIFACT_DOWNLOAD_URL="$AXOLOTLSAY_DOWNLOAD_URL"
+elif [ -n "${INSTALLER_DOWNLOAD_URL:-}" ]; then
+ ARTIFACT_DOWNLOAD_URL="$INSTALLER_DOWNLOAD_URL"
+else
+ ARTIFACT_DOWNLOAD_URL="${INSTALLER_BASE_URL}/axodotdev/axolotlsay/releases/download/v0.2.2"
+fi
+if [ -n "${AXOLOTLSAY_PRINT_VERBOSE:-}" ]; then
+ PRINT_VERBOSE="$AXOLOTLSAY_PRINT_VERBOSE"
+else
+ PRINT_VERBOSE=${INSTALLER_PRINT_VERBOSE:-0}
+fi
+if [ -n "${AXOLOTLSAY_PRINT_QUIET:-}" ]; then
+ PRINT_QUIET="$AXOLOTLSAY_PRINT_QUIET"
+else
+ PRINT_QUIET=${INSTALLER_PRINT_QUIET:-0}
+fi
+if [ -n "${AXOLOTLSAY_NO_MODIFY_PATH:-}" ]; then
+ NO_MODIFY_PATH="$AXOLOTLSAY_NO_MODIFY_PATH"
+else
+ NO_MODIFY_PATH=${INSTALLER_NO_MODIFY_PATH:-0}
+fi
+if [ "${AXOLOTLSAY_DISABLE_UPDATE:-0}" = "1" ]; then
+ INSTALL_UPDATER=0
+else
+ INSTALL_UPDATER=1
+fi
+UNMANAGED_INSTALL="${AXOLOTLSAY_UNMANAGED_INSTALL:-}"
+if [ -n "${UNMANAGED_INSTALL}" ]; then
+ NO_MODIFY_PATH=1
+ INSTALL_UPDATER=0
+fi
+AUTH_TOKEN="${AXOLOTLSAY_GITHUB_TOKEN:-}"
+
+read -r RECEIPT <&2
+ say_verbose " from $_url" 1>&2
+ say_verbose " to $_file" 1>&2
+
+ ensure mkdir -p "$_dir"
+
+ if ! downloader "$_url" "$_file"; then
+ say "failed to download $_url"
+ say "this may be a standard network error, but it may also indicate"
+ say "that $APP_NAME's release process is not working. When in doubt"
+ say "please feel free to open an issue!"
+ exit 1
+ fi
+
+ if [ -n "${_checksum_style:-}" ]; then
+ verify_checksum "$_file" "$_checksum_style" "$_checksum_value"
+ else
+ say "no checksums to verify"
+ fi
+
+ # ...and then the updater, if it exists
+ if [ -n "$_updater_name" ] && [ "$INSTALL_UPDATER" = "1" ]; then
+ local _updater_url="$ARTIFACT_DOWNLOAD_URL/$_updater_name"
+ # This renames the artifact while doing the download, removing the
+ # target triple and leaving just the appname-update format
+ local _updater_file="$_dir/$APP_NAME-update"
+
+ if ! downloader "$_updater_url" "$_updater_file"; then
+ say "failed to download $_updater_url"
+ say "this may be a standard network error, but it may also indicate"
+ say "that $APP_NAME's release process is not working. When in doubt"
+ say "please feel free to open an issue!"
+ exit 1
+ fi
+
+ # Add the updater to the list of binaries to install
+ _bins="$_bins $APP_NAME-update"
+ fi
+
+ # unpack the archive
+ case "$_zip_ext" in
+ ".zip")
+ ensure unzip -q "$_file" -d "$_dir"
+ ;;
+
+ ".tar."*)
+ ensure tar xf "$_file" --strip-components 1 -C "$_dir"
+ ;;
+ *)
+ err "unknown archive format: $_zip_ext"
+ ;;
+ esac
+
+ install "$_dir" "$_bins" "$_libs" "$_staticlibs" "$_arch" "$@"
+ local _retval=$?
+ if [ "$_retval" != 0 ]; then
+ return "$_retval"
+ fi
+
+ ignore rm -rf "$_dir"
+
+ # Install the install receipt
+ if [ "$INSTALL_UPDATER" = "1" ]; then
+ if ! mkdir -p "$RECEIPT_HOME"; then
+ err "unable to create receipt directory at $RECEIPT_HOME"
+ else
+ echo "$RECEIPT" > "$RECEIPT_HOME/$APP_NAME-receipt.json"
+ # shellcheck disable=SC2320
+ local _retval=$?
+ fi
+ else
+ local _retval=0
+ fi
+
+ return "$_retval"
+}
+
+# Replaces $HOME with the variable name for display to the user,
+# only if $HOME is defined.
+replace_home() {
+ local _str="$1"
+
+ if [ -n "${HOME:-}" ]; then
+ echo "$_str" | sed "s,$HOME,\$HOME,"
+ else
+ echo "$_str"
+ fi
+}
+
+json_binary_aliases() {
+ local _arch="$1"
+
+ case "$_arch" in
+ "aarch64-apple-darwin")
+ echo '{}'
+ ;;
+ "x86_64-apple-darwin")
+ echo '{}'
+ ;;
+ "x86_64-pc-windows-gnu")
+ echo '{}'
+ ;;
+ "x86_64-unknown-linux-gnu")
+ echo '{}'
+ ;;
+ *)
+ echo '{}'
+ ;;
+ esac
+}
+
+aliases_for_binary() {
+ local _bin="$1"
+ local _arch="$2"
+
+ case "$_arch" in
+ "aarch64-apple-darwin")
+ case "$_bin" in
+ *)
+ echo ""
+ ;;
+ esac
+ ;;
+ "x86_64-apple-darwin")
+ case "$_bin" in
+ *)
+ echo ""
+ ;;
+ esac
+ ;;
+ "x86_64-pc-windows-gnu")
+ case "$_bin" in
+ *)
+ echo ""
+ ;;
+ esac
+ ;;
+ "x86_64-unknown-linux-gnu")
+ case "$_bin" in
+ *)
+ echo ""
+ ;;
+ esac
+ ;;
+ *)
+ echo ""
+ ;;
+ esac
+}
+
+select_archive_for_arch() {
+ local _true_arch="$1"
+ local _archive
+
+ # try each archive, checking runtime conditions like libc versions
+ # accepting the first one that matches, as it's the best match
+ case "$_true_arch" in
+ "aarch64-apple-darwin")
+ _archive="axolotlsay-aarch64-apple-darwin.tar.gz"
+ if [ -n "$_archive" ]; then
+ echo "$_archive"
+ return 0
+ fi
+ _archive="axolotlsay-x86_64-apple-darwin.tar.gz"
+ if [ -n "$_archive" ]; then
+ echo "$_archive"
+ return 0
+ fi
+ ;;
+ "aarch64-pc-windows-msvc")
+ _archive="axolotlsay-x86_64-pc-windows-msvc.tar.gz"
+ if [ -n "$_archive" ]; then
+ echo "$_archive"
+ return 0
+ fi
+ ;;
+ "x86_64-apple-darwin")
+ _archive="axolotlsay-x86_64-apple-darwin.tar.gz"
+ if [ -n "$_archive" ]; then
+ echo "$_archive"
+ return 0
+ fi
+ ;;
+ "x86_64-pc-windows-gnu")
+ _archive="axolotlsay-x86_64-pc-windows-msvc.tar.gz"
+ if [ -n "$_archive" ]; then
+ echo "$_archive"
+ return 0
+ fi
+ ;;
+ "x86_64-pc-windows-msvc")
+ _archive="axolotlsay-x86_64-pc-windows-msvc.tar.gz"
+ if [ -n "$_archive" ]; then
+ echo "$_archive"
+ return 0
+ fi
+ ;;
+ "x86_64-unknown-linux-gnu")
+ _archive="axolotlsay-x86_64-unknown-linux-gnu.tar.gz"
+ if ! check_glibc "2" "31"; then
+ _archive=""
+ fi
+ if [ -n "$_archive" ]; then
+ echo "$_archive"
+ return 0
+ fi
+ ;;
+ *)
+ err "there isn't a download for your platform $_true_arch"
+ ;;
+ esac
+ err "no compatible downloads were found for your platform $_true_arch"
+}
+
+check_glibc() {
+ local _min_glibc_major="$1"
+ local _min_glibc_series="$2"
+
+ # Parsing version out from line 1 like:
+ # ldd (Ubuntu GLIBC 2.35-0ubuntu3.1) 2.35
+ _local_glibc="$(ldd --version | awk -F' ' '{ if (FNR<=1) print $NF }')"
+
+ if [ "$(echo "${_local_glibc}" | awk -F. '{ print $1 }')" = "$_min_glibc_major" ] && [ "$(echo "${_local_glibc}" | awk -F. '{ print $2 }')" -ge "$_min_glibc_series" ]; then
+ return 0
+ else
+ say "System glibc version (\`${_local_glibc}') is too old; checking alternatives" >&2
+ return 1
+ fi
+}
+
+# See discussion of late-bound vs early-bound for why we use single-quotes with env vars
+# shellcheck disable=SC2016
+install() {
+ # This code needs to both compute certain paths for itself to write to, and
+ # also write them to shell/rc files so that they can look them up to e.g.
+ # add them to PATH. This requires an active distinction between paths
+ # and expressions that can compute them.
+ #
+ # The distinction lies in when we want env-vars to be evaluated. For instance
+ # if we determine that we want to install to $HOME/.myapp, which do we add
+ # to e.g. $HOME/.profile:
+ #
+ # * early-bound: export PATH="/home/myuser/.myapp:$PATH"
+ # * late-bound: export PATH="$HOME/.myapp:$PATH"
+ #
+ # In this case most people would prefer the late-bound version, but in other
+ # cases the early-bound version might be a better idea. In particular when using
+ # other env-vars than $HOME, they are more likely to be only set temporarily
+ # for the duration of this install script, so it's more advisable to erase their
+ # existence with early-bounding.
+ #
+ # This distinction is handled by "double-quotes" (early) vs 'single-quotes' (late).
+ #
+ # However if we detect that "$SOME_VAR/..." is a subdir of $HOME, we try to rewrite
+ # it to be '$HOME/...' to get the best of both worlds.
+ #
+ # This script has a few different variants, the most complex one being the
+ # CARGO_HOME version which attempts to install things to Cargo's bin dir,
+ # potentially setting up a minimal version if the user hasn't ever installed Cargo.
+ #
+ # In this case we need to:
+ #
+ # * Install to $HOME/.cargo/bin/
+ # * Create a shell script at $HOME/.cargo/env that:
+ # * Checks if $HOME/.cargo/bin/ is on PATH
+ # * and if not prepends it to PATH
+ # * Edits $INFERRED_HOME/.profile to run $HOME/.cargo/env (if the line doesn't exist)
+ #
+ # To do this we need these 4 values:
+
+ # The actual path we're going to install to
+ local _install_dir
+ # The directory C dynamic/static libraries install to
+ local _lib_install_dir
+ # The install prefix we write to the receipt.
+ # For organized install methods like CargoHome, which have
+ # subdirectories, this is the root without `/bin`. For other
+ # methods, this is the same as `_install_dir`.
+ local _receipt_install_dir
+ # Path to the an shell script that adds install_dir to PATH
+ local _env_script_path
+ # Potentially-late-bound version of install_dir to write env_script
+ local _install_dir_expr
+ # Potentially-late-bound version of env_script_path to write to rcfiles like $HOME/.profile
+ local _env_script_path_expr
+ # Forces the install to occur at this path, not the default
+ local _force_install_dir
+ # Which install layout to use - "flat" or "hierarchical"
+ local _install_layout="unspecified"
+ # A list of binaries which are shadowed in the PATH
+ local _shadowed_bins=""
+
+ # Check the newer app-specific variable before falling back
+ # to the older generic one
+ if [ -n "${AXOLOTLSAY_INSTALL_DIR:-}" ]; then
+ _force_install_dir="$AXOLOTLSAY_INSTALL_DIR"
+ _install_layout="cargo-home"
+ elif [ -n "${CARGO_DIST_FORCE_INSTALL_DIR:-}" ]; then
+ _force_install_dir="$CARGO_DIST_FORCE_INSTALL_DIR"
+ _install_layout="cargo-home"
+ elif [ -n "$UNMANAGED_INSTALL" ]; then
+ _force_install_dir="$UNMANAGED_INSTALL"
+ _install_layout="flat"
+ fi
+
+ # Check if the install layout should be changed from `flat` to `cargo-home`
+ # for backwards compatible updates of applications that switched layouts.
+ if [ -n "${_force_install_dir:-}" ]; then
+ if [ "$_install_layout" = "flat" ]; then
+ # If the install directory is targeting the Cargo home directory, then
+ # we assume this application was previously installed that layout
+ if [ "$_force_install_dir" = "${CARGO_HOME:-${INFERRED_HOME:-}/.cargo}" ]; then
+ _install_layout="cargo-home"
+ fi
+ fi
+ fi
+
+ # Before actually consulting the configured install strategy, see
+ # if we're overriding it.
+ if [ -n "${_force_install_dir:-}" ]; then
+ case "$_install_layout" in
+ "hierarchical")
+ _install_dir="$_force_install_dir/bin"
+ _lib_install_dir="$_force_install_dir/lib"
+ _receipt_install_dir="$_force_install_dir"
+ _env_script_path="$_force_install_dir/env"
+ _install_dir_expr="$(replace_home "$_force_install_dir/bin")"
+ _env_script_path_expr="$(replace_home "$_force_install_dir/env")"
+ ;;
+ "cargo-home")
+ _install_dir="$_force_install_dir/bin"
+ _lib_install_dir="$_force_install_dir/bin"
+ _receipt_install_dir="$_force_install_dir"
+ _env_script_path="$_force_install_dir/env"
+ _install_dir_expr="$(replace_home "$_force_install_dir/bin")"
+ _env_script_path_expr="$(replace_home "$_force_install_dir/env")"
+ ;;
+ "flat")
+ _install_dir="$_force_install_dir"
+ _lib_install_dir="$_force_install_dir"
+ _receipt_install_dir="$_install_dir"
+ _env_script_path="$_force_install_dir/env"
+ _install_dir_expr="$(replace_home "$_force_install_dir")"
+ _env_script_path_expr="$(replace_home "$_force_install_dir/env")"
+ ;;
+ *)
+ err "Unrecognized install layout: $_install_layout"
+ ;;
+ esac
+ fi
+ if [ -z "${_install_dir:-}" ]; then
+ _install_layout="cargo-home"
+ # first try $CARGO_HOME, then fallback to $HOME/.cargo
+ if [ -n "${CARGO_HOME:-}" ]; then
+ _receipt_install_dir="$CARGO_HOME"
+ _install_dir="$CARGO_HOME/bin"
+ _lib_install_dir="$CARGO_HOME/bin"
+ _env_script_path="$CARGO_HOME/env"
+ # Initially make this early-bound to erase the potentially-temporary env-var
+ _install_dir_expr="$_install_dir"
+ _env_script_path_expr="$_env_script_path"
+ # If CARGO_HOME was set but it ended up being the default $HOME-based path,
+ # then keep things late-bound. Otherwise bake the value for safety.
+ # This is what rustup does, and accurately reproducing it is useful.
+ if [ -n "${INFERRED_HOME:-}" ]; then
+ if [ "$INFERRED_HOME/.cargo/bin" = "$_install_dir" ]; then
+ _install_dir_expr="$INFERRED_HOME_EXPRESSION/.cargo/bin"
+ _env_script_path_expr="$INFERRED_HOME_EXPRESSION/.cargo/env"
+ fi
+ fi
+ elif [ -n "${INFERRED_HOME:-}" ]; then
+ _receipt_install_dir="$INFERRED_HOME/.cargo"
+ _install_dir="$INFERRED_HOME/.cargo/bin"
+ _lib_install_dir="$INFERRED_HOME/.cargo/bin"
+ _env_script_path="$INFERRED_HOME/.cargo/env"
+ _install_dir_expr="$INFERRED_HOME_EXPRESSION/.cargo/bin"
+ _env_script_path_expr="$INFERRED_HOME_EXPRESSION/.cargo/env"
+ fi
+ fi
+
+ if [ -z "$_install_dir_expr" ]; then
+ err "could not find a valid path to install to!"
+ fi
+
+ # Identical to the sh version, just with a .fish file extension
+ # We place it down here to wait until it's been assigned in every
+ # path.
+ _fish_env_script_path="${_env_script_path}.fish"
+ _fish_env_script_path_expr="${_env_script_path_expr}.fish"
+
+ # Replace the temporary cargo home with the calculated one
+ RECEIPT=$(echo "$RECEIPT" | sed "s,AXO_INSTALL_PREFIX,$_receipt_install_dir,")
+ # Also replace the aliases with the arch-specific one
+ RECEIPT=$(echo "$RECEIPT" | sed "s'\"binary_aliases\":{}'\"binary_aliases\":$(json_binary_aliases "$_arch")'")
+ # And replace the install layout
+ RECEIPT=$(echo "$RECEIPT" | sed "s'\"install_layout\":\"unspecified\"'\"install_layout\":\"$_install_layout\"'")
+ if [ "$NO_MODIFY_PATH" = "1" ]; then
+ RECEIPT=$(echo "$RECEIPT" | sed "s'\"modify_path\":true'\"modify_path\":false'")
+ fi
+
+ say "installing to $_install_dir"
+ ensure mkdir -p "$_install_dir"
+ ensure mkdir -p "$_lib_install_dir"
+
+ # copy all the binaries to the install dir
+ local _src_dir="$1"
+ local _bins="$2"
+ local _libs="$3"
+ local _staticlibs="$4"
+ local _arch="$5"
+ for _bin_name in $_bins; do
+ local _bin="$_src_dir/$_bin_name"
+ ensure mv "$_bin" "$_install_dir"
+ # unzip seems to need this chmod
+ ensure chmod +x "$_install_dir/$_bin_name"
+ for _dest in $(aliases_for_binary "$_bin_name" "$_arch"); do
+ ln -sf "$_install_dir/$_bin_name" "$_install_dir/$_dest"
+ done
+ say " $_bin_name"
+ done
+ # Like the above, but no aliases
+ for _lib_name in $_libs; do
+ local _lib="$_src_dir/$_lib_name"
+ ensure mv "$_lib" "$_lib_install_dir"
+ # unzip seems to need this chmod
+ ensure chmod +x "$_lib_install_dir/$_lib_name"
+ say " $_lib_name"
+ done
+ for _lib_name in $_staticlibs; do
+ local _lib="$_src_dir/$_lib_name"
+ ensure mv "$_lib" "$_lib_install_dir"
+ # unzip seems to need this chmod
+ ensure chmod +x "$_lib_install_dir/$_lib_name"
+ say " $_lib_name"
+ done
+
+ say ">o_o< everything's installed!"
+
+ # Avoid modifying the users PATH if they are managing their PATH manually
+ case :$PATH:
+ in *:$_install_dir:*) NO_MODIFY_PATH=1 ;;
+ *) ;;
+ esac
+
+ if [ "0" = "$NO_MODIFY_PATH" ]; then
+ add_install_dir_to_ci_path "$_install_dir"
+ add_install_dir_to_path "$_install_dir_expr" "$_env_script_path" "$_env_script_path_expr" ".profile" "sh"
+ exit1=$?
+ shotgun_install_dir_to_path "$_install_dir_expr" "$_env_script_path" "$_env_script_path_expr" ".profile .bashrc .bash_profile .bash_login" "sh"
+ exit2=$?
+ add_install_dir_to_path "$_install_dir_expr" "$_env_script_path" "$_env_script_path_expr" ".zshrc .zshenv" "sh"
+ exit3=$?
+ # This path may not exist by default
+ ensure mkdir -p "$INFERRED_HOME/.config/fish/conf.d"
+ exit4=$?
+ add_install_dir_to_path "$_install_dir_expr" "$_fish_env_script_path" "$_fish_env_script_path_expr" ".config/fish/conf.d/$APP_NAME.env.fish" "fish"
+ exit5=$?
+
+ if [ "${exit1:-0}" = 1 ] || [ "${exit2:-0}" = 1 ] || [ "${exit3:-0}" = 1 ] || [ "${exit4:-0}" = 1 ] || [ "${exit5:-0}" = 1 ]; then
+ say ""
+ say "To add $_install_dir_expr to your PATH, either restart your shell or run:"
+ say ""
+ say " source $_env_script_path_expr (sh, bash, zsh)"
+ say " source $_fish_env_script_path_expr (fish)"
+ fi
+ fi
+
+ _shadowed_bins="$(check_for_shadowed_bins "$_install_dir" "$_bins")"
+ if [ -n "$_shadowed_bins" ]; then
+ warn "The following commands are shadowed by other commands in your PATH:$_shadowed_bins"
+ fi
+}
+
+check_for_shadowed_bins() {
+ local _install_dir="$1"
+ local _bins="$2"
+ local _shadow
+
+ for _bin_name in $_bins; do
+ _shadow="$(command -v "$_bin_name")"
+ if [ -n "$_shadow" ] && [ "$_shadow" != "$_install_dir/$_bin_name" ]; then
+ _shadowed_bins="$_shadowed_bins $_bin_name"
+ fi
+ done
+
+ echo "$_shadowed_bins"
+}
+
+print_home_for_script() {
+ local script="$1"
+
+ local _home
+ case "$script" in
+ # zsh has a special ZDOTDIR directory, which if set
+ # should be considered instead of $HOME
+ .zsh*)
+ if [ -n "${ZDOTDIR:-}" ]; then
+ _home="$ZDOTDIR"
+ else
+ _home="$INFERRED_HOME"
+ fi
+ ;;
+ *)
+ _home="$INFERRED_HOME"
+ ;;
+ esac
+
+ echo "$_home"
+}
+
+add_install_dir_to_ci_path() {
+ # Attempt to do CI-specific rituals to get the install-dir on PATH faster
+ local _install_dir="$1"
+
+ # If GITHUB_PATH is present, then write install_dir to the file it refs.
+ # After each GitHub Action, the contents will be added to PATH.
+ # So if you put a curl | sh for this script in its own "run" step,
+ # the next step will have this dir on PATH.
+ #
+ # Note that GITHUB_PATH will not resolve any variables, so we in fact
+ # want to write install_dir and not install_dir_expr
+ if [ -n "${GITHUB_PATH:-}" ]; then
+ ensure echo "$_install_dir" >> "$GITHUB_PATH"
+ fi
+}
+
+add_install_dir_to_path() {
+ # Edit rcfiles ($HOME/.profile) to add install_dir to $PATH
+ #
+ # We do this slightly indirectly by creating an "env" shell script which checks if install_dir
+ # is on $PATH already, and prepends it if not. The actual line we then add to rcfiles
+ # is to just source that script. This allows us to blast it into lots of different rcfiles and
+ # have it run multiple times without causing problems. It's also specifically compatible
+ # with the system rustup uses, so that we don't conflict with it.
+ local _install_dir_expr="$1"
+ local _env_script_path="$2"
+ local _env_script_path_expr="$3"
+ local _rcfiles="$4"
+ local _shell="$5"
+
+ if [ -n "${INFERRED_HOME:-}" ]; then
+ local _target
+ local _home
+
+ # Find the first file in the array that exists and choose
+ # that as our target to write to
+ for _rcfile_relative in $_rcfiles; do
+ _home="$(print_home_for_script "$_rcfile_relative")"
+ local _rcfile="$_home/$_rcfile_relative"
+
+ if [ -f "$_rcfile" ]; then
+ _target="$_rcfile"
+ break
+ fi
+ done
+
+ # If we didn't find anything, pick the first entry in the
+ # list as the default to create and write to
+ if [ -z "${_target:-}" ]; then
+ local _rcfile_relative
+ _rcfile_relative="$(echo "$_rcfiles" | awk '{ print $1 }')"
+ _home="$(print_home_for_script "$_rcfile_relative")"
+ _target="$_home/$_rcfile_relative"
+ fi
+
+ # `source x` is an alias for `. x`, and the latter is more portable/actually-posix.
+ # This apparently comes up a lot on freebsd. It's easy enough to always add
+ # the more robust line to rcfiles, but when telling the user to apply the change
+ # to their current shell ". x" is pretty easy to misread/miscopy, so we use the
+ # prettier "source x" line there. Hopefully people with Weird Shells are aware
+ # this is a thing and know to tweak it (or just restart their shell).
+ local _robust_line=". \"$_env_script_path_expr\""
+ local _pretty_line="source \"$_env_script_path_expr\""
+
+ # Add the env script if it doesn't already exist
+ if [ ! -f "$_env_script_path" ]; then
+ say_verbose "creating $_env_script_path"
+ if [ "$_shell" = "sh" ]; then
+ write_env_script_sh "$_install_dir_expr" "$_env_script_path"
+ else
+ write_env_script_fish "$_install_dir_expr" "$_env_script_path"
+ fi
+ else
+ say_verbose "$_env_script_path already exists"
+ fi
+
+ # Check if the line is already in the rcfile
+ # grep: 0 if matched, 1 if no match, and 2 if an error occurred
+ #
+ # Ideally we could use quiet grep (-q), but that makes "match" and "error"
+ # have the same behaviour, when we want "no match" and "error" to be the same
+ # (on error we want to create the file, which >> conveniently does)
+ #
+ # We search for both kinds of line here just to do the right thing in more cases.
+ if ! grep -F "$_robust_line" "$_target" > /dev/null 2>/dev/null && \
+ ! grep -F "$_pretty_line" "$_target" > /dev/null 2>/dev/null
+ then
+ # If the script now exists, add the line to source it to the rcfile
+ # (This will also create the rcfile if it doesn't exist)
+ if [ -f "$_env_script_path" ]; then
+ local _line
+ # Fish has deprecated `.` as an alias for `source` and
+ # it will be removed in a later version.
+ # https://fishshell.com/docs/current/cmds/source.html
+ # By contrast, `.` is the traditional syntax in sh and
+ # `source` isn't always supported in all circumstances.
+ if [ "$_shell" = "fish" ]; then
+ _line="$_pretty_line"
+ else
+ _line="$_robust_line"
+ fi
+ say_verbose "adding $_line to $_target"
+ # prepend an extra newline in case the user's file is missing a trailing one
+ ensure echo "" >> "$_target"
+ ensure echo "$_line" >> "$_target"
+ return 1
+ fi
+ else
+ say_verbose "$_install_dir already on PATH"
+ fi
+ fi
+}
+
+shotgun_install_dir_to_path() {
+ # Edit rcfiles ($HOME/.profile) to add install_dir to $PATH
+ # (Shotgun edition - write to all provided files that exist rather than just the first)
+ local _install_dir_expr="$1"
+ local _env_script_path="$2"
+ local _env_script_path_expr="$3"
+ local _rcfiles="$4"
+ local _shell="$5"
+
+ if [ -n "${INFERRED_HOME:-}" ]; then
+ local _found=false
+ local _home
+
+ for _rcfile_relative in $_rcfiles; do
+ _home="$(print_home_for_script "$_rcfile_relative")"
+ local _rcfile_abs="$_home/$_rcfile_relative"
+
+ if [ -f "$_rcfile_abs" ]; then
+ _found=true
+ add_install_dir_to_path "$_install_dir_expr" "$_env_script_path" "$_env_script_path_expr" "$_rcfile_relative" "$_shell"
+ fi
+ done
+
+ # Fall through to previous "create + write to first file in list" behavior
+ if [ "$_found" = false ]; then
+ add_install_dir_to_path "$_install_dir_expr" "$_env_script_path" "$_env_script_path_expr" "$_rcfiles" "$_shell"
+ fi
+ fi
+}
+
+write_env_script_sh() {
+ # write this env script to the given path (this cat/EOF stuff is a "heredoc" string)
+ local _install_dir_expr="$1"
+ local _env_script_path="$2"
+ ensure cat < "$_env_script_path"
+#!/bin/sh
+# add binaries to PATH if they aren't added yet
+# affix colons on either side of \$PATH to simplify matching
+case ":\${PATH}:" in
+ *:"$_install_dir_expr":*)
+ ;;
+ *)
+ # Prepending path in case a system-installed binary needs to be overridden
+ export PATH="$_install_dir_expr:\$PATH"
+ ;;
+esac
+EOF
+}
+
+write_env_script_fish() {
+ # write this env script to the given path (this cat/EOF stuff is a "heredoc" string)
+ local _install_dir_expr="$1"
+ local _env_script_path="$2"
+ ensure cat < "$_env_script_path"
+if not contains "$_install_dir_expr" \$PATH
+ # Prepending path in case a system-installed binary needs to be overridden
+ set -x PATH "$_install_dir_expr" \$PATH
+end
+EOF
+}
+
+get_current_exe() {
+ # Returns the executable used for system architecture detection
+ # This is only run on Linux
+ local _current_exe
+ if test -L /proc/self/exe ; then
+ _current_exe=/proc/self/exe
+ else
+ warn "Unable to find /proc/self/exe. System architecture detection might be inaccurate."
+ if test -n "$SHELL" ; then
+ _current_exe=$SHELL
+ else
+ need_cmd /bin/sh
+ _current_exe=/bin/sh
+ fi
+ warn "Falling back to $_current_exe."
+ fi
+ echo "$_current_exe"
+}
+
+get_bitness() {
+ need_cmd head
+ # Architecture detection without dependencies beyond coreutils.
+ # ELF files start out "\x7fELF", and the following byte is
+ # 0x01 for 32-bit and
+ # 0x02 for 64-bit.
+ # The printf builtin on some shells like dash only supports octal
+ # escape sequences, so we use those.
+ local _current_exe=$1
+ local _current_exe_head
+ _current_exe_head=$(head -c 5 "$_current_exe")
+ if [ "$_current_exe_head" = "$(printf '\177ELF\001')" ]; then
+ echo 32
+ elif [ "$_current_exe_head" = "$(printf '\177ELF\002')" ]; then
+ echo 64
+ else
+ err "unknown platform bitness"
+ fi
+}
+
+is_host_amd64_elf() {
+ local _current_exe=$1
+
+ need_cmd head
+ need_cmd tail
+ # ELF e_machine detection without dependencies beyond coreutils.
+ # Two-byte field at offset 0x12 indicates the CPU,
+ # but we're interested in it being 0x3E to indicate amd64, or not that.
+ local _current_exe_machine
+ _current_exe_machine=$(head -c 19 "$_current_exe" | tail -c 1)
+ [ "$_current_exe_machine" = "$(printf '\076')" ]
+}
+
+get_endianness() {
+ local _current_exe=$1
+ local cputype=$2
+ local suffix_eb=$3
+ local suffix_el=$4
+
+ # detect endianness without od/hexdump, like get_bitness() does.
+ need_cmd head
+ need_cmd tail
+
+ local _current_exe_endianness
+ _current_exe_endianness="$(head -c 6 "$_current_exe" | tail -c 1)"
+ if [ "$_current_exe_endianness" = "$(printf '\001')" ]; then
+ echo "${cputype}${suffix_el}"
+ elif [ "$_current_exe_endianness" = "$(printf '\002')" ]; then
+ echo "${cputype}${suffix_eb}"
+ else
+ err "unknown platform endianness"
+ fi
+}
+
+# Detect the Linux/LoongArch UAPI flavor, with all errors being non-fatal.
+# Returns 0 or 234 in case of successful detection, 1 otherwise (/tmp being
+# noexec, or other causes).
+check_loongarch_uapi() {
+ need_cmd base64
+
+ local _tmp
+ if ! _tmp="$(ensure mktemp)"; then
+ return 1
+ fi
+
+ # Minimal Linux/LoongArch UAPI detection, exiting with 0 in case of
+ # upstream ("new world") UAPI, and 234 (-EINVAL truncated) in case of
+ # old-world (as deployed on several early commercial Linux distributions
+ # for LoongArch).
+ #
+ # See https://gist.github.com/xen0n/5ee04aaa6cecc5c7794b9a0c3b65fc7f for
+ # source to this helper binary.
+ ignore base64 -d > "$_tmp" <&1 | grep -q 'musl'; then
+ _clibtype="musl-dynamic"
+ else
+ # Assume all other linuxes are glibc (even if wrong, static libc fallback will apply)
+ _clibtype="gnu"
+ fi
+ fi
+
+ if [ "$_ostype" = Darwin ]; then
+ # Darwin `uname -m` can lie due to Rosetta shenanigans. If you manage to
+ # invoke a native shell binary and then a native uname binary, you can
+ # get the real answer, but that's hard to ensure, so instead we use
+ # `sysctl` (which doesn't lie) to check for the actual architecture.
+ if [ "$_cputype" = i386 ]; then
+ # Handling i386 compatibility mode in older macOS versions (<10.15)
+ # running on x86_64-based Macs.
+ # Starting from 10.15, macOS explicitly bans all i386 binaries from running.
+ # See:
+
+ # Avoid `sysctl: unknown oid` stderr output and/or non-zero exit code.
+ if sysctl hw.optional.x86_64 2> /dev/null || true | grep -q ': 1'; then
+ _cputype=x86_64
+ fi
+ elif [ "$_cputype" = x86_64 ]; then
+ # Handling x86-64 compatibility mode (a.k.a. Rosetta 2)
+ # in newer macOS versions (>=11) running on arm64-based Macs.
+ # Rosetta 2 is built exclusively for x86-64 and cannot run i386 binaries.
+
+ # Avoid `sysctl: unknown oid` stderr output and/or non-zero exit code.
+ if sysctl hw.optional.arm64 2> /dev/null || true | grep -q ': 1'; then
+ _cputype=arm64
+ fi
+ fi
+ fi
+
+ if [ "$_ostype" = SunOS ]; then
+ # Both Solaris and illumos presently announce as "SunOS" in "uname -s"
+ # so use "uname -o" to disambiguate. We use the full path to the
+ # system uname in case the user has coreutils uname first in PATH,
+ # which has historically sometimes printed the wrong value here.
+ if [ "$(/usr/bin/uname -o)" = illumos ]; then
+ _ostype=illumos
+ fi
+
+ # illumos systems have multi-arch userlands, and "uname -m" reports the
+ # machine hardware name; e.g., "i86pc" on both 32- and 64-bit x86
+ # systems. Check for the native (widest) instruction set on the
+ # running kernel:
+ if [ "$_cputype" = i86pc ]; then
+ _cputype="$(isainfo -n)"
+ fi
+ fi
+
+ local _current_exe
+ case "$_ostype" in
+
+ Android)
+ _ostype=linux-android
+ ;;
+
+ Linux)
+ _current_exe=$(get_current_exe)
+ _ostype=unknown-linux-$_clibtype
+ _bitness=$(get_bitness "$_current_exe")
+ ;;
+
+ FreeBSD)
+ _ostype=unknown-freebsd
+ ;;
+
+ NetBSD)
+ _ostype=unknown-netbsd
+ ;;
+
+ DragonFly)
+ _ostype=unknown-dragonfly
+ ;;
+
+ Darwin)
+ _ostype=apple-darwin
+ ;;
+
+ illumos)
+ _ostype=unknown-illumos
+ ;;
+
+ MINGW* | MSYS* | CYGWIN* | Windows_NT)
+ _ostype=pc-windows-gnu
+ ;;
+
+ *)
+ err "unrecognized OS type: $_ostype"
+ ;;
+
+ esac
+
+ case "$_cputype" in
+
+ i386 | i486 | i686 | i786 | x86)
+ _cputype=i686
+ ;;
+
+ xscale | arm)
+ _cputype=arm
+ if [ "$_ostype" = "linux-android" ]; then
+ _ostype=linux-androideabi
+ fi
+ ;;
+
+ armv6l)
+ _cputype=arm
+ if [ "$_ostype" = "linux-android" ]; then
+ _ostype=linux-androideabi
+ else
+ _ostype="${_ostype}eabihf"
+ fi
+ ;;
+
+ armv7l | armv8l)
+ _cputype=armv7
+ if [ "$_ostype" = "linux-android" ]; then
+ _ostype=linux-androideabi
+ else
+ _ostype="${_ostype}eabihf"
+ fi
+ ;;
+
+ aarch64 | arm64)
+ _cputype=aarch64
+ ;;
+
+ x86_64 | x86-64 | x64 | amd64)
+ _cputype=x86_64
+ ;;
+
+ mips)
+ _cputype=$(get_endianness "$_current_exe" mips '' el)
+ ;;
+
+ mips64)
+ if [ "$_bitness" -eq 64 ]; then
+ # only n64 ABI is supported for now
+ _ostype="${_ostype}abi64"
+ _cputype=$(get_endianness "$_current_exe" mips64 '' el)
+ fi
+ ;;
+
+ ppc)
+ _cputype=powerpc
+ ;;
+
+ ppc64)
+ _cputype=powerpc64
+ ;;
+
+ ppc64le)
+ _cputype=powerpc64le
+ ;;
+
+ s390x)
+ _cputype=s390x
+ ;;
+ riscv64)
+ _cputype=riscv64gc
+ ;;
+ loongarch64)
+ _cputype=loongarch64
+ ensure_loongarch_uapi
+ ;;
+ *)
+ err "unknown CPU type: $_cputype"
+
+ esac
+
+ # Detect 64-bit linux with 32-bit userland
+ if [ "${_ostype}" = unknown-linux-gnu ] && [ "${_bitness}" -eq 32 ]; then
+ case $_cputype in
+ x86_64)
+ # 32-bit executable for amd64 = x32
+ if is_host_amd64_elf "$_current_exe"; then {
+ err "x32 linux unsupported"
+ }; else
+ _cputype=i686
+ fi
+ ;;
+ mips64)
+ _cputype=$(get_endianness "$_current_exe" mips '' el)
+ ;;
+ powerpc64)
+ _cputype=powerpc
+ ;;
+ aarch64)
+ _cputype=armv7
+ if [ "$_ostype" = "linux-android" ]; then
+ _ostype=linux-androideabi
+ else
+ _ostype="${_ostype}eabihf"
+ fi
+ ;;
+ riscv64gc)
+ err "riscv64 with 32-bit userland unsupported"
+ ;;
+ esac
+ fi
+
+ # Detect armv7 but without the CPU features Rust needs in that build,
+ # and fall back to arm.
+ if [ "$_ostype" = "unknown-linux-gnueabihf" ] && [ "$_cputype" = armv7 ]; then
+ if ! (ensure grep '^Features' /proc/cpuinfo | grep -E -q 'neon|simd') ; then
+ # Either `/proc/cpuinfo` is malformed or unavailable, or
+ # at least one processor does not have NEON (which is asimd on armv8+).
+ _cputype=arm
+ fi
+ fi
+
+ _arch="${_cputype}-${_ostype}"
+
+ RETVAL="$_arch"
+}
+
+say() {
+ if [ "0" = "$PRINT_QUIET" ]; then
+ echo "$1"
+ fi
+}
+
+say_verbose() {
+ if [ "1" = "$PRINT_VERBOSE" ]; then
+ echo "$1"
+ fi
+}
+
+warn() {
+ if [ "0" = "$PRINT_QUIET" ]; then
+ local red
+ local reset
+ red=$(tput setaf 1 2>/dev/null || echo '')
+ reset=$(tput sgr0 2>/dev/null || echo '')
+ say "${red}WARN${reset}: $1" >&2
+ fi
+}
+
+err() {
+ if [ "0" = "$PRINT_QUIET" ]; then
+ local red
+ local reset
+ red=$(tput setaf 1 2>/dev/null || echo '')
+ reset=$(tput sgr0 2>/dev/null || echo '')
+ say "${red}ERROR${reset}: $1" >&2
+ fi
+ exit 1
+}
+
+need_cmd() {
+ if ! check_cmd "$1"
+ then err "need '$1' (command not found)"
+ fi
+}
+
+check_cmd() {
+ command -v "$1" > /dev/null 2>&1
+ return $?
+}
+
+assert_nz() {
+ if [ -z "$1" ]; then err "assert_nz $2"; fi
+}
+
+# Run a command that should never fail. If the command fails execution
+# will immediately terminate with an error showing the failing
+# command.
+ensure() {
+ if ! "$@"; then err "command failed: $*"; fi
+}
+
+# This is just for indicating that commands' results are being
+# intentionally ignored. Usually, because it's being executed
+# as part of error handling.
+ignore() {
+ "$@"
+}
+
+# This wraps curl or wget. Try curl first, if not installed,
+# use wget instead.
+downloader() {
+ # Check if we have a broken snap curl
+ # https://github.com/boukendesho/curl-snap/issues/1
+ _snap_curl=0
+ if command -v curl > /dev/null 2>&1; then
+ _curl_path=$(command -v curl)
+ if echo "$_curl_path" | grep "/snap/" > /dev/null 2>&1; then
+ _snap_curl=1
+ fi
+ fi
+
+ # Check if we have a working (non-snap) curl
+ if check_cmd curl && [ "$_snap_curl" = "0" ]
+ then _dld=curl
+ # Try wget for both no curl and the broken snap curl
+ elif check_cmd wget
+ then _dld=wget
+ # If we can't fall back from broken snap curl to wget, report the broken snap curl
+ elif [ "$_snap_curl" = "1" ]
+ then
+ say "curl installed with snap cannot be used to install $APP_NAME"
+ say "due to missing permissions. Please uninstall it and"
+ say "reinstall curl with a different package manager (e.g., apt)."
+ say "See https://github.com/boukendesho/curl-snap/issues/1"
+ exit 1
+ else _dld='curl or wget' # to be used in error message of need_cmd
+ fi
+
+ if [ "$1" = --check ]
+ then need_cmd "$_dld"
+ elif [ "$_dld" = curl ]; then
+ if [ -n "${AUTH_TOKEN:-}" ]; then
+ curl -sSfL --header "Authorization: Bearer ${AUTH_TOKEN}" "$1" -o "$2"
+ else
+ curl -sSfL "$1" -o "$2"
+ fi
+ elif [ "$_dld" = wget ]; then
+ if [ -n "${AUTH_TOKEN:-}" ]; then
+ wget --header "Authorization: Bearer ${AUTH_TOKEN}" "$1" -O "$2"
+ else
+ wget "$1" -O "$2"
+ fi
+ else err "Unknown downloader" # should not reach here
+ fi
+}
+
+verify_checksum() {
+ local _file="$1"
+ local _checksum_style="$2"
+ local _checksum_value="$3"
+ local _calculated_checksum
+
+ if [ -z "$_checksum_value" ]; then
+ return 0
+ fi
+ case "$_checksum_style" in
+ sha256)
+ if ! check_cmd sha256sum; then
+ say "skipping sha256 checksum verification (it requires the 'sha256sum' command)"
+ return 0
+ fi
+ _calculated_checksum="$(sha256sum -b "$_file" | awk '{printf $1}')"
+ ;;
+ sha512)
+ if ! check_cmd sha512sum; then
+ say "skipping sha512 checksum verification (it requires the 'sha512sum' command)"
+ return 0
+ fi
+ _calculated_checksum="$(sha512sum -b "$_file" | awk '{printf $1}')"
+ ;;
+ sha3-256)
+ if ! check_cmd openssl; then
+ say "skipping sha3-256 checksum verification (it requires the 'openssl' command)"
+ return 0
+ fi
+ _calculated_checksum="$(openssl dgst -sha3-256 "$_file" | awk '{printf $NF}')"
+ ;;
+ sha3-512)
+ if ! check_cmd openssl; then
+ say "skipping sha3-512 checksum verification (it requires the 'openssl' command)"
+ return 0
+ fi
+ _calculated_checksum="$(openssl dgst -sha3-512 "$_file" | awk '{printf $NF}')"
+ ;;
+ blake2s)
+ if ! check_cmd b2sum; then
+ say "skipping blake2s checksum verification (it requires the 'b2sum' command)"
+ return 0
+ fi
+ # Test if we have official b2sum with blake2s support
+ local _well_known_blake2s_checksum="93314a61f470985a40f8da62df10ba0546dc5216e1d45847bf1dbaa42a0e97af"
+ local _test_blake2s
+ _test_blake2s="$(printf "can do blake2s" | b2sum -a blake2s | awk '{printf $1}')" || _test_blake2s=""
+
+ if [ "X$_test_blake2s" = "X$_well_known_blake2s_checksum" ]; then
+ _calculated_checksum="$(b2sum -a blake2s "$_file" | awk '{printf $1}')" || _calculated_checksum=""
+ else
+ say "skipping blake2s checksum verification (installed b2sum doesn't support blake2s)"
+ return 0
+ fi
+ ;;
+ blake2b)
+ if ! check_cmd b2sum; then
+ say "skipping blake2b checksum verification (it requires the 'b2sum' command)"
+ return 0
+ fi
+ _calculated_checksum="$(b2sum "$_file" | awk '{printf $1}')"
+ ;;
+ false)
+ ;;
+ *)
+ say "skipping unknown checksum style: $_checksum_style"
+ return 0
+ ;;
+ esac
+
+ if [ "$_calculated_checksum" != "$_checksum_value" ]; then
+ err "checksum mismatch
+ want: $_checksum_value
+ got: $_calculated_checksum"
+ fi
+}
+
+download_binary_and_run_installer "$@" || exit 1
+
+================ axolotlsay.rb ================
+class Axolotlsay < Formula
+ desc "š¬ a CLI for learning to distribute CLIs in rust"
+ homepage "https://github.com/axodotdev/axolotlsay"
+ version "0.2.2"
+ if OS.mac?
+ if Hardware::CPU.arm?
+ url "https://github.com/axodotdev/axolotlsay/releases/download/v0.2.2/axolotlsay-aarch64-apple-darwin.tar.gz"
+ end
+ if Hardware::CPU.intel?
+ url "https://github.com/axodotdev/axolotlsay/releases/download/v0.2.2/axolotlsay-x86_64-apple-darwin.tar.gz"
+ end
+ end
+ if OS.linux?
+ if Hardware::CPU.intel?
+ url "https://github.com/axodotdev/axolotlsay/releases/download/v0.2.2/axolotlsay-x86_64-unknown-linux-gnu.tar.gz"
+ end
+ end
+ license any_of: ["MIT", "Apache-2.0"]
+
+ BINARY_ALIASES = {
+ "aarch64-apple-darwin": {},
+ "x86_64-apple-darwin": {},
+ "x86_64-pc-windows-gnu": {},
+ "x86_64-unknown-linux-gnu": {}
+ }
+
+ def target_triple
+ cpu = Hardware::CPU.arm? ? "aarch64" : "x86_64"
+ os = OS.mac? ? "apple-darwin" : "unknown-linux-gnu"
+
+ "#{cpu}-#{os}"
+ end
+
+ def install_binary_aliases!
+ BINARY_ALIASES[target_triple.to_sym].each do |source, dests|
+ dests.each do |dest|
+ bin.install_symlink bin/source.to_s => dest
+ end
+ end
+ end
+
+ def install
+ if OS.mac? && Hardware::CPU.arm?
+ bin.install "axolotlsay"
+ end
+ if OS.mac? && Hardware::CPU.intel?
+ bin.install "axolotlsay"
+ end
+ if OS.linux? && Hardware::CPU.intel?
+ bin.install "axolotlsay"
+ end
+
+ install_binary_aliases!
+
+ # Homebrew will automatically install these, so we don't need to do that
+ doc_files = Dir["README.*", "readme.*", "LICENSE", "LICENSE.*", "CHANGELOG.*"]
+ leftover_contents = Dir["*"] - doc_files
+
+ # Install any leftover files in pkgshare; these are probably config or
+ # sample files.
+ pkgshare.install(*leftover_contents) unless leftover_contents.empty?
+ end
+end
+
+================ axolotlsay-installer.ps1 ================
+# Licensed under the MIT license
+# , at your
+# option. This file may not be copied, modified, or distributed
+# except according to those terms.
+
+<#
+.SYNOPSIS
+
+The installer for axolotlsay 0.2.2
+
+.DESCRIPTION
+
+This script detects what platform you're on and fetches an appropriate archive from
+https://github.com/axodotdev/axolotlsay/releases/download/v0.2.2
+then unpacks the binaries and installs them to
+
+ $env:CARGO_HOME/bin (or $HOME/.cargo/bin)
+
+It will then add that dir to PATH by editing your Environment.Path registry key
+
+.PARAMETER ArtifactDownloadUrl
+The URL of the directory where artifacts can be fetched from
+
+.PARAMETER NoModifyPath
+Don't add the install directory to PATH
+
+.PARAMETER Help
+Print help
+
+#>
+
+param (
+ [Parameter(HelpMessage = "The URL of the directory where artifacts can be fetched from")]
+ [string]$ArtifactDownloadUrl = 'https://github.com/axodotdev/axolotlsay/releases/download/v0.2.2',
+ [Parameter(HelpMessage = "Don't add the install directory to PATH")]
+ [switch]$NoModifyPath,
+ [Parameter(HelpMessage = "Print Help")]
+ [switch]$Help
+)
+
+$app_name = 'axolotlsay'
+$app_version = '0.2.2'
+if ($env:AXOLOTLSAY_INSTALLER_GHE_BASE_URL) {
+ $installer_base_url = $env:AXOLOTLSAY_INSTALLER_GHE_BASE_URL
+} elseif ($env:AXOLOTLSAY_INSTALLER_GITHUB_BASE_URL) {
+ $installer_base_url = $env:AXOLOTLSAY_INSTALLER_GITHUB_BASE_URL
+} else {
+ $installer_base_url = "https://github.com"
+}
+if ($env:AXOLOTLSAY_DOWNLOAD_URL) {
+ $ArtifactDownloadUrl = $env:AXOLOTLSAY_DOWNLOAD_URL
+} elseif ($env:INSTALLER_DOWNLOAD_URL) {
+ $ArtifactDownloadUrl = $env:INSTALLER_DOWNLOAD_URL
+} else {
+ $ArtifactDownloadUrl = "$installer_base_url/axodotdev/axolotlsay/releases/download/v0.2.2"
+}
+$auth_token = $env:AXOLOTLSAY_GITHUB_TOKEN
+
+$receipt = @"
+{"binaries":["CARGO_DIST_BINS"],"binary_aliases":{},"cdylibs":["CARGO_DIST_DYLIBS"],"cstaticlibs":["CARGO_DIST_STATICLIBS"],"install_layout":"unspecified","install_prefix":"AXO_INSTALL_PREFIX","modify_path":true,"provider":{"source":"cargo-dist","version":"CENSORED"},"source":{"app_name":"axolotlsay","name":"axolotlsay","owner":"axodotdev","release_type":"github"},"version":"CENSORED"}
+"@
+if ($env:XDG_CONFIG_HOME) {
+ $receipt_home = "${env:XDG_CONFIG_HOME}\axolotlsay"
+} else {
+ $receipt_home = "${env:LOCALAPPDATA}\axolotlsay"
+}
+
+if ($env:AXOLOTLSAY_DISABLE_UPDATE) {
+ $install_updater = $false
+} else {
+ $install_updater = $true
+}
+
+if ($NoModifyPath) {
+ Write-Information "-NoModifyPath has been deprecated; please set AXOLOTLSAY_NO_MODIFY_PATH=1 in the environment"
+}
+
+if ($env:AXOLOTLSAY_NO_MODIFY_PATH) {
+ $NoModifyPath = $true
+}
+
+$unmanaged_install = $env:AXOLOTLSAY_UNMANAGED_INSTALL
+
+if ($unmanaged_install) {
+ $NoModifyPath = $true
+ $install_updater = $false
+}
+
+function Install-Binary($install_args) {
+ if ($Help) {
+ Get-Help $PSCommandPath -Detailed
+ Exit
+ }
+
+ Initialize-Environment
+
+ # Platform info injected by dist
+ $platforms = @{
+ "aarch64-pc-windows-msvc" = @{
+ "artifact_name" = "axolotlsay-x86_64-pc-windows-msvc.tar.gz"
+ "bins" = @("axolotlsay.exe")
+ "libs" = @()
+ "staticlibs" = @()
+ "zip_ext" = ".tar.gz"
+ "aliases" = @{
+ }
+ "aliases_json" = '{}'
+ }
+ "x86_64-pc-windows-gnu" = @{
+ "artifact_name" = "axolotlsay-x86_64-pc-windows-msvc.tar.gz"
+ "bins" = @("axolotlsay.exe")
+ "libs" = @()
+ "staticlibs" = @()
+ "zip_ext" = ".tar.gz"
+ "aliases" = @{
+ }
+ "aliases_json" = '{}'
+ }
+ "x86_64-pc-windows-msvc" = @{
+ "artifact_name" = "axolotlsay-x86_64-pc-windows-msvc.tar.gz"
+ "bins" = @("axolotlsay.exe")
+ "libs" = @()
+ "staticlibs" = @()
+ "zip_ext" = ".tar.gz"
+ "aliases" = @{
+ }
+ "aliases_json" = '{}'
+ }
+ }
+
+ $fetched = Download "$ArtifactDownloadUrl" $platforms
+ # FIXME: add a flag that lets the user not do this step
+ try {
+ Invoke-Installer -artifacts $fetched -platforms $platforms "$install_args"
+ } catch {
+ throw @"
+We encountered an error trying to perform the installation;
+please review the error messages below.
+
+$_
+"@
+ }
+}
+
+function Get-TargetTriple($platforms) {
+ $double = Get-Arch
+ if ($platforms.Contains("$double-msvc")) {
+ return "$double-msvc"
+ } else {
+ return "$double-gnu"
+ }
+}
+
+function Get-Arch() {
+ try {
+ # NOTE: this might return X64 on ARM64 Windows, which is OK since emulation is available.
+ # It works correctly starting in PowerShell Core 7.3 and Windows PowerShell in Win 11 22H2.
+ # Ideally this would just be
+ # [System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture
+ # but that gets a type from the wrong assembly on Windows PowerShell (i.e. not Core)
+ $a = [System.Reflection.Assembly]::LoadWithPartialName("System.Runtime.InteropServices.RuntimeInformation")
+ $t = $a.GetType("System.Runtime.InteropServices.RuntimeInformation")
+ $p = $t.GetProperty("OSArchitecture")
+ # Possible OSArchitecture Values: https://learn.microsoft.com/dotnet/api/system.runtime.interopservices.architecture
+ # Rust supported platforms: https://doc.rust-lang.org/stable/rustc/platform-support.html
+ switch ($p.GetValue($null).ToString())
+ {
+ "X86" { return "i686-pc-windows" }
+ "X64" { return "x86_64-pc-windows" }
+ "Arm" { return "thumbv7a-pc-windows" }
+ "Arm64" { return "aarch64-pc-windows" }
+ }
+ } catch {
+ # The above was added in .NET 4.7.1, so Windows PowerShell in versions of Windows
+ # prior to Windows 10 v1709 may not have this API.
+ Write-Verbose "Get-TargetTriple: Exception when trying to determine OS architecture."
+ Write-Verbose $_
+ }
+
+ # This is available in .NET 4.0. We already checked for PS 5, which requires .NET 4.5.
+ Write-Verbose("Get-TargetTriple: falling back to Is64BitOperatingSystem.")
+ if ([System.Environment]::Is64BitOperatingSystem) {
+ return "x86_64-pc-windows"
+ } else {
+ return "i686-pc-windows"
+ }
+}
+
+function Download($download_url, $platforms) {
+ $arch = Get-TargetTriple $platforms
+
+ if (-not $platforms.ContainsKey($arch)) {
+ $platforms_json = ConvertTo-Json $platforms
+ throw "ERROR: could not find binaries for this platform. Last platform tried: $arch platform info: $platforms_json"
+ }
+
+ # Lookup what we expect this platform to look like
+ $info = $platforms[$arch]
+ $zip_ext = $info["zip_ext"]
+ $bin_names = $info["bins"]
+ $lib_names = $info["libs"]
+ $staticlib_names = $info["staticlibs"]
+ $artifact_name = $info["artifact_name"]
+
+ # Make a new temp dir to unpack things to
+ $tmp = New-Temp-Dir
+ $dir_path = "$tmp\$app_name$zip_ext"
+
+ # Download and unpack!
+ $url = "$download_url/$artifact_name"
+ Write-Information "Downloading $app_name $app_version ($arch)"
+ Write-Verbose " from $url"
+ Write-Verbose " to $dir_path"
+ $wc = New-Object Net.Webclient
+ if ($auth_token) {
+ $wc.Headers["Authorization"] = "Bearer $auth_token"
+ }
+ $wc.downloadFile($url, $dir_path)
+
+ Write-Verbose "Unpacking to $tmp"
+
+ # Select the tool to unpack the files with.
+ #
+ # As of windows 10(?), powershell comes with tar preinstalled, but in practice
+ # it only seems to support .tar.gz, and not xz/zstd. Still, we should try to
+ # forward all tars to it in case the user has a machine that can handle it!
+ switch -Wildcard ($zip_ext) {
+ ".zip" {
+ Expand-Archive -Path $dir_path -DestinationPath "$tmp";
+ Break
+ }
+ ".tar.*" {
+ tar xf $dir_path --strip-components 1 -C "$tmp";
+ Break
+ }
+ Default {
+ throw "ERROR: unknown archive format $zip_ext"
+ }
+ }
+
+ # Let the next step know what to copy
+ $bin_paths = @()
+ foreach ($bin_name in $bin_names) {
+ Write-Verbose " Unpacked $bin_name"
+ $bin_paths += "$tmp\$bin_name"
+ }
+ $lib_paths = @()
+ foreach ($lib_name in $lib_names) {
+ Write-Verbose " Unpacked $lib_name"
+ $lib_paths += "$tmp\$lib_name"
+ }
+ $staticlib_paths = @()
+ foreach ($lib_name in $staticlib_names) {
+ Write-Verbose " Unpacked $lib_name"
+ $staticlib_paths += "$tmp\$lib_name"
+ }
+
+ if (($null -ne $info["updater"]) -and $install_updater) {
+ $updater_id = $info["updater"]["artifact_name"]
+ $updater_url = "$download_url/$updater_id"
+ $out_name = "$tmp\axolotlsay-update.exe"
+
+ $wc.downloadFile($updater_url, $out_name)
+ $bin_paths += $out_name
+ }
+
+ return @{
+ "bin_paths" = $bin_paths
+ "lib_paths" = $lib_paths
+ "staticlib_paths" = $staticlib_paths
+ }
+}
+
+function Invoke-Installer($artifacts, $platforms) {
+ # Replaces the placeholder binary entry with the actual list of binaries
+ $arch = Get-TargetTriple $platforms
+
+ if (-not $platforms.ContainsKey($arch)) {
+ $platforms_json = ConvertTo-Json $platforms
+ throw "ERROR: could not find binaries for this platform. Last platform tried: $arch platform info: $platforms_json"
+ }
+
+ $info = $platforms[$arch]
+
+ # Forces the install to occur at this path, not the default
+ $force_install_dir = $null
+ $install_layout = "unspecified"
+ # Check the newer app-specific variable before falling back
+ # to the older generic one
+ if (($env:AXOLOTLSAY_INSTALL_DIR)) {
+ $force_install_dir = $env:AXOLOTLSAY_INSTALL_DIR
+ $install_layout = "cargo-home"
+ } elseif (($env:CARGO_DIST_FORCE_INSTALL_DIR)) {
+ $force_install_dir = $env:CARGO_DIST_FORCE_INSTALL_DIR
+ $install_layout = "cargo-home"
+ } elseif ($unmanaged_install) {
+ $force_install_dir = $unmanaged_install
+ $install_layout = "flat"
+ }
+
+ # Check if the install layout should be changed from `flat` to `cargo-home`
+ # for backwards compatible updates of applications that switched layouts.
+ if (($force_install_dir) -and ($install_layout -eq "flat")) {
+ # If the install directory is targeting the Cargo home directory, then
+ # we assume this application was previously installed that layout
+ # Note the installer passes the path with `\\` separators, but here they are
+ # `\` so we normalize for comparison. We don't use `Resolve-Path` because they
+ # may not exist.
+ $cargo_home = if ($env:CARGO_HOME) { $env:CARGO_HOME } else {
+ Join-Path $(if ($HOME) { $HOME } else { "." }) ".cargo"
+ }
+ if ($force_install_dir.Replace('\\', '\') -eq $cargo_home) {
+ $install_layout = "cargo-home"
+ }
+ }
+
+ # The actual path we're going to install to
+ $dest_dir = $null
+ $dest_dir_lib = $null
+ # The install prefix we write to the receipt.
+ # For organized install methods like CargoHome, which have
+ # subdirectories, this is the root without `/bin`. For other
+ # methods, this is the same as `_install_dir`.
+ $receipt_dest_dir = $null
+ # Before actually consulting the configured install strategy, see
+ # if we're overriding it.
+ if (($force_install_dir)) {
+ switch ($install_layout) {
+ "hierarchical" {
+ $dest_dir = Join-Path $force_install_dir "bin"
+ $dest_dir_lib = Join-Path $force_install_dir "lib"
+ }
+ "cargo-home" {
+ $dest_dir = Join-Path $force_install_dir "bin"
+ $dest_dir_lib = $dest_dir
+ }
+ "flat" {
+ $dest_dir = $force_install_dir
+ $dest_dir_lib = $dest_dir
+ }
+ Default {
+ throw "Error: unrecognized installation layout: $install_layout"
+ }
+ }
+ $receipt_dest_dir = $force_install_dir
+ }
+ if (-Not $dest_dir) {
+ # first try $env:CARGO_HOME, then fallback to $HOME
+ # (for whatever reason $HOME is not a normal env var and doesn't need the $env: prefix)
+ $root = if (($base_dir = $env:CARGO_HOME)) {
+ $base_dir
+ } elseif (($base_dir = $HOME)) {
+ Join-Path $base_dir ".cargo"
+ } else {
+ throw "ERROR: could not find your HOME dir or CARGO_HOME to install binaries to"
+ }
+
+ $dest_dir = Join-Path $root "bin"
+ $dest_dir_lib = $dest_dir
+ $receipt_dest_dir = $root
+ $install_layout = "cargo-home"
+ }
+
+ # Looks like all of the above assignments failed
+ if (-Not $dest_dir) {
+ throw "ERROR: could not find a valid path to install to; please check the installation instructions"
+ }
+
+ # The replace call here ensures proper escaping is inlined into the receipt
+ $receipt = $receipt.Replace('AXO_INSTALL_PREFIX', $receipt_dest_dir.replace("\", "\\"))
+ $receipt = $receipt.Replace('"install_layout":"unspecified"', -join('"install_layout":"', $install_layout, '"'))
+
+ $dest_dir = New-Item -Force -ItemType Directory -Path $dest_dir
+ $dest_dir_lib = New-Item -Force -ItemType Directory -Path $dest_dir_lib
+ Write-Information "Installing to $dest_dir"
+ # Just copy the binaries from the temp location to the install dir
+ foreach ($bin_path in $artifacts["bin_paths"]) {
+ $installed_file = Split-Path -Path "$bin_path" -Leaf
+ Copy-Item "$bin_path" -Destination "$dest_dir" -ErrorAction Stop
+ Remove-Item "$bin_path" -Recurse -Force -ErrorAction Stop
+ Write-Information " $installed_file"
+
+ if (($dests = $info["aliases"][$installed_file])) {
+ $source = Join-Path "$dest_dir" "$installed_file"
+ foreach ($dest_name in $dests) {
+ $dest = Join-Path $dest_dir $dest_name
+ $null = New-Item -ItemType HardLink -Target "$source" -Path "$dest" -Force -ErrorAction Stop
+ }
+ }
+ }
+ foreach ($lib_path in $artifacts["lib_paths"]) {
+ $installed_file = Split-Path -Path "$lib_path" -Leaf
+ Copy-Item "$lib_path" -Destination "$dest_dir_lib" -ErrorAction Stop
+ Remove-Item "$lib_path" -Recurse -Force -ErrorAction Stop
+ Write-Information " $installed_file"
+ }
+ foreach ($lib_path in $artifacts["staticlib_paths"]) {
+ $installed_file = Split-Path -Path "$lib_path" -Leaf
+ Copy-Item "$lib_path" -Destination "$dest_dir_lib" -ErrorAction Stop
+ Remove-Item "$lib_path" -Recurse -Force -ErrorAction Stop
+ Write-Information " $installed_file"
+ }
+
+ $formatted_bins = ($info["bins"] | ForEach-Object { '"' + $_ + '"' }) -join ","
+ $receipt = $receipt.Replace('"CARGO_DIST_BINS"', $formatted_bins)
+ $formatted_libs = ($info["libs"] | ForEach-Object { '"' + $_ + '"' }) -join ","
+ $receipt = $receipt.Replace('"CARGO_DIST_DYLIBS"', $formatted_libs)
+ $formatted_staticlibs = ($info["staticlibs"] | ForEach-Object { '"' + $_ + '"' }) -join ","
+ $receipt = $receipt.Replace('"CARGO_DIST_STATICLIBS"', $formatted_staticlibs)
+ # Also replace the aliases with the arch-specific one
+ $receipt = $receipt.Replace('"binary_aliases":{}', -join('"binary_aliases":', $info['aliases_json']))
+ if ($NoModifyPath) {
+ $receipt = $receipt.Replace('"modify_path":true', '"modify_path":false')
+ }
+
+ # Write the install receipt
+ if ($install_updater) {
+ $null = New-Item -Path $receipt_home -ItemType "directory" -ErrorAction SilentlyContinue
+ # Trying to get Powershell 5.1 (not 6+, which is fake and lies) to write utf8 is a crime
+ # because "Out-File -Encoding utf8" actually still means utf8BOM, so we need to pull out
+ # .NET's APIs which actually do what you tell them (also apparently utf8NoBOM is the
+ # default in newer .NETs but I'd rather not rely on that at this point).
+ $Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding $False
+ [IO.File]::WriteAllLines("$receipt_home/axolotlsay-receipt.json", "$receipt", $Utf8NoBomEncoding)
+ }
+
+ # Respect the environment, but CLI takes precedence
+ if ($null -eq $NoModifyPath) {
+ $NoModifyPath = $env:INSTALLER_NO_MODIFY_PATH
+ }
+
+ Write-Information ">o_o< everything's installed!"
+ if (-not $NoModifyPath) {
+ Add-Ci-Path $dest_dir
+ if (Add-Path $dest_dir) {
+ Write-Information ""
+ Write-Information "To add $dest_dir to your PATH, either restart your shell or run:"
+ Write-Information ""
+ Write-Information " set Path=$dest_dir;%Path% (cmd)"
+ Write-Information " `$env:Path = `"$dest_dir;`$env:Path`" (powershell)"
+ }
+ }
+}
+
+# Attempt to do CI-specific rituals to get the install-dir on PATH faster
+function Add-Ci-Path($OrigPathToAdd) {
+ # If GITHUB_PATH is present, then write install_dir to the file it refs.
+ # After each GitHub Action, the contents will be added to PATH.
+ # So if you put a curl | sh for this script in its own "run" step,
+ # the next step will have this dir on PATH.
+ #
+ # Note that GITHUB_PATH will not resolve any variables, so we in fact
+ # want to write the install dir and not an expression that evals to it
+ if (($gh_path = $env:GITHUB_PATH)) {
+ Write-Output "$OrigPathToAdd" | Out-File -FilePath "$gh_path" -Encoding utf8 -Append
+ }
+}
+
+# Try to permanently add the given path to the user-level
+# PATH via the registry
+#
+# Returns true if the registry was modified, otherwise returns false
+# (indicating it was already on PATH)
+#
+# This is a lightly modified version of this solution:
+# https://stackoverflow.com/questions/69236623/adding-path-permanently-to-windows-using-powershell-doesnt-appear-to-work/69239861#69239861
+function Add-Path($LiteralPath) {
+ Write-Verbose "Adding $LiteralPath to your user-level PATH"
+
+ $RegistryPath = 'registry::HKEY_CURRENT_USER\Environment'
+
+ # Note the use of the .GetValue() method to ensure that the *unexpanded* value is returned.
+ # If 'Path' is not an existing item in the registry, '' is returned.
+ $CurrentDirectories = (Get-Item -LiteralPath $RegistryPath).GetValue('Path', '', 'DoNotExpandEnvironmentNames') -split ';' -ne ''
+
+ if ($LiteralPath -in $CurrentDirectories) {
+ Write-Verbose "Install directory $LiteralPath already on PATH, all done!"
+ return $false
+ }
+
+ Write-Verbose "Actually mutating 'Path' Property"
+
+ # Add the new path to the front of the PATH.
+ # The ',' turns $LiteralPath into an array, which the array of
+ # $CurrentDirectories is then added to.
+ $NewPath = (,$LiteralPath + $CurrentDirectories) -join ';'
+
+ # Update the registry. Will create the property if it did not already exist.
+ # Note the use of ExpandString to create a registry property with a REG_EXPAND_SZ data type.
+ Set-ItemProperty -Type ExpandString -LiteralPath $RegistryPath Path $NewPath
+
+ # Broadcast WM_SETTINGCHANGE to get the Windows shell to reload the
+ # updated environment, via a dummy [Environment]::SetEnvironmentVariable() operation.
+ $DummyName = 'cargo-dist-' + [guid]::NewGuid().ToString()
+ [Environment]::SetEnvironmentVariable($DummyName, 'cargo-dist-dummy', 'User')
+ [Environment]::SetEnvironmentVariable($DummyName, [NullString]::value, 'User')
+
+ Write-Verbose "Successfully added $LiteralPath to your user-level PATH"
+ return $true
+}
+
+function Initialize-Environment() {
+ If (($PSVersionTable.PSVersion.Major) -lt 5) {
+ throw @"
+Error: PowerShell 5 or later is required to install $app_name.
+Upgrade PowerShell:
+
+ https://docs.microsoft.com/en-us/powershell/scripting/setup/installing-windows-powershell
+
+"@
+ }
+
+ # show notification to change execution policy:
+ $allowedExecutionPolicy = @('Unrestricted', 'RemoteSigned', 'Bypass')
+ If ((Get-ExecutionPolicy).ToString() -notin $allowedExecutionPolicy) {
+ throw @"
+Error: PowerShell requires an execution policy in [$($allowedExecutionPolicy -join ", ")] to run $app_name. For example, to set the execution policy to 'RemoteSigned' please run:
+
+ Set-ExecutionPolicy RemoteSigned -scope CurrentUser
+
+"@
+ }
+
+ # GitHub requires TLS 1.2
+ If ([System.Enum]::GetNames([System.Net.SecurityProtocolType]) -notcontains 'Tls12') {
+ throw @"
+Error: Installing $app_name requires at least .NET Framework 4.5
+Please download and install it first:
+
+ https://www.microsoft.com/net/download
+
+"@
+ }
+}
+
+function New-Temp-Dir() {
+ [CmdletBinding(SupportsShouldProcess)]
+ param()
+ $parent = [System.IO.Path]::GetTempPath()
+ [string] $name = [System.Guid]::NewGuid()
+ New-Item -ItemType Directory -Path (Join-Path $parent $name)
+}
+
+# PSScriptAnalyzer doesn't like how we use our params as globals, this calms it
+$Null = $ArtifactDownloadUrl, $NoModifyPath, $Help
+# Make Write-Information statements be visible
+$InformationPreference = "Continue"
+
+# The default interactive handler
+try {
+ Install-Binary "$Args"
+} catch {
+ Write-Information $_
+ exit 1
+}
+
+================ axolotlsay-npm-package.tar.gz/package/.gitignore ================
+/node_modules
+
+
+================ axolotlsay-npm-package.tar.gz/package/CHANGELOG.md ================
+# Version 0.2.2
+
+```text
+ +----------------------------------+
+ | now with arm64 linux binaries!!! |
+ +----------------------------------+
+ /
+ā½(ā į“ ā)ā¼
+```
+
+# Version 0.2.1
+
+```text
+ +--------------------------------------+
+ | now with linux static musl binary!!! |
+ +--------------------------------------+
+ /
+ā½(ā į“ ā)ā¼
+```
+
+# Version 0.2.0
+
+```text
+ +-----------------------------------------+
+ | now with homebrew and msi installers!!! |
+ +-----------------------------------------+
+ /
+ā½(ā į“ ā)ā¼
+```
+
+# Version 0.1.0
+
+```text
+ +------------------------+
+ | the initial release!!! |
+ +------------------------+
+ /
+ā½(ā į“ ā)ā¼
+```
+
+================ axolotlsay-npm-package.tar.gz/package/LICENSE-APACHE ================
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+Copyright 2022-2024 Axo Developer Co.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+================ axolotlsay-npm-package.tar.gz/package/LICENSE-MIT ================
+Copyright (c) 2022-2024 Axo Developer Co.
+
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+================ axolotlsay-npm-package.tar.gz/package/README.md ================
+# axolotlsay
+> š¬ a CLI for learning to distribute CLIs in rust
+
+
+## Usage
+
+```sh
+> axolotlsay "hello world"
+
+ +-------------+
+ | hello world |
+ +-------------+
+ /
+ā½(ā į“ ā)ā¼
+```
+
+## License
+
+Licensed under either of
+
+* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or [apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0))
+* MIT license ([LICENSE-MIT](LICENSE-MIT) or [opensource.org/licenses/MIT](https://opensource.org/licenses/MIT))
+
+at your option.
+
+================ axolotlsay-npm-package.tar.gz/package/binary-install.js ================
+const { createWriteStream, existsSync, mkdirSync, mkdtemp } = require("fs");
+const { join, sep } = require("path");
+const { spawnSync } = require("child_process");
+const { tmpdir } = require("os");
+
+const axios = require("axios");
+const rimraf = require("rimraf");
+const tmpDir = tmpdir();
+
+const error = (msg) => {
+ console.error(msg);
+ process.exit(1);
+};
+
+class Package {
+ constructor(platform, name, url, filename, zipExt, binaries) {
+ let errors = [];
+ if (typeof url !== "string") {
+ errors.push("url must be a string");
+ } else {
+ try {
+ new URL(url);
+ } catch (e) {
+ errors.push(e);
+ }
+ }
+ if (name && typeof name !== "string") {
+ errors.push("package name must be a string");
+ }
+ if (!name) {
+ errors.push("You must specify the name of your package");
+ }
+ if (binaries && typeof binaries !== "object") {
+ errors.push("binaries must be a string => string map");
+ }
+ if (!binaries) {
+ errors.push("You must specify the binaries in the package");
+ }
+
+ if (errors.length > 0) {
+ let errorMsg =
+ "One or more of the parameters you passed to the Binary constructor are invalid:\n";
+ errors.forEach((error) => {
+ errorMsg += error;
+ });
+ errorMsg +=
+ '\n\nCorrect usage: new Package("my-binary", "https://example.com/binary/download.tar.gz", {"my-binary": "my-binary"})';
+ error(errorMsg);
+ }
+
+ this.platform = platform;
+ this.url = url;
+ this.name = name;
+ this.filename = filename;
+ this.zipExt = zipExt;
+ this.installDirectory = join(__dirname, "node_modules", ".bin_real");
+ this.binaries = binaries;
+
+ if (!existsSync(this.installDirectory)) {
+ mkdirSync(this.installDirectory, { recursive: true });
+ }
+ }
+
+ exists() {
+ for (const binaryName in this.binaries) {
+ const binRelPath = this.binaries[binaryName];
+ const binPath = join(this.installDirectory, binRelPath);
+ if (!existsSync(binPath)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ install(fetchOptions, suppressLogs = false) {
+ if (this.exists()) {
+ if (!suppressLogs) {
+ console.error(
+ `${this.name} is already installed, skipping installation.`,
+ );
+ }
+ return Promise.resolve();
+ }
+
+ if (existsSync(this.installDirectory)) {
+ rimraf.sync(this.installDirectory);
+ }
+
+ mkdirSync(this.installDirectory, { recursive: true });
+
+ if (!suppressLogs) {
+ console.error(`Downloading release from ${this.url}`);
+ }
+
+ return axios({ ...fetchOptions, url: this.url, responseType: "stream" })
+ .then((res) => {
+ return new Promise((resolve, reject) => {
+ mkdtemp(`${tmpDir}${sep}`, (err, directory) => {
+ let tempFile = join(directory, this.filename);
+ const sink = res.data.pipe(createWriteStream(tempFile));
+ sink.on("error", (err) => reject(err));
+ sink.on("close", () => {
+ if (/\.tar\.*/.test(this.zipExt)) {
+ const result = spawnSync("tar", [
+ "xf",
+ tempFile,
+ // The tarballs are stored with a leading directory
+ // component; we strip one component in the
+ // shell installers too.
+ "--strip-components",
+ "1",
+ "-C",
+ this.installDirectory,
+ ]);
+ if (result.status == 0) {
+ resolve();
+ } else if (result.error) {
+ reject(result.error);
+ } else {
+ reject(
+ new Error(
+ `An error occurred untarring the artifact: stdout: ${result.stdout}; stderr: ${result.stderr}`,
+ ),
+ );
+ }
+ } else if (this.zipExt == ".zip") {
+ let result;
+ if (this.platform.artifactName.includes("windows")) {
+ // Windows does not have "unzip" by default on many installations, instead
+ // we use Expand-Archive from powershell
+ result = spawnSync("powershell.exe", [
+ "-NoProfile",
+ "-NonInteractive",
+ "-Command",
+ `& {
+ param([string]$LiteralPath, [string]$DestinationPath)
+ Expand-Archive -LiteralPath $LiteralPath -DestinationPath $DestinationPath -Force
+ }`,
+ tempFile,
+ this.installDirectory,
+ ]);
+ } else {
+ result = spawnSync("unzip", [
+ "-q",
+ tempFile,
+ "-d",
+ this.installDirectory,
+ ]);
+ }
+
+ if (result.status == 0) {
+ resolve();
+ } else if (result.error) {
+ reject(result.error);
+ } else {
+ reject(
+ new Error(
+ `An error occurred unzipping the artifact: stdout: ${result.stdout}; stderr: ${result.stderr}`,
+ ),
+ );
+ }
+ } else {
+ reject(
+ new Error(`Unrecognized file extension: ${this.zipExt}`),
+ );
+ }
+ });
+ });
+ });
+ })
+ .then(() => {
+ if (!suppressLogs) {
+ console.error(`${this.name} has been installed!`);
+ }
+ })
+ .catch((e) => {
+ error(`Error fetching release: ${e.message}`);
+ });
+ }
+
+ run(binaryName, fetchOptions) {
+ const promise = !this.exists()
+ ? this.install(fetchOptions, true)
+ : Promise.resolve();
+
+ promise
+ .then(() => {
+ const [, , ...args] = process.argv;
+
+ const options = { cwd: process.cwd(), stdio: "inherit" };
+
+ const binRelPath = this.binaries[binaryName];
+ if (!binRelPath) {
+ error(`${binaryName} is not a known binary in ${this.name}`);
+ }
+ const binPath = join(this.installDirectory, binRelPath);
+ const result = spawnSync(binPath, args, options);
+
+ if (result.error) {
+ error(result.error);
+ }
+
+ process.exit(result.status);
+ })
+ .catch((e) => {
+ error(e.message);
+ process.exit(1);
+ });
+ }
+}
+
+module.exports.Package = Package;
+
+================ axolotlsay-npm-package.tar.gz/package/binary.js ================
+const { Package } = require("./binary-install");
+const os = require("os");
+const cTable = require("console.table");
+const libc = require("detect-libc");
+const { configureProxy } = require("axios-proxy-builder");
+
+const error = (msg) => {
+ console.error(msg);
+ process.exit(1);
+};
+
+const {
+ name,
+ artifactDownloadUrl,
+ supportedPlatforms,
+ glibcMinimum,
+} = require("./package.json");
+
+const builderGlibcMajorVersion = glibcMinimum.major;
+const builderGlibcMInorVersion = glibcMinimum.series;
+
+const getPlatform = () => {
+ const rawOsType = os.type();
+ const rawArchitecture = os.arch();
+
+ // We want to use rust-style target triples as the canonical key
+ // for a platform, so translate the "os" library's concepts into rust ones
+ let osType = "";
+ switch (rawOsType) {
+ case "Windows_NT":
+ osType = "pc-windows-msvc";
+ break;
+ case "Darwin":
+ osType = "apple-darwin";
+ break;
+ case "Linux":
+ osType = "unknown-linux-gnu";
+ break;
+ }
+
+ let arch = "";
+ switch (rawArchitecture) {
+ case "x64":
+ arch = "x86_64";
+ break;
+ case "arm64":
+ arch = "aarch64";
+ break;
+ }
+
+ if (rawOsType === "Linux") {
+ if (libc.familySync() == "musl") {
+ osType = "unknown-linux-musl-dynamic";
+ } else if (libc.isNonGlibcLinuxSync()) {
+ console.warn(
+ "Your libc is neither glibc nor musl; trying static musl binary instead",
+ );
+ osType = "unknown-linux-musl-static";
+ } else {
+ let libcVersion = libc.versionSync();
+ let splitLibcVersion = libcVersion.split(".");
+ let libcMajorVersion = splitLibcVersion[0];
+ let libcMinorVersion = splitLibcVersion[1];
+ if (
+ libcMajorVersion != builderGlibcMajorVersion ||
+ libcMinorVersion < builderGlibcMInorVersion
+ ) {
+ // We can't run the glibc binaries, but we can run the static musl ones
+ // if they exist
+ console.warn(
+ "Your glibc isn't compatible; trying static musl binary instead",
+ );
+ osType = "unknown-linux-musl-static";
+ }
+ }
+ }
+
+ // Assume the above succeeded and build a target triple to look things up with.
+ // If any of it failed, this lookup will fail and we'll handle it like normal.
+ let targetTriple = `${arch}-${osType}`;
+ let platform = supportedPlatforms[targetTriple];
+
+ if (!platform) {
+ error(
+ `Platform with type "${rawOsType}" and architecture "${rawArchitecture}" is not supported by ${name}.\nYour system must be one of the following:\n\n${Object.keys(
+ supportedPlatforms,
+ ).join(",")}`,
+ );
+ }
+
+ return platform;
+};
+
+const getPackage = () => {
+ const platform = getPlatform();
+ const url = `${artifactDownloadUrl}/${platform.artifactName}`;
+ let filename = platform.artifactName;
+ let ext = platform.zipExt;
+ let binary = new Package(platform, name, url, filename, ext, platform.bins);
+
+ return binary;
+};
+
+const install = (suppressLogs) => {
+ if (!artifactDownloadUrl || artifactDownloadUrl.length === 0) {
+ console.warn("in demo mode, not installing binaries");
+ return;
+ }
+ const package = getPackage();
+ const proxy = configureProxy(package.url);
+
+ return package.install(proxy, suppressLogs);
+};
+
+const run = (binaryName) => {
+ const package = getPackage();
+ const proxy = configureProxy(package.url);
+
+ package.run(binaryName, proxy);
+};
+
+module.exports = {
+ install,
+ run,
+ getPackage,
+};
+
+================ axolotlsay-npm-package.tar.gz/package/install.js ================
+#!/usr/bin/env node
+
+const { install } = require("./binary");
+install(false);
+
+================ axolotlsay-npm-package.tar.gz/package/npm-shrinkwrap.json ================
+{
+ "lockfileVersion": 3,
+ "name": "@axodotdev/axolotlsay",
+ "packages": {
+ "": {
+ "bin": {
+ "axolotlsay": "run-axolotlsay.js"
+ },
+ "dependencies": {
+ "axios": "^1.11.0",
+ "axios-proxy-builder": "^0.1.2",
+ "console.table": "^0.10.0",
+ "detect-libc": "^2.0.4",
+ "rimraf": "^6.0.1"
+ },
+ "devDependencies": {
+ "prettier": "^3.6.2"
+ },
+ "engines": {
+ "node": ">=14",
+ "npm": ">=6"
+ },
+ "hasInstallScript": true,
+ "license": "MIT OR Apache-2.0",
+ "name": "@axodotdev/axolotlsay",
+ "version": "0.2.2"
+ },
+ "node_modules/@isaacs/balanced-match": {
+ "engines": {
+ "node": "20 || >=22"
+ },
+ "integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==",
+ "license": "MIT",
+ "resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz",
+ "version": "4.0.1"
+ },
+ "node_modules/@isaacs/brace-expansion": {
+ "dependencies": {
+ "@isaacs/balanced-match": "^4.0.1"
+ },
+ "engines": {
+ "node": "20 || >=22"
+ },
+ "integrity": "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==",
+ "license": "MIT",
+ "resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.0.tgz",
+ "version": "5.0.0"
+ },
+ "node_modules/@isaacs/cliui": {
+ "dependencies": {
+ "string-width": "^5.1.2",
+ "string-width-cjs": "npm:string-width@^4.2.0",
+ "strip-ansi": "^7.0.1",
+ "strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
+ "wrap-ansi": "^8.1.0",
+ "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
+ "license": "ISC",
+ "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
+ "version": "8.0.2"
+ },
+ "node_modules/ansi-regex": {
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ },
+ "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
+ "license": "MIT",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
+ "version": "6.1.0"
+ },
+ "node_modules/ansi-styles": {
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ },
+ "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
+ "license": "MIT",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
+ "version": "6.2.1"
+ },
+ "node_modules/asynckit": {
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
+ "license": "MIT",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "version": "0.4.0"
+ },
+ "node_modules/axios": {
+ "dependencies": {
+ "follow-redirects": "^1.15.6",
+ "form-data": "^4.0.4",
+ "proxy-from-env": "^1.1.0"
+ },
+ "integrity": "sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==",
+ "license": "MIT",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.11.0.tgz",
+ "version": "1.11.0"
+ },
+ "node_modules/axios-proxy-builder": {
+ "dependencies": {
+ "tunnel": "^0.0.6"
+ },
+ "integrity": "sha512-6uBVsBZzkB3tCC8iyx59mCjQckhB8+GQrI9Cop8eC7ybIsvs/KtnNgEBfRMSEa7GqK2VBGUzgjNYMdPIfotyPA==",
+ "license": "MIT",
+ "resolved": "https://registry.npmjs.org/axios-proxy-builder/-/axios-proxy-builder-0.1.2.tgz",
+ "version": "0.1.2"
+ },
+ "node_modules/call-bind-apply-helpers": {
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
+ "license": "MIT",
+ "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
+ "version": "1.0.2"
+ },
+ "node_modules/clone": {
+ "engines": {
+ "node": ">=0.8"
+ },
+ "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==",
+ "license": "MIT",
+ "optional": true,
+ "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
+ "version": "1.0.4"
+ },
+ "node_modules/color-convert": {
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ },
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "license": "MIT",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "version": "2.0.1"
+ },
+ "node_modules/color-name": {
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "license": "MIT",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "version": "1.1.4"
+ },
+ "node_modules/combined-stream": {
+ "dependencies": {
+ "delayed-stream": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ },
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "license": "MIT",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "version": "1.0.8"
+ },
+ "node_modules/console.table": {
+ "dependencies": {
+ "easy-table": "1.1.0"
+ },
+ "engines": {
+ "node": "> 0.10"
+ },
+ "integrity": "sha512-dPyZofqggxuvSf7WXvNjuRfnsOk1YazkVP8FdxH4tcH2c37wc79/Yl6Bhr7Lsu00KMgy2ql/qCMuNu8xctZM8g==",
+ "license": "MIT",
+ "resolved": "https://registry.npmjs.org/console.table/-/console.table-0.10.0.tgz",
+ "version": "0.10.0"
+ },
+ "node_modules/cross-spawn": {
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ },
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
+ "license": "MIT",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+ "version": "7.0.6"
+ },
+ "node_modules/defaults": {
+ "dependencies": {
+ "clone": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ },
+ "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==",
+ "license": "MIT",
+ "optional": true,
+ "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz",
+ "version": "1.0.4"
+ },
+ "node_modules/delayed-stream": {
+ "engines": {
+ "node": ">=0.4.0"
+ },
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+ "license": "MIT",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "version": "1.0.0"
+ },
+ "node_modules/detect-libc": {
+ "engines": {
+ "node": ">=8"
+ },
+ "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==",
+ "license": "Apache-2.0",
+ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz",
+ "version": "2.0.4"
+ },
+ "node_modules/dunder-proto": {
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.2.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
+ "license": "MIT",
+ "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
+ "version": "1.0.1"
+ },
+ "node_modules/eastasianwidth": {
+ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
+ "license": "MIT",
+ "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
+ "version": "0.2.0"
+ },
+ "node_modules/easy-table": {
+ "integrity": "sha512-oq33hWOSSnl2Hoh00tZWaIPi1ievrD9aFG82/IgjlycAnW9hHx5PkJiXpxPsgEE+H7BsbVQXFVFST8TEXS6/pA==",
+ "license": "MIT",
+ "optionalDependencies": {
+ "wcwidth": ">=1.0.1"
+ },
+ "resolved": "https://registry.npmjs.org/easy-table/-/easy-table-1.1.0.tgz",
+ "version": "1.1.0"
+ },
+ "node_modules/emoji-regex": {
+ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
+ "license": "MIT",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
+ "version": "9.2.2"
+ },
+ "node_modules/es-define-property": {
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
+ "license": "MIT",
+ "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
+ "version": "1.0.1"
+ },
+ "node_modules/es-errors": {
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+ "license": "MIT",
+ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
+ "version": "1.3.0"
+ },
+ "node_modules/es-object-atoms": {
+ "dependencies": {
+ "es-errors": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
+ "license": "MIT",
+ "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
+ "version": "1.1.1"
+ },
+ "node_modules/es-set-tostringtag": {
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.6",
+ "has-tostringtag": "^1.0.2",
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
+ "license": "MIT",
+ "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
+ "version": "2.1.0"
+ },
+ "node_modules/follow-redirects": {
+ "engines": {
+ "node": ">=4.0"
+ },
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/RubenVerborgh"
+ }
+ ],
+ "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==",
+ "license": "MIT",
+ "peerDependenciesMeta": {
+ "debug": {
+ "optional": true
+ }
+ },
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
+ "version": "1.15.6"
+ },
+ "node_modules/foreground-child": {
+ "dependencies": {
+ "cross-spawn": "^7.0.6",
+ "signal-exit": "^4.0.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ },
+ "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==",
+ "license": "ISC",
+ "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz",
+ "version": "3.3.1"
+ },
+ "node_modules/form-data": {
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "es-set-tostringtag": "^2.1.0",
+ "hasown": "^2.0.2",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 6"
+ },
+ "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==",
+ "license": "MIT",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz",
+ "version": "4.0.4"
+ },
+ "node_modules/function-bind": {
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ },
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "license": "MIT",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+ "version": "1.1.2"
+ },
+ "node_modules/get-intrinsic": {
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.2",
+ "es-define-property": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.1.1",
+ "function-bind": "^1.1.2",
+ "get-proto": "^1.0.1",
+ "gopd": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "hasown": "^2.0.2",
+ "math-intrinsics": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ },
+ "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
+ "license": "MIT",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
+ "version": "1.3.0"
+ },
+ "node_modules/get-proto": {
+ "dependencies": {
+ "dunder-proto": "^1.0.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
+ "license": "MIT",
+ "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
+ "version": "1.0.1"
+ },
+ "node_modules/glob": {
+ "bin": {
+ "glob": "dist/esm/bin.mjs"
+ },
+ "dependencies": {
+ "foreground-child": "^3.3.1",
+ "jackspeak": "^4.1.1",
+ "minimatch": "^10.0.3",
+ "minipass": "^7.1.2",
+ "package-json-from-dist": "^1.0.0",
+ "path-scurry": "^2.0.0"
+ },
+ "engines": {
+ "node": "20 || >=22"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ },
+ "integrity": "sha512-2Nim7dha1KVkaiF4q6Dj+ngPPMdfvLJEOpZk/jKiUAkqKebpGAWQXAq9z1xu9HKu5lWfqw/FASuccEjyznjPaA==",
+ "license": "ISC",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.3.tgz",
+ "version": "11.0.3"
+ },
+ "node_modules/gopd": {
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ },
+ "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
+ "license": "MIT",
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
+ "version": "1.2.0"
+ },
+ "node_modules/has-symbols": {
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ },
+ "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
+ "license": "MIT",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
+ "version": "1.1.0"
+ },
+ "node_modules/has-tostringtag": {
+ "dependencies": {
+ "has-symbols": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ },
+ "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
+ "license": "MIT",
+ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
+ "version": "1.0.2"
+ },
+ "node_modules/hasown": {
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+ "license": "MIT",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
+ "version": "2.0.2"
+ },
+ "node_modules/is-fullwidth-code-point": {
+ "engines": {
+ "node": ">=8"
+ },
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "license": "MIT",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "version": "3.0.0"
+ },
+ "node_modules/isexe": {
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "license": "ISC",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "version": "2.0.0"
+ },
+ "node_modules/jackspeak": {
+ "dependencies": {
+ "@isaacs/cliui": "^8.0.2"
+ },
+ "engines": {
+ "node": "20 || >=22"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ },
+ "integrity": "sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==",
+ "license": "BlueOak-1.0.0",
+ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.1.1.tgz",
+ "version": "4.1.1"
+ },
+ "node_modules/lru-cache": {
+ "engines": {
+ "node": "20 || >=22"
+ },
+ "integrity": "sha512-QIXZUBJUx+2zHUdQujWejBkcD9+cs94tLn0+YL8UrCh+D5sCXZ4c7LaEH48pNwRY3MLDgqUFyhlCyjJPf1WP0A==",
+ "license": "ISC",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.1.0.tgz",
+ "version": "11.1.0"
+ },
+ "node_modules/math-intrinsics": {
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
+ "license": "MIT",
+ "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
+ "version": "1.1.0"
+ },
+ "node_modules/mime-db": {
+ "engines": {
+ "node": ">= 0.6"
+ },
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "license": "MIT",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "version": "1.52.0"
+ },
+ "node_modules/mime-types": {
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ },
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "license": "MIT",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "version": "2.1.35"
+ },
+ "node_modules/minimatch": {
+ "dependencies": {
+ "@isaacs/brace-expansion": "^5.0.0"
+ },
+ "engines": {
+ "node": "20 || >=22"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ },
+ "integrity": "sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw==",
+ "license": "ISC",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.3.tgz",
+ "version": "10.0.3"
+ },
+ "node_modules/minipass": {
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
+ "license": "ISC",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
+ "version": "7.1.2"
+ },
+ "node_modules/package-json-from-dist": {
+ "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
+ "license": "BlueOak-1.0.0",
+ "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
+ "version": "1.0.1"
+ },
+ "node_modules/path-key": {
+ "engines": {
+ "node": ">=8"
+ },
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "license": "MIT",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "version": "3.1.1"
+ },
+ "node_modules/path-scurry": {
+ "dependencies": {
+ "lru-cache": "^11.0.0",
+ "minipass": "^7.1.2"
+ },
+ "engines": {
+ "node": "20 || >=22"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ },
+ "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==",
+ "license": "BlueOak-1.0.0",
+ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz",
+ "version": "2.0.0"
+ },
+ "node_modules/prettier": {
+ "bin": {
+ "prettier": "bin/prettier.cjs"
+ },
+ "dev": true,
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/prettier/prettier?sponsor=1"
+ },
+ "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==",
+ "license": "MIT",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz",
+ "version": "3.6.2"
+ },
+ "node_modules/proxy-from-env": {
+ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
+ "license": "MIT",
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+ "version": "1.1.0"
+ },
+ "node_modules/rimraf": {
+ "bin": {
+ "rimraf": "dist/esm/bin.mjs"
+ },
+ "dependencies": {
+ "glob": "^11.0.0",
+ "package-json-from-dist": "^1.0.0"
+ },
+ "engines": {
+ "node": "20 || >=22"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ },
+ "integrity": "sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A==",
+ "license": "ISC",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.0.1.tgz",
+ "version": "6.0.1"
+ },
+ "node_modules/shebang-command": {
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "license": "MIT",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "version": "2.0.0"
+ },
+ "node_modules/shebang-regex": {
+ "engines": {
+ "node": ">=8"
+ },
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "license": "MIT",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "version": "3.0.0"
+ },
+ "node_modules/signal-exit": {
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ },
+ "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
+ "license": "ISC",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
+ "version": "4.1.0"
+ },
+ "node_modules/string-width": {
+ "dependencies": {
+ "eastasianwidth": "^0.2.0",
+ "emoji-regex": "^9.2.2",
+ "strip-ansi": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ },
+ "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
+ "license": "MIT",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
+ "version": "5.1.2"
+ },
+ "node_modules/string-width-cjs": {
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "license": "MIT",
+ "name": "string-width",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "version": "4.2.3"
+ },
+ "node_modules/string-width-cjs/node_modules/ansi-regex": {
+ "engines": {
+ "node": ">=8"
+ },
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "license": "MIT",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "version": "5.0.1"
+ },
+ "node_modules/string-width-cjs/node_modules/emoji-regex": {
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "license": "MIT",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "version": "8.0.0"
+ },
+ "node_modules/string-width-cjs/node_modules/strip-ansi": {
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "license": "MIT",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "version": "6.0.1"
+ },
+ "node_modules/strip-ansi": {
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ },
+ "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+ "license": "MIT",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+ "version": "7.1.0"
+ },
+ "node_modules/strip-ansi-cjs": {
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "license": "MIT",
+ "name": "strip-ansi",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "version": "6.0.1"
+ },
+ "node_modules/strip-ansi-cjs/node_modules/ansi-regex": {
+ "engines": {
+ "node": ">=8"
+ },
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "license": "MIT",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "version": "5.0.1"
+ },
+ "node_modules/tunnel": {
+ "engines": {
+ "node": ">=0.6.11 <=0.7.0 || >=0.7.3"
+ },
+ "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==",
+ "license": "MIT",
+ "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
+ "version": "0.0.6"
+ },
+ "node_modules/wcwidth": {
+ "dependencies": {
+ "defaults": "^1.0.3"
+ },
+ "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==",
+ "license": "MIT",
+ "optional": true,
+ "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz",
+ "version": "1.0.1"
+ },
+ "node_modules/which": {
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ },
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "license": "ISC",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "version": "2.0.2"
+ },
+ "node_modules/wrap-ansi": {
+ "dependencies": {
+ "ansi-styles": "^6.1.0",
+ "string-width": "^5.0.1",
+ "strip-ansi": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ },
+ "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
+ "license": "MIT",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
+ "version": "8.1.0"
+ },
+ "node_modules/wrap-ansi-cjs": {
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ },
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "license": "MIT",
+ "name": "wrap-ansi",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "version": "7.0.0"
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": {
+ "engines": {
+ "node": ">=8"
+ },
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "license": "MIT",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "version": "5.0.1"
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": {
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ },
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "license": "MIT",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "version": "4.3.0"
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": {
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "license": "MIT",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "version": "8.0.0"
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/string-width": {
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "license": "MIT",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "version": "4.2.3"
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": {
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "license": "MIT",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "version": "6.0.1"
+ }
+ },
+ "requires": true,
+ "version": "0.2.2"
+}
+================ axolotlsay-npm-package.tar.gz/package/package.json ================
+{
+ "artifactDownloadUrl": "https://github.com/axodotdev/axolotlsay/releases/download/v0.2.2",
+ "author": "axodotdev ",
+ "bin": {
+ "axolotlsay": "run-axolotlsay.js"
+ },
+ "dependencies": {
+ "axios": "^1.11.0",
+ "axios-proxy-builder": "^0.1.2",
+ "console.table": "^0.10.0",
+ "detect-libc": "^2.0.4",
+ "rimraf": "^6.0.1"
+ },
+ "description": "š¬ a CLI for learning to distribute CLIs in rust",
+ "devDependencies": {
+ "prettier": "^3.6.2"
+ },
+ "engines": {
+ "node": ">=14",
+ "npm": ">=6"
+ },
+ "glibcMinimum": {
+ "major": 2,
+ "series": 31
+ },
+ "homepage": "https://github.com/axodotdev/axolotlsay",
+ "license": "MIT OR Apache-2.0",
+ "name": "@axodotdev/axolotlsay",
+ "preferUnplugged": true,
+ "repository": "https://github.com/axodotdev/axolotlsay.git",
+ "scripts": {
+ "fmt": "prettier --write **/*.js",
+ "fmt:check": "prettier --check **/*.js",
+ "postinstall": "node ./install.js"
+ },
+ "supportedPlatforms": {
+ "aarch64-apple-darwin": {
+ "artifactName": "axolotlsay-aarch64-apple-darwin.tar.gz",
+ "bins": {
+ "axolotlsay": "axolotlsay"
+ },
+ "zipExt": ".tar.gz"
+ },
+ "aarch64-pc-windows-msvc": {
+ "artifactName": "axolotlsay-x86_64-pc-windows-msvc.tar.gz",
+ "bins": {
+ "axolotlsay": "axolotlsay.exe"
+ },
+ "zipExt": ".tar.gz"
+ },
+ "x86_64-apple-darwin": {
+ "artifactName": "axolotlsay-x86_64-apple-darwin.tar.gz",
+ "bins": {
+ "axolotlsay": "axolotlsay"
+ },
+ "zipExt": ".tar.gz"
+ },
+ "x86_64-pc-windows-gnu": {
+ "artifactName": "axolotlsay-x86_64-pc-windows-msvc.tar.gz",
+ "bins": {
+ "axolotlsay": "axolotlsay.exe"
+ },
+ "zipExt": ".tar.gz"
+ },
+ "x86_64-pc-windows-msvc": {
+ "artifactName": "axolotlsay-x86_64-pc-windows-msvc.tar.gz",
+ "bins": {
+ "axolotlsay": "axolotlsay.exe"
+ },
+ "zipExt": ".tar.gz"
+ },
+ "x86_64-unknown-linux-gnu": {
+ "artifactName": "axolotlsay-x86_64-unknown-linux-gnu.tar.gz",
+ "bins": {
+ "axolotlsay": "axolotlsay"
+ },
+ "zipExt": ".tar.gz"
+ }
+ },
+ "version": "0.2.2",
+ "volta": {
+ "node": "18.14.1",
+ "npm": "9.5.0"
+ }
+}
+================ axolotlsay-npm-package.tar.gz/package/run-axolotlsay.js ================
+#!/usr/bin/env node
+
+const { run } = require("./binary");
+run("axolotlsay");
+
+================ sha256.sum ================
+CENSORED (see https://github.com/axodotdev/cargo-dist/issues/1477) axolotlsay-npm-package.tar.gz
+CENSORED (see https://github.com/axodotdev/cargo-dist/issues/1477) source.tar.gz
+
+
+================ dist-manifest.json ================
+{
+ "dist_version": "CENSORED",
+ "announcement_tag": "v0.2.2",
+ "announcement_tag_is_implicit": true,
+ "announcement_is_prerelease": false,
+ "announcement_title": "Version 0.2.2",
+ "announcement_changelog": "```text\n +----------------------------------+\n | now with arm64 linux binaries!!! |\n +----------------------------------+\n /\nā½(ā į“ ā)ā¼\n```",
+ "announcement_github_body": "## Release Notes\n\n```text\n +----------------------------------+\n | now with arm64 linux binaries!!! |\n +----------------------------------+\n /\nā½(ā į“ ā)ā¼\n```\n\n## Install axolotlsay 0.2.2\n\n### Install prebuilt binaries via shell script\n\n```sh\ncurl --proto '=https' --tlsv1.2 -LsSf https://github.com/axodotdev/axolotlsay/releases/download/v0.2.2/axolotlsay-installer.sh | sh\n```\n\n### Install prebuilt binaries via powershell script\n\n```sh\npowershell -ExecutionPolicy Bypass -c \"irm https://github.com/axodotdev/axolotlsay/releases/download/v0.2.2/axolotlsay-installer.ps1 | iex\"\n```\n\n### Install prebuilt binaries via Homebrew\n\n```sh\nbrew install axodotdev/packages/axolotlsay\n```\n\n### Install prebuilt binaries into your npm project\n\n```sh\nnpm install @axodotdev/axolotlsay@0.2.2\n```\n\n## Download axolotlsay 0.2.2\n\n| File | Platform | Checksum |\n|--------|----------|----------|\n| [axolotlsay-aarch64-apple-darwin.tar.gz](https://github.com/axodotdev/axolotlsay/releases/download/v0.2.2/axolotlsay-aarch64-apple-darwin.tar.gz) | Apple Silicon macOS | [checksum](https://github.com/axodotdev/axolotlsay/releases/download/v0.2.2/axolotlsay-aarch64-apple-darwin.tar.gz.sha256) |\n| [axolotlsay-aarch64-apple-darwin.pkg](https://github.com/axodotdev/axolotlsay/releases/download/v0.2.2/axolotlsay-aarch64-apple-darwin.pkg) | Apple Silicon macOS | [checksum](https://github.com/axodotdev/axolotlsay/releases/download/v0.2.2/axolotlsay-aarch64-apple-darwin.pkg.sha256) |\n| [axolotlsay-x86_64-apple-darwin.tar.gz](https://github.com/axodotdev/axolotlsay/releases/download/v0.2.2/axolotlsay-x86_64-apple-darwin.tar.gz) | Intel macOS | [checksum](https://github.com/axodotdev/axolotlsay/releases/download/v0.2.2/axolotlsay-x86_64-apple-darwin.tar.gz.sha256) |\n| [axolotlsay-x86_64-apple-darwin.pkg](https://github.com/axodotdev/axolotlsay/releases/download/v0.2.2/axolotlsay-x86_64-apple-darwin.pkg) | Intel macOS | [checksum](https://github.com/axodotdev/axolotlsay/releases/download/v0.2.2/axolotlsay-x86_64-apple-darwin.pkg.sha256) |\n| [axolotlsay-x86_64-pc-windows-msvc.tar.gz](https://github.com/axodotdev/axolotlsay/releases/download/v0.2.2/axolotlsay-x86_64-pc-windows-msvc.tar.gz) | x64 Windows | [checksum](https://github.com/axodotdev/axolotlsay/releases/download/v0.2.2/axolotlsay-x86_64-pc-windows-msvc.tar.gz.sha256) |\n| [axolotlsay-x86_64-pc-windows-msvc.msi](https://github.com/axodotdev/axolotlsay/releases/download/v0.2.2/axolotlsay-x86_64-pc-windows-msvc.msi) | x64 Windows | [checksum](https://github.com/axodotdev/axolotlsay/releases/download/v0.2.2/axolotlsay-x86_64-pc-windows-msvc.msi.sha256) |\n| [axolotlsay-x86_64-unknown-linux-gnu.tar.gz](https://github.com/axodotdev/axolotlsay/releases/download/v0.2.2/axolotlsay-x86_64-unknown-linux-gnu.tar.gz) | x64 Linux | [checksum](https://github.com/axodotdev/axolotlsay/releases/download/v0.2.2/axolotlsay-x86_64-unknown-linux-gnu.tar.gz.sha256) |\n\n",
+ "releases": [
+ {
+ "app_name": "axolotlsay",
+ "app_version": "0.2.2",
+ "env": {
+ "install_dir_env_var": "AXOLOTLSAY_INSTALL_DIR",
+ "unmanaged_dir_env_var": "AXOLOTLSAY_UNMANAGED_INSTALL",
+ "disable_update_env_var": "AXOLOTLSAY_DISABLE_UPDATE",
+ "no_modify_path_env_var": "AXOLOTLSAY_NO_MODIFY_PATH",
+ "print_quiet_env_var": "AXOLOTLSAY_PRINT_QUIET",
+ "print_verbose_env_var": "AXOLOTLSAY_PRINT_VERBOSE",
+ "download_url_env_var": "AXOLOTLSAY_DOWNLOAD_URL",
+ "github_base_url_env_var": "AXOLOTLSAY_INSTALLER_GITHUB_BASE_URL",
+ "ghe_base_url_env_var": "AXOLOTLSAY_INSTALLER_GHE_BASE_URL",
+ "github_token_env_var": "AXOLOTLSAY_GITHUB_TOKEN"
+ },
+ "display_name": "axolotlsay",
+ "display": true,
+ "artifacts": [
+ "source.tar.gz",
+ "source.tar.gz.sha256",
+ "axolotlsay-installer.sh",
+ "axolotlsay-installer.ps1",
+ "axolotlsay.rb",
+ "axolotlsay-npm-package.tar.gz",
+ "sha256.sum",
+ "axolotlsay-aarch64-apple-darwin.tar.gz",
+ "axolotlsay-aarch64-apple-darwin.tar.gz.sha256",
+ "axolotlsay-aarch64-apple-darwin.pkg",
+ "axolotlsay-aarch64-apple-darwin.pkg.sha256",
+ "axolotlsay-x86_64-apple-darwin.tar.gz",
+ "axolotlsay-x86_64-apple-darwin.tar.gz.sha256",
+ "axolotlsay-x86_64-apple-darwin.pkg",
+ "axolotlsay-x86_64-apple-darwin.pkg.sha256",
+ "axolotlsay-x86_64-pc-windows-msvc.tar.gz",
+ "axolotlsay-x86_64-pc-windows-msvc.tar.gz.sha256",
+ "axolotlsay-x86_64-pc-windows-msvc.msi",
+ "axolotlsay-x86_64-pc-windows-msvc.msi.sha256",
+ "axolotlsay-x86_64-unknown-linux-gnu.tar.gz",
+ "axolotlsay-x86_64-unknown-linux-gnu.tar.gz.sha256"
+ ],
+ "hosting": {
+ "github": {
+ "artifact_base_url": "https://github.com",
+ "artifact_download_path": "/axodotdev/axolotlsay/releases/download/v0.2.2",
+ "owner": "axodotdev",
+ "repo": "axolotlsay"
+ }
+ }
+ }
+ ],
+ "artifacts": {
+ "axolotlsay-aarch64-apple-darwin.pkg": {
+ "name": "axolotlsay-aarch64-apple-darwin.pkg",
+ "kind": "installer",
+ "target_triples": [
+ "aarch64-apple-darwin"
+ ],
+ "assets": [
+ {
+ "id": "axolotlsay-aarch64-apple-darwin-exe-axolotlsay",
+ "name": "axolotlsay",
+ "path": "axolotlsay",
+ "kind": "executable"
+ }
+ ],
+ "description": "install via pkg",
+ "checksum": "axolotlsay-aarch64-apple-darwin.pkg.sha256"
+ },
+ "axolotlsay-aarch64-apple-darwin.pkg.sha256": {
+ "name": "axolotlsay-aarch64-apple-darwin.pkg.sha256",
+ "kind": "checksum",
+ "target_triples": [
+ "aarch64-apple-darwin"
+ ]
+ },
+ "axolotlsay-aarch64-apple-darwin.tar.gz": {
+ "name": "axolotlsay-aarch64-apple-darwin.tar.gz",
+ "kind": "executable-zip",
+ "target_triples": [
+ "aarch64-apple-darwin"
+ ],
+ "assets": [
+ {
+ "name": "CHANGELOG.md",
+ "path": "CHANGELOG.md",
+ "kind": "changelog"
+ },
+ {
+ "name": "LICENSE-APACHE",
+ "path": "LICENSE-APACHE",
+ "kind": "license"
+ },
+ {
+ "name": "LICENSE-MIT",
+ "path": "LICENSE-MIT",
+ "kind": "license"
+ },
+ {
+ "name": "README.md",
+ "path": "README.md",
+ "kind": "readme"
+ },
+ {
+ "id": "axolotlsay-aarch64-apple-darwin-exe-axolotlsay",
+ "name": "axolotlsay",
+ "path": "axolotlsay",
+ "kind": "executable"
+ }
+ ],
+ "checksum": "axolotlsay-aarch64-apple-darwin.tar.gz.sha256"
+ },
+ "axolotlsay-aarch64-apple-darwin.tar.gz.sha256": {
+ "name": "axolotlsay-aarch64-apple-darwin.tar.gz.sha256",
+ "kind": "checksum",
+ "target_triples": [
+ "aarch64-apple-darwin"
+ ]
+ },
+ "axolotlsay-installer.ps1": {
+ "name": "axolotlsay-installer.ps1",
+ "kind": "installer",
+ "target_triples": [
+ "aarch64-pc-windows-msvc",
+ "x86_64-pc-windows-gnu",
+ "x86_64-pc-windows-msvc"
+ ],
+ "install_hint": "powershell -ExecutionPolicy Bypass -c \"irm https://github.com/axodotdev/axolotlsay/releases/download/v0.2.2/axolotlsay-installer.ps1 | iex\"",
+ "description": "Install prebuilt binaries via powershell script"
+ },
+ "axolotlsay-installer.sh": {
+ "name": "axolotlsay-installer.sh",
+ "kind": "installer",
+ "target_triples": [
+ "aarch64-apple-darwin",
+ "x86_64-apple-darwin",
+ "x86_64-pc-windows-gnu",
+ "x86_64-unknown-linux-gnu"
+ ],
+ "install_hint": "curl --proto '=https' --tlsv1.2 -LsSf https://github.com/axodotdev/axolotlsay/releases/download/v0.2.2/axolotlsay-installer.sh | sh",
+ "description": "Install prebuilt binaries via shell script"
+ },
+ "axolotlsay-npm-package.tar.gz": {
+ "name": "axolotlsay-npm-package.tar.gz",
+ "kind": "installer",
+ "target_triples": [
+ "aarch64-apple-darwin",
+ "aarch64-pc-windows-msvc",
+ "x86_64-apple-darwin",
+ "x86_64-pc-windows-gnu",
+ "x86_64-pc-windows-msvc",
+ "x86_64-unknown-linux-gnu"
+ ],
+ "assets": [
+ {
+ "name": ".gitignore",
+ "path": ".gitignore",
+ "kind": "unknown"
+ },
+ {
+ "name": "CHANGELOG.md",
+ "path": "CHANGELOG.md",
+ "kind": "changelog"
+ },
+ {
+ "name": "LICENSE-APACHE",
+ "path": "LICENSE-APACHE",
+ "kind": "license"
+ },
+ {
+ "name": "LICENSE-MIT",
+ "path": "LICENSE-MIT",
+ "kind": "license"
+ },
+ {
+ "name": "README.md",
+ "path": "README.md",
+ "kind": "readme"
+ },
+ {
+ "name": "binary-install.js",
+ "path": "binary-install.js",
+ "kind": "unknown"
+ },
+ {
+ "name": "binary.js",
+ "path": "binary.js",
+ "kind": "unknown"
+ },
+ {
+ "name": "install.js",
+ "path": "install.js",
+ "kind": "unknown"
+ },
+ {
+ "name": "npm-shrinkwrap.json",
+ "path": "npm-shrinkwrap.json",
+ "kind": "unknown"
+ },
+ {
+ "name": "package.json",
+ "path": "package.json",
+ "kind": "unknown"
+ },
+ {
+ "name": "run.js",
+ "path": "run.js",
+ "kind": "unknown"
+ }
+ ],
+ "install_hint": "npm install @axodotdev/axolotlsay@0.2.2",
+ "description": "Install prebuilt binaries into your npm project"
+ },
+ "axolotlsay-x86_64-apple-darwin.pkg": {
+ "name": "axolotlsay-x86_64-apple-darwin.pkg",
+ "kind": "installer",
+ "target_triples": [
+ "x86_64-apple-darwin"
+ ],
+ "assets": [
+ {
+ "id": "axolotlsay-x86_64-apple-darwin-exe-axolotlsay",
+ "name": "axolotlsay",
+ "path": "axolotlsay",
+ "kind": "executable"
+ }
+ ],
+ "description": "install via pkg",
+ "checksum": "axolotlsay-x86_64-apple-darwin.pkg.sha256"
+ },
+ "axolotlsay-x86_64-apple-darwin.pkg.sha256": {
+ "name": "axolotlsay-x86_64-apple-darwin.pkg.sha256",
+ "kind": "checksum",
+ "target_triples": [
+ "x86_64-apple-darwin"
+ ]
+ },
+ "axolotlsay-x86_64-apple-darwin.tar.gz": {
+ "name": "axolotlsay-x86_64-apple-darwin.tar.gz",
+ "kind": "executable-zip",
+ "target_triples": [
+ "x86_64-apple-darwin"
+ ],
+ "assets": [
+ {
+ "name": "CHANGELOG.md",
+ "path": "CHANGELOG.md",
+ "kind": "changelog"
+ },
+ {
+ "name": "LICENSE-APACHE",
+ "path": "LICENSE-APACHE",
+ "kind": "license"
+ },
+ {
+ "name": "LICENSE-MIT",
+ "path": "LICENSE-MIT",
+ "kind": "license"
+ },
+ {
+ "name": "README.md",
+ "path": "README.md",
+ "kind": "readme"
+ },
+ {
+ "id": "axolotlsay-x86_64-apple-darwin-exe-axolotlsay",
+ "name": "axolotlsay",
+ "path": "axolotlsay",
+ "kind": "executable"
+ }
+ ],
+ "checksum": "axolotlsay-x86_64-apple-darwin.tar.gz.sha256"
+ },
+ "axolotlsay-x86_64-apple-darwin.tar.gz.sha256": {
+ "name": "axolotlsay-x86_64-apple-darwin.tar.gz.sha256",
+ "kind": "checksum",
+ "target_triples": [
+ "x86_64-apple-darwin"
+ ]
+ },
+ "axolotlsay-x86_64-pc-windows-msvc.msi": {
+ "name": "axolotlsay-x86_64-pc-windows-msvc.msi",
+ "kind": "installer",
+ "target_triples": [
+ "x86_64-pc-windows-msvc"
+ ],
+ "assets": [
+ {
+ "id": "axolotlsay-x86_64-pc-windows-msvc-exe-axolotlsay",
+ "name": "axolotlsay",
+ "path": "axolotlsay.exe",
+ "kind": "executable"
+ }
+ ],
+ "description": "install via msi",
+ "checksum": "axolotlsay-x86_64-pc-windows-msvc.msi.sha256"
+ },
+ "axolotlsay-x86_64-pc-windows-msvc.msi.sha256": {
+ "name": "axolotlsay-x86_64-pc-windows-msvc.msi.sha256",
+ "kind": "checksum",
+ "target_triples": [
+ "x86_64-pc-windows-msvc"
+ ]
+ },
+ "axolotlsay-x86_64-pc-windows-msvc.tar.gz": {
+ "name": "axolotlsay-x86_64-pc-windows-msvc.tar.gz",
+ "kind": "executable-zip",
+ "target_triples": [
+ "x86_64-pc-windows-msvc"
+ ],
+ "assets": [
+ {
+ "name": "CHANGELOG.md",
+ "path": "CHANGELOG.md",
+ "kind": "changelog"
+ },
+ {
+ "name": "LICENSE-APACHE",
+ "path": "LICENSE-APACHE",
+ "kind": "license"
+ },
+ {
+ "name": "LICENSE-MIT",
+ "path": "LICENSE-MIT",
+ "kind": "license"
+ },
+ {
+ "name": "README.md",
+ "path": "README.md",
+ "kind": "readme"
+ },
+ {
+ "id": "axolotlsay-x86_64-pc-windows-msvc-exe-axolotlsay",
+ "name": "axolotlsay",
+ "path": "axolotlsay.exe",
+ "kind": "executable"
+ }
+ ],
+ "checksum": "axolotlsay-x86_64-pc-windows-msvc.tar.gz.sha256"
+ },
+ "axolotlsay-x86_64-pc-windows-msvc.tar.gz.sha256": {
+ "name": "axolotlsay-x86_64-pc-windows-msvc.tar.gz.sha256",
+ "kind": "checksum",
+ "target_triples": [
+ "x86_64-pc-windows-msvc"
+ ]
+ },
+ "axolotlsay-x86_64-unknown-linux-gnu.tar.gz": {
+ "name": "axolotlsay-x86_64-unknown-linux-gnu.tar.gz",
+ "kind": "executable-zip",
+ "target_triples": [
+ "x86_64-unknown-linux-gnu"
+ ],
+ "assets": [
+ {
+ "name": "CHANGELOG.md",
+ "path": "CHANGELOG.md",
+ "kind": "changelog"
+ },
+ {
+ "name": "LICENSE-APACHE",
+ "path": "LICENSE-APACHE",
+ "kind": "license"
+ },
+ {
+ "name": "LICENSE-MIT",
+ "path": "LICENSE-MIT",
+ "kind": "license"
+ },
+ {
+ "name": "README.md",
+ "path": "README.md",
+ "kind": "readme"
+ },
+ {
+ "id": "axolotlsay-x86_64-unknown-linux-gnu-exe-axolotlsay",
+ "name": "axolotlsay",
+ "path": "axolotlsay",
+ "kind": "executable"
+ }
+ ],
+ "checksum": "axolotlsay-x86_64-unknown-linux-gnu.tar.gz.sha256"
+ },
+ "axolotlsay-x86_64-unknown-linux-gnu.tar.gz.sha256": {
+ "name": "axolotlsay-x86_64-unknown-linux-gnu.tar.gz.sha256",
+ "kind": "checksum",
+ "target_triples": [
+ "x86_64-unknown-linux-gnu"
+ ]
+ },
+ "axolotlsay.rb": {
+ "name": "axolotlsay.rb",
+ "kind": "installer",
+ "target_triples": [
+ "aarch64-apple-darwin",
+ "x86_64-apple-darwin",
+ "x86_64-pc-windows-gnu",
+ "x86_64-unknown-linux-gnu"
+ ],
+ "install_hint": "brew install axodotdev/packages/axolotlsay",
+ "description": "Install prebuilt binaries via Homebrew"
+ },
+ "sha256.sum": {
+ "name": "sha256.sum",
+ "kind": "unified-checksum"
+ },
+ "source.tar.gz": {
+ "name": "source.tar.gz",
+ "kind": "source-tarball",
+ "checksum": "source.tar.gz.sha256"
+ },
+ "source.tar.gz.sha256": {
+ "name": "source.tar.gz.sha256",
+ "kind": "checksum"
+ }
+ },
+ "systems": {
+ "plan:all:": {
+ "id": "plan:all:",
+ "cargo_version_line": "CENSORED"
+ "build_environment": "indeterminate"
+ }
+ },
+ "publish_prereleases": false,
+ "force_latest": false,
+ "ci": {
+ "github": {
+ "artifacts_matrix": {
+ "include": [
+ {
+ "runner": "macos-13",
+ "host": "x86_64-apple-darwin",
+ "install_dist": {
+ "shell": "sh",
+ "run": "curl --proto '=https' --tlsv1.2 -LsSf https://github.com/axodotdev/cargo-dist/releases/download/vSOME_VERSION/cargo-dist-installer.sh | sh"
+ },
+ "dist_args": "--artifacts=local --target=aarch64-apple-darwin",
+ "targets": [
+ "aarch64-apple-darwin"
+ ],
+ "cache_provider": "github"
+ },
+ {
+ "runner": "macos-13",
+ "host": "x86_64-apple-darwin",
+ "install_dist": {
+ "shell": "sh",
+ "run": "curl --proto '=https' --tlsv1.2 -LsSf https://github.com/axodotdev/cargo-dist/releases/download/vSOME_VERSION/cargo-dist-installer.sh | sh"
+ },
+ "dist_args": "--artifacts=local --target=x86_64-apple-darwin",
+ "targets": [
+ "x86_64-apple-darwin"
+ ],
+ "cache_provider": "github"
+ },
+ {
+ "runner": "windows-2022",
+ "host": "x86_64-pc-windows-msvc",
+ "install_dist": {
+ "shell": "pwsh",
+ "run": "irm https://github.com/axodotdev/cargo-dist/releases/download/vSOME_VERSION/cargo-dist-installer.ps1 | iex"
+ },
+ "dist_args": "--artifacts=local --target=x86_64-pc-windows-msvc",
+ "targets": [
+ "x86_64-pc-windows-msvc"
+ ],
+ "cache_provider": "github"
+ },
+ {
+ "runner": "ubuntu-22.04",
+ "host": "x86_64-unknown-linux-gnu",
+ "install_dist": {
+ "shell": "sh",
+ "run": "curl --proto '=https' --tlsv1.2 -LsSf https://github.com/axodotdev/cargo-dist/releases/download/vSOME_VERSION/cargo-dist-installer.sh | sh"
+ },
+ "dist_args": "--artifacts=local --target=x86_64-unknown-linux-gnu",
+ "targets": [
+ "x86_64-unknown-linux-gnu"
+ ],
+ "cache_provider": "github"
+ }
+ ]
+ },
+ "pr_run_mode": "plan"
+ }
+ },
+ "linkage": [],
+ "upload_files": []
+}
+
+================ release.yml ================
+# This file was autogenerated by dist: https://axodotdev.github.io/cargo-dist
+#
+# Copyright 2022-2024, axodotdev
+# SPDX-License-Identifier: MIT or Apache-2.0
+#
+# CI that:
+#
+# * checks for a Git Tag that looks like a release
+# * builds artifacts with dist (archives, installers, hashes)
+# * uploads those artifacts to temporary workflow zip
+# * on success, uploads the artifacts to a GitHub Release
+#
+# Note that the GitHub Release will be created with a generated
+# title/body based on your changelogs.
+
+name: Release
+permissions:
+ "contents": "write"
+
+# This task will run whenever you push a git tag that looks like a version
+# like "1.0.0", "v0.1.0-prerelease.1", "my-app/0.1.0", "releases/v1.0.0", etc.
+# Various formats will be parsed into a VERSION and an optional PACKAGE_NAME, where
+# PACKAGE_NAME must be the name of a Cargo package in your workspace, and VERSION
+# must be a Cargo-style SemVer Version (must have at least major.minor.patch).
+#
+# If PACKAGE_NAME is specified, then the announcement will be for that
+# package (erroring out if it doesn't have the given version or isn't dist-able).
+#
+# If PACKAGE_NAME isn't specified, then the announcement will be for all
+# (dist-able) packages in the workspace with that version (this mode is
+# intended for workspaces with only one dist-able package, or with all dist-able
+# packages versioned/released in lockstep).
+#
+# If you push multiple tags at once, separate instances of this workflow will
+# spin up, creating an independent announcement for each one. However, GitHub
+# will hard limit this to 3 tags per commit, as it will assume more tags is a
+# mistake.
+#
+# If there's a prerelease-style suffix to the version, then the release(s)
+# will be marked as a prerelease.
+on:
+ pull_request:
+ push:
+ tags:
+ - '**[0-9]+.[0-9]+.[0-9]+*'
+
+jobs:
+ # Run 'dist plan' (or host) to determine what tasks we need to do
+ plan:
+ runs-on: "ubuntu-22.04"
+ outputs:
+ val: ${{ steps.plan.outputs.manifest }}
+ tag: ${{ !github.event.pull_request && github.ref_name || '' }}
+ tag-flag: ${{ !github.event.pull_request && format('--tag={0}', github.ref_name) || '' }}
+ publishing: ${{ !github.event.pull_request }}
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ persist-credentials: false
+ submodules: recursive
+ - name: Install dist
+ # we specify bash to get pipefail; it guards against the `curl` command
+ # failing. otherwise `sh` won't catch that `curl` returned non-0
+ shell: bash
+ run: "curl --proto '=https' --tlsv1.2 -LsSf https://github.com/axodotdev/cargo-dist/releases/download/vSOME_VERSION/cargo-dist-installer.sh | sh"
+ - name: Cache dist
+ uses: actions/upload-artifact@v4
+ with:
+ name: cargo-dist-cache
+ path: ~/.cargo/bin/dist
+ - name: "Some build step"
+ uses: "some-action-user/some-action"
+ with:
+ "input1": "input1"
+ "input2": "input2"
+ - name: "Some Other build step"
+ uses: "some-action-user/some-other-action"
+ env:
+ "ENV_VAR": "${{ github.head_ref }}"
+ - name: "Some Run Step simple"
+ if: false
+ run: "echo \"hello world!\""
+ - name: "Some Run Step Multi"
+ run: |
+ HW="hello world"
+ echo $HW
+ shell: "bash"
+ # sure would be cool if github gave us proper conditionals...
+ # so here's a doubly-nested ternary-via-truthiness to try to provide the best possible
+ # functionality based on whether this is a pull_request, and whether it's from a fork.
+ # (PRs run on the *source* but secrets are usually on the *target* -- that's *good*
+ # but also really annoying to build CI around when it needs secrets to work right.)
+ - id: plan
+ run: |
+ dist ${{ (!github.event.pull_request && format('host --steps=create --tag={0}', github.ref_name)) || 'plan' }} --output-format=json > plan-dist-manifest.json
+ echo "dist ran successfully"
+ cat plan-dist-manifest.json
+ echo "manifest=$(jq -c "." plan-dist-manifest.json)" >> "$GITHUB_OUTPUT"
+ - name: "Upload dist-manifest.json"
+ uses: actions/upload-artifact@v4
+ with:
+ name: artifacts-plan-dist-manifest
+ path: plan-dist-manifest.json
+
+ # Build and packages all the platform-specific things
+ build-local-artifacts:
+ name: build-local-artifacts (${{ join(matrix.targets, ', ') }})
+ # Let the initial task tell us to not run (currently very blunt)
+ needs:
+ - plan
+ if: ${{ fromJson(needs.plan.outputs.val).ci.github.artifacts_matrix.include != null && (needs.plan.outputs.publishing == 'true' || fromJson(needs.plan.outputs.val).ci.github.pr_run_mode == 'upload') }}
+ strategy:
+ fail-fast: false
+ # Target platforms/runners are computed by dist in create-release.
+ # Each member of the matrix has the following arguments:
+ #
+ # - runner: the github runner
+ # - dist-args: cli flags to pass to dist
+ # - install-dist: expression to run to install dist on the runner
+ #
+ # Typically there will be:
+ # - 1 "global" task that builds universal installers
+ # - N "local" tasks that build each platform's binaries and platform-specific installers
+ matrix: ${{ fromJson(needs.plan.outputs.val).ci.github.artifacts_matrix }}
+ runs-on: ${{ matrix.runner }}
+ container: ${{ matrix.container && matrix.container.image || null }}
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ BUILD_MANIFEST_NAME: target/distrib/${{ join(matrix.targets, '-') }}-dist-manifest.json
+ steps:
+ - name: enable windows longpaths
+ run: |
+ git config --global core.longpaths true
+ - uses: actions/checkout@v4
+ with:
+ persist-credentials: false
+ submodules: recursive
+ - name: Install Rust non-interactively if not already installed
+ if: ${{ matrix.container }}
+ run: |
+ if ! command -v cargo > /dev/null 2>&1; then
+ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
+ echo "$HOME/.cargo/bin" >> $GITHUB_PATH
+ fi
+ - name: "Some build step"
+ uses: "some-action-user/some-action"
+ with:
+ "input1": "input1"
+ "input2": "input2"
+ - name: "Some Other build step"
+ uses: "some-action-user/some-other-action"
+ env:
+ "ENV_VAR": "${{ github.head_ref }}"
+ - name: "Some Run Step simple"
+ if: false
+ run: "echo \"hello world!\""
+ - name: "Some Run Step Multi"
+ run: |
+ HW="hello world"
+ echo $HW
+ shell: "bash"
+ - name: Install dist
+ run: ${{ matrix.install_dist.run }}
+ # Get the dist-manifest
+ - name: Fetch local artifacts
+ uses: actions/download-artifact@v4
+ with:
+ pattern: artifacts-*
+ path: target/distrib/
+ merge-multiple: true
+ - name: Install dependencies
+ run: |
+ ${{ matrix.packages_install }}
+ - name: Build artifacts
+ run: |
+ # Actually do builds and make zips and whatnot
+ dist build ${{ needs.plan.outputs.tag-flag }} --print=linkage --output-format=json ${{ matrix.dist_args }} > dist-manifest.json
+ echo "dist ran successfully"
+ - id: cargo-dist
+ name: Post-build
+ # We force bash here just because github makes it really hard to get values up
+ # to "real" actions without writing to env-vars, and writing to env-vars has
+ # inconsistent syntax between shell and powershell.
+ shell: bash
+ run: |
+ # Parse out what we just built and upload it to scratch storage
+ echo "paths<> "$GITHUB_OUTPUT"
+ dist print-upload-files-from-manifest --manifest dist-manifest.json >> "$GITHUB_OUTPUT"
+ echo "EOF" >> "$GITHUB_OUTPUT"
+
+ cp dist-manifest.json "$BUILD_MANIFEST_NAME"
+ - name: "Upload artifacts"
+ uses: actions/upload-artifact@v4
+ with:
+ name: artifacts-build-local-${{ join(matrix.targets, '_') }}
+ path: |
+ ${{ steps.cargo-dist.outputs.paths }}
+ ${{ env.BUILD_MANIFEST_NAME }}
+
+ # Build and package all the platform-agnostic(ish) things
+ build-global-artifacts:
+ needs:
+ - plan
+ - build-local-artifacts
+ runs-on: "ubuntu-22.04"
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ BUILD_MANIFEST_NAME: target/distrib/global-dist-manifest.json
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ persist-credentials: false
+ submodules: recursive
+ - name: Install cached dist
+ uses: actions/download-artifact@v4
+ with:
+ name: cargo-dist-cache
+ path: ~/.cargo/bin/
+ - run: chmod +x ~/.cargo/bin/dist
+ # Get all the local artifacts for the global tasks to use (for e.g. checksums)
+ - name: Fetch local artifacts
+ uses: actions/download-artifact@v4
+ with:
+ pattern: artifacts-*
+ path: target/distrib/
+ merge-multiple: true
+ - id: cargo-dist
+ shell: bash
+ run: |
+ dist build ${{ needs.plan.outputs.tag-flag }} --output-format=json "--artifacts=global" > dist-manifest.json
+ echo "dist ran successfully"
+
+ # Parse out what we just built and upload it to scratch storage
+ echo "paths<> "$GITHUB_OUTPUT"
+ jq --raw-output ".upload_files[]" dist-manifest.json >> "$GITHUB_OUTPUT"
+ echo "EOF" >> "$GITHUB_OUTPUT"
+
+ cp dist-manifest.json "$BUILD_MANIFEST_NAME"
+ - name: "Upload artifacts"
+ uses: actions/upload-artifact@v4
+ with:
+ name: artifacts-build-global
+ path: |
+ ${{ steps.cargo-dist.outputs.paths }}
+ ${{ env.BUILD_MANIFEST_NAME }}
+ # Determines if we should publish/announce
+ host:
+ needs:
+ - plan
+ - build-local-artifacts
+ - build-global-artifacts
+ # Only run if we're "publishing", and only if local and global didn't fail (skipped is fine)
+ if: ${{ always() && needs.plan.outputs.publishing == 'true' && (needs.build-global-artifacts.result == 'skipped' || needs.build-global-artifacts.result == 'success') && (needs.build-local-artifacts.result == 'skipped' || needs.build-local-artifacts.result == 'success') }}
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ runs-on: "ubuntu-22.04"
+ outputs:
+ val: ${{ steps.host.outputs.manifest }}
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ persist-credentials: false
+ submodules: recursive
+ - name: Install cached dist
+ uses: actions/download-artifact@v4
+ with:
+ name: cargo-dist-cache
+ path: ~/.cargo/bin/
+ - run: chmod +x ~/.cargo/bin/dist
+ # Fetch artifacts from scratch-storage
+ - name: Fetch artifacts
+ uses: actions/download-artifact@v4
+ with:
+ pattern: artifacts-*
+ path: target/distrib/
+ merge-multiple: true
+ - name: "Some build step"
+ uses: "some-action-user/some-action"
+ with:
+ "input1": "input1"
+ "input2": "input2"
+ - name: "Some Other build step"
+ uses: "some-action-user/some-other-action"
+ env:
+ "ENV_VAR": "${{ github.head_ref }}"
+ - name: "Some Run Step simple"
+ if: false
+ run: "echo \"hello world!\""
+ - name: "Some Run Step Multi"
+ run: |
+ HW="hello world"
+ echo $HW
+ shell: "bash"
+ - id: host
+ shell: bash
+ run: |
+ dist host ${{ needs.plan.outputs.tag-flag }} --steps=upload --steps=release --output-format=json > dist-manifest.json
+ echo "artifacts uploaded and released successfully"
+ cat dist-manifest.json
+ echo "manifest=$(jq -c "." dist-manifest.json)" >> "$GITHUB_OUTPUT"
+ - name: "Upload dist-manifest.json"
+ uses: actions/upload-artifact@v4
+ with:
+ # Overwrite the previous copy
+ name: artifacts-dist-manifest
+ path: dist-manifest.json
+ # Create a GitHub Release while uploading all files to it
+ - name: "Download GitHub Artifacts"
+ uses: actions/download-artifact@v4
+ with:
+ pattern: artifacts-*
+ path: artifacts
+ merge-multiple: true
+ - name: Cleanup
+ run: |
+ # Remove the granular manifests
+ rm -f artifacts/*-dist-manifest.json
+ - name: Create GitHub Release
+ env:
+ PRERELEASE_FLAG: "${{ fromJson(steps.host.outputs.manifest).announcement_is_prerelease && '--prerelease' || '' }}"
+ ANNOUNCEMENT_TITLE: "${{ fromJson(steps.host.outputs.manifest).announcement_title }}"
+ ANNOUNCEMENT_BODY: "${{ fromJson(steps.host.outputs.manifest).announcement_github_body }}"
+ RELEASE_COMMIT: "${{ github.sha }}"
+ run: |
+ # Write and read notes from a file to avoid quoting breaking things
+ echo "$ANNOUNCEMENT_BODY" > $RUNNER_TEMP/notes.txt
+
+ gh release create "${{ needs.plan.outputs.tag }}" --target "$RELEASE_COMMIT" $PRERELEASE_FLAG --title "$ANNOUNCEMENT_TITLE" --notes-file "$RUNNER_TEMP/notes.txt" artifacts/*
+
+ publish-homebrew-formula:
+ needs:
+ - plan
+ - host
+ runs-on: "ubuntu-22.04"
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ PLAN: ${{ needs.plan.outputs.val }}
+ GITHUB_USER: "axo bot"
+ GITHUB_EMAIL: "admin+bot@axo.dev"
+ if: ${{ !fromJson(needs.plan.outputs.val).announcement_is_prerelease || fromJson(needs.plan.outputs.val).publish_prereleases }}
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ persist-credentials: true
+ repository: "axodotdev/homebrew-packages"
+ token: ${{ secrets.HOMEBREW_TAP_TOKEN }}
+ # So we have access to the formula
+ - name: Fetch homebrew formulae
+ uses: actions/download-artifact@v4
+ with:
+ pattern: artifacts-*
+ path: Formula/
+ merge-multiple: true
+ # This is extra complex because you can make your Formula name not match your app name
+ # so we need to find releases with a *.rb file, and publish with that filename.
+ - name: Commit formula files
+ run: |
+ git config --global user.name "${GITHUB_USER}"
+ git config --global user.email "${GITHUB_EMAIL}"
+
+ for release in $(echo "$PLAN" | jq --compact-output '.releases[] | select([.artifacts[] | endswith(".rb")] | any)'); do
+ filename=$(echo "$release" | jq '.artifacts[] | select(endswith(".rb"))' --raw-output)
+ name=$(echo "$filename" | sed "s/\.rb$//")
+ version=$(echo "$release" | jq .app_version --raw-output)
+
+ export PATH="/home/linuxbrew/.linuxbrew/bin:$PATH"
+ brew update
+ # We avoid reformatting user-provided data such as the app description and homepage.
+ brew style --except-cops FormulaAudit/Homepage,FormulaAudit/Desc,FormulaAuditStrict --fix "Formula/${filename}" || true
+
+ git add "Formula/${filename}"
+ git commit -m "${name} ${version}"
+ done
+ git push
+
+ publish-npm:
+ needs:
+ - plan
+ - host
+ runs-on: "ubuntu-22.04"
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ PLAN: ${{ needs.plan.outputs.val }}
+ if: ${{ !fromJson(needs.plan.outputs.val).announcement_is_prerelease || fromJson(needs.plan.outputs.val).publish_prereleases }}
+ steps:
+ - name: Fetch npm packages
+ uses: actions/download-artifact@v4
+ with:
+ pattern: artifacts-*
+ path: npm/
+ merge-multiple: true
+ - uses: actions/setup-node@v4
+ with:
+ node-version: '20.x'
+ registry-url: 'https://registry.npmjs.org'
+ - run: |
+ for release in $(echo "$PLAN" | jq --compact-output '.releases[] | select([.artifacts[] | endswith("-npm-package.tar.gz")] | any)'); do
+ pkg=$(echo "$release" | jq '.artifacts[] | select(endswith("-npm-package.tar.gz"))' --raw-output)
+ npm publish --access public "./npm/${pkg}"
+ done
+ env:
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
+
+ announce:
+ needs:
+ - plan
+ - host
+ - publish-homebrew-formula
+ - publish-npm
+ # use "always() && ..." to allow us to wait for all publish jobs while
+ # still allowing individual publish jobs to skip themselves (for prereleases).
+ # "host" however must run to completion, no skipping allowed!
+ if: ${{ always() && needs.host.result == 'success' && (needs.publish-homebrew-formula.result == 'skipped' || needs.publish-homebrew-formula.result == 'success') && (needs.publish-npm.result == 'skipped' || needs.publish-npm.result == 'success') }}
+ runs-on: "ubuntu-22.04"
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ persist-credentials: false
+ submodules: recursive
+
+================ main.wxs ================
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+