chsrc/tool/installer.sh
2025-03-25 16:54:25 +08:00

415 lines
11 KiB
Bash
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env bash
# ---------------------------------------------------------------
# File Name : installer.sh
# File Authors : GnixAij <gaojiaxing0220@gmail.com>
# | xuan <wick.dynex@qq.com>
# | ChatGPT <https://chatgpt.com>
# | Aoran Zeng <ccmywish@qq.com>
# Contributors : GitHub Copilot <https://github.com/copilot>
# | DeepSeek <https://chat.deepseek.com/>
# |
# Created On : <2024-10-25>
# Last Modified : <2025-03-25>
#
# chsrc installer for POSIX (mainly Linux & macOS)
# ---------------------------------------------------------------
binary_name="chsrc"
# 用户指定的安装目录函数set_install_dir()将填充/校验该变量
userOpt_install_dir=""
# 默认安装目录
default_install_dir_4root="/usr/local/bin"
default_install_dir_4nonroot="$HOME/.local/bin"
# 若用户指定的目录不存在则会创建该目录
tmp_created_install_dir=""
userOpt_version="pre"
userOpt_help=0
userOpt_lang="zh"
info() {
echo "[INFO] $*"
}
warn() {
echo "[WARN] $*"
}
error() {
echo "[ERROR] $*"
}
# 用户自己输入
typeit() {
echo "[->] $ $*"
}
error_exit() {
echo -e "[ERROR] $*" >&2
exit 1
}
is_zh() {
if [ "$userOpt_lang" = "zh" ]; then
return 0
else
return 1
fi
}
help() {
if is_zh; then
echo "chsrc-installer: 在类Unix操作系统上安装 chsrc"
echo
echo "使用: install.sh [选项]"
echo "选项:"
echo "-h 打印此帮助信息"
echo "-d <dir> 指定安装目录,默认为 $default_install_dir_4root$default_install_dir_4nonroot"
echo "-v <version> 指定 chsrc 版本"
echo "-l <lang> 指定输出语言,支持 zh 和 en "
echo
else
echo "chsrc-installer: Install chsrc on any Unix-like OS"
echo
echo "Usage: install.sh [options]"
echo "Options:"
echo "-h Print this help information"
echo "-d <dir> Specify installation directory, default is $default_install_dir_4root OR $default_install_dir_4nonroot"
echo "-v <version> Specify chsrc version"
echo "-l <lang> Specify output language, supports zh and en"
echo
fi
}
let_user_build() {
if command -v make &>/dev/null; then
# 检测是否是 GNU make如果是则用 make如果不是则用C编译器来编译
if make --version | grep -q "GNU Make"; then
typeit "make"
else
if is_zh; then
warn "检测到非 GNU make本项目的Makefile仅支持GNU make"
else
warn "Non-GNU make was detected, the Makefile for this project only supports GNU make"
fi
typeit "cc/gcc/clang -Iinclude -Ilib src/chsrc-main.c -o chsrc"
fi
else
if is_zh; then
warn "未检测到GNU make需手动执行编译命令"
else
warn "GNU make was not detected, so we need to run the compile command manually:"
fi
typeit "cc/gcc/clang -Iinclude -Ilib src/chsrc-main.c -o chsrc"
fi
}
let_user_compile() {
source_zip_url="https://gitee.com/RubyMetric/chsrc/repository/archive/main.zip"
echo ""
if command -v git &>/dev/null; then
typeit "git clone https://gitee.com/RubyMetric/chsrc.git"
typeit "cd chsrc"
let_user_build
exit 1
elif command -v curl &>/dev/null; then
typeit "curl -LO $source_zip_url"
elif command -v wget &>/dev/null; then
typeit "wget $source_zip_url"
else
info "Please download the source code: $source_zip_url"
fi
typeit "unzip ./main.zip "
typeit "cd ./chsrc-main"
let_user_build
exit 1;
}
get_arch() {
echo $(uname -m | tr '[:upper:]' '[:lower:]')
}
get_platform() {
echo $(uname -s | awk '{print tolower($0)}')
}
# Linux -> GNU/Linux
# Android -> Android
get_os() {
echo $(uname -o | awk '{print tolower($0)}')
}
set_arch() {
arch=$(get_arch)
case "$arch" in
x86_64) arch="x64" ;;
aarch64|arm64) arch="aarch64" ;;
riscv64) arch="riscv64" ;;
armv7*) arch="armv7" ;;
*)
if is_zh; then
warn "抱歉, 暂无预编译二进制文件供您的架构: ${arch} 使用。请自行编译:"
else
warn "Sorry, No precompiled binaries for your arch: ${arch}. Please compile it on your own:"
fi
let_user_compile
exit 1
;;
esac
}
set_platform() {
platform=$(get_platform)
case "$platform" in
linux)
platform="linux"
whatos=$(get_os)
if [ "$whatos" = "android" ]; then
if is_zh; then
info "抱歉, 暂无预编译二进制文件供安卓使用。请自行编译:"
else
info "Sorry, No precompiled binaries for Android! Please compile it on your own:"
fi
let_user_compile
exit 1
fi
;;
darwin) platform="macos" ;;
bsd|dragonfly)
platform="bsd"
if is_zh; then
info "抱歉, 暂无预编译二进制文件供BSD使用。请自行编译"
else
info "Sorry, No precompiled binaries for BSD! Please compile it on your own:"
fi
let_user_compile
exit 1
;;
*)
if is_zh; then
error_exit "抱歉,暂无预编译二进制文件供您的平台: ${platform} 使用。请自行编译:"
else
error_exit "Sorry, No precompiled binaries for your platform: ${platform}. Please compile it on your own:"
fi
let_user_compile
exit 1
;;
esac
}
set_binary_version() {
if [[ ! "$userOpt_version" =~ ^(pre|0\.([1-9])\.([0-9]))$ ]]; then
# version 不符合条件,报错
if is_zh; then
error_exit "不支持的版本: ${userOpt_version},版本号必须为 0.x.y (>=0.1.4) 或 'pre'"
else
error_exit "Unsupported version: ${userOpt_version}. Version number must be 0.x.y (>=0.1.4) or 'pre'"
fi
fi
binary_version="${userOpt_version}"
# version 版本不是 'pre',添加'v'前缀
if [[ "$userOpt_version" =~ ^(0\.([1-9])\.([0-9]))$ ]]; then
binary_version="v${userOpt_version}"
fi
}
#
# 1. 若用户指定了安装目录,则安装至那里
#
# 若安装目录不存在,该脚本会为用户创建
#
# 2. 若用户没有指定安装目录:
#
# 2.1 若 chsrc 已存在,自动安装到该位置
# 2.2 若 chsrc 不存在,安装到两个预定义的默认安装位置
#
set_install_dir() {
if [ -n "$userOpt_install_dir" ]; then
# 扩展 ~ 符号
userOpt_install_dir="${userOpt_install_dir/#\~/$HOME}"
# 检查目录是否存在,如果不存在则创建该目录
if [ ! -d "$userOpt_install_dir" ]; then
if is_zh; then
echo "目录 $userOpt_install_dir 不存在,正在创建..."
else
echo "Directory $userOpt_install_dir does not exist. Creating..."
fi
if ! mkdir -p "$userOpt_install_dir"; then
if is_zh; then
echo "创建目录失败,请重试"
else
echo "Failed to create directory, please try again"
fi
exit 1
fi
tmp_created_install_dir="$userOpt_install_dir" # 记录临时安装目录
fi
elif existing_path=$(command -v "$binary_name" 2>/dev/null); then
if is_zh; then
info "$binary_name 已安装,更新路径: ${existing_path}"
else
info "$binary_name is already installed, updating path: ${existing_path}"
fi
userOpt_install_dir=$(dirname "$existing_path")
if [ ! -w "$userOpt_install_dir" ]; then
if is_zh; then
error_exit "目录 $userOpt_install_dir 不可写,请使用 sudo 命令运行脚本;或通过 -d 参数指定其它目录安装"
else
error_exit "Directory $userOpt_install_dir is not writable. Please run the script with sudo; or specify another dir using the -d option."
fi
fi
else
# 检查默认安装目录
if [ -d "$default_install_dir_4root" ] && [ -w "$default_install_dir_4root" ]; then
userOpt_install_dir="$default_install_dir_4root"
elif [ -d "$default_install_dir_4nonroot" ] && [ -w "$default_install_dir_4nonroot" ]; then
userOpt_install_dir="$default_install_dir_4nonroot"
else
if is_zh; then
error_exit "默认安装目录 $default_install_dir_4root$default_install_dir_4nonroot 不可写,请使用 sudo 命令运行脚本;或通过 -d 参数指定其它目录安装"
else
error_exit "Default install dir $default_install_dir_4root and $default_install_dir_4nonroot is not writable. Please run the script with sudo; or specify another dir using the -d option."
fi
fi
fi
}
#
# @param $1: 下载链接
# @param $2: 保存路径(带文件名)
#
download() {
if command -v curl &>/dev/null; then
curl -sL "$1" -o "$2"
return $? # 只能单独 return
fi
if command -v wget &>/dev/null; then
# follow 是wget默认行为
wget -qO "$2" "$1"
return $?
fi
if is_zh; then
error_exit "缺乏必要的下载工具(curl或wget),无法下载文件"
else
error_exit "Missing necessary download tools (curl or wget) to download the file!"
fi
}
install() {
set_binary_version
set_arch
set_platform
set_install_dir
url="https://gitee.com/RubyMetric/chsrc/releases/download/${binary_version}/${binary_name}-${arch}-${platform}"
path_to_executable="${userOpt_install_dir}/${binary_name}"
if is_zh; then
info "下载 ${binary_name} (架构: ${arch}, 平台: ${platform}, 版本: ${binary_version}) 到 ${path_to_executable}"
else
info "Downloading ${binary_name} (arch: ${arch}, platform: ${platform}, version: ${binary_version}) to ${path_to_executable}"
fi
if download $url "$path_to_executable"; then
chmod +x "$path_to_executable"
if is_zh; then
info "🎉 安装完成,路径: $path_to_executable"
else
info "🎉 Installation completed, path: $path_to_executable"
fi
else
if is_zh; then
error_exit "下载失败,请检查您的网络连接和代理设置: ${url}"
else
error_exit "Download failed, please check your network connection and proxy settings: ${url}"
fi
fi
}
cleanup() {
if [ -n "$tmp_created_install_dir" ] && [ -d "$tmp_created_install_dir" ]; then
if is_zh; then
echo "清理创建的目录: $tmp_created_install_dir"
else
echo "Cleaning up created directory: $tmp_created_install_dir"
fi
rm -rf "$tmp_created_install_dir"
fi
}
trap cleanup EXIT
# main
while getopts ":hd:v:l:" option; do
case $option in
h)
userOpt_help=1
;;
d)
userOpt_install_dir=${OPTARG}
;;
v)
userOpt_version=${OPTARG}
;;
l)
userOpt_lang=${OPTARG}
;;
\?)
echo "无效的命令行选项,请使用 -h 查看帮助"
exit 1
;;
esac
done
if [[ "$userOpt_lang" != "zh" && "$userOpt_lang" != "en" ]]; then
error_exit "无效的语言选项: $userOpt_lang,支持的选项为 zh 和 en"
fi
if [ "$userOpt_help" -eq 1 ]; then
help
exit 0;
fi
install