Refactor setup workflow
This commit is contained in:
268
Scripts/base.sh
Normal file
268
Scripts/base.sh
Normal file
@@ -0,0 +1,268 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Path: Scripts/base.sh
|
||||
|
||||
set -e
|
||||
|
||||
BLUE='\033[1;34m'
|
||||
YELLOW='\033[1;33m'
|
||||
GREEN='\033[1;32m'
|
||||
RED='\033[1;31m'
|
||||
NC='\033[0m'
|
||||
|
||||
DOTFILES_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
REPO_ROOT="$(dirname "$DOTFILES_DIR")"
|
||||
source "$DOTFILES_DIR/lib/distro.sh"
|
||||
|
||||
echo -e "${BLUE} LOG:${YELLOW} Initializing Base System Layer...${NC}"
|
||||
|
||||
# Confirm Architecture
|
||||
ARCH=$(uname -m)
|
||||
if [ "$ARCH" != "x86_64" ] && [ "$ARCH" != "aarch64" ]; then
|
||||
echo -e "${RED} ERROR: Unsupported architecture: $ARCH${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Package Installation
|
||||
PACKAGES=(
|
||||
curl wget git sudo
|
||||
zsh tmux
|
||||
unzip tar gzip
|
||||
build-essential
|
||||
openssl
|
||||
python bison mercurial
|
||||
ripgrep fd bat fzf jq
|
||||
btop httpie gnupg
|
||||
zoxide stow direnv
|
||||
bind nmap socat tcpdump net-tools
|
||||
strace gdb hexyl
|
||||
ninja-build libcurl4-openssl-dev
|
||||
just
|
||||
)
|
||||
|
||||
FINAL_PACKAGES=()
|
||||
|
||||
for pkg in "${PACKAGES[@]}"; do
|
||||
case "$pkg" in
|
||||
"build-essential")
|
||||
if is_arch_family; then
|
||||
FINAL_PACKAGES+=(base-devel)
|
||||
elif is_debian_family; then
|
||||
FINAL_PACKAGES+=(build-essential)
|
||||
elif is_fedora_family; then
|
||||
FINAL_PACKAGES+=(gcc gcc-c++ make patch)
|
||||
fi
|
||||
continue
|
||||
;;
|
||||
"python")
|
||||
if is_arch_family; then
|
||||
FINAL_PACKAGES+=(python)
|
||||
elif is_debian_family; then
|
||||
FINAL_PACKAGES+=(python3 python3-pip python3-venv)
|
||||
elif is_fedora_family; then
|
||||
FINAL_PACKAGES+=(python3 python3-pip)
|
||||
fi
|
||||
continue
|
||||
;;
|
||||
"fd")
|
||||
if is_arch_family; then
|
||||
FINAL_PACKAGES+=(fd)
|
||||
elif is_debian_family || is_fedora_family; then
|
||||
FINAL_PACKAGES+=(fd-find)
|
||||
fi
|
||||
continue
|
||||
;;
|
||||
"bat")
|
||||
FINAL_PACKAGES+=(bat)
|
||||
continue
|
||||
;;
|
||||
"openssl")
|
||||
if is_arch_family; then
|
||||
FINAL_PACKAGES+=(openssl)
|
||||
elif is_debian_family; then
|
||||
FINAL_PACKAGES+=(libssl-dev)
|
||||
elif is_fedora_family; then
|
||||
FINAL_PACKAGES+=(openssl openssl-devel)
|
||||
fi
|
||||
continue
|
||||
;;
|
||||
"bind")
|
||||
if is_arch_family; then
|
||||
FINAL_PACKAGES+=(bind)
|
||||
elif is_debian_family; then
|
||||
FINAL_PACKAGES+=(dnsutils)
|
||||
elif is_fedora_family; then
|
||||
FINAL_PACKAGES+=(bind-utils)
|
||||
fi
|
||||
continue
|
||||
;;
|
||||
"ninja-build")
|
||||
if is_arch_family; then
|
||||
FINAL_PACKAGES+=(ninja)
|
||||
elif is_debian_family || is_fedora_family; then
|
||||
FINAL_PACKAGES+=(ninja-build)
|
||||
fi
|
||||
continue
|
||||
;;
|
||||
"libcurl4-openssl-dev")
|
||||
if is_arch_family; then
|
||||
FINAL_PACKAGES+=(curl)
|
||||
elif is_debian_family; then
|
||||
FINAL_PACKAGES+=(libcurl4-openssl-dev)
|
||||
elif is_fedora_family; then
|
||||
FINAL_PACKAGES+=(libcurl-devel)
|
||||
fi
|
||||
continue
|
||||
;;
|
||||
"gnupg")
|
||||
if is_fedora_family; then
|
||||
FINAL_PACKAGES+=(gnupg2)
|
||||
else
|
||||
FINAL_PACKAGES+=(gnupg)
|
||||
fi
|
||||
continue
|
||||
;;
|
||||
*)
|
||||
esac
|
||||
|
||||
FINAL_PACKAGES+=("$pkg")
|
||||
done
|
||||
|
||||
if is_debian_family; then
|
||||
FINAL_PACKAGES+=(ca-certificates bsdmainutils pkg-config cmake)
|
||||
fi
|
||||
|
||||
if is_fedora_family; then
|
||||
FINAL_PACKAGES+=(ca-certificates pkgconf-pkg-config cmake)
|
||||
FINAL_PACKAGES+=(R-core gcc-gfortran bzip2 bzip2-devel readline-devel sqlite sqlite-devel tk-devel libffi-devel xz xz-devel ncurses-devel zlib-devel findutils llvm)
|
||||
fi
|
||||
|
||||
echo -e "${BLUE} LOG:${YELLOW} Installing: ${NC}${FINAL_PACKAGES[*]}"
|
||||
|
||||
install_status=0
|
||||
install_packages "${FINAL_PACKAGES[@]}" || install_status=$?
|
||||
|
||||
if [ "$install_status" -eq 42 ]; then
|
||||
exit 0
|
||||
elif [ "$install_status" -ne 0 ]; then
|
||||
exit "$install_status"
|
||||
fi
|
||||
|
||||
if is_debian_family || is_fedora_family; then
|
||||
echo -e "${BLUE} LOG:${YELLOW} Fixing fd/bat binary names when needed...${NC}"
|
||||
[ -f /usr/bin/fdfind ] && sudo ln -sf /usr/bin/fdfind /usr/local/bin/fd
|
||||
[ -f /usr/bin/batcat ] && sudo ln -sf /usr/bin/batcat /usr/local/bin/bat
|
||||
fi
|
||||
|
||||
# Installing pinned repo-managed CLI binaries
|
||||
bash "$REPO_ROOT/Scripts/bin/install.sh" --all
|
||||
|
||||
if ! command -v rclone &> /dev/null; then
|
||||
echo -e "${BLUE} LOG:${YELLOW} Installing Rclone CLI...${NC}"
|
||||
|
||||
case "$ARCH" in
|
||||
x86_64)
|
||||
RCLONE_ARCH="amd64"
|
||||
;;
|
||||
aarch64)
|
||||
RCLONE_ARCH="arm64"
|
||||
;;
|
||||
esac
|
||||
|
||||
TEMP_DIR="$(mktemp -d)"
|
||||
RCLONE_ZIP="$TEMP_DIR/rclone.zip"
|
||||
|
||||
curl -fLsS "https://downloads.rclone.org/rclone-current-linux-${RCLONE_ARCH}.zip" -o "$RCLONE_ZIP"
|
||||
unzip -q "$RCLONE_ZIP" -d "$TEMP_DIR"
|
||||
install -m 755 "$TEMP_DIR"/rclone-*-linux-"${RCLONE_ARCH}"/rclone "$HOME/.local/bin/rclone"
|
||||
rm -rf "$TEMP_DIR"
|
||||
fi
|
||||
|
||||
if ! command -v earthly &> /dev/null; then
|
||||
echo -e "${BLUE} LOG:${YELLOW} Installing Earthly CLI...${NC}"
|
||||
|
||||
case "$ARCH" in
|
||||
x86_64)
|
||||
EARTHLY_ARCH="amd64"
|
||||
;;
|
||||
aarch64)
|
||||
EARTHLY_ARCH="arm64"
|
||||
;;
|
||||
esac
|
||||
|
||||
curl -fLsS "https://github.com/earthly/earthly/releases/latest/download/earthly-linux-${EARTHLY_ARCH}" \
|
||||
-o "$HOME/.local/bin/earthly"
|
||||
chmod +x "$HOME/.local/bin/earthly"
|
||||
fi
|
||||
|
||||
# Docker Installation
|
||||
if command -v docker &> /dev/null; then
|
||||
echo -e "${GREEN} LOG: Docker is already installed.${NC}"
|
||||
else
|
||||
if grep -qEi "(Microsoft|WSL)" /proc/version &> /dev/null; then
|
||||
echo -e "${RED} LOG: WSL Detected! Skipping Native Docker.${NC}"
|
||||
echo -e "${RED} >>> Please install Docker Desktop on Windows.${NC}"
|
||||
else
|
||||
echo -e "${BLUE} LOG:${YELLOW} Installing Native Docker...${NC}"
|
||||
if is_arch_family; then
|
||||
sudo pacman -S --noconfirm --needed docker docker-compose
|
||||
sudo systemctl enable --now docker
|
||||
elif is_debian_family; then
|
||||
curl -fsSL https://get.docker.com | sh
|
||||
elif is_fedora_family; then
|
||||
if is_atomic_fedora; then
|
||||
echo -e "${YELLOW} NOTE:${NC} Skipping native Docker auto-install on rpm-ostree systems."
|
||||
echo -e "${YELLOW} NOTE:${NC} After reboot, install your preferred container runtime separately if needed."
|
||||
else
|
||||
sudo dnf install -y moby-engine docker-compose
|
||||
sudo systemctl enable --now docker
|
||||
fi
|
||||
fi
|
||||
|
||||
# Add user to group
|
||||
if getent group docker >/dev/null 2>&1; then
|
||||
sudo usermod -aG docker $(whoami)
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# 4. Zsh & Configuration
|
||||
if [ ! -d "$HOME/.oh-my-zsh" ]; then
|
||||
echo -e "${BLUE} LOG:${YELLOW} Installing Oh My Zsh...${NC}"
|
||||
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" "" --unattended
|
||||
fi
|
||||
|
||||
# Plugins
|
||||
ZSH_CUSTOM="${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}"
|
||||
mkdir -p "$ZSH_CUSTOM/plugins"
|
||||
[ ! -d "$ZSH_CUSTOM/plugins/zsh-syntax-highlighting" ] && git clone https://github.com/zsh-users/zsh-syntax-highlighting.git "$ZSH_CUSTOM/plugins/zsh-syntax-highlighting"
|
||||
[ ! -d "$ZSH_CUSTOM/plugins/zsh-autosuggestions" ] && git clone https://github.com/zsh-users/zsh-autosuggestions "$ZSH_CUSTOM/plugins/zsh-autosuggestions"
|
||||
|
||||
# 5. Git Credentials (WSL Bridge)
|
||||
if grep -qEi "(Microsoft|WSL)" /proc/version &> /dev/null; then
|
||||
GCM_WIN="/mnt/c/Program Files/Git/mingw64/bin/git-credential-manager.exe"
|
||||
[ -f "$GCM_WIN" ] && git config --global credential.helper "! \"$GCM_WIN\""
|
||||
else
|
||||
git config --global credential.helper 'cache --timeout=43200'
|
||||
fi
|
||||
|
||||
# 6. Cleanup & Secrets
|
||||
rm -f "$HOME/.zshrc" "$HOME/.zsh_aliases"
|
||||
mkdir -p "$REPO_ROOT/Zsh"
|
||||
touch "$REPO_ROOT/Zsh/.zsh_secrets"
|
||||
|
||||
# 7. Set Shell
|
||||
TARGET_SHELL="$(command -v zsh)"
|
||||
CURRENT_LOGIN_SHELL="$(getent passwd "$(whoami)" | cut -d: -f7)"
|
||||
|
||||
if [ "$CURRENT_LOGIN_SHELL" != "$TARGET_SHELL" ]; then
|
||||
if command -v chsh >/dev/null 2>&1; then
|
||||
sudo chsh -s "$TARGET_SHELL" "$(whoami)"
|
||||
elif command -v usermod >/dev/null 2>&1; then
|
||||
sudo usermod -s "$TARGET_SHELL" "$(whoami)"
|
||||
else
|
||||
echo -e "${YELLOW} NOTE:${NC} Could not find chsh/usermod. Please change your login shell to $TARGET_SHELL manually."
|
||||
fi
|
||||
fi
|
||||
|
||||
echo -e "${GREEN} LOG: Base System Setup Complete.${NC}"
|
||||
99
Scripts/bin/install.sh
Normal file
99
Scripts/bin/install.sh
Normal file
@@ -0,0 +1,99 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(dirname "$(dirname "$SCRIPT_DIR")")"
|
||||
MANIFEST="$REPO_ROOT/Bins/versions.json"
|
||||
TARGET_DIR="$HOME/.local/bin"
|
||||
|
||||
ensure_deps() {
|
||||
local missing=()
|
||||
|
||||
for cmd in jq curl tar; do
|
||||
if ! command -v "$cmd" >/dev/null 2>&1; then
|
||||
missing+=("$cmd")
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "${#missing[@]}" -gt 0 ]; then
|
||||
printf 'Missing required commands: %s\n' "${missing[*]}" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
detect_arch() {
|
||||
case "$(uname -m)" in
|
||||
x86_64) printf 'x86_64\n' ;;
|
||||
aarch64|arm64) printf 'aarch64\n' ;;
|
||||
*)
|
||||
printf 'Unsupported architecture: %s\n' "$(uname -m)" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
install_tool() {
|
||||
local tool="$1"
|
||||
local arch version owner repo asset binary_rel url tmp_dir archive_path extracted_path target_path
|
||||
|
||||
arch="$(detect_arch)"
|
||||
|
||||
if ! jq -e --arg tool "$tool" '.[$tool]' "$MANIFEST" >/dev/null; then
|
||||
printf 'Unsupported tool: %s\n' "$tool" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
version="$(jq -r --arg tool "$tool" '.[$tool].version' "$MANIFEST")"
|
||||
owner="$(jq -r --arg tool "$tool" '.[$tool].owner' "$MANIFEST")"
|
||||
repo="$(jq -r --arg tool "$tool" '.[$tool].repo' "$MANIFEST")"
|
||||
asset="$(jq -r --arg tool "$tool" --arg arch "$arch" '.[$tool].linux[$arch].asset' "$MANIFEST")"
|
||||
binary_rel="$(jq -r --arg tool "$tool" --arg arch "$arch" '.[$tool].linux[$arch].binary' "$MANIFEST")"
|
||||
|
||||
if [ -z "$asset" ] || [ "$asset" = "null" ] || [ -z "$binary_rel" ] || [ "$binary_rel" = "null" ]; then
|
||||
printf 'No Linux asset mapping for %s on %s\n' "$tool" "$arch" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p "$TARGET_DIR"
|
||||
tmp_dir="$(mktemp -d)"
|
||||
archive_path="$tmp_dir/$asset"
|
||||
url="https://github.com/$owner/$repo/releases/download/$version/$asset"
|
||||
|
||||
printf 'Installing %s %s\n' "$tool" "$version"
|
||||
curl -fL "$url" -o "$archive_path"
|
||||
tar -xzf "$archive_path" -C "$tmp_dir"
|
||||
|
||||
extracted_path="$tmp_dir/$binary_rel"
|
||||
if [ ! -f "$extracted_path" ]; then
|
||||
printf 'Expected binary not found after extraction: %s\n' "$binary_rel" >&2
|
||||
rm -rf "$tmp_dir"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
target_path="$TARGET_DIR/$tool"
|
||||
install -m 755 "$extracted_path" "$target_path"
|
||||
rm -rf "$tmp_dir"
|
||||
|
||||
printf 'Installed %s -> %s\n' "$tool" "$target_path"
|
||||
}
|
||||
|
||||
main() {
|
||||
ensure_deps
|
||||
|
||||
if [ "${1:-}" = "--all" ]; then
|
||||
while IFS= read -r tool; do
|
||||
install_tool "$tool"
|
||||
done < <(jq -r 'keys[]' "$MANIFEST")
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ -z "${1:-}" ]; then
|
||||
printf 'Usage: %s [--all|tool]\n' "$0" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
install_tool "$1"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
135
Scripts/bin/update.sh
Normal file
135
Scripts/bin/update.sh
Normal file
@@ -0,0 +1,135 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(dirname "$(dirname "$SCRIPT_DIR")")"
|
||||
MANIFEST="$REPO_ROOT/Bins/versions.json"
|
||||
|
||||
ensure_deps() {
|
||||
local missing=()
|
||||
|
||||
for cmd in jq curl python3; do
|
||||
if ! command -v "$cmd" >/dev/null 2>&1; then
|
||||
missing+=("$cmd")
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "${#missing[@]}" -gt 0 ]; then
|
||||
printf 'Missing required commands: %s\n' "${missing[*]}" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
github_api() {
|
||||
local path="$1"
|
||||
local auth_args=()
|
||||
|
||||
if [ -n "${GITHUB_TOKEN:-}" ]; then
|
||||
auth_args=(-H "Authorization: Bearer $GITHUB_TOKEN")
|
||||
fi
|
||||
|
||||
curl -fsSL \
|
||||
-H "Accept: application/vnd.github+json" \
|
||||
"${auth_args[@]}" \
|
||||
"https://api.github.com${path}"
|
||||
}
|
||||
|
||||
list_versions() {
|
||||
local tool="$1" owner repo
|
||||
|
||||
if ! jq -e --arg tool "$tool" '.[$tool]' "$MANIFEST" >/dev/null; then
|
||||
printf 'Unsupported tool: %s\n' "$tool" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
owner="$(jq -r --arg tool "$tool" '.[$tool].owner' "$MANIFEST")"
|
||||
repo="$(jq -r --arg tool "$tool" '.[$tool].repo' "$MANIFEST")"
|
||||
|
||||
github_api "/repos/$owner/$repo/releases?per_page=100" | jq -r '.[].tag_name'
|
||||
}
|
||||
|
||||
select_version() {
|
||||
local tool="$1"
|
||||
local versions
|
||||
|
||||
versions="$(list_versions "$tool")"
|
||||
|
||||
if [ -z "$versions" ]; then
|
||||
printf 'No releases found for %s\n' "$tool" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if command -v fzf >/dev/null 2>&1; then
|
||||
printf '%s\n' "$versions" | fzf --prompt="Select ${tool} version > " --height=20 --reverse
|
||||
else
|
||||
printf '%s\n' "$versions" | sed -n '1,20p' >&2
|
||||
printf 'fzf is not installed, so pass a version explicitly.\n' >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
update_version() {
|
||||
local tool="$1" version="$2"
|
||||
local tmp_file
|
||||
|
||||
if [ -z "$version" ]; then
|
||||
printf 'No version selected for %s\n' "$tool" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
tmp_file="$(mktemp)"
|
||||
python3 - "$MANIFEST" "$tool" "$version" "$tmp_file" <<'PY'
|
||||
import json
|
||||
import pathlib
|
||||
import sys
|
||||
|
||||
manifest_path = pathlib.Path(sys.argv[1])
|
||||
tool = sys.argv[2]
|
||||
version = sys.argv[3]
|
||||
tmp_path = pathlib.Path(sys.argv[4])
|
||||
|
||||
data = json.loads(manifest_path.read_text())
|
||||
if tool not in data:
|
||||
raise SystemExit(f"Unsupported tool: {tool}")
|
||||
|
||||
data[tool]["version"] = version
|
||||
tmp_path.write_text(json.dumps(data, indent=2) + "\n")
|
||||
PY
|
||||
|
||||
mv "$tmp_file" "$MANIFEST"
|
||||
printf 'Pinned %s to %s\n' "$tool" "$version"
|
||||
}
|
||||
|
||||
main() {
|
||||
local mode="update" tool version
|
||||
|
||||
ensure_deps
|
||||
|
||||
if [ "${1:-}" = "--list" ]; then
|
||||
mode="list"
|
||||
shift
|
||||
fi
|
||||
|
||||
tool="${1:-}"
|
||||
version="${2:-}"
|
||||
|
||||
if [ -z "$tool" ]; then
|
||||
printf 'Usage: %s [--list] tool [version]\n' "$0" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
case "$mode" in
|
||||
list)
|
||||
list_versions "$tool"
|
||||
;;
|
||||
update)
|
||||
if [ -z "$version" ]; then
|
||||
version="$(select_version "$tool")"
|
||||
fi
|
||||
update_version "$tool" "$version"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
main "$@"
|
||||
38
Scripts/cpp.sh
Normal file
38
Scripts/cpp.sh
Normal file
@@ -0,0 +1,38 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Path: Scripts/cpp.sh
|
||||
|
||||
set -e
|
||||
|
||||
BLUE='\033[1;34m'
|
||||
YELLOW='\033[1;33m'
|
||||
GREEN='\033[1;32m'
|
||||
NC='\033[0m'
|
||||
|
||||
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
source "$SCRIPT_DIR/lib/distro.sh"
|
||||
|
||||
echo -e "${BLUE} LOG:${YELLOW} Setting up C++ Tooling (LLVM/Clang)...${NC}"
|
||||
|
||||
if is_arch_family; then
|
||||
CPP_PACKAGES=(clang cmake ninja lldb gdb)
|
||||
elif is_debian_family || is_fedora_family; then
|
||||
CPP_PACKAGES=(clang cmake ninja-build lldb gdb)
|
||||
else
|
||||
echo -e "${RED} ERROR:${NC} Unsupported OS: $OS"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
install_status=0
|
||||
install_packages "${CPP_PACKAGES[@]}" || install_status=$?
|
||||
|
||||
if [ "$install_status" -eq 42 ]; then
|
||||
exit 0
|
||||
elif [ "$install_status" -ne 0 ]; then
|
||||
exit "$install_status"
|
||||
fi
|
||||
|
||||
echo -e "${GREEN} SUCCESS:${NC} C++ Environment Ready."
|
||||
echo -e " - Compiler: $(clang --version | head -n 1)"
|
||||
echo -e " - Builder: $(cmake --version | head -n 1)"
|
||||
echo -e " - Debugger: $(lldb --version | head -n 1)"
|
||||
80
Scripts/go.sh
Normal file
80
Scripts/go.sh
Normal file
@@ -0,0 +1,80 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Path: Scripts/go.sh
|
||||
|
||||
set -e
|
||||
|
||||
BLUE='\033[1;34m'
|
||||
YELLOW='\033[1;33m'
|
||||
GREEN='\033[1;32m'
|
||||
RED='\033[1;31m'
|
||||
NC='\033[0m'
|
||||
|
||||
export GVM_ROOT="$HOME/.programming/go"
|
||||
BOOTSTRAP_GO="$GVM_ROOT/bootstrap"
|
||||
|
||||
ARCH="$(uname -m)"
|
||||
|
||||
case "$ARCH" in
|
||||
x86_64)
|
||||
GO_BOOTSTRAP_ARCH="amd64"
|
||||
;;
|
||||
aarch64)
|
||||
GO_BOOTSTRAP_ARCH="arm64"
|
||||
;;
|
||||
*)
|
||||
echo -e "${RED} ERROR:${NC} Unsupported architecture for Go bootstrap: $ARCH"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
echo -e "${BLUE} LOG:${YELLOW} Setting up Go and GVM in ${GVM_ROOT}...${NC}"
|
||||
|
||||
if [ ! -d "$GVM_ROOT/scripts" ]; then
|
||||
echo -e "${BLUE} LOG:${YELLOW} Cloning GVM...${NC}"
|
||||
git clone https://github.com/moovweb/gvm.git "$GVM_ROOT"
|
||||
rm -rf "$GVM_ROOT/.git"
|
||||
echo -e "${BLUE} LOG:${YELLOW} Configuring GVM scripts...${NC}"
|
||||
cp "$GVM_ROOT/scripts/gvm-default" "$GVM_ROOT/scripts/gvm"
|
||||
sed -i "s|^GVM_ROOT=.*|GVM_ROOT=\"$GVM_ROOT\"|" "$GVM_ROOT/scripts/gvm"
|
||||
|
||||
echo -e "${GREEN} SUCCESS:${NC} GVM cloned and configured."
|
||||
else
|
||||
echo -e "${GREEN} SKIP:${NC} GVM already installed."
|
||||
fi
|
||||
|
||||
if [ ! -d "$BOOTSTRAP_GO" ]; then
|
||||
echo -e "${BLUE} LOG:${YELLOW} Downloading Bootstrap Go...${NC}"
|
||||
mkdir -p "$BOOTSTRAP_GO"
|
||||
|
||||
wget -q "https://go.dev/dl/go1.20.5.linux-${GO_BOOTSTRAP_ARCH}.tar.gz" -O /tmp/go-bootstrap.tar.gz
|
||||
tar -C "$BOOTSTRAP_GO" -xzf /tmp/go-bootstrap.tar.gz --strip-components=1
|
||||
rm /tmp/go-bootstrap.tar.gz
|
||||
|
||||
echo -e "${GREEN} SUCCESS:${NC} Bootstrap Go installed."
|
||||
else
|
||||
echo -e "${GREEN} SKIP:${NC} Bootstrap Go already exists."
|
||||
fi
|
||||
|
||||
export PATH="$BOOTSTRAP_GO/bin:$PATH"
|
||||
export GOROOT_BOOTSTRAP="$BOOTSTRAP_GO"
|
||||
|
||||
set +e
|
||||
source "$GVM_ROOT/scripts/gvm"
|
||||
set -e
|
||||
|
||||
if ! command -v gvm &> /dev/null; then
|
||||
echo -e "${RED} ERROR:${NC} GVM failed to load."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
TARGET_VER="go1.24.11"
|
||||
|
||||
if ! gvm list | grep -q "$TARGET_VER"; then
|
||||
echo -e "${BLUE} LOG:${YELLOW} Installing ${TARGET_VER}...${NC}"
|
||||
gvm install "$TARGET_VER" --prefer-binary
|
||||
fi
|
||||
|
||||
gvm use "$TARGET_VER" --default
|
||||
|
||||
echo -e "${GREEN} SUCCESS:${NC} Go setup completed."
|
||||
131
Scripts/lib/distro.sh
Normal file
131
Scripts/lib/distro.sh
Normal file
@@ -0,0 +1,131 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Shared distro helpers for install scripts.
|
||||
|
||||
SCRIPT_LIB_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="${REPO_ROOT:-$(dirname "$(dirname "$SCRIPT_LIB_DIR")")}"
|
||||
REBOOT_MARKER="${REBOOT_MARKER:-$REPO_ROOT/.setup-reboot-required}"
|
||||
|
||||
if [ -f /etc/os-release ]; then
|
||||
. /etc/os-release
|
||||
OS="${ID}"
|
||||
OS_LIKE="${ID_LIKE:-}"
|
||||
else
|
||||
echo "Unable to detect operating system: /etc/os-release not found."
|
||||
return 1 2>/dev/null || exit 1
|
||||
fi
|
||||
|
||||
is_arch_family() {
|
||||
[[ "$OS" == "arch" || "$OS" == "manjaro" || " $OS_LIKE " == *" arch "* ]]
|
||||
}
|
||||
|
||||
is_debian_family() {
|
||||
[[ "$OS" == "ubuntu" || "$OS" == "debian" || " $OS_LIKE " == *" debian "* ]]
|
||||
}
|
||||
|
||||
is_fedora_family() {
|
||||
[[ "$OS" == "fedora" || "$OS" == "bazzite" || " $OS_LIKE " == *" fedora "* || " $OS_LIKE " == *" rhel "* ]]
|
||||
}
|
||||
|
||||
is_atomic_fedora() {
|
||||
is_fedora_family && command -v rpm-ostree >/dev/null 2>&1 && [ -f /run/ostree-booted ]
|
||||
}
|
||||
|
||||
mark_reboot_required() {
|
||||
touch "$REBOOT_MARKER"
|
||||
echo ""
|
||||
echo " REBOOT REQUIRED: Fedora atomic package layering finished."
|
||||
echo " Please reboot, then rerun the same make target."
|
||||
echo ""
|
||||
}
|
||||
|
||||
get_atomic_requested_packages() {
|
||||
local python_bin=""
|
||||
local candidate
|
||||
|
||||
for candidate in python3 python /usr/libexec/platform-python; do
|
||||
if command -v "$candidate" >/dev/null 2>&1; then
|
||||
python_bin="$candidate"
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -z "$python_bin" ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
rpm-ostree status --json 2>/dev/null | "$python_bin" -c '
|
||||
import json, sys
|
||||
|
||||
try:
|
||||
data = json.load(sys.stdin)
|
||||
except Exception:
|
||||
raise SystemExit(0)
|
||||
|
||||
for deployment in data.get("deployments", []):
|
||||
if deployment.get("booted"):
|
||||
for key in ("requested-packages", "requested-local-packages"):
|
||||
for package in deployment.get(key, []):
|
||||
if package:
|
||||
print(package)
|
||||
break
|
||||
'
|
||||
}
|
||||
|
||||
install_packages() {
|
||||
local packages=("$@")
|
||||
|
||||
if [ ${#packages[@]} -eq 0 ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
if is_arch_family; then
|
||||
sudo pacman -S --noconfirm --needed "${packages[@]}"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if is_debian_family; then
|
||||
sudo DEBIAN_FRONTEND=noninteractive apt-get update
|
||||
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y "${packages[@]}"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if is_fedora_family; then
|
||||
if is_atomic_fedora; then
|
||||
local requested_pkg
|
||||
local missing_packages=()
|
||||
declare -A requested_packages=()
|
||||
local pkg
|
||||
|
||||
while IFS= read -r requested_pkg; do
|
||||
[ -n "$requested_pkg" ] && requested_packages["$requested_pkg"]=1
|
||||
done < <(get_atomic_requested_packages)
|
||||
|
||||
for pkg in "${packages[@]}"; do
|
||||
if rpm -q "$pkg" >/dev/null 2>&1; then
|
||||
continue
|
||||
fi
|
||||
|
||||
if [ -n "${requested_packages[$pkg]:-}" ]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
missing_packages+=("$pkg")
|
||||
done
|
||||
|
||||
if [ ${#missing_packages[@]} -eq 0 ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
sudo rpm-ostree install "${missing_packages[@]}"
|
||||
mark_reboot_required
|
||||
return 42
|
||||
fi
|
||||
|
||||
sudo dnf install -y "${packages[@]}"
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo "Unsupported OS: $OS"
|
||||
return 1
|
||||
}
|
||||
39
Scripts/node.sh
Normal file
39
Scripts/node.sh
Normal file
@@ -0,0 +1,39 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Path: Scripts/node.sh
|
||||
|
||||
set -e
|
||||
|
||||
BLUE='\033[1;34m'
|
||||
YELLOW='\033[1;33m'
|
||||
GREEN='\033[1;32m'
|
||||
NC='\033[0m'
|
||||
|
||||
export NVM_DIR="$HOME/.programming/node"
|
||||
export COREPACK_ENABLE_DOWNLOAD_PROMPT=0
|
||||
|
||||
echo -e "${BLUE} LOG:${YELLOW} Setting up Node.js (NVM) in ${NVM_DIR}...${NC}"
|
||||
|
||||
if [ ! -d "$NVM_DIR" ]; then
|
||||
mkdir -p "$NVM_DIR"
|
||||
echo -e "${BLUE} LOG:${YELLOW} Installing NVM to custom path...${NC}"
|
||||
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | PROFILE=/dev/null bash
|
||||
fi
|
||||
|
||||
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"
|
||||
|
||||
if command -v nvm &> /dev/null; then
|
||||
echo -e "${BLUE} LOG:${YELLOW} Installing Node LTS...${NC}"
|
||||
nvm install --lts --no-progress
|
||||
nvm use --lts
|
||||
|
||||
echo -e "${BLUE} LOG:${YELLOW} Enabling Corepack (pnpm/yarn)...${NC}"
|
||||
|
||||
corepack enable
|
||||
|
||||
echo -e "${GREEN} LOG: Node setup complete. $(node -v)${NC}"
|
||||
echo -e "${GREEN} LOG: Package Managers: pnpm $(pnpm -v), yarn $(yarn -v)${NC}"
|
||||
else
|
||||
echo -e "${RED} ERROR: NVM failed to load from $NVM_DIR${NC}"
|
||||
exit 1
|
||||
fi
|
||||
118
Scripts/provision.sh
Normal file
118
Scripts/provision.sh
Normal file
@@ -0,0 +1,118 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Path: Scripts/provision.sh
|
||||
|
||||
set -e
|
||||
|
||||
GREEN='\033[1;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
RED='\033[1;31m'
|
||||
NC='\033[0m'
|
||||
|
||||
DEFAULT_USER="mangopig"
|
||||
DEFAULT_UID="1000"
|
||||
DEFAULT_GID="1000"
|
||||
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
source "$SCRIPT_DIR/lib/distro.sh"
|
||||
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
echo -e "${RED}Please run this script as root.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -e "${YELLOW}LOG: Detecting OS...${NC}"
|
||||
|
||||
echo -e "${YELLOW}LOG: Determining primary IPv4 address...${NC}"
|
||||
if command -v hostname >/dev/null 2>&1 && hostname -I >/dev/null 2>&1; then
|
||||
IP=$(hostname -I | awk '{print $1}')
|
||||
elif command -v ip >/dev/null 2>&1; then
|
||||
IP=$(ip route get 1.1.1.1 2>/dev/null | awk '/src/ {print $NF; exit}')
|
||||
elif command -v ifconfig >/dev/null 2>&1; then
|
||||
IP=$(ifconfig | awk '/inet /{print $2}' | grep -v '^127' | head -n1)
|
||||
else
|
||||
IP="127.0.0.1"
|
||||
fi
|
||||
|
||||
echo -e "${YELLOW}LOG: Updating system and installing base tools...${NC}"
|
||||
|
||||
if is_arch_family; then
|
||||
pacman -Sy --noconfirm git make curl zsh sudo
|
||||
SUDO_GROUP="wheel"
|
||||
elif is_debian_family; then
|
||||
apt-get update
|
||||
apt-get install -y git make curl sudo zsh
|
||||
SUDO_GROUP="sudo"
|
||||
elif is_fedora_family; then
|
||||
if is_atomic_fedora; then
|
||||
echo -e "${RED}Provisioning on Fedora atomic systems is not supported by this root script.${NC}"
|
||||
echo -e "${RED}Use the normal user workflow and run make setup after login instead.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
dnf install -y git make curl sudo zsh
|
||||
SUDO_GROUP="wheel"
|
||||
else
|
||||
echo -e "${RED}Unsupported OS: $OS${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ZSH_PATH="$(command -v zsh)"
|
||||
|
||||
if [ -t 0 ]; then
|
||||
echo -e "${GREEN}---------------------------------------${NC}"
|
||||
echo -e "${GREEN} USER PROVISIONING WIZARD ${NC}"
|
||||
echo -e "${GREEN}---------------------------------------${NC}"
|
||||
|
||||
read -p "Enter Username (default: $DEFAULT_USER): " INPUT_USER
|
||||
USERNAME=${INPUT_USER:-$DEFAULT_USER}
|
||||
|
||||
read -p "Enter UID (default: $DEFAULT_UID): " INPUT_UID
|
||||
USER_UID=${INPUT_UID:-$DEFAULT_UID}
|
||||
|
||||
read -p "Enter GID (default: $DEFAULT_GID): " INPUT_GID
|
||||
USER_GID=${INPUT_GID:-$DEFAULT_GID}
|
||||
else
|
||||
echo -e "${YELLOW}LOG: Non-interactive session detected. Using defaults.${NC}"
|
||||
USERNAME=${USERNAME:-$DEFAULT_USER}
|
||||
USER_UID=${USER_UID:-$DEFAULT_UID}
|
||||
USER_GID=${USER_GID:-$DEFAULT_GID}
|
||||
fi
|
||||
|
||||
if getent group "$USER_GID" >/dev/null; then
|
||||
echo -e "${YELLOW}LOG: Group with GID $USER_GID already exists. Using it.${NC}"
|
||||
else
|
||||
echo -e "${YELLOW}LOG: Creating group $USERNAME with GID $USER_GID...${NC}"
|
||||
groupadd -g "$USER_GID" "$USERNAME"
|
||||
fi
|
||||
|
||||
if id "$USERNAME" &>/dev/null; then
|
||||
echo -e "${YELLOW}LOG: User $USERNAME already exists. Skipping creation.${NC}"
|
||||
else
|
||||
echo -e "${YELLOW}LOG: Creating user $USERNAME...${NC}"
|
||||
useradd -m -u "$USER_UID" -g "$USER_GID" -G "$SUDO_GROUP" -s "$ZSH_PATH" "$USERNAME"
|
||||
echo -e "${GREEN}LOG: Setting password for $USERNAME...${NC}"
|
||||
|
||||
if [ -t 0 ]; then
|
||||
echo -e "${GREEN}LOG: Setting password for $USERNAME...${NC}"
|
||||
passwd "$USERNAME"
|
||||
else
|
||||
echo -e "${YELLOW}LOG: Non-interactive: Setting password to '$USERNAME'...${NC}"
|
||||
echo "$USERNAME:$USERNAME" | chpasswd
|
||||
fi
|
||||
fi
|
||||
|
||||
echo -e "${YELLOW}LOG: Configuring passwordless sudo...${NC}"
|
||||
echo "$USERNAME ALL=(ALL) NOPASSWD:ALL" > "/etc/sudoers.d/90-$USERNAME"
|
||||
chmod 0440 "/etc/sudoers.d/90-$USERNAME"
|
||||
|
||||
if is_arch_family || is_fedora_family; then
|
||||
sed -i 's/^# %wheel ALL=(ALL:ALL) ALL/%wheel ALL=(ALL:ALL) ALL/' /etc/sudoers
|
||||
fi
|
||||
|
||||
echo -e "${YELLOW}LOG: Cloning dotfiles for $USERNAME...${NC}"
|
||||
sudo -u "$USERNAME" git clone https://git.mangopig.tech/MangoPig/Dot-Zsh.git "/home/$USERNAME/Config/Dot-Zsh"
|
||||
|
||||
|
||||
echo -e "${GREEN}✅ Server Provisioned!"
|
||||
echo -e "${GREEN} sudo su - $USERNAME${NC} OR logout and SSH back in as $USERNAME@$IP.${NC}"
|
||||
echo -e "${GREEN} Then run cd ~/Config/Dot-Zsh && make setup ${NC}"
|
||||
78
Scripts/python.sh
Normal file
78
Scripts/python.sh
Normal file
@@ -0,0 +1,78 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Path: Scripts/python.sh
|
||||
set -e
|
||||
|
||||
BLUE='\033[1;34m'
|
||||
YELLOW='\033[1;33m'
|
||||
GREEN='\033[1;32m'
|
||||
RED='\033[1;31m'
|
||||
NC='\033[0m'
|
||||
|
||||
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
source "$SCRIPT_DIR/lib/distro.sh"
|
||||
|
||||
# Install Build Dependencies
|
||||
if is_arch_family; then
|
||||
echo -e "${BLUE} LOG:${YELLOW} Installing Arch build dependencies...${NC}"
|
||||
PYTHON_BUILD_DEPS=(base-devel openssl zlib xz tk libffi bzip2 git)
|
||||
elif is_debian_family; then
|
||||
echo -e "${BLUE} LOG:${YELLOW} Installing Debian build dependencies...${NC}"
|
||||
PYTHON_BUILD_DEPS=(make build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev libncursesw5-dev xz-utils tk-dev libffi-dev liblzma-dev git)
|
||||
elif is_fedora_family; then
|
||||
echo -e "${BLUE} LOG:${YELLOW} Installing Fedora build dependencies...${NC}"
|
||||
PYTHON_BUILD_DEPS=(make gcc gcc-c++ patch zlib-devel bzip2 bzip2-devel readline-devel sqlite sqlite-devel openssl-devel tk-devel libffi-devel xz xz-devel ncurses-devel findutils git)
|
||||
else
|
||||
echo -e "${RED} ERROR:${NC} Unsupported OS: $OS"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
install_status=0
|
||||
install_packages "${PYTHON_BUILD_DEPS[@]}" || install_status=$?
|
||||
|
||||
if [ "$install_status" -eq 42 ]; then
|
||||
exit 0
|
||||
elif [ "$install_status" -ne 0 ]; then
|
||||
exit "$install_status"
|
||||
fi
|
||||
|
||||
# Define the Black Box Location
|
||||
export PYENV_ROOT="$HOME/.programming/python/pyenv"
|
||||
export PATH="$PYENV_ROOT/bin:$PATH"
|
||||
|
||||
echo -e "${BLUE} LOG:${YELLOW} Setting up Pyenv in ${PYENV_ROOT}...${NC}"
|
||||
|
||||
# Install Pyenv
|
||||
if [ ! -d "$PYENV_ROOT" ]; then
|
||||
echo -e "${BLUE} LOG:${YELLOW} Cloning Pyenv...${NC}"
|
||||
git clone https://github.com/pyenv/pyenv.git "$PYENV_ROOT"
|
||||
|
||||
echo -e "${BLUE} LOG:${YELLOW} Compiling Pyenv dynamic bash extension...${NC}"
|
||||
cd "$PYENV_ROOT" && src/configure && make -C src
|
||||
|
||||
echo -e "${GREEN} SUCCESS:${NC} Pyenv installed."
|
||||
else
|
||||
echo -e "${GREEN} SKIP:${NC} Pyenv already installed."
|
||||
fi
|
||||
|
||||
# Initialize Pyenv for this script session
|
||||
eval "$(pyenv init -)"
|
||||
|
||||
# Install Miniforge (The Community Standard)
|
||||
TARGET_VER="miniforge3-latest"
|
||||
|
||||
if ! pyenv versions | grep -q "$TARGET_VER"; then
|
||||
echo -e "${BLUE} LOG:${YELLOW} Installing ${TARGET_VER}...${NC}"
|
||||
echo -e "${YELLOW} NOTE: This avoids Anaconda licensing issues and uses conda-forge default.${NC}"
|
||||
|
||||
pyenv install "$TARGET_VER"
|
||||
|
||||
echo -e "${GREEN} SUCCESS:${NC} Miniforge installed."
|
||||
else
|
||||
echo -e "${GREEN} SKIP:${NC} Miniforge already installed."
|
||||
fi
|
||||
|
||||
# Set Global Default
|
||||
pyenv global "$TARGET_VER"
|
||||
|
||||
echo -e "${GREEN} SUCCESS:${NC} Python setup completed. Default is now Miniforge (Conda)."
|
||||
132
Scripts/r.sh
Normal file
132
Scripts/r.sh
Normal file
@@ -0,0 +1,132 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Path: Scripts/r.sh
|
||||
set -e
|
||||
|
||||
BLUE='\033[1;34m'
|
||||
YELLOW='\033[1;33m'
|
||||
GREEN='\033[1;32m'
|
||||
RED='\033[1;31m'
|
||||
NC='\033[0m'
|
||||
|
||||
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
source "$SCRIPT_DIR/lib/distro.sh"
|
||||
|
||||
PROG_DIR="$HOME/.programming"
|
||||
R_ROOT="$PROG_DIR/r"
|
||||
R_BIN_DIR="$R_ROOT/bin"
|
||||
R_LIB_DIR="$R_ROOT/library"
|
||||
|
||||
mkdir -p "$R_BIN_DIR" "$R_LIB_DIR"
|
||||
|
||||
write_r_wrapper() {
|
||||
local target_name="$1"
|
||||
local command_body="$2"
|
||||
|
||||
cat > "$R_BIN_DIR/$target_name" <<EOF
|
||||
#!/bin/bash
|
||||
set -e
|
||||
export R_LIBS_USER="$R_LIB_DIR"
|
||||
$command_body "\$@"
|
||||
EOF
|
||||
|
||||
chmod +x "$R_BIN_DIR/$target_name"
|
||||
}
|
||||
|
||||
echo -e "${BLUE} LOG:${YELLOW} Detecting R installation strategy for $OS...${NC}"
|
||||
|
||||
if is_arch_family; then
|
||||
|
||||
echo -e "${BLUE} LOG:${YELLOW} Arch Linux detected. Using system R (Pacman)...${NC}"
|
||||
|
||||
# Install R + Build Tools
|
||||
install_status=0
|
||||
install_packages r gcc-fortran curl tar || install_status=$?
|
||||
if [ "$install_status" -eq 42 ]; then
|
||||
exit 0
|
||||
elif [ "$install_status" -ne 0 ]; then
|
||||
exit "$install_status"
|
||||
fi
|
||||
|
||||
echo -e "${GREEN} SUCCESS:${NC} R installed via Pacman."
|
||||
|
||||
R_BIN="R"
|
||||
write_r_wrapper "R" 'exec "$(command -v R)"'
|
||||
write_r_wrapper "Rscript" 'exec "$(command -v Rscript)"'
|
||||
|
||||
elif is_debian_family; then
|
||||
|
||||
echo -e "${BLUE} LOG:${YELLOW} Installing Debian build dependencies...${NC}"
|
||||
install_status=0
|
||||
install_packages gfortran curl tar ca-certificates || install_status=$?
|
||||
if [ "$install_status" -eq 42 ]; then
|
||||
exit 0
|
||||
elif [ "$install_status" -ne 0 ]; then
|
||||
exit "$install_status"
|
||||
fi
|
||||
|
||||
if ! command -v rig >/dev/null 2>&1; then
|
||||
echo -e "${BLUE} LOG:${YELLOW} Installing Rig for Debian/Ubuntu...${NC}"
|
||||
|
||||
DEB_ARCH=$(dpkg --print-architecture)
|
||||
case "$DEB_ARCH" in
|
||||
amd64|arm64)
|
||||
;;
|
||||
*)
|
||||
echo -e "${RED} ERROR:${NC} Unsupported Debian architecture for Rig: $DEB_ARCH"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
LATEST_REL_DATA=$(curl -fsSL https://api.github.com/repos/r-lib/rig/releases/latest)
|
||||
RIG_URL=$(echo "$LATEST_REL_DATA" | grep -o "https://[^\"]*r-rig_[^\"]*_${DEB_ARCH}\.deb" | head -n 1)
|
||||
|
||||
if [ -z "$RIG_URL" ]; then
|
||||
echo -e "${RED} ERROR:${NC} Could not find Rig .deb download URL for architecture: $DEB_ARCH"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
TEMP_DEB=$(mktemp --suffix=.deb)
|
||||
curl -fLsS "$RIG_URL" -o "$TEMP_DEB"
|
||||
sudo apt-get install -y "$TEMP_DEB"
|
||||
rm -f "$TEMP_DEB"
|
||||
fi
|
||||
|
||||
TARGET_VER="release"
|
||||
if ! rig list | grep -q "release"; then
|
||||
echo -e "${BLUE} LOG:${YELLOW} Installing R (${TARGET_VER})...${NC}"
|
||||
sudo rig add "$TARGET_VER" --without-cran-mirror
|
||||
sudo rig default "$TARGET_VER"
|
||||
fi
|
||||
|
||||
R_BIN="rig run"
|
||||
write_r_wrapper "R" 'exec rig run'
|
||||
write_r_wrapper "Rscript" 'exec rig run Rscript'
|
||||
|
||||
elif is_fedora_family; then
|
||||
|
||||
echo -e "${BLUE} LOG:${YELLOW} Fedora detected. Using system R...${NC}"
|
||||
install_status=0
|
||||
install_packages R-core gcc-gfortran curl tar || install_status=$?
|
||||
if [ "$install_status" -eq 42 ]; then
|
||||
exit 0
|
||||
elif [ "$install_status" -ne 0 ]; then
|
||||
exit "$install_status"
|
||||
fi
|
||||
|
||||
R_BIN="R"
|
||||
write_r_wrapper "R" 'exec "$(command -v R)"'
|
||||
write_r_wrapper "Rscript" 'exec "$(command -v Rscript)"'
|
||||
|
||||
else
|
||||
echo -e "${RED} ERROR:${NC} Unsupported OS: $OS"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
export R_LIBS_USER="$R_LIB_DIR"
|
||||
|
||||
echo -e "${BLUE} LOG:${YELLOW} Installing 'renv' package in the user R library...${NC}"
|
||||
|
||||
$R_BIN -e 'user_lib <- path.expand(Sys.getenv("R_LIBS_USER", unset = "~/.programming/r/library")); dir.create(user_lib, recursive = TRUE, showWarnings = FALSE); .libPaths(c(user_lib, .libPaths())); if (!require("renv", quietly=TRUE)) install.packages("renv", lib = user_lib, repos = "https://cloud.r-project.org")'
|
||||
|
||||
echo -e "${GREEN} SUCCESS:${NC} R setup completed."
|
||||
41
Scripts/rust.sh
Normal file
41
Scripts/rust.sh
Normal file
@@ -0,0 +1,41 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Path: Scripts/rust.sh
|
||||
|
||||
set -e
|
||||
|
||||
BLUE='\033[1;34m'
|
||||
YELLOW='\033[1;33m'
|
||||
GREEN='\033[1;32m'
|
||||
NC='\033[0m'
|
||||
|
||||
export RUSTUP_HOME="$HOME/.programming/rust/multirust"
|
||||
export CARGO_HOME="$HOME/.programming/rust/cargo"
|
||||
|
||||
echo -e "${BLUE} LOG:${YELLOW} Setting up Rust (Rustup) in ${CARGO_HOME}...${NC}"
|
||||
|
||||
if [ ! -f "$CARGO_HOME/bin/rustup" ]; then
|
||||
echo -e "${BLUE} LOG:${YELLOW} Installing Rustup to custom path...${NC}"
|
||||
mkdir -p "$RUSTUP_HOME" "$CARGO_HOME"
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --no-modify-path
|
||||
else
|
||||
echo -e "${GREEN} LOG: Rustup already installed in custom path.${NC}"
|
||||
fi
|
||||
|
||||
if [ -f "$CARGO_HOME/env" ]; then
|
||||
source "$CARGO_HOME/env"
|
||||
fi
|
||||
|
||||
if command -v cargo &> /dev/null; then
|
||||
echo -e "${BLUE} LOG:${YELLOW} Updating toolchain...${NC}"
|
||||
rustup default stable
|
||||
rustup update
|
||||
|
||||
echo -e "${BLUE} LOG:${YELLOW} Installing rust-src for 'Go to Definition'...${NC}"
|
||||
rustup component add rust-src
|
||||
|
||||
echo -e "${GREEN} LOG: Rust setup complete. $(cargo --version)${NC}"
|
||||
else
|
||||
echo -e "${RED} ERROR: Cargo not found in PATH. Check CARGO_HOME.${NC}"
|
||||
exit 1
|
||||
fi
|
||||
68
Scripts/setup.sh
Normal file
68
Scripts/setup.sh
Normal file
@@ -0,0 +1,68 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(dirname "$SCRIPT_DIR")"
|
||||
REBOOT_MARKER="$REPO_ROOT/.setup-reboot-required"
|
||||
REPO_SECRET_FILE="$REPO_ROOT/Zsh/.zsh_secrets"
|
||||
HOME_SECRET_FILE="$HOME/.zsh_secrets"
|
||||
|
||||
handle_reboot_marker() {
|
||||
if [ -f "$REBOOT_MARKER" ]; then
|
||||
rm -f "$REBOOT_MARKER"
|
||||
echo "Package layering finished. Reboot, then rerun the same command."
|
||||
exit 0
|
||||
fi
|
||||
}
|
||||
|
||||
sync_repo_managed_secret_file() {
|
||||
mkdir -p "$(dirname "$REPO_SECRET_FILE")"
|
||||
|
||||
if [ -L "$HOME_SECRET_FILE" ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [ -f "$HOME_SECRET_FILE" ]; then
|
||||
if [ ! -f "$REPO_SECRET_FILE" ] || [ ! -s "$REPO_SECRET_FILE" ]; then
|
||||
mv "$HOME_SECRET_FILE" "$REPO_SECRET_FILE"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if cmp -s "$HOME_SECRET_FILE" "$REPO_SECRET_FILE"; then
|
||||
rm -f "$HOME_SECRET_FILE"
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo "Conflict: both $HOME_SECRET_FILE and $REPO_SECRET_FILE exist with different contents."
|
||||
echo "Please merge them manually, then rerun the command."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
touch "$REPO_SECRET_FILE"
|
||||
}
|
||||
|
||||
main() {
|
||||
rm -f "$REBOOT_MARKER"
|
||||
|
||||
bash "$SCRIPT_DIR/base.sh"
|
||||
handle_reboot_marker
|
||||
|
||||
bash "$SCRIPT_DIR/node.sh"
|
||||
bash "$SCRIPT_DIR/go.sh"
|
||||
bash "$SCRIPT_DIR/rust.sh"
|
||||
bash "$SCRIPT_DIR/python.sh"
|
||||
handle_reboot_marker
|
||||
|
||||
bash "$SCRIPT_DIR/r.sh"
|
||||
handle_reboot_marker
|
||||
|
||||
sync_repo_managed_secret_file
|
||||
|
||||
stow --dir="$REPO_ROOT" -D Zsh --target="$HOME" 2>/dev/null || true
|
||||
stow --dir="$REPO_ROOT" Zsh --target="$HOME"
|
||||
|
||||
echo "Full setup completed."
|
||||
}
|
||||
|
||||
main "$@"
|
||||
Reference in New Issue
Block a user