From daf465368f81a0662d8b8e006b4bd92e2e31feb2 Mon Sep 17 00:00:00 2001 From: peoplemiau1 Date: Fri, 29 May 2026 07:51:10 +0300 Subject: [PATCH] Add BSD install script and update compatibility table in README --- README.md | 16 +++- install_bsd.sh | 224 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 237 insertions(+), 3 deletions(-) create mode 100755 install_bsd.sh diff --git a/README.md b/README.md index 99a3130..f36efcf 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,16 @@ cargo install dcr curl -fsSL https://dcr.dexoron.su/install.sh | bash ``` + + + +BSD (script) + + +```sh +curl -fsSL https://raw.githubusercontent.com/dexoron/dcr/dev/install_bsd.sh | bash +``` + @@ -159,9 +169,9 @@ other in [docs/](docs/) and `dcr --help` | Linux | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | | macOS | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | | Windows | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | -| FreeBSD | ⚠️ | ⚠️ | ❌ | ❌ | ❌ | ⚠️ | ❌ | ❌ | ❌ | -| OpenBSD | ⚠️ | ⚠️ | ❌ | ❌ | ❌ | ⚠️ | ❌ | ❌ | ❌ | -| NetBSD | ⚠️ | ⚠️ | ❌ | ❌ | ❌ | ⚠️ | ❌ | ❌ | ❌ | +| FreeBSD | ✅ | ⚠️ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | +| OpenBSD | ✅ | ⚠️ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | +| NetBSD | ✅ | ⚠️ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ✅ officially supported · ⚠️ community / best-effort · ❌ not supported diff --git a/install_bsd.sh b/install_bsd.sh new file mode 100755 index 0000000..46cb818 --- /dev/null +++ b/install_bsd.sh @@ -0,0 +1,224 @@ +#!/usr/bin/env bash +set -Eeuo pipefail + +TMPDIR="/tmp/dcr-install" +INSTALL_PATH="$HOME/.local/share/dcr" +BINPATH="$HOME/.local/bin" +LOGFILE="$HOME/.cache/dcr-install.log" +REPO_URL="https://github.com/dexoron/dcr" +GITHUB_API_LATEST="https://api.github.com/repos/dexoron/dcr/releases/latest" +GITHUB_API_ALL="https://api.github.com/repos/dexoron/dcr/releases" + +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' + +mkdir -p "$(dirname "$LOGFILE")" +exec > >(tee -a "$LOGFILE") 2>&1 + +log() { echo -e "${BLUE}[$(date '+%Y-%m-%d %H:%M:%S')]${NC} $1"; } +success() { echo -e "${GREEN}✔ $1${NC}"; } +warn() { echo -e "${YELLOW}⚠ $1${NC}"; } +error() { echo -e "${RED}✖ $1${NC}"; } + +trap 'error "Error on line $LINENO"; exit 1' ERR + +INSTALL_MODE="" +CHANNEL="" + +check_os() { + case "$(uname -s)" in + FreeBSD|OpenBSD|NetBSD|DragonFly) ;; + *) error "Only BSD systems (FreeBSD, OpenBSD, NetBSD, DragonFly) are supported by this script"; exit 1 ;; + esac +} + +detect_target() { + local os arch + os="$(uname -s)" + arch="$(uname -m)" + + case "$os:$arch" in + FreeBSD:x86_64|FreeBSD:amd64) TARGET_TRIPLE="x86_64-unknown-freebsd" ;; + OpenBSD:x86_64|OpenBSD:amd64) TARGET_TRIPLE="x86_64-unknown-openbsd" ;; + NetBSD:x86_64|NetBSD:amd64) TARGET_TRIPLE="x86_64-unknown-netbsd" ;; + DragonFly:x86_64|DragonFly:amd64) TARGET_TRIPLE="x86_64-unknown-dragonfly" ;; + *) error "Unsupported BSD platform: $os/$arch"; exit 1 ;; + esac +} + +check_common_dependencies() { + command -v curl >/dev/null 2>&1 || { error "curl is not installed"; exit 1; } + if [[ "$CHANNEL" == "dev" ]]; then + if ! command -v python3 >/dev/null 2>&1 && ! command -v jq >/dev/null 2>&1; then + error "For dev installations, either 'python3' or 'jq' must be installed to parse GitHub API response." + exit 1 + fi + fi +} + +check_build_dependencies() { + command -v git >/dev/null 2>&1 || { error "git is not installed"; exit 1; } + command -v cargo >/dev/null 2>&1 || { error "cargo is not installed"; exit 1; } +} + +select_channel() { + echo "Choose channel:" + echo " 1) Latest stable release (default)" + echo " 2) Latest dev (pre-release)" + read -r -p "Enter 1 or 2 [1]: " choice + + case "${choice:-1}" in + 1) CHANNEL="stable" ;; + 2) CHANNEL="dev" ;; + *) error "Unknown option"; exit 1 ;; + esac +} + +select_install_mode() { + echo "Choose installation mode:" + echo " 1) Download prebuilt binary from GitHub Release (recommended)" + echo " 2) Build from git" + read -r -p "Enter 1 or 2 [1]: " choice + + case "${choice:-1}" in + 1) INSTALL_MODE="release" ;; + 2) INSTALL_MODE="build" ;; + *) error "Unknown option"; exit 1 ;; + esac +} + +fetch_release_json() { + if [[ "$CHANNEL" == "dev" ]]; then + log "Looking for latest dev (pre-release)..." + local json result + json="$(curl -fsSL "$GITHUB_API_ALL")" + if command -v jq >/dev/null 2>&1; then + result="$(printf '%s' "$json" | jq -e -c 'map(select(.prerelease == true))[0]')" + else + result="$(printf '%s' "$json" | python3 - <<'EOF' +import sys, json +releases = json.load(sys.stdin) +pre = [r for r in releases if r.get("prerelease", False)] +if not pre: + print("{}", end="") +else: + print(json.dumps(pre[0]), end="") +EOF +)" + fi + + if [[ -z "$result" || "$result" == "{}" || "$result" == "null" ]]; then + error "No dev (pre-release) found on GitHub" + exit 1 + fi + printf '%s' "$result" + else + curl -fsSL "$GITHUB_API_LATEST" + fi +} + +download_binary() { + local release_json tag version asset_name download_url + + release_json="$(fetch_release_json)" + + tag="$(printf '%s\n' "$release_json" | \ + sed -n 's/.*"tag_name": "\([^"]*\)".*/\1/p' | head -n1)" + if [[ -z "$tag" ]]; then + error "Failed to determine release version" + exit 1 + fi + + version="${tag#v}" + asset_name="dcr-${TARGET_TRIPLE}-${version}" + + log "Fetching release ${tag} (channel: ${CHANNEL})..." + + download_url="$(printf '%s\n' "$release_json" | \ + sed -n "s#.*\"browser_download_url\": \"\([^\"]*/${asset_name}\)\".*#\1#p" | head -n1)" + + if [[ -z "$download_url" ]]; then + error "Asset ${asset_name} not found in release ${tag}" + exit 1 + fi + + mkdir -p "$INSTALL_PATH" + curl -fL "$download_url" -o "$INSTALL_PATH/dcr" + chmod +x "$INSTALL_PATH/dcr" + success "Binary ${asset_name} downloaded (${tag})" +} + +prepare_sources() { + log "Fetching sources..." + rm -rf "$TMPDIR" + git clone --depth 1 "$REPO_URL" "$TMPDIR" + if [[ "$CHANNEL" == "dev" ]]; then + git clone --depth 1 --branch dev "$REPO_URL" "$TMPDIR" 2>/dev/null || \ + git clone --depth 1 "$REPO_URL" "$TMPDIR" + fi + success "Sources fetched" +} + +build_binary() { + log "Building release binary..." + (cd "$TMPDIR" && cargo build --release) + success "Build completed" +} + +install_built_binary() { + mkdir -p "$INSTALL_PATH" + cp "$TMPDIR/target/release/dcr" "$INSTALL_PATH/dcr" + chmod +x "$INSTALL_PATH/dcr" + success "Binary installed from source" +} + +install_link() { + log "Creating symlink..." + mkdir -p "$BINPATH" + ln -sf "$INSTALL_PATH/dcr" "$BINPATH/dcr" + success "Command 'dcr' added to $BINPATH" +} + +check_path() { + if ! echo "$PATH" | grep -q "$BINPATH"; then + warn "Directory $BINPATH not found in PATH" + echo "Add this to ~/.bashrc, ~/.zshrc or ~/.profile:" + echo "export PATH=\"$BINPATH:\$PATH\"" + fi +} + +cleanup() { + rm -rf "$TMPDIR" 2>/dev/null || true +} + +main() { + log "Starting DCR installation for BSD" + + check_os + select_channel + check_common_dependencies + detect_target + select_install_mode + cleanup + + if [[ "$INSTALL_MODE" == "build" ]]; then + check_build_dependencies + prepare_sources + build_binary + install_built_binary + else + download_binary + fi + + install_link + check_path + cleanup + + success "Installation completed successfully" + log "Log saved to $LOGFILE" +} + +main "$@"