diff --git a/README.md b/README.md index 28cbf6151..55d672385 100644 --- a/README.md +++ b/README.md @@ -27,31 +27,61 @@

- soar-list + soar-list

+

+ 📘 Documentation | + 🔮 PackageForge +

+

- Soar is a Fast, Modern, Bloat-Free Distro-Independent Package Manager that Just Works
- Supports Static Binaries, AppImages, and other Portable formats on any *Unix-based Distro + Soar is a Fast, Modern, Bloat-Free Distro-Independent Package Manager that Just Works
+ Supports Static Binaries, AppImages, and other Portable formats on any *Unix-based Distro

-# Soar Package Manager + +## 🪄 Quickstart + +> [!TIP] +> - Soar comes as a single-file, statically-linked executable with no dependencies that you can simply [download](https://github.com/pkgforge/soar/releases/latest) & run. +> - The [install script](https://github.com/pkgforge/soar/blob/main/install.sh) does this & more automatically for you. + +```bash +❯ cURL +curl -fsSL "https://raw.githubusercontent.com/pkgforge/soar/main/install.sh" | sh + +❯ wget +wget -qO- "https://raw.githubusercontent.com/pkgforge/soar/main/install.sh" | sh +``` + +> [!NOTE] +> - Please read & verify what's inside the script before running it +> - The script is also available through https://soar.qaidvoid.dev/install.sh & https://soar.pkgforge.dev/install.sh +> - Additionally, if you want to customize your installation, please read the docs @ https://soar.qaidvoid.dev/installation.html +> - For, extra Guide & Information on infra backends & adding more repos: https://docs.pkgforge.dev +> - Next, Check [Configuration](https://soar.qaidvoid.dev/configuration) & [Usage](https://soar.qaidvoid.dev/package-management) ## 🌟 Key Features +> [!TIP] +> - The comparison page @ https://docs.pkgforge.dev/soar/readme goes into more detail. + | Feature | Description | |:--:|:--| | **Universal Package Format Support** | Soar can install and manage portable package formats including [static binaries](https://docs.pkgforge.dev/formats/binaries/static), [self-extractable archives](https://docs.pkgforge.dev/formats/packages/archive), and [AppImages](https://docs.pkgforge.dev/formats/packages/appimage). | | **System Integration** | Soar [automatically integrates](https://soar.qaidvoid.dev/#desktop-integration) installed packages with your system to provide a native-like experience. | | **Flexible Repository System** | While Soar comes preconfigured with [official repositories](https://docs.pkgforge.dev/repositories), you can [configure custom repositories](https://soar.qaidvoid.dev/configuration#custom-repository-support) that use any build format as long as they provide compatible metadata. The `.SBUILD` format is only required for the official repositories, not for custom ones. | | **Security First** | Soar enforces security through checksums and signing verification for package installations. | +| **Userspace** | Soar works completely in Userspace without Superuser (admin/sudo) Privileges. | | **External Repository Support** | Soar can access packages from sources like [ivan-hc/AM](https://github.com/ivan-hc/AM) and [appimage.github.io](https://github.com/AppImage/appimage.github.io) through metadata provided by pkgforge. These external sources don't directly work with soar but are made compatible through pkgforge's metadata conversion. **Note:** Packages from external repositories are not verified. | | **Fast Package Operations** | Soar provides efficient package searching, installation, and management with minimal overhead. | -## 📦 Packages Available Through Official Repositories +## 📦 Packages -Packages in the official Soar repositories have these characteristics: +> [!TIP] +> Check out the detailed documentation @ https://docs.pkgforge.dev/repositories/soarpkgs | Feature | Description | |:--:|:--| @@ -65,57 +95,58 @@ Packages in the official Soar repositories have these characteristics: | **Decentralized** | The portable nature of packages means they can be downloaded and used independently of Soar if needed. | ## ☢️ Caveats -#### Soar doesn't reinvent things -Soar isn't a package manager in the traditional sense, neither is it a [new standard](https://xkcd.com/927/), thus soar doesn't handle core system tools/libraries by design. -This means soar is not a replacement for your distro's official package manager.
-Instead, Soar complements existing package managers by providing your distro with additional packages or newer version of packages that your distro may not provide.
-Soar is meant to coexist with existing package managers by avoiding conflicts, being completely functional in userspace & using XDG Specifications.
-For more questions, check our [FAQ](https://docs.pkgforge.dev/repositories/soarpkgs/faq) or [create a discussion](https://github.com/pkgforge/soar/discussions). -## 🔧 Installation +> [!NOTE] +> - If you have additional questions, check our [FAQ](https://docs.pkgforge.dev/repositories/soarpkgs/faq) or [create a discussion](https://github.com/pkgforge/soar/discussions). -Soar comes as a single-file, statically-linked executable with no dependencies that you can simply [download](https://github.com/pkgforge/soar/releases/latest) & run. -- Docs: https://soar.qaidvoid.dev/installation.html -- Extra Guide & Information: https://docs.pkgforge.dev +| Design Decisions | The Rationale | +|:--:|:--| +| **Not Reinvent things** | Soar isn't a package manager in the traditional sense, neither is it a [new standard](https://xkcd.com/927/). Think of soar as an amalgamation & the natural progression of tools like [AM](https://github.com/ivan-hc/AM), [bin](https://github.com/marcosnils/bin), [eget](https://github.com/zyedidia/eget), [hysp](https://github.com/pwnwriter/hysp), [nami](https://github.com/txthinking/nami) & [zap](https://github.com/srevinsaju/zap). | +| **Not a System Package Manager** | Soar intentionally complements rather than replaces your distro's package manager. Unlike [Homebrew](https://github.com/Homebrew/brew), we don't handle core system tools/libraries — we let distro package managers excel at that job. Soar provides additional packages or newer versions while avoiding conflicts by operating entirely in userspace and following XDG specifications. | +| **Not a Devtools Manager** | Soar doesn't handle development toolchains by design. We do have completely static/relocatable toolchains in our repo, but it will always be better to just use dedicated tools like [asdf](https://github.com/asdf-vm/asdf), [aqua](https://github.com/aquaproj/aqua), [chsrc](https://github.com/RubyMetric/chsrc), [mise](https://github.com/jdx/mise), [vfox](https://github.com/version-fox/vfox) etc. | -## ⚙️ Configuration +## 🐞 Bug Reports & Feature Requests -Soar comes with [sane defaults](https://soar.qaidvoid.dev/configuration.html) & [official repositories](https://docs.pkgforge.dev/repositories/) preconfigured
-For additional configuration guide, see [here](https://soar.qaidvoid.dev/configuration.html) +> [!WARNING] +> For reporting any issues related to packaging (Not Soar Core), please use our [Official package repository](https://docs.pkgforge.dev/repositories) at [pkgforge/soarpkgs](https://github.com/pkgforge/soarpkgs). -## 🎯 Usage +Soar is a FOSS project primarily maintained by [@QaidVoid](https://github.com/QaidVoid) & a few other [core contributors](https://github.com/pkgforge/soar/graphs/contributors), who are all volunteers and do it as a hobby.
+To save our time triaging & to ensure your issue/feature-request gets addressed quickly, make sure to: +- Search the [Issues](https://github.com/pkgforge/soar/issues) & [Discussion](https://github.com/pkgforge/soar/discussions?discussions_q=) tab (Both Closed/Opened) for same/similar issue in case it was already addressed. +- [Open a Discussion](https://github.com/pkgforge/soar/discussions/new/choose) instead of an issue if you have a question. Issues should be only created for bug reports and feature requests.
+- Use our [Issue Templates](https://github.com/pkgforge/soar/issues/new/choose) rather than a blank issue.
-Simply run `soar --help` for general options. -- General Guide & Manual is maintained at: [soar.qaidvoid.dev](https://soar.qaidvoid.dev/) -- Detailed guide regarding each format is at: [docs.pkgforge.dev](https://docs.pkgforge.dev/formats/packages) +> [!NOTE] +> - We assign a specific [priority level (`p0-p3`)](https://github.com/pkgforge/soar/labels) for each [valid issue](https://github.com/pkgforge/soar/issues) created. +> - Based on the assigned [priority level (`p0-p3`)](https://github.com/pkgforge/soar/labels) & our free time, we will do our best to respond/address it. +> - However, this is not a guarantee or an [SLA](https://en.wikipedia.org/wiki/Service-level_agreement). Please have patience & wait before tagging us again for a response. We thank you for your understanding. -## 📦 Packages -For reporting any issues related to packaging, please use our [Official package repository](https://docs.pkgforge.dev/repositories) at [pkgforge/soarpkgs](https://github.com/pkgforge/soarpkgs).
## 💬 Community -Be a part of our community to interact with our team, get quick help, and share your ideas +We have a growing community on discord to discuss not only Soar/Pkgforge but also other cool projects, feel free to join & hangout anytime. - [![Discord](https://img.shields.io/discord/1313385177703256064?logo=%235865F2&label=Discord)](https://discord.gg/djJUs48Zbu) - Other Channels: https://docs.pkgforge.dev/contact/chat ## 🤝 Contributing -We welcome contributions! Please feel free to fork the repository and submit -pull requests. If you have suggestions or feature requests, open an [discussion](https://github.com/pkgforge/soar/discussions) to -discuss. +> [!WARNING] +> While we welcome contributions of all kinds, please read [CONTRIBUTING.md](https://github.com/pkgforge/soar/blob/main/CONTRIBUTING.md) before submitting us a PR. Please feel free to: 1. Fork the repository 2. Create your feature branch 3. Submit a pull request +## 📊 Repo Stats + ![Alt](https://repobeats.axiom.co/api/embed/7c089611431897ab74236ac506187c2f563c2886.svg "Repobeats analytics image") [![Stargazers](https://reporoster.com/stars/dark/pkgforge/soar)](https://github.com/pkgforge/soar/stargazers) [![Stargazers over time](https://starchart.cc/pkgforge/soar.svg?variant=dark)](https://starchart.cc/pkgforge/soar) ## 📝 License -This project is licensed under [MIT](https://spdx.org/licenses/MIT.html) - see the [LICENSE](LICENSE) file for details.
+This project is licensed under [MIT](https://spdx.org/licenses/MIT.html) - see the [LICENSE](LICENSE) file for details.

[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fpkgforge%2Fsoar.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Fpkgforge%2Fsoar?ref=badge_large) ## Minimum Supported Rust Version (MSRV) diff --git a/install.sh b/install.sh index cdf882f5e..3d309924b 100755 --- a/install.sh +++ b/install.sh @@ -2,256 +2,385 @@ # Soar Installation Script (v1.0.0) # Tries to be as POSIX compliant as possible (Any deviation is intentional) # Assumptions: User has a supported downloader -# Supported Downloaders: +# Supported Downloaders: # aria2 (aria2c) axel bash (/dev/tcp) busybox curl http (httpie) nushell (http) perl (libww) python/python3 soar-dl soar wget # If no supported downloaders are found (happens often), a fallback to bash+sed or nushell is used set -eu #shellcheck disable=SC2016,SC2059 main() { - DEFAULT_VERSION="latest" - SOAR_VERSION="${SOAR_VERSION:-$DEFAULT_VERSION}" - # ASCII Colors - RED="\033[0;31m" - GREEN="\033[0;32m" - BLUE="\033[0;34m" - YELLOW="\033[0;33m" - RESET="\033[0m" + # Enable Debug? + DEBUG="${DEBUG:-}" + if [ -n "$DEBUG" ]; then + set -x + fi - # Function to check for a downloader, sorted by sanest choice - check_download_tool() { - if command -v curl >/dev/null 2>&1; then - printf "curl -fSL -o" - return 0 - elif command -v wget >/dev/null 2>&1; then - printf "wget -O" - return 0 - elif command -v soar-dl >/dev/null 2>&1; then - printf "soar-dl -o" - return 0 - elif command -v soar >/dev/null 2>&1; then - printf "soar dl -o" - return 0 - elif command -v aria2 >/dev/null 2>&1; then - printf "aria2 -o" - return 0 - elif command -v aria2c >/dev/null 2>&1; then - printf "aria2c -o" - return 0 - elif command -v axel >/dev/null 2>&1; then - printf "axel -o" - return 0 - elif command -v http >/dev/null 2>&1; then - printf "http -Fdm -o" - return 0 - elif command -v nu >/dev/null 2>&1; then - printf "NU_HTTP" - return 0 - elif command -v GET >/dev/null 2>&1; then - printf "PERL_GET" - return 0 - elif command -v python >/dev/null 2>&1; then - printf "PYTHON_GET" - return 0 - elif command -v python3 >/dev/null 2>&1; then - printf "PYTHON3_GET" - return 0 - elif command -v busybox >/dev/null 2>&1; then - printf "busybox wget --no-check-certificate -O" - return 0 - elif command -v bash >/dev/null 2>&1 && command -v sed >/dev/null 2>&1; then - printf "BASH_DEV_TCP" - return 0 - else - printf "${RED}✗ Error: Could not find a downloader (curl, wget, soar-dl, aria2, axel, httpie, perl, python, busybox).${RESET}\n" >&2 - return 1 - fi - } + # Default + DEFAULT_VERSION="latest" + SOAR_VERSION="${SOAR_VERSION:-$DEFAULT_VERSION}" - # Function to determine installation directory - get_install_dir() { - # Check environment variables first - if [ -n "${SOAR_INSTALL_DIR-}" ]; then - if [ -d "$SOAR_INSTALL_DIR" ] && [ -w "$SOAR_INSTALL_DIR" ]; then - printf "%s" "$SOAR_INSTALL_DIR" - return - else - printf "${RED}✗ Error: SOAR_INSTALL_DIR ${BLUE}($SOAR_INSTALL_DIR)${RED} is not writable or doesn't exist${RESET}\n" >&2 - exit 1 - fi - fi - if [ -n "${INSTALL_DIR-}" ]; then - if [ -d "$INSTALL_DIR" ] && [ -w "$INSTALL_DIR" ]; then - printf "%s" "$INSTALL_DIR" - return - else - printf "${RED}✗ Error: INSTALL_DIR ${BLUE}($INSTALL_DIR)${RED} is not writable or doesn't exist${RESET}\n" >&2 - exit 1 - fi - fi + # ASCII Colors + RED="\033[0;31m" + GREEN="\033[0;32m" + BLUE="\033[0;34m" + YELLOW="\033[0;33m" + RESET="\033[0m" - # Check ~/.local/bin - local_bin="$HOME/.local/bin" - if [ -d "$local_bin" ] && [ -w "$local_bin" ]; then - printf "%s" "$local_bin" - return - fi + # Refresh command -v + if command -v hash >/dev/null 2>&1; then + hash -r >/dev/null 2>&1 + fi - # Fallback to /usr/local/bin if running as root - if [ "$(id -u)" = "0" ]; then - if [ -d "/usr/local/bin" ] && [ -w "/usr/local/bin" ]; then - printf "/usr/local/bin" - return - fi - fi + # Ensure HOME + if [ -z "$HOME" ]; then + printf "${YELLOW}⚠ Notice: ${BLUE}\$HOME${YELLOW} is not set. (Will try guessing...)${RESET}\n" >&2 - # Fallback to current directory - printf "${YELLOW}⚠ Notice: ${BLUE}~/.local/bin${YELLOW} not found or not writable. Installing in current directory.${RESET}\n" >&2 - printf "${YELLOW}You should move the binary to a location in your ${BLUE}\$PATH.${RESET}\n" >&2 - printf "%s" "$(pwd)" - } + case $( + command -v awk getent grep tr whoami >/dev/null 2>&1 + echo $? + ) in + 0) + [ -z "$USER" ] && { + printf "${YELLOW}⚠ Notice: ${BLUE}\$USER${YELLOW} is not set. (Will try guessing...)${RESET}\n" >&2 + USER="$(whoami | tr -d '[:space:]')" + } + HOME="$(getent passwd "$USER" | awk -F':' 'NF >= 6 {print $6}' | tr -d '[:space:]')" + ;; + esac - # Function to download and install - install_soar() { - DOWNLOAD_TOOL="" - if ! DOWNLOAD_TOOL=$(check_download_tool); then - exit 1 - fi - INSTALL_PATH=$(get_install_dir) + if [ ! -d "$HOME" ]; then + printf "${RED}✗ Error: Could not determine ${BLUE}\$HOME${RESET}\n" >&2 + else + printf "${YELLOW}⚠ Notice: ${BLUE}\$HOME${YELLOW} is set to ${BLUE}$HOME${RESET}\n" >&2 + fi + fi - # Detect architecture - ARCH=$(uname -m) - case "$ARCH" in - x86_64) - ARCH="x86_64" - ;; - aarch64) - ARCH="aarch64" - ;; - *) - printf "${RED}Error: Unsupported architecture: ${YELLOW}$ARCH${RESET}\n" >&2 - exit 1 - ;; - esac + # Check XDG/Fallback Vars & Perms + for var in X_BIN X_CONFIG X_CACHE X_DATA; do + dir_var="" + dir_path="" - # Get latest release URL - printf "Downloading Soar..." - case "$SOAR_VERSION" in - *nightly*) - RELEASE_URL="https://github.com/pkgforge/soar/releases/download/nightly/soar-$ARCH-linux" - ;; - *latest*) - RELEASE_URL="https://github.com/pkgforge/soar/releases/latest/download/soar-$ARCH-linux" - ;; - *) - RELEASE_URL="https://github.com/pkgforge/soar/releases/download/v$SOAR_VERSION/soar-$ARCH-linux" - ;; - esac - printf " <== $RELEASE_URL\n" + case $var in + X_BIN) + dir_var="BIN_DIR" + xdg_var="XDG_BIN_HOME" + fallback="$HOME/.local/bin" + ;; + X_CONFIG) + dir_var="CONFIG_DIR" + xdg_var="XDG_CONFIG_HOME" + fallback="$HOME/.config" + ;; + X_CACHE) + dir_var="CACHE_DIR" + xdg_var="XDG_CACHE_HOME" + fallback="$HOME/.cache" + ;; + X_DATA) + dir_var="DATA_DIR" + xdg_var="XDG_DATA_HOME" + fallback="$HOME/.local/share" + ;; + esac - # Download and install - if [ "$DOWNLOAD_TOOL" = "NU_HTTP" ]; then - printf "[+] Using HTTP (nushell)\n" - RELEASE_URL="http://http.pkgforge.dev/$RELEASE_URL" INSTALL_PATH="$INSTALL_PATH" nu --no-config-file -c \ - 'http get --redirect-mode follow --insecure --raw $env.RELEASE_URL | save -f ($env.INSTALL_PATH + "/soar")' - printf "\n" - elif [ "$DOWNLOAD_TOOL" = "PERL_GET" ]; then - printf "[+] Using GET\n" - GET "$RELEASE_URL" > "$INSTALL_PATH/soar" - printf "\n" - elif [ "$DOWNLOAD_TOOL" = "PYTHON_GET" ]; then - printf "[+] Using python -c\n" - python -c "import urllib.request; urllib.request.urlretrieve('$RELEASE_URL', '$INSTALL_PATH/soar')" - printf "\n" - elif [ "$DOWNLOAD_TOOL" = "PYTHON3_GET" ]; then - printf "[+] Using python3 -c\n" - python3 -c "import urllib.request; urllib.request.urlretrieve('$RELEASE_URL', '$INSTALL_PATH/soar')" - printf "\n" - elif [ "$DOWNLOAD_TOOL" = "BASH_DEV_TCP" ]; then - printf "\n${YELLOW}⚠ Attempting to download using ${BLUE}Bash${YELLOW} (${GREEN}/dev/tcp${YELLOW}) over HTTP${RESET}\n" >&2 - printf "${YELLOW}⚠ This is highly unreliable & may not Work${RESET}\n\n" >&2 - RELEASE_URL="http://http.pkgforge.dev/$RELEASE_URL" INSTALL_PATH="$INSTALL_PATH" bash -c \ - ' - raw_http_get() { - #Get Input - url=$1 - port=${2:-80} - #Actually Verify we are in bash - is_bash=0 - [[ -n "${BASH}" ]] && is_bash=1 - if [[ $is_bash -eq 0 ]]; then - (shopt -p >/dev/null 2>&1) && is_bash=1 - fi - #Proceed - if [ $is_bash -eq 1 ]; then - #Parse Input - url=${url#http://} - url=${url#https://} - host=${url%%/*} - if [[ "$url" = "$host" ]]; then - path="/" - else - path="/${url#$host/}" - fi - #Download - exec 3<>/dev/tcp/$host/$port - echo -e "GET $path HTTP/1.1\r\nHost: $host\r\nConnection: close\r\n\r\n" >&3 - if command -v dd >/dev/null 2>&1; then - dd bs=1K <&3 - elif command -v cat >/dev/null 2>&1; then - cat <&3 - fi - exec 3>&- + xdg_value="" + eval "xdg_value=\"\${$xdg_var:-}\"" + + if [ -n "$xdg_value" ]; then + xdg_path="$xdg_value" + mkdir -p "$xdg_path" >/dev/null 2>&1 + if [ -d "$xdg_path" ] && [ -w "$xdg_path" ]; then + eval "$dir_var=\"$xdg_path\"" + continue + fi + fi + + if [ -n "$HOME" ]; then + mkdir -p "$fallback" >/dev/null 2>&1 + if [ -d "$fallback" ] && [ -w "$fallback" ]; then + eval "$dir_var=\"$fallback\"" + fi + fi + done + + # Check for a downloader, sorted by sanest choice + check_download_tool() { + if command -v curl >/dev/null 2>&1; then + printf "curl -fSL -o" + return 0 + elif command -v wget >/dev/null 2>&1; then + printf "wget -O" + return 0 + elif command -v soar-dl >/dev/null 2>&1; then + printf "soar-dl -o" + return 0 + elif command -v soar >/dev/null 2>&1; then + printf "soar dl -o" + return 0 + elif command -v aria2 >/dev/null 2>&1; then + printf "aria2 -o" + return 0 + elif command -v aria2c >/dev/null 2>&1; then + printf "aria2c -o" + return 0 + elif command -v axel >/dev/null 2>&1; then + printf "axel -o" + return 0 + elif command -v http >/dev/null 2>&1; then + printf "http -Fdm -o" + return 0 + elif command -v nu >/dev/null 2>&1; then + printf "NU_HTTP" + return 0 + elif command -v GET >/dev/null 2>&1; then + printf "PERL_GET" + return 0 + elif command -v python >/dev/null 2>&1; then + printf "PYTHON_GET" + return 0 + elif command -v python3 >/dev/null 2>&1; then + printf "PYTHON3_GET" + return 0 + elif command -v busybox >/dev/null 2>&1; then + printf "busybox wget --no-check-certificate -O" + return 0 + elif command -v bash >/dev/null 2>&1 && command -v sed >/dev/null 2>&1; then + printf "BASH_DEV_TCP" + return 0 + else + printf "${RED}✗ Error: Could not find a downloader (curl, wget, soar-dl, aria2, axel, httpie, perl, python, busybox).${RESET}\n" >&2 + return 1 + fi + } + + # Determine installation directory + get_install_dir() { + # Check environment variables first + if [ -n "${SOAR_INSTALL_DIR-}" ]; then + if [ -d "$SOAR_INSTALL_DIR" ] && [ -w "$SOAR_INSTALL_DIR" ]; then + printf "%s" "$SOAR_INSTALL_DIR" + return + else + printf "${RED}✗ Error: SOAR_INSTALL_DIR ${BLUE}($SOAR_INSTALL_DIR)${RED} is not writable or doesn't exist${RESET}\n" >&2 + exit 1 + fi + fi + if [ -n "${INSTALL_DIR-}" ]; then + if [ -d "$INSTALL_DIR" ] && [ -w "$INSTALL_DIR" ]; then + printf "%s" "$INSTALL_DIR" + return + else + printf "${RED}✗ Error: INSTALL_DIR ${BLUE}($INSTALL_DIR)${RED} is not writable or doesn't exist${RESET}\n" >&2 + exit 1 + fi + fi + + # Check Writable BIN Dir + if [ -n "$BIN_DIR" ]; then + if [ -d "$BIN_DIR" ] && [ -w "$BIN_DIR" ]; then + printf "%s" "$BIN_DIR" + return + fi + fi + + # Fallback to /usr/local/bin if running as root + if [ "$(id -u)" = "0" ]; then + if [ -d "/usr/local/bin" ] && [ -w "/usr/local/bin" ]; then + printf "/usr/local/bin" + return + fi + fi + + # Fallback to current directory + printf "${YELLOW}⚠ Notice: ${BLUE}~/.local/bin${YELLOW} not found or not writable. Installing in current directory.${RESET}\n" >&2 + printf "${YELLOW}You should move the binary to a location in your ${BLUE}\$PATH.${RESET}\n" >&2 + printf "%s" "$(pwd)" + } + + # Function to download and install + install_soar() { + DOWNLOAD_TOOL="" + if ! DOWNLOAD_TOOL=$(check_download_tool); then + exit 1 + fi + INSTALL_PATH=$(get_install_dir) + + # Detect architecture + ARCH=$(uname -m) + case "$ARCH" in + x86_64) + ARCH="x86_64" + ;; + aarch64) + ARCH="aarch64" + ;; + *) + printf "${RED}Error: Unsupported architecture: ${YELLOW}$ARCH${RESET}\n" >&2 + exit 1 + ;; + esac + + # Get latest release URL + printf "Downloading Soar..." + case "$SOAR_VERSION" in + *nightly*) + RELEASE_URL="https://github.com/pkgforge/soar/releases/download/nightly/soar-$ARCH-linux" + ;; + *latest*) + RELEASE_URL="https://github.com/pkgforge/soar/releases/latest/download/soar-$ARCH-linux" + ;; + *) + RELEASE_URL="https://github.com/pkgforge/soar/releases/download/v$SOAR_VERSION/soar-$ARCH-linux" + ;; + esac + printf " <== $RELEASE_URL\n" + + # Download and install + if [ "$DOWNLOAD_TOOL" = "NU_HTTP" ]; then + printf "[+] Using HTTP (nushell)\n" + RELEASE_URL="http://http.pkgforge.dev/$RELEASE_URL" INSTALL_PATH="$INSTALL_PATH" nu --no-config-file -c \ + 'http get --redirect-mode follow --insecure --raw $env.RELEASE_URL | save -f ($env.INSTALL_PATH + "/soar")' + printf "\n" + elif [ "$DOWNLOAD_TOOL" = "PERL_GET" ]; then + printf "[+] Using GET\n" + GET "$RELEASE_URL" >"$INSTALL_PATH/soar" + printf "\n" + elif [ "$DOWNLOAD_TOOL" = "PYTHON_GET" ]; then + printf "[+] Using python -c\n" + python -c "import urllib.request; urllib.request.urlretrieve('$RELEASE_URL', '$INSTALL_PATH/soar')" + printf "\n" + elif [ "$DOWNLOAD_TOOL" = "PYTHON3_GET" ]; then + printf "[+] Using python3 -c\n" + python3 -c "import urllib.request; urllib.request.urlretrieve('$RELEASE_URL', '$INSTALL_PATH/soar')" + printf "\n" + elif [ "$DOWNLOAD_TOOL" = "BASH_DEV_TCP" ]; then + printf "\n${YELLOW}⚠ Attempting to download using ${BLUE}Bash${YELLOW} (${GREEN}/dev/tcp${YELLOW}) over HTTP${RESET}\n" >&2 + printf "${YELLOW}⚠ This is highly unreliable & may not Work${RESET}\n\n" >&2 + RELEASE_URL="http://http.pkgforge.dev/$RELEASE_URL" INSTALL_PATH="$INSTALL_PATH" bash -c \ + ' + raw_http_get() { + #Get Input + url=$1 + port=${2:-80} + #Actually Verify we are in bash + is_bash=0 + [[ -n "${BASH}" ]] && is_bash=1 + if [[ $is_bash -eq 0 ]]; then + (shopt -p >/dev/null 2>&1) && is_bash=1 + fi + #Proceed + if [ $is_bash -eq 1 ]; then + #Parse Input + url=${url#http://} + url=${url#https://} + host=${url%%/*} + if [[ "$url" = "$host" ]]; then + path="/" else - echo "Error: No method available to make HTTP requests. Requires Bash with /dev/tcp" >&2 - return 1 + path="/${url#$host/}" fi - } - raw_http_get "${RELEASE_URL}" > "${INSTALL_PATH}/soar" - if [[ -s "${INSTALL_PATH}/soar" ]]; then - #Removes HTTP Headers - sed "1,/^\r\{0,1\}$/d" -i "${INSTALL_PATH}/soar" - fi - ' - printf "\n" - else - printf "[+] Using $DOWNLOAD_TOOL\n" - $DOWNLOAD_TOOL "$INSTALL_PATH/soar" "$RELEASE_URL" - fi - if [ ! -f "$INSTALL_PATH/soar" ]; then - if [ "$DOWNLOAD_TOOL" = "BASH_DEV_TCP" ]; then - printf "${RED}Error: Download failed.${YELLOW} Install ${BLUE}curl/wget${YELLOW} & try again${RESET}\n" - else - printf "${RED}Error: Download failed${RESET}\n" - fi - exit 1 - fi - # Make executable - chmod +x "$INSTALL_PATH/soar" - # Check for valid elf in case sed failed - if [ "$DOWNLOAD_TOOL" = "BASH_DEV_TCP" ]; then - if ! "$INSTALL_PATH/soar" --version >/dev/null 2>&1; then - printf "${RED}Error: Failed to properly extract soar.${YELLOW} Install ${BLUE}curl/wget${YELLOW} & try again${RESET}\n" - rm -fv "$INSTALL_PATH/soar" - printf "\n" - exit 1 + #Download + exec 3<>/dev/tcp/$host/$port + echo -e "GET $path HTTP/1.1\r\nHost: $host\r\nConnection: close\r\n\r\n" >&3 + if command -v dd >/dev/null 2>&1; then + dd bs=1K <&3 + elif command -v cat >/dev/null 2>&1; then + cat <&3 + fi + exec 3>&- + else + echo "Error: No method available to make HTTP requests. Requires Bash with /dev/tcp" >&2 + return 1 fi - fi - # Finalize - "$INSTALL_PATH/soar" --version || printf "${RED}Error: Failed to properly download soar${RESET}" - printf "${GREEN}✓ Soar has been installed to: ${BLUE}$INSTALL_PATH/soar${RESET}\n" - printf "${YELLOW}ⓘ Make sure ${BLUE}$INSTALL_PATH${YELLOW} is in your ${BLUE}PATH.${RESET}\n" - printf "${YELLOW}ⓘ Documentation: ${BLUE}https://soar.qaidvoid.dev${RESET}\n" - printf "${YELLOW}ⓘ Discord: ${BLUE}https://docs.pkgforge.dev/contact/chat${RESET}\n" - printf "${YELLOW}ⓘ External Repositories are ${RED}NOT Enabled${YELLOW} by default${RESET}\n" - printf "${YELLOW}ⓘ Learn More: ${BLUE}https://docs.pkgforge.dev/repositories/external${RESET}\n" - printf "${YELLOW}ⓘ To enable external repos, Run: ${GREEN}soar defconfig --external${RESET}\n" - printf "${YELLOW}ⓘ Finally, To synchronize all repos, Run: ${GREEN}soar sync${RESET}\n\n" - } + } + raw_http_get "${RELEASE_URL}" > "${INSTALL_PATH}/soar" + if [[ -s "${INSTALL_PATH}/soar" ]]; then + #Removes HTTP Headers + sed "1,/^\r\{0,1\}$/d" -i "${INSTALL_PATH}/soar" + fi + ' + printf "\n" + else + printf "[+] Using $DOWNLOAD_TOOL\n" + $DOWNLOAD_TOOL "$INSTALL_PATH/soar" "$RELEASE_URL" + fi + # Check + if [ ! -f "$INSTALL_PATH/soar" ]; then + if [ "$DOWNLOAD_TOOL" = "BASH_DEV_TCP" ]; then + printf "${RED}Error: Download failed.${YELLOW} Install ${BLUE}curl/wget${YELLOW} & try again${RESET}\n" + else + printf "${RED}Error: Download failed${RESET}\n" + fi + exit 1 + fi + # Make executable + chmod +x "$INSTALL_PATH/soar" + # Check for valid elf in case sed failed + if [ "$DOWNLOAD_TOOL" = "BASH_DEV_TCP" ]; then + if ! "$INSTALL_PATH/soar" --version >/dev/null 2>&1; then + printf "${RED}Error: Failed to properly extract soar.${YELLOW} Install ${BLUE}curl/wget${YELLOW} & try again${RESET}\n" + rm -fv "$INSTALL_PATH/soar" + printf "\n" + exit 1 + fi + fi + # Check & Print Docs + "$INSTALL_PATH/soar" --version || printf "${RED}Error: Failed to properly download soar${RESET}" + printf "\n${GREEN}✓ Soar has been installed to: ${BLUE}$INSTALL_PATH/soar${RESET}\n" + printf "${YELLOW}ⓘ Documentation: ${BLUE}https://soar.qaidvoid.dev${RESET}\n" + printf "${YELLOW}ⓘ Discord: ${BLUE}https://docs.pkgforge.dev/contact/chat${RESET}\n" + # Check if in PATH + if command -v expr >/dev/null 2>&1; then + if expr ":$PATH:" : ".*:$BIN_DIR:" >/dev/null || + expr ":$PATH:" : ".*:$(expr "$BIN_DIR" : '\(.*\)/$'):" >/dev/null; then + : + else + printf "\n${YELLOW}⚠ ${BLUE}$INSTALL_PATH${RED} is NOT in your ${BLUE}PATH${RESET}\n" + printf "${YELLOW}ⓘ Put this in your ${BLUE}SHELL/Profile${YELLOW}:${RESET}\n" + printf "\n${GREEN} export PATH=\"\$PATH:$INSTALL_PATH\"${RESET}\n\n" + fi + else + printf "${YELLOW}ⓘ Make sure ${BLUE}$INSTALL_PATH${YELLOW} is in your ${BLUE}PATH.${RESET}\n" + fi + # Enable External Repos + printf "${YELLOW}ⓘ External Repositories are ${RED}NOT Enabled${YELLOW} by default${RESET}\n" + printf "${YELLOW}ⓘ Learn More: ${BLUE}https://docs.pkgforge.dev/repositories/external${RESET}\n" + printf "${YELLOW}ⓘ To enable external repos, Run: ${GREEN}soar defconfig --external${RESET}\n" + # Sync + printf "${YELLOW}ⓘ Finally, To synchronize all repos, Run: ${GREEN}soar sync${RESET}\n" + # Check Current Config + SOAR_ENV_OUT="$($INSTALL_PATH/soar env 2>/dev/null)" + if [ -n "$SOAR_ENV_OUT" ]; then + if command -v awk >/dev/null 2>&1 && command -v expr >/dev/null 2>&1; then + SOAR_BIN_PATH="$(printf "$SOAR_ENV_OUT" | awk -F= '/^SOAR_BIN=/{print $2}')" + if [ -n "$SOAR_BIN_PATH" ]; then + if expr ":$PATH:" : ".*:$SOAR_BIN_PATH:" >/dev/null || + expr ":$PATH:" : ".*:$(expr "$SOAR_BIN_PATH" : '\(.*\)/$'):" >/dev/null; then + : + else + printf "\n${YELLOW}⚠ ${BLUE}$SOAR_BIN_PATH${RED} is NOT in your ${BLUE}\$PATH${RESET}\n" + printf "${YELLOW}ⓘ Put this in your ${BLUE}SHELL/Profile${YELLOW}:${RESET}\n" + printf "\n${GREEN} export PATH=\"\$PATH:$INSTALL_PATH:$SOAR_BIN_PATH\"${RESET}\n\n" + fi + fi + fi + fi + # Print Current config + printf "\n${YELLOW}ⓘ Current Soar Configuration:${RESET}\n\n" + "$INSTALL_PATH/soar" env + printf "\n" + } + + # Run Installation + install_soar - # Execute installation - install_soar + # Disable Debug? + if [ -z "$DEBUG" ]; then + : + elif [ -n "$DEBUG" ]; then + set +x + fi } # Call main function