################################################################################ # # # _____ _ _ _____ _______ _ # # |_ _| \ | |/ ____|__ __| | # # | | | \| | (___ | | | | # # | | | . ` |\___ \ | | | | # # _| |_| |\ |____) | | | | |____ # # |_____|_| \_|_____/ |_| |______| # # # # # # Instl is an automated installer for GitHub Projects. # # This script is automatically generated by https://instl.sh. # # # # Running this script will install the specified GitHub project on your # # system. # # # # For full transperancy this script is a single file, combined from multiple # # files. # # # # You can see the source code of this server on GitHub: # # https://github.com/installer/instl # # # # Instl and its members are not associated with the # # project that will be installed! # # # # # # This script will perform the following actions: # # - Fetch the project metadata from the public GitHub API # # - Find the right asset for your system # # - Download the asset from GitHub # # - Extract the asset to the correct location # # - Add the installation directory to your system PATH # ################################################################################ # Install script for: https://github.com/username/reponame # # To use this install script, run the following command: # # Linux: # curl -sSL instl.sh/username/reponame/linux | bash # # macOS: # curl -sSL instl.sh/username/reponame/macos | bash # # Windows: # iwr instl.sh/username/reponame/windows | iex # Import libraries # --- Sourced from file: ./lib/colors.sh --- # Foreground Colors fRed() { printf "\e[31m%s\e[0m" "$1" } fRedLight() { printf "\e[91m%s\e[0m" "$1" } fYellow() { printf "\e[33m%s\e[0m" "$1" } fYellowLight() { printf "\e[93m%s\e[0m" "$1" } fGreen() { printf "\e[32m%s\e[0m" "$1" } fGreenLight() { printf "\e[92m%s\e[0m" "$1" } fBlue() { printf "\e[34m%s\e[0m" "$1" } fBlueLight() { printf "\e[94m%s\e[0m" "$1" } fMagenta() { printf "\e[35m%s\e[0m" "$1" } fMagentaLight() { printf "\e[95m%s\e[0m" "$1" } fCyan() { printf "\e[36m%s\e[0m" "$1" } fCyanLight() { printf "\e[96m%s\e[0m" "$1" } fWhite() { printf "\e[37m%s\e[0m" "$1" } fBlack() { printf "\e[30m%s\e[0m" "$1" } fGray() { printf "\e[90m%s\e[0m" "$1" } fGrayLight() { printf "\e[37m%s\e[0m" "$1" } ## Background Colors bRed() { printf "\e[41m%s\e[0m" "$1" } bRedLight() { printf "\e[101m%s\e[0m" "$1" } bYellow() { printf "\e[43m%s\e[0m" "$1" } bYellowLight() { printf "\e[103m%s\e[0m" "$1" } bGreen() { printf "\e[42m%s\e[0m" "$1" } bGreenLight() { printf "\e[102m%s\e[0m" "$1" } bBlue() { printf "\e[44m%s\e[0m" "$1" } bBlueLight() { printf "\e[104m%s\e[0m" "$1" } bMagenta() { printf "\e[45m%s\e[0m" "$1" } bMagentaLight() { printf "\e[105m%s\e[0m" "$1" } bCyan() { printf "\e[46m%s\e[0m" "$1" } bCyanLight() { printf "\e[106m%s\e[0m" "$1" } bWhite() { printf "\e[47m%s\e[0m" "$1" } bBlack() { printf "\e[40m%s\e[0m" "$1" } bGray() { printf "\e[100m%s\e[0m" "$1" } bGrayLight() { printf "\e[37m%s\e[0m" "$1" } # Special Colors resetColor() { printf "\e[0m" } # Theme primaryColor() { fCyan "$1" } secondaryColor() { fMagentaLight "$1" } info() { fBlueLight " i " && resetColor && fBlue "$1" && echo } warning() { fYellowLight " ! " && resetColor && fYellow "$1" && echo } error() { fRedLight " X " && resetColor && fRed "$1" && echo exit 1 } success() { fGreenLight " + " && resetColor && fGreen "$1" && echo } verbose() { if [ $verbose == true ]; then fGrayLight " > " && resetColor && fGray "$1" && echo fi } # --- End of ./lib/colors.sh --- # --- Sourced from file: ./lib/map.sh --- # map_put map_name key value map_put() { alias "${1}$2"="$3" } # map_get map_name key # @return value map_get() { alias "${1}$2" | awk -F"'" '{ print $2; }' } # map_keys map_name # @return map keys map_keys() { alias -p | grep $1 | cut -d'=' -f1 | awk -F"$1" '{print $2; }' } # --- End of ./lib/map.sh --- # Setup variables verbose="false" if [ "$verbose" = "true" ]; then verbose=true else verbose=false fi # Pass variables from the go server into the script verbose "Setting up variables" owner="username" repo="reponame" verbose "Creating temporary directory" tmpDir="$(mktemp -d)" verbose "Temporary directory: $tmpDir" binaryLocation="$HOME/.local/bin" verbose "Binary location: $binaryLocation" mkdir -p "$binaryLocation" installLocation="$HOME/.local/bin/.instl/$repo" verbose "Install location: $installLocation" # Remove installLocation directory if it exists if [ -d "$installLocation" ]; then verbose "Removing existing install location" rm -rf "$installLocation" fi mkdir -p "$installLocation" # Print "INSTL" header # --- Sourced from file: ../shared/intro.ps1 --- secondaryColor ' _____ _ _ _____ _______ _ |_ _| \ | |/ ____|__ __| | | | | \| | (___ | | | | | | | . ` |\___ \ | | | | _| |_| |\ |____) | | | | |____ |_____|_| \_|_____/ |_| |______|' echo "" echo "" fBlueLight ' Instl is an installer for GitHub Projects' echo "" fBlue ' > https://instl.sh' echo "" echo "" verbose "Instl version: dev" # --- End of ../shared/intro.ps1 --- # Installation curlOpts=("-sSL" "--retry" "5" "--retry-delay" "2" "--retry-max-time" "15") if [ -n "$GH_TOKEN" ]; then verbose "Using authentication with GH_TOKEN" curlOpts+=("--header" "Authorization: Bearer $GH_TOKEN") elif [ -n "$GITHUB_TOKEN" ]; then verbose "Using authentication with GITHUB_TOKEN" curlOpts+=("--header" "Authorization: Bearer $GITHUB_TOKEN") else verbose "No authentication" fi # GitHub public API latestReleaseURL="https://api.github.com/repos/$owner/$repo/releases/latest" verbose "Getting latest release from GitHub" getReleaseArgs=("${curlOpts[@]}" "$latestReleaseURL") verbose "Release curl args: ${getReleaseArgs[*]}" releaseJSON="$(curl "${getReleaseArgs[@]}")" tagName="$(echo "$releaseJSON" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')" info "Found latest release of $repo (version: $tagName)" # Get list of assets verbose "Parsing release json" assets=$(echo "$releaseJSON" | grep "browser_download_url" | sed -E 's/.*"([^"]+)".*/\1/') verbose "Found assets:" verbose "$assets" assetCount="$(echo "$assets" | wc -l | sed -E 's/^[[:space:]]*//')" info "Found $assetCount assets in '$tagName' - searching for one that fits your system..." # Get architecture of host arch="$(uname -m)" # Convert arch to lowercase arch="$(echo "$arch" | tr '[:upper:]' '[:lower:]')" verbose "Host architecture: $arch" # Set aliases for architectures amd64=("amd64" "x86_64" "x86-64" "x64") amd32=("386" "i386" "i686" "x86") arm=("arm" "armv7" "armv6" "armv8" "armv8l" "armv7l" "armv6l" "armv8l" "armv7l" "armv6l") currentArchAliases=() # Set the right aliases for current host system if [ "$arch" == "x86_64" ]; then currentArchAliases=("${amd64[@]}") elif [ "$arch" == "i386" ] || [ "$arch" == "i686" ]; then currentArchAliases=("${amd32[@]}") # Else if starts with "arm" elif [[ "$arch" =~ ^arm ]]; then currentArchAliases=("${arm[@]}") else error "Unsupported architecture: $arch" fi verbose "Current architecture aliases: ${currentArchAliases[*]}" # Get operating system of host os="$(uname -s)" # Convert os to lowercase os="$(echo "$os" | tr '[:upper:]' '[:lower:]')" verbose "Host operating system: $os" # Set aliases for operating systems linux=("linux") darwin=("darwin" "macos" "osx") currentOsAliases=() # If current os is linux, add linux aliases to the curentOsAliases array if [ "${os}" == "linux" ]; then currentOsAliases+=("${linux[@]}") elif [ "${os}" == "darwin" ]; then currentOsAliases+=("${darwin[@]}") fi verbose "Current operating system aliases: ${currentOsAliases[*]}" # Create map of assets and a score for asset in $assets; do score=0 # Get file name from asset path fileName="$(echo "$asset" | awk -F'/' '{ print $NF; }')" # Set filename to lowercase fileName="$(echo "$fileName" | tr '[:upper:]' '[:lower:]')" # Set score to one, if the file name contains the current os for osAlias in "${currentOsAliases[@]}"; do if [[ "${fileName}" == *"$osAlias"* ]]; then score=10 break fi done # Add two to the score for every alias that matches the current architecture for archAlias in "${currentArchAliases[@]}"; do if [[ "${fileName}" == *"$archAlias"* ]]; then verbose "Adding one to score for asset $fileName because it matches architecture $archAlias" score=$((score + 2)) fi done # Add one to the score if the file name contains .tar or .tar.gz or .tar.bz2 if [[ "$fileName" == *".tar" ]] || [[ "$fileName" == *".tar.gz" ]] || [[ "$fileName" == *".tar.bz2" ]]; then verbose "Adding one to score for asset $fileName because it is a .tar or .tar.gz or .tar.bz2 file" score=$((score + 1)) fi # Add two to the score if the file name contains the repo name if [[ "$fileName" == *"$repo"* ]]; then verbose "Adding two to score for asset $fileName because it contains the repo name" score=$((score + 2)) fi # Add one to the score if the file name is exactly the repo name if [[ "$fileName" == "$repo" ]]; then verbose "Adding one to score for asset $fileName because it is exactly the repo name" score=$((score + 1)) fi # Initialize asset with score map_put assets "$fileName" "$score" done # Get map entry with highest score verbose "Finding asset with highest score" maxScore=0 maxKey="" for asset in $(map_keys assets); do score="$(map_get assets "$asset")" if [ $score -gt $maxScore ]; then maxScore=$score maxKey=$asset fi verbose "Asset: $asset, score: $score" done assetName="$maxKey" # Check if asset name is still empty if [ -z "$assetName" ]; then error "Could not find any assets that fit your system" fi # Get asset URL from release assets assetURL="$(echo "$assets" | grep -i "$assetName")" info "Found asset with highest match score: $assetName" info "Downloading asset..." # Download asset downloadAssetArgs=$curlOpts downloadAssetArgs+=(-L "$assetURL" -o "$tmpDir/$assetName") verbose "${downloadAssetArgs[@]}" curl "${downloadAssetArgs[@]}" # Unpack asset if it is compressed if [[ "$assetName" == *".tar" ]]; then verbose "Unpacking .tar asset to $tmpDir" tar -xf "$tmpDir/$assetName" -C "$tmpDir" verbose "Removing packed asset ($tmpDir/$assetName)" rm "$tmpDir/$assetName" elif [[ "$assetName" == *".tar.gz" ]]; then verbose "Unpacking .tar.gz asset to $tmpDir" tar -xzf "$tmpDir/$assetName" -C "$tmpDir" verbose "Removing packed asset ($tmpDir/$assetName)" rm "$tmpDir/$assetName" elif [[ "$assetName" == *".gz" ]]; then verbose "Unpacking .gz asset to $tmpDir/$repo" gunzip -c "$tmpDir/$assetName" >"$tmpDir/$repo" verbose "Removing packed asset ($tmpDir/$assetName)" rm "$tmpDir/$assetName" verbose "Setting asset name to $repo, because it is a .gz file" assetName="$repo" verbose "Marking asset as executable" chmod +x "$tmpDir/$repo" elif [[ "$assetName" == *".tar.bz2" ]]; then verbose "Unpacking .tar.bz2 asset to $tmpDir" tar -xjf "$tmpDir/$assetName" -C "$tmpDir" verbose "Removing packed asset" rm "$tmpDir/$assetName" elif [[ "$assetName" == *".zip" ]]; then verbose "Unpacking .zip asset to $tmpDir/$repo" unzip "$tmpDir/$assetName" -d "$tmpDir" >/dev/null 2>&1 verbose "Removing packed asset ($tmpDir/$assetName)" rm "$tmpDir/$assetName" else verbose "Asset is not a tar or zip file. Skipping unpacking." fi # If it was unpacked to a single directory, move the files to the root of the tmpDir # Also check that there are not other non directory files in the tmpDir verbose "Checking if asset was unpacked to a single directory" if [ "$(ls -d "$tmpDir"/* | wc -l)" -eq 1 ] && [ -d "$(ls -d "$tmpDir"/*)" ]; then verbose "Asset was unpacked to a single directory" verbose "Moving files to root of tmpDir" mv "$tmpDir"/*/* "$tmpDir" else verbose "Asset was not unpacked to a single directory" fi # Copy files to install location info "Installing '$repo'" verbose "Copying files to install location" # verbose print tmpDir files verbose "Files in $tmpDir:" verbose "$(ls "$tmpDir")" cp -r "$tmpDir"/* "$installLocation" # Find binary in install location to symlink to it later verbose "Finding binary in install location" binary="" for file in "$installLocation"/*; do # Check if the file is a binary file verbose "Checking if $file is a binary file" if [ -f "$file" ] && [ -x "$file" ]; then binary="$file" verbose "Found binary: $binary" break fi done # Get name of binary binaryName="$(basename "$binary")" verbose "Binary name: $binaryName" # Check if binary is empty if [ -z "$binary" ]; then error "Could not find binary in install location" fi # Remove previous symlink if it exists verbose "Removing previous symlink" rm "$binaryLocation/$repo" >/dev/null 2>&1 || true # Create symlink to binary verbose "Creating symlink '$binaryLocation/$binaryName' -> '$binary'" ln -s "$binary" "$binaryLocation/$binaryName" # Add binaryLocation to PATH, if it is not already in PATH if ! echo "$PATH" | grep -q "$binaryLocation"; then verbose "Adding $binaryLocation to PATH" # Array of common shell configuration files config_files=("$HOME/.bashrc" "$HOME/.bash_profile" "$HOME/.zshrc" "$HOME/.profile") for config in "${config_files[@]}"; do # Check if the file exists if [ -f "$config" ]; then # Check if binaryLocation is already in the file if ! grep -q -s "export PATH=$binaryLocation:\$PATH" "$config"; then verbose "Appending $binaryLocation to $config" echo "" >>"$config" echo "# Instl.sh installer binary location" >>"$config" echo "export PATH=$binaryLocation:\$PATH" >>"$config" else verbose "$binaryLocation is already in $config" fi else verbose "$config does not exist. Skipping append." fi done else verbose "$binaryLocation is already in PATH" fi info "Running clean up..."https://github.com/installer/instl verbose "Removing temporary directory" rm -rf "$tmpDir" # Test if binary exists if [ ! -f "$binary" ]; then error "Binary does not exist in installation location" else verbose "Binary exists in installation location" fi echo success "You can now run '$binaryName' in your terminal!" info "You might have to restart your terminal session for the changes to take effect" ################################################################################## # MIT License # # # # Copyright (c) 2022 Marvin Wendt (Instl | https://instl.sh) # # # # 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. # ################################################################################## # --------------------------------- Metadata ----------------------------------- # # Script generated for https://github.com/username/reponame # Script generated at 2025-04-18 19:07:44.954876723 +0000 UTC m=+3096852.737308915 # Script generated for version "latest" # Script generated with instl version "dev"