From f17e4c6642dd2c16625191944ef83cf40f265291 Mon Sep 17 00:00:00 2001 From: Dexoron Date: Sun, 11 Oct 2026 15:04:16 +0800 Subject: [PATCH] fix dcrup installers and installation docs --- dcrup.ps1 | 71 +- dcrup.sh | 996 +++++++++++++------------- docs/getting-started/installation.mdx | 11 +- 3 files changed, 573 insertions(+), 505 deletions(-) mode change 100755 => 100644 dcrup.sh diff --git a/dcrup.ps1 b/dcrup.ps1 index 094b9a9..c42459a 100644 --- a/dcrup.ps1 +++ b/dcrup.ps1 @@ -1,4 +1,4 @@ -#Requires -Version 5.1 +#Requires -Version 5.1 $ErrorActionPreference = 'Stop' $DcrupHome = if ($env:DCRUP_HOME) { $env:DCRUP_HOME } else { Join-Path $env:USERPROFILE '.dcr' } @@ -6,6 +6,7 @@ $DcrupBin = if ($env:DCRUP_BIN) { $env:DCRUP_BIN } else { Join-Path $DcrupHom $DcrupTc = Join-Path $DcrupHome 'toolchains' $DcrupMeta = Join-Path $DcrupHome 'meta' $RepoUrl = if ($env:DCRUP_REPO) { $env:DCRUP_REPO } else { 'https://github.com/dexoron/dcr' } +$InstallUrl = if ($env:DCRUP_INSTALL_URL) { $env:DCRUP_INSTALL_URL } else { 'https://ps1.dcr-tool.ru' } $DcrupMirror = if ($env:DCRUP_MIRROR) { $env:DCRUP_MIRROR } else { 'auto' } $ApiLatest = 'https://api.github.com/repos/dexoron/dcr/releases/latest' $ApiAll = 'https://api.github.com/repos/dexoron/dcr/releases' @@ -18,7 +19,7 @@ function Die($m) { Write-Host "[error] $m" -ForegroundColor Red; exit 1 } function Show-Usage { @' -dcrup — install and switch DCR versions (Windows) +dcrup - install and switch DCR versions (Windows) Usage: dcrup install [--build|--release] [--force] [--mirror auto|cf|gh|sf|ya] @@ -33,10 +34,10 @@ Usage: Spec: stable | dev | night - VERSION → VERSION@stable (e.g. 0.8.2) + VERSION в†’ VERSION@stable (e.g. 0.8.2) VERSION@stable VERSION@dev - night → always build from branch "dev" HEAD + night в†’ always build from branch "dev" HEAD Modes: --release download prebuilt binary (default for stable/dev) @@ -44,7 +45,7 @@ Modes: night always --build (prebuilt not available) Mirrors (prebuilt download only): - --mirror auto try cf → gh → sf → ya, first successful download wins (default) + --mirror auto try cf в†’ gh в†’ sf в†’ ya, first successful download wins (default) --mirror cf download from cdn-global.dcr-tool.ru --mirror gh download from github.com/dexoron/dcr --mirror sf download from sourceforge.net/projects/dcr-tool @@ -130,7 +131,19 @@ function Link-Default([string]$id) { $dst = Join-Path $DcrupBin 'dcr.exe' Copy-Item $src $dst -Force Write-Active $id - Ok "default → $id ($dst)" + Ok "default в†’ $id ($dst)" +} + +function Resolve-InstalledId([string]$spec) { + Parse-Spec $spec + if ($script:SpecChannel -eq 'night' -or $script:SpecFloating) { + $item = Get-ChildItem $DcrupTc -Directory -ErrorAction SilentlyContinue | + Where-Object { $_.Name -like "$($script:SpecChannel)-*" } | + Sort-Object Name | Select-Object -Last 1 + if ($item) { return $item.Name } + return $null + } + return (Toolchain-Id) } function Set-Mirror([string]$value) { @@ -162,7 +175,7 @@ function Download-FromMirrors([string]$tag, [string]$asset, [string]$destFile) { $tmp = "$destFile.download" foreach ($m in (Get-MirrorsToTry)) { $url = Get-MirrorUrl $m $tag $asset - Info "trying mirror $m …" + Info "trying mirror $m …" Remove-Item $tmp -ErrorAction SilentlyContinue try { Invoke-WebRequest -Uri $url -OutFile $tmp -UserAgent 'dcrup' @@ -210,10 +223,10 @@ function Install-Prebuilt([switch]$Force) { } Ensure-Dirs New-Item -ItemType Directory -Force -Path $dest | Out-Null - Info "downloading $assetName (mirror=$($script:DcrupMirror)) …" + Info "downloading $assetName (mirror=$($script:DcrupMirror)) …" $mirror = Download-FromMirrors $tag $assetName $bin if (-not $mirror) { Die "no mirror reachable for $assetName (try: --mirror cf|gh|sf|ya)" } - Info "mirror → $mirror" + Info "mirror в†’ $mirror" @" channel=$($script:SpecChannel) version=$ver @@ -235,7 +248,7 @@ function Install-Build([switch]$Force) { try { $src = Join-Path $tmp 'src' if ($script:SpecChannel -eq 'night') { - Info "cloning dev for night …" + Info "cloning dev for night …" git clone --depth 1 --branch dev $RepoUrl $src 2>$null if ($LASTEXITCODE -ne 0) { git clone --depth 1 $RepoUrl $src | Out-Null } $sha = (git -C $src rev-parse --short HEAD).Trim() @@ -246,7 +259,7 @@ function Install-Build([switch]$Force) { $tag = $rel.tag_name $ver = Normalize-Version $tag $id = Toolchain-Id $ver - Info "cloning $tag …" + Info "cloning $tag …" git clone --depth 1 --branch $tag $RepoUrl $src 2>$null if ($LASTEXITCODE -ne 0) { git clone --depth 1 $RepoUrl $src | Out-Null @@ -258,7 +271,7 @@ function Install-Build([switch]$Force) { $tag = "v$($script:SpecVersion)" $ver = $script:SpecVersion $id = Toolchain-Id - Info "cloning $tag …" + Info "cloning $tag …" git clone --depth 1 --branch $tag $RepoUrl $src 2>$null if ($LASTEXITCODE -ne 0) { git clone --depth 1 $RepoUrl $src | Out-Null @@ -277,7 +290,7 @@ function Install-Build([switch]$Force) { } $triple = Get-Target - Info "building release (features: $Features) …" + Info "building release (features: $Features) …" Push-Location $src cargo build --release --features $Features --target $triple if ($LASTEXITCODE -ne 0) { Die 'cargo build failed' } @@ -379,10 +392,22 @@ function Cmd-Show { function Cmd-SelfInstall { Ensure-Dirs - Copy-Item $PSCommandPath (Join-Path $DcrupBin 'dcrup.ps1') -Force + if ([string]::IsNullOrWhiteSpace($PSCommandPath) -or -not (Test-Path $PSCommandPath)) { + # With `irm URL | iex`, PowerShell evaluates text and there is no + # source path. Download the canonical installer for self-install. + $tmp = Join-Path $env:TEMP ("dcrup-" + [guid]::NewGuid().ToString('N') + '.ps1') + try { + Invoke-WebRequest -Uri $InstallUrl -OutFile $tmp -UseBasicParsing -UserAgent 'dcrup' + Copy-Item $tmp (Join-Path $DcrupBin 'dcrup.ps1') -Force + } finally { + Remove-Item $tmp -Force -ErrorAction SilentlyContinue + } + } else { + Copy-Item $PSCommandPath (Join-Path $DcrupBin 'dcrup.ps1') -Force + } Install-CmdShim Ensure-UserPath - Ok "dcrup installed to $DcrupBin (use: dcrup …)" + Ok "dcrup installed to $DcrupBin (use: dcrup …)" } $cmd = if ($args.Count -ge 1) { $args[0] } else { 'help' } @@ -417,7 +442,7 @@ switch ($cmd) { if ($a -like 'night-*') { Cmd-Install @('night', '--build', '--force') } elseif ($a -like 'stable-*') { Cmd-Install @('stable', '--force') } elseif ($a -like 'dev-*') { Cmd-Install @('dev', '--force') } - else { Ok "pinned $a — install a newer version explicitly" } + else { Ok "pinned $a - install a newer version explicitly" } } 'uninstall' { if ($rest -contains '--all') { @@ -426,9 +451,21 @@ switch ($cmd) { Remove-Item (Active-Path) -ErrorAction SilentlyContinue Ok 'removed all' } else { - Die 'use: dcrup uninstall --all (or install a replacement first)' + if ($rest.Count -ne 1) { Die 'usage: dcrup uninstall |--all' } + $id = Resolve-InstalledId $rest[0] + if (-not $id) { Die "not installed: $($rest[0])" } + $dir = Join-Path $DcrupTc $id + if (-not (Test-Path $dir)) { Die "not installed: $($rest[0])" } + Remove-Item -Recurse -Force $dir + if ((Read-Active) -eq $id) { + Remove-Item (Join-Path $DcrupBin 'dcr.exe') -ErrorAction SilentlyContinue + Remove-Item (Active-Path) -ErrorAction SilentlyContinue + Warn 'removed active toolchain; install or select another default' + } + Ok "removed $id" } } 'self-install' { Cmd-SelfInstall } default { Die "unknown command: $cmd" } } + diff --git a/dcrup.sh b/dcrup.sh old mode 100755 new mode 100644 index 7f0bc7a..1d70fa6 --- a/dcrup.sh +++ b/dcrup.sh @@ -6,6 +6,7 @@ DCRUP_BIN="${DCRUP_BIN:-$DCRUP_HOME/bin}" DCRUP_TC="${DCRUP_HOME}/toolchains" DCRUP_META="${DCRUP_HOME}/meta" REPO_URL="${DCRUP_REPO:-https://github.com/dexoron/dcr}" +DCRUP_INSTALL_URL="${DCRUP_INSTALL_URL:-https://sh.dcr-tool.ru}" DCRUP_MIRROR="${DCRUP_MIRROR:-auto}" API_LATEST="https://api.github.com/repos/dexoron/dcr/releases/latest" API_ALL="https://api.github.com/repos/dexoron/dcr/releases" @@ -17,13 +18,16 @@ YELLOW='\033[1;33m' CYAN='\033[0;36m' NC='\033[0m' -log() { printf "${CYAN}[dcrup]${NC} %s\n" "$*"; } -ok() { printf "${GREEN}[ok]${NC} %s\n" "$*"; } +log() { printf "${CYAN}[dcrup]${NC} %s\n" "$*"; } +ok() { printf "${GREEN}[ok]${NC} %s\n" "$*"; } warn() { printf "${YELLOW}[warn]${NC} %s\n" "$*"; } -die() { printf "${RED}[error]${NC} %s\n" "$*" >&2; exit 1; } +die() { + printf "${RED}[error]${NC} %s\n" "$*" >&2 + exit 1 +} usage() { - cat <<'EOF' + cat <<'EOF' dcrup — install and switch DCR versions Usage: @@ -73,596 +77,624 @@ EOF } need_cmd() { - command -v "$1" >/dev/null 2>&1 || die "required command not found: $1" + command -v "$1" >/dev/null 2>&1 || die "required command not found: $1" } detect_linux_libc() { - local pref="${DCRUP_LIBC:-gnu}" - case "$pref" in - gnu|glibc) echo "gnu" ;; - musl) echo "musl" ;; - auto) - if command -v ldd >/dev/null 2>&1; then - if ldd --version 2>&1 | grep -qi musl; then - echo "musl" - return 0 - fi - fi - if [[ -e /lib/ld-musl-x86_64.so.1 || -e /lib/ld-musl-aarch64.so.1 ]]; then - echo "musl" - return 0 - fi - if command -v getconf >/dev/null 2>&1 && getconf GNU_LIBC_VERSION >/dev/null 2>&1; then - echo "gnu" - return 0 - fi - echo "gnu" - ;; - *) die "invalid DCRUP_LIBC / --libc: $pref (use gnu|musl|auto)" ;; - esac + local pref="${DCRUP_LIBC:-gnu}" + case "$pref" in + gnu | glibc) echo "gnu" ;; + musl) echo "musl" ;; + auto) + if command -v ldd >/dev/null 2>&1; then + if ldd --version 2>&1 | grep -qi musl; then + echo "musl" + return 0 + fi + fi + if [[ -e /lib/ld-musl-x86_64.so.1 || -e /lib/ld-musl-aarch64.so.1 ]]; then + echo "musl" + return 0 + fi + if command -v getconf >/dev/null 2>&1 && getconf GNU_LIBC_VERSION >/dev/null 2>&1; then + echo "gnu" + return 0 + fi + echo "gnu" + ;; + *) die "invalid DCRUP_LIBC / --libc: $pref (use gnu|musl|auto)" ;; + esac } detect_triple() { - local os arch libc - os="$(uname -s)" - arch="$(uname -m)" - case "$os:$arch" in - Linux:x86_64) - libc="$(detect_linux_libc)" - if [[ "$libc" == "musl" ]]; then - echo "x86_64-unknown-linux-musl" - else - echo "x86_64-unknown-linux-gnu" - fi - ;; - Linux:aarch64|Linux:arm64) - libc="$(detect_linux_libc)" - if [[ "$libc" == "musl" ]]; then - echo "aarch64-unknown-linux-musl" - else - echo "aarch64-unknown-linux-gnu" - fi - ;; - Linux:i686|Linux:i386) - libc="$(detect_linux_libc)" - if [[ "$libc" == "musl" ]]; then - echo "i686-unknown-linux-musl" - else - echo "i686-unknown-linux-gnu" - fi - ;; - Linux:armv7l|Linux:armv7) - libc="$(detect_linux_libc)" - if [[ "$libc" == "musl" ]]; then - echo "armv7-unknown-linux-musleabihf" - else - echo "armv7-unknown-linux-gnueabihf" - fi - ;; - Linux:riscv64) - libc="$(detect_linux_libc)" - if [[ "$libc" == "musl" ]]; then - echo "riscv64gc-unknown-linux-musl" - else - echo "riscv64gc-unknown-linux-gnu" - fi - ;; - Darwin:x86_64) echo "x86_64-apple-darwin" ;; - Darwin:arm64|Darwin:aarch64) echo "aarch64-apple-darwin" ;; - FreeBSD:x86_64|FreeBSD:amd64) echo "x86_64-unknown-freebsd" ;; - FreeBSD:aarch64|FreeBSD:arm64) echo "aarch64-unknown-freebsd" ;; - OpenBSD:x86_64|OpenBSD:amd64) echo "x86_64-unknown-openbsd" ;; - NetBSD:x86_64|NetBSD:amd64) echo "x86_64-unknown-netbsd" ;; - MINGW*|MSYS*|CYGWIN*) - case "$arch" in - x86_64|amd64) echo "x86_64-pc-windows-gnu" ;; - aarch64|arm64) echo "aarch64-pc-windows-gnullvm" ;; - i686|i386) echo "i686-pc-windows-gnu" ;; - *) die "unsupported Windows arch under MSYS: $arch" ;; - esac - ;; - *) die "unsupported platform: $os/$arch" ;; + local os arch libc + os="$(uname -s)" + arch="$(uname -m)" + case "$os:$arch" in + Linux:x86_64) + libc="$(detect_linux_libc)" + if [[ "$libc" == "musl" ]]; then + echo "x86_64-unknown-linux-musl" + else + echo "x86_64-unknown-linux-gnu" + fi + ;; + Linux:aarch64 | Linux:arm64) + libc="$(detect_linux_libc)" + if [[ "$libc" == "musl" ]]; then + echo "aarch64-unknown-linux-musl" + else + echo "aarch64-unknown-linux-gnu" + fi + ;; + Linux:i686 | Linux:i386) + libc="$(detect_linux_libc)" + if [[ "$libc" == "musl" ]]; then + echo "i686-unknown-linux-musl" + else + echo "i686-unknown-linux-gnu" + fi + ;; + Linux:armv7l | Linux:armv7) + libc="$(detect_linux_libc)" + if [[ "$libc" == "musl" ]]; then + echo "armv7-unknown-linux-musleabihf" + else + echo "armv7-unknown-linux-gnueabihf" + fi + ;; + Linux:riscv64) + libc="$(detect_linux_libc)" + if [[ "$libc" == "musl" ]]; then + echo "riscv64gc-unknown-linux-musl" + else + echo "riscv64gc-unknown-linux-gnu" + fi + ;; + Darwin:x86_64) echo "x86_64-apple-darwin" ;; + Darwin:arm64 | Darwin:aarch64) echo "aarch64-apple-darwin" ;; + FreeBSD:x86_64 | FreeBSD:amd64) echo "x86_64-unknown-freebsd" ;; + FreeBSD:aarch64 | FreeBSD:arm64) echo "aarch64-unknown-freebsd" ;; + OpenBSD:x86_64 | OpenBSD:amd64) echo "x86_64-unknown-openbsd" ;; + NetBSD:x86_64 | NetBSD:amd64) echo "x86_64-unknown-netbsd" ;; + MINGW* | MSYS* | CYGWIN*) + case "$arch" in + x86_64 | amd64) echo "x86_64-pc-windows-gnu" ;; + aarch64 | arm64) echo "aarch64-pc-windows-gnullvm" ;; + i686 | i386) echo "i686-pc-windows-gnu" ;; + *) die "unsupported Windows arch under MSYS: $arch" ;; esac + ;; + *) die "unsupported platform: $os/$arch" ;; + esac } normalize_version() { - local v="$1" - v="${v#v}" - printf '%s' "$v" + local v="$1" + v="${v#v}" + printf '%s' "$v" } parse_spec() { - local raw="$1" - SPEC_RAW="$raw" - SPEC_CHANNEL="" - SPEC_VERSION="" - SPEC_FLOATING=0 + local raw="$1" + SPEC_RAW="$raw" + SPEC_CHANNEL="" + SPEC_VERSION="" + SPEC_FLOATING=0 - case "$raw" in - "") die "missing version/channel spec" ;; - stable|dev|night) - SPEC_CHANNEL="$raw" - SPEC_VERSION="" - SPEC_FLOATING=1 - ;; - *@*) - SPEC_VERSION="$(normalize_version "${raw%@*}")" - SPEC_CHANNEL="${raw#*@}" - case "$SPEC_CHANNEL" in - stable|dev) ;; - night) die "cannot pin a version on night (use: dcrup install night)" ;; - *) die "unknown channel in spec: $SPEC_CHANNEL (use stable|dev)" ;; - esac - [[ -n "$SPEC_VERSION" ]] || die "empty version in spec: $raw" - ;; - *) - SPEC_VERSION="$(normalize_version "$raw")" - SPEC_CHANNEL="stable" - [[ -n "$SPEC_VERSION" ]] || die "invalid spec: $raw" - ;; + case "$raw" in + "") die "missing version/channel spec" ;; + stable | dev | night) + SPEC_CHANNEL="$raw" + SPEC_VERSION="" + SPEC_FLOATING=1 + ;; + *@*) + SPEC_VERSION="$(normalize_version "${raw%@*}")" + SPEC_CHANNEL="${raw#*@}" + case "$SPEC_CHANNEL" in + stable | dev) ;; + night) die "cannot pin a version on night (use: dcrup install night)" ;; + *) die "unknown channel in spec: $SPEC_CHANNEL (use stable|dev)" ;; esac + [[ -n "$SPEC_VERSION" ]] || die "empty version in spec: $raw" + ;; + *) + SPEC_VERSION="$(normalize_version "$raw")" + SPEC_CHANNEL="stable" + [[ -n "$SPEC_VERSION" ]] || die "invalid spec: $raw" + ;; + esac } toolchain_id() { - if [[ "$SPEC_CHANNEL" == "night" ]]; then - local sha="${1:-unknown}" - echo "night-${sha}" - elif [[ "$SPEC_FLOATING" -eq 1 ]]; then - local ver="${1:-latest}" - echo "${SPEC_CHANNEL}-${ver}" - else - echo "${SPEC_VERSION}-${SPEC_CHANNEL}" - fi + if [[ "$SPEC_CHANNEL" == "night" ]]; then + local sha="${1:-unknown}" + echo "night-${sha}" + elif [[ "$SPEC_FLOATING" -eq 1 ]]; then + local ver="${1:-latest}" + echo "${SPEC_CHANNEL}-${ver}" + else + echo "${SPEC_VERSION}-${SPEC_CHANNEL}" + fi } ensure_dirs() { - mkdir -p "$DCRUP_TC" "$DCRUP_BIN" "$DCRUP_META" + mkdir -p "$DCRUP_TC" "$DCRUP_BIN" "$DCRUP_META" } active_file() { echo "$DCRUP_META/active"; } read_active() { - if [[ -f "$(active_file)" ]]; then - cat "$(active_file)" - fi + if [[ -f "$(active_file)" ]]; then + cat "$(active_file)" + fi } write_active() { - printf '%s\n' "$1" >"$(active_file)" + printf '%s\n' "$1" >"$(active_file)" } link_default() { - local id="$1" - local src="$DCRUP_TC/$id/dcr" - [[ -x "$src" ]] || die "toolchain not installed: $id" - ln -sfn "$src" "$DCRUP_BIN/dcr" - write_active "$id" - ok "default → $id ($DCRUP_BIN/dcr)" + local id="$1" + local src="$DCRUP_TC/$id/dcr" + [[ -x "$src" ]] || die "toolchain not installed: $id" + # Resolve the source so a relative DCRUP_HOME cannot create a broken link. + src="$(cd "$(dirname "$src")" && pwd)/$(basename "$src")" + ln -sfn "$src" "$DCRUP_BIN/dcr" + write_active "$id" + ok "default → $id ($DCRUP_BIN/dcr)" } fetch_json() { - need_cmd curl - curl -fsSL "$1" + need_cmd curl + curl -fsSL "$1" } json_tag() { - printf '%s' "$1" | sed -n 's/.*"tag_name"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' | head -n1 + printf '%s' "$1" | sed -n 's/.*"tag_name"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' | head -n1 } set_mirror() { - case "$1" in - auto|cf|gh|sf|ya) DCRUP_MIRROR="$1" ;; - *) die "invalid --mirror: $1 (use auto|cf|gh|sf|ya)" ;; - esac + case "$1" in + auto | cf | gh | sf | ya) DCRUP_MIRROR="$1" ;; + *) die "invalid --mirror: $1 (use auto|cf|gh|sf|ya)" ;; + esac } mirror_url() { - local mirror="$1" tag="$2" asset="$3" - case "$mirror" in - cf) printf 'https://cdn-global.dcr-tool.ru/%s/%s' "$tag" "$asset" ;; - gh) printf 'https://github.com/dexoron/dcr/releases/download/%s/%s' "$tag" "$asset" ;; - sf) printf 'https://sourceforge.net/projects/dcr-tool/files/%s/%s/download' "$tag" "$asset" ;; - ya) printf 'https://cdn-ru.dcr-tool.ru/%s/%s' "$tag" "$asset" ;; - *) return 1 ;; - esac + local mirror="$1" tag="$2" asset="$3" + case "$mirror" in + cf) printf 'https://cdn-global.dcr-tool.ru/%s/%s' "$tag" "$asset" ;; + gh) printf 'https://github.com/dexoron/dcr/releases/download/%s/%s' "$tag" "$asset" ;; + sf) printf 'https://sourceforge.net/projects/dcr-tool/files/%s/%s/download' "$tag" "$asset" ;; + ya) printf 'https://cdn-ru.dcr-tool.ru/%s/%s' "$tag" "$asset" ;; + *) return 1 ;; + esac } mirror_chain() { echo "cf gh sf ya"; } mirrors_to_try() { - case "$DCRUP_MIRROR" in - auto) mirror_chain ;; - cf|gh|sf|ya) echo "$DCRUP_MIRROR" ;; - *) die "invalid mirror: $DCRUP_MIRROR (use auto|cf|gh|sf|ya)" ;; - esac + case "$DCRUP_MIRROR" in + auto) mirror_chain ;; + cf | gh | sf | ya) echo "$DCRUP_MIRROR" ;; + *) die "invalid mirror: $DCRUP_MIRROR (use auto|cf|gh|sf|ya)" ;; + esac } download_from_mirrors() { - local tag="$1" asset="$2" dest="$3" - local tmp="$dest/dcr.download" m url size - USED_MIRROR="" - for m in $(mirrors_to_try); do - url="$(mirror_url "$m" "$tag" "$asset")" - log "trying mirror $m …" - rm -f "$tmp" - if curl -fL --retry 2 --retry-delay 1 --connect-timeout 10 --max-time 180 \ - -A "dcrup" "$url" -o "$tmp"; then - size="$(wc -c <"$tmp" | tr -d ' ')" - if [[ "${size:-0}" -gt 100000 ]]; then - mv "$tmp" "$dest/dcr" - USED_MIRROR="$m" - return 0 - fi - warn "mirror $m returned a too-small file (${size:-0} bytes)" - else - warn "mirror $m failed" - fi - rm -f "$tmp" - done - return 1 + local tag="$1" asset="$2" dest="$3" + local tmp="$dest/dcr.download" m url size + USED_MIRROR="" + for m in $(mirrors_to_try); do + url="$(mirror_url "$m" "$tag" "$asset")" + log "trying mirror $m …" + rm -f "$tmp" + if curl -fL --retry 2 --retry-delay 1 --connect-timeout 10 --max-time 180 \ + -A "dcrup" "$url" -o "$tmp"; then + size="$(wc -c <"$tmp" | tr -d ' ')" + if [[ "${size:-0}" -gt 100000 ]]; then + mv "$tmp" "$dest/dcr" + USED_MIRROR="$m" + return 0 + fi + warn "mirror $m returned a too-small file (${size:-0} bytes)" + else + warn "mirror $m failed" + fi + rm -f "$tmp" + done + return 1 } latest_stable_json() { - fetch_json "$API_LATEST" + fetch_json "$API_LATEST" } latest_dev_json() { - need_cmd curl - local json result - json="$(fetch_json "$API_ALL")" - if command -v jq >/dev/null 2>&1; then - result="$(printf '%s' "$json" | jq -e -c '[.[] | select(.prerelease == true)][0]')" || true - elif command -v python3 >/dev/null 2>&1; then - result="$(printf '%s' "$json" | python3 -c ' + need_cmd curl + local json result + json="$(fetch_json "$API_ALL")" + if command -v jq >/dev/null 2>&1; then + result="$(printf '%s' "$json" | jq -e -c '[.[] | select(.prerelease == true)][0]')" || true + elif command -v python3 >/dev/null 2>&1; then + result="$(printf '%s' "$json" | python3 -c ' import sys, json rels = json.load(sys.stdin) pre = [r for r in rels if r.get("prerelease")] print(json.dumps(pre[0]) if pre else "", end="") ')" - else - die "dev channel needs jq or python3 to parse GitHub API" - fi - [[ -n "$result" && "$result" != "null" ]] || die "no prerelease (dev) found" - printf '%s' "$result" + else + die "dev channel needs jq or python3 to parse GitHub API" + fi + [[ -n "$result" && "$result" != "null" ]] || die "no prerelease (dev) found" + printf '%s' "$result" } release_json_for_spec() { - if [[ "$SPEC_FLOATING" -eq 1 ]]; then - case "$SPEC_CHANNEL" in - stable) latest_stable_json ;; - dev) latest_dev_json ;; - night) die "night has no GitHub release binary" ;; - esac - else - fetch_json "https://api.github.com/repos/dexoron/dcr/releases/tags/v${SPEC_VERSION}" - fi + if [[ "$SPEC_FLOATING" -eq 1 ]]; then + case "$SPEC_CHANNEL" in + stable) latest_stable_json ;; + dev) latest_dev_json ;; + night) die "night has no GitHub release binary" ;; + esac + else + fetch_json "https://api.github.com/repos/dexoron/dcr/releases/tags/v${SPEC_VERSION}" + fi } install_prebuilt() { - local triple asset tag version id dest mirror - need_cmd curl - triple="$(detect_triple)" - json="$(release_json_for_spec)" - tag="$(json_tag "$json")" - [[ -n "$tag" ]] || die "failed to parse release tag" - version="$(normalize_version "$tag")" - asset="dcr-${triple}-${version}" - case "$triple" in - *windows*) asset="${asset}.exe" ;; - esac + local triple asset tag version id dest mirror + need_cmd curl + triple="$(detect_triple)" + json="$(release_json_for_spec)" + tag="$(json_tag "$json")" + [[ -n "$tag" ]] || die "failed to parse release tag" + version="$(normalize_version "$tag")" + asset="dcr-${triple}-${version}" + case "$triple" in + *windows*) asset="${asset}.exe" ;; + esac - id="$(toolchain_id "$version")" - dest="$DCRUP_TC/$id" - if [[ -x "$dest/dcr" && "${FORCE:-0}" != "1" ]]; then - ok "already installed: $id" - link_default "$id" - return 0 - fi - - mkdir -p "$dest" - log "downloading $asset (mirror=$DCRUP_MIRROR) …" - download_from_mirrors "$tag" "$asset" "$dest" \ - || die "no mirror reachable for $asset (try: --mirror cf|gh|sf|ya)" - mirror="$USED_MIRROR" - log "mirror → $mirror" - chmod +x "$dest/dcr" - printf '%s\n' \ - "channel=$SPEC_CHANNEL" \ - "version=$version" \ - "tag=$tag" \ - "source=release" \ - "triple=$triple" \ - "mirror=$mirror" \ - "libc=${DCRUP_LIBC:-gnu}" \ - >"$dest/dcrup-meta" - ok "installed prebuilt $id ($triple via $mirror)" + id="$(toolchain_id "$version")" + dest="$DCRUP_TC/$id" + if [[ -x "$dest/dcr" && "${FORCE:-0}" != "1" ]]; then + ok "already installed: $id" link_default "$id" + return 0 + fi + + mkdir -p "$dest" + log "downloading $asset (mirror=$DCRUP_MIRROR) …" + download_from_mirrors "$tag" "$asset" "$dest" || + die "no mirror reachable for $asset (try: --mirror cf|gh|sf|ya)" + mirror="$USED_MIRROR" + log "mirror → $mirror" + chmod +x "$dest/dcr" + printf '%s\n' \ + "channel=$SPEC_CHANNEL" \ + "version=$version" \ + "tag=$tag" \ + "source=release" \ + "triple=$triple" \ + "mirror=$mirror" \ + "libc=${DCRUP_LIBC:-gnu}" \ + >"$dest/dcrup-meta" + ok "installed prebuilt $id ($triple via $mirror)" + link_default "$id" } install_build() { - local tmp id dest sha version branch_or_tag - need_cmd git - need_cmd cargo + local tmp id dest sha version branch_or_tag + need_cmd git + need_cmd cargo - tmp="$(mktemp -d "${TMPDIR:-/tmp}/dcrup.XXXXXX")" - cleanup_tmp() { rm -rf "$tmp"; } - trap cleanup_tmp EXIT + tmp="$(mktemp -d "${TMPDIR:-/tmp}/dcrup.XXXXXX")" + cleanup_tmp() { rm -rf "$tmp"; } + trap cleanup_tmp EXIT - if [[ "$SPEC_CHANNEL" == "night" ]]; then - log "cloning $REPO_URL (branch dev) for night …" - git clone --depth 1 --branch dev "$REPO_URL" "$tmp/src" 2>/dev/null \ - || git clone --depth 1 "$REPO_URL" "$tmp/src" - sha="$(git -C "$tmp/src" rev-parse --short HEAD)" - version="night" - id="$(toolchain_id "$sha")" - elif [[ "$SPEC_FLOATING" -eq 1 ]]; then - local json tag - json="$(release_json_for_spec)" - tag="$(json_tag "$json")" - [[ -n "$tag" ]] || die "failed to resolve floating channel tag" - version="$(normalize_version "$tag")" - id="$(toolchain_id "$version")" - log "cloning $REPO_URL @ $tag …" - git clone --depth 1 --branch "$tag" "$REPO_URL" "$tmp/src" 2>/dev/null \ - || { - git clone --depth 1 "$REPO_URL" "$tmp/src" - git -C "$tmp/src" fetch --depth 1 origin "refs/tags/${tag}:refs/tags/${tag}" - git -C "$tmp/src" checkout "$tag" - } - sha="$(git -C "$tmp/src" rev-parse --short HEAD)" - else - version="$SPEC_VERSION" - id="$(toolchain_id)" - local tag="v${SPEC_VERSION}" - log "cloning $REPO_URL @ $tag …" - git clone --depth 1 --branch "$tag" "$REPO_URL" "$tmp/src" 2>/dev/null \ - || { - git clone --depth 1 "$REPO_URL" "$tmp/src" - git -C "$tmp/src" fetch --depth 1 origin "refs/tags/${tag}:refs/tags/${tag}" - git -C "$tmp/src" checkout "$tag" - } - sha="$(git -C "$tmp/src" rev-parse --short HEAD)" - fi + if [[ "$SPEC_CHANNEL" == "night" ]]; then + log "cloning $REPO_URL (branch dev) for night …" + git clone --depth 1 --branch dev "$REPO_URL" "$tmp/src" 2>/dev/null || + git clone --depth 1 "$REPO_URL" "$tmp/src" + sha="$(git -C "$tmp/src" rev-parse --short HEAD)" + version="night" + id="$(toolchain_id "$sha")" + elif [[ "$SPEC_FLOATING" -eq 1 ]]; then + local json tag + json="$(release_json_for_spec)" + tag="$(json_tag "$json")" + [[ -n "$tag" ]] || die "failed to resolve floating channel tag" + version="$(normalize_version "$tag")" + id="$(toolchain_id "$version")" + log "cloning $REPO_URL @ $tag …" + git clone --depth 1 --branch "$tag" "$REPO_URL" "$tmp/src" 2>/dev/null || + { + git clone --depth 1 "$REPO_URL" "$tmp/src" + git -C "$tmp/src" fetch --depth 1 origin "refs/tags/${tag}:refs/tags/${tag}" + git -C "$tmp/src" checkout "$tag" + } + sha="$(git -C "$tmp/src" rev-parse --short HEAD)" + else + version="$SPEC_VERSION" + id="$(toolchain_id)" + local tag="v${SPEC_VERSION}" + log "cloning $REPO_URL @ $tag …" + git clone --depth 1 --branch "$tag" "$REPO_URL" "$tmp/src" 2>/dev/null || + { + git clone --depth 1 "$REPO_URL" "$tmp/src" + git -C "$tmp/src" fetch --depth 1 origin "refs/tags/${tag}:refs/tags/${tag}" + git -C "$tmp/src" checkout "$tag" + } + sha="$(git -C "$tmp/src" rev-parse --short HEAD)" + fi - dest="$DCRUP_TC/$id" - if [[ -x "$dest/dcr" && "${FORCE:-0}" != "1" ]]; then - ok "already installed: $id" - link_default "$id" - return 0 - fi - - log "building release (features: $FEATURES) …" - ( - cd "$tmp/src" - # shellcheck disable=SC2086 - cargo build --release --features $FEATURES - ) - mkdir -p "$dest" - cp "$tmp/src/target/release/dcr" "$dest/dcr" - chmod +x "$dest/dcr" - printf '%s\n' "channel=$SPEC_CHANNEL" "version=$version" "git=$sha" "source=build" "features=$FEATURES" >"$dest/dcrup-meta" - ok "installed build $id" + dest="$DCRUP_TC/$id" + if [[ -x "$dest/dcr" && "${FORCE:-0}" != "1" ]]; then + ok "already installed: $id" link_default "$id" - trap - EXIT - cleanup_tmp + return 0 + fi + + log "building release (features: $FEATURES) …" + ( + cd "$tmp/src" + # shellcheck disable=SC2086 + cargo build --release --features $FEATURES + ) + mkdir -p "$dest" + cp "$tmp/src/target/release/dcr" "$dest/dcr" + chmod +x "$dest/dcr" + printf '%s\n' "channel=$SPEC_CHANNEL" "version=$version" "git=$sha" "source=build" "features=$FEATURES" >"$dest/dcrup-meta" + ok "installed build $id" + link_default "$id" + trap - EXIT + cleanup_tmp } cmd_install() { - local mode="release" FORCE=0 - local spec="" - local libc_cli="" - while [[ $# -gt 0 ]]; do - case "$1" in - --build) mode="build"; shift ;; - --release) mode="release"; shift ;; - --force) FORCE=1; shift ;; - --libc) - [[ $# -ge 2 ]] || die "--libc needs gnu|musl|auto" - libc_cli="$2" - shift 2 - ;; - --libc=*) - libc_cli="${1#--libc=}" - shift - ;; - --mirror) - [[ $# -ge 2 ]] || die "--mirror needs auto|cf|gh|sf|ya" - set_mirror "$2" - shift 2 - ;; - --mirror=*) - set_mirror "${1#--mirror=}" - shift - ;; - -h|--help) usage; exit 0 ;; - -*) die "unknown flag: $1" ;; - *) - [[ -z "$spec" ]] || die "unexpected argument: $1" - spec="$1" - shift - ;; - esac - done - [[ -n "$spec" ]] || die "usage: dcrup install [--build|--release] [--force] [--libc gnu|musl|auto] [--mirror auto|cf|gh|sf|ya]" - parse_spec "$spec" - ensure_dirs + local mode="release" FORCE=0 + local spec="" + local libc_cli="" + while [[ $# -gt 0 ]]; do + case "$1" in + --build) + mode="build" + shift + ;; + --release) + mode="release" + shift + ;; + --force) + FORCE=1 + shift + ;; + --libc) + [[ $# -ge 2 ]] || die "--libc needs gnu|musl|auto" + libc_cli="$2" + shift 2 + ;; + --libc=*) + libc_cli="${1#--libc=}" + shift + ;; + --mirror) + [[ $# -ge 2 ]] || die "--mirror needs auto|cf|gh|sf|ya" + set_mirror "$2" + shift 2 + ;; + --mirror=*) + set_mirror "${1#--mirror=}" + shift + ;; + -h | --help) + usage + exit 0 + ;; + -*) die "unknown flag: $1" ;; + *) + [[ -z "$spec" ]] || die "unexpected argument: $1" + spec="$1" + shift + ;; + esac + done + [[ -n "$spec" ]] || die "usage: dcrup install [--build|--release] [--force] [--libc gnu|musl|auto] [--mirror auto|cf|gh|sf|ya]" + parse_spec "$spec" + ensure_dirs - if [[ -n "$libc_cli" ]]; then - case "$libc_cli" in - gnu|glibc|musl|auto) DCRUP_LIBC="$libc_cli" ;; - *) die "invalid --libc: $libc_cli (use gnu|musl|auto)" ;; - esac - fi - export DCRUP_LIBC="${DCRUP_LIBC:-gnu}" + if [[ -n "$libc_cli" ]]; then + case "$libc_cli" in + gnu | glibc | musl | auto) DCRUP_LIBC="$libc_cli" ;; + *) die "invalid --libc: $libc_cli (use gnu|musl|auto)" ;; + esac + fi + export DCRUP_LIBC="${DCRUP_LIBC:-gnu}" - if [[ "$SPEC_CHANNEL" == "night" ]]; then - mode="build" - fi + if [[ "$SPEC_CHANNEL" == "night" ]]; then + mode="build" + fi - export FORCE - log "install spec=$SPEC_RAW channel=$SPEC_CHANNEL version=${SPEC_VERSION:-∅} mode=$mode libc=$DCRUP_LIBC mirror=$DCRUP_MIRROR" - if [[ "$mode" == "build" ]]; then - install_build - else - install_prebuilt - fi - check_path + export FORCE + log "install spec=$SPEC_RAW channel=$SPEC_CHANNEL version=${SPEC_VERSION:-∅} mode=$mode libc=$DCRUP_LIBC mirror=$DCRUP_MIRROR" + if [[ "$mode" == "build" ]]; then + install_build + else + install_prebuilt + fi + check_path } cmd_default() { - [[ $# -eq 1 ]] || die "usage: dcrup default " - parse_spec "$1" - ensure_dirs - local id - if [[ "$SPEC_CHANNEL" == "night" || "$SPEC_FLOATING" -eq 1 ]]; then - id="$(ls -1 "$DCRUP_TC" 2>/dev/null | grep -E "^${SPEC_CHANNEL}-" | sort | tail -n1 || true)" - [[ -n "$id" ]] || die "no installed toolchain for channel $SPEC_CHANNEL (run: dcrup install $SPEC_CHANNEL)" - else - id="$(toolchain_id)" - [[ -d "$DCRUP_TC/$id" ]] || die "not installed: $id (run: dcrup install $1)" - fi - link_default "$id" + [[ $# -eq 1 ]] || die "usage: dcrup default " + parse_spec "$1" + ensure_dirs + local id + if [[ "$SPEC_CHANNEL" == "night" || "$SPEC_FLOATING" -eq 1 ]]; then + id="$(ls -1 "$DCRUP_TC" 2>/dev/null | grep -E "^${SPEC_CHANNEL}-" | sort | tail -n1 || true)" + [[ -n "$id" ]] || die "no installed toolchain for channel $SPEC_CHANNEL (run: dcrup install $SPEC_CHANNEL)" + else + id="$(toolchain_id)" + [[ -d "$DCRUP_TC/$id" ]] || die "not installed: $id (run: dcrup install $1)" + fi + link_default "$id" } cmd_update() { - ensure_dirs - local active - active="$(read_active)" - [[ -n "$active" ]] || die "no active toolchain (run: dcrup install stable)" - case "$active" in - night-*) - log "updating night (rebuild HEAD) …" - FORCE=1 cmd_install night --build --force - ;; - stable-*|dev-*) - local ch="${active%%-*}" - log "updating floating channel $ch …" - FORCE=1 cmd_install "$ch" --force - ;; - *-stable|*-dev) - ok "pinned toolchain $active — not floating; install a newer version explicitly" - ;; - *) - warn "unknown active id $active; try: dcrup install stable" - ;; - esac + ensure_dirs + local active + active="$(read_active)" + [[ -n "$active" ]] || die "no active toolchain (run: dcrup install stable)" + case "$active" in + night-*) + log "updating night (rebuild HEAD) …" + FORCE=1 cmd_install night --build --force + ;; + stable-* | dev-*) + local ch="${active%%-*}" + log "updating floating channel $ch …" + FORCE=1 cmd_install "$ch" --force + ;; + *-stable | *-dev) + ok "pinned toolchain $active — not floating; install a newer version explicitly" + ;; + *) + warn "unknown active id $active; try: dcrup install stable" + ;; + esac } cmd_list() { - ensure_dirs - local active - active="$(read_active)" - if [[ ! -d "$DCRUP_TC" ]] || [[ -z "$(ls -A "$DCRUP_TC" 2>/dev/null || true)" ]]; then - warn "no toolchains installed" - return 0 + ensure_dirs + local active + active="$(read_active)" + if [[ ! -d "$DCRUP_TC" ]] || [[ -z "$(ls -A "$DCRUP_TC" 2>/dev/null || true)" ]]; then + warn "no toolchains installed" + return 0 + fi + local d base + for d in "$DCRUP_TC"/*; do + [[ -d "$d" ]] || continue + base="$(basename "$d")" + if [[ "$base" == "$active" ]]; then + printf ' * %s\n' "$base" + else + printf ' %s\n' "$base" fi - local d base - for d in "$DCRUP_TC"/*; do - [[ -d "$d" ]] || continue - base="$(basename "$d")" - if [[ "$base" == "$active" ]]; then - printf ' * %s\n' "$base" - else - printf ' %s\n' "$base" - fi - done + done } cmd_show() { - ensure_dirs - local active - active="$(read_active)" - echo "DCRUP_HOME=$DCRUP_HOME" - echo "DCRUP_BIN=$DCRUP_BIN" - echo "active=${active:-none}" - if [[ -n "$active" && -f "$DCRUP_TC/$active/dcrup-meta" ]]; then - echo "--- meta ---" - cat "$DCRUP_TC/$active/dcrup-meta" - fi - if [[ -x "$DCRUP_BIN/dcr" ]]; then - echo "--- dcr --version ---" - "$DCRUP_BIN/dcr" --version 2>/dev/null || true - fi + ensure_dirs + local active + active="$(read_active)" + echo "DCRUP_HOME=$DCRUP_HOME" + echo "DCRUP_BIN=$DCRUP_BIN" + echo "active=${active:-none}" + if [[ -n "$active" && -f "$DCRUP_TC/$active/dcrup-meta" ]]; then + echo "--- meta ---" + cat "$DCRUP_TC/$active/dcrup-meta" + fi + if [[ -x "$DCRUP_BIN/dcr" ]]; then + echo "--- dcr --version ---" + "$DCRUP_BIN/dcr" --version 2>/dev/null || true + fi } cmd_which() { - if [[ -L "$DCRUP_BIN/dcr" || -e "$DCRUP_BIN/dcr" ]]; then - readlink -f "$DCRUP_BIN/dcr" 2>/dev/null || readlink "$DCRUP_BIN/dcr" 2>/dev/null || echo "$DCRUP_BIN/dcr" - else - die "dcr not linked (run: dcrup install stable)" - fi + if [[ -L "$DCRUP_BIN/dcr" || -e "$DCRUP_BIN/dcr" ]]; then + readlink -f "$DCRUP_BIN/dcr" 2>/dev/null || readlink "$DCRUP_BIN/dcr" 2>/dev/null || echo "$DCRUP_BIN/dcr" + else + die "dcr not linked (run: dcrup install stable)" + fi } cmd_uninstall() { - ensure_dirs - if [[ "${1:-}" == "--all" ]]; then - rm -rf "$DCRUP_TC" - rm -f "$DCRUP_BIN/dcr" "$(active_file)" - ok "removed all toolchains" - return 0 - fi - [[ $# -eq 1 ]] || die "usage: dcrup uninstall |--all" - parse_spec "$1" - local id - if [[ "$SPEC_FLOATING" -eq 1 || "$SPEC_CHANNEL" == "night" ]]; then - id="$(ls -1 "$DCRUP_TC" 2>/dev/null | grep -E "^${SPEC_CHANNEL}-" | sort | tail -n1 || true)" - else - id="$(toolchain_id)" - fi - [[ -n "$id" && -d "$DCRUP_TC/$id" ]] || die "not installed: $1" - rm -rf "$DCRUP_TC/$id" - if [[ "$(read_active)" == "$id" ]]; then - rm -f "$DCRUP_BIN/dcr" "$(active_file)" - warn "removed active toolchain; run: dcrup install stable" - fi - ok "removed $id" + ensure_dirs + if [[ "${1:-}" == "--all" ]]; then + rm -rf "$DCRUP_TC" + rm -f "$DCRUP_BIN/dcr" "$(active_file)" + ok "removed all toolchains" + return 0 + fi + [[ $# -eq 1 ]] || die "usage: dcrup uninstall |--all" + parse_spec "$1" + local id + if [[ "$SPEC_FLOATING" -eq 1 || "$SPEC_CHANNEL" == "night" ]]; then + id="$(ls -1 "$DCRUP_TC" 2>/dev/null | grep -E "^${SPEC_CHANNEL}-" | sort | tail -n1 || true)" + else + id="$(toolchain_id)" + fi + [[ -n "$id" && -d "$DCRUP_TC/$id" ]] || die "not installed: $1" + rm -rf "$DCRUP_TC/$id" + if [[ "$(read_active)" == "$id" ]]; then + rm -f "$DCRUP_BIN/dcr" "$(active_file)" + warn "removed active toolchain; run: dcrup install stable" + fi + ok "removed $id" } check_path() { - case ":$PATH:" in - *":$DCRUP_BIN:"*) ;; - *) - warn "$DCRUP_BIN is not in PATH" - echo "Add to ~/.bashrc / ~/.zshrc / ~/.profile:" - echo " export PATH=\"$DCRUP_BIN:\$PATH\"" - ;; - esac + case ":$PATH:" in + *":$DCRUP_BIN:"*) ;; + *) + warn "$DCRUP_BIN is not in PATH" + echo "Add to ~/.bashrc / ~/.zshrc / ~/.profile:" + echo " export PATH=\"$DCRUP_BIN:\$PATH\"" + ;; + esac } cmd_self_install() { - local dest="$DCRUP_BIN" - while [[ $# -gt 0 ]]; do - case "$1" in - --to) dest="$2"; shift 2 ;; - *) die "usage: dcrup self-install [--to DIR]" ;; - esac - done - ensure_dirs - mkdir -p "$dest" - local self - self="$(readlink -f "$0" 2>/dev/null || realpath "$0" 2>/dev/null || echo "$0")" - cp "$self" "$dest/dcrup" - chmod +x "$dest/dcrup" - ok "dcrup installed to $dest/dcrup" - check_path - echo "Then: dcrup install stable" + local dest="$DCRUP_BIN" + while [[ $# -gt 0 ]]; do + case "$1" in + --to) + dest="$2" + shift 2 + ;; + *) die "usage: dcrup self-install [--to DIR]" ;; + esac + done + ensure_dirs + mkdir -p "$dest" + local self + self="$(readlink -f "$0" 2>/dev/null || realpath "$0" 2>/dev/null || true)" + if [[ -z "$self" || ! -f "$self" ]]; then + # When invoked as `curl ... | sh`, the shell has no script file to copy. + # Fetch the same trusted installer URL and install that exact script. + need_cmd curl + self="$(mktemp "${TMPDIR:-/tmp}/dcrup.XXXXXX")" + curl -fsSL --proto '=https' --tlsv1.2 "$DCRUP_INSTALL_URL" -o "$self" || { + rm -f "$self" + die "unable to download installer for self-install" + } + trap 'rm -f "$self"' EXIT + fi + cp "$self" "$dest/dcrup" + chmod +x "$dest/dcrup" + ok "dcrup installed to $dest/dcrup" + check_path + echo "Then: dcrup install stable" } main() { - local cmd="${1:-}" - shift || true - case "$cmd" in - ""|-h|--help|help) usage ;; - install) cmd_install "$@" ;; - default) cmd_default "$@" ;; - update) cmd_update "$@" ;; - list) cmd_list "$@" ;; - show) cmd_show "$@" ;; - which) cmd_which "$@" ;; - uninstall) cmd_uninstall "$@" ;; - self-install) cmd_self_install "$@" ;; - *) die "unknown command: $cmd (try: dcrup help)" ;; - esac + local cmd="${1:-}" + shift || true + case "$cmd" in + "" | -h | --help | help) usage ;; + install) cmd_install "$@" ;; + default) cmd_default "$@" ;; + update) cmd_update "$@" ;; + list) cmd_list "$@" ;; + show) cmd_show "$@" ;; + which) cmd_which "$@" ;; + uninstall) cmd_uninstall "$@" ;; + self-install) cmd_self_install "$@" ;; + *) die "unknown command: $cmd (try: dcrup help)" ;; + esac } main "$@" diff --git a/docs/getting-started/installation.mdx b/docs/getting-started/installation.mdx index 9b9a26f..e840e55 100644 --- a/docs/getting-started/installation.mdx +++ b/docs/getting-started/installation.mdx @@ -11,7 +11,7 @@ Install and switch DCR versions (stable / dev / night, pin `0.8.2`, optional bui ### Linux / macOS / BSD / Windows (bash) ```sh -curl -fsSL https://sh.dcr-tool.ru | sh -s -- self-install +curl --proto '=https' --tlsv1.2 -sSf https://sh.dcr-tool.ru | sh -s -- self-install export PATH="$HOME/.dcr/bin:$PATH" dcrup install stable ``` @@ -19,17 +19,14 @@ dcrup install stable Non-interactive install of DCR in one shot: ```sh -curl -fsSL https://sh.dcr-tool.ru | sh -s -- install stable +curl --proto '=https' --tlsv1.2 -sSf https://sh.dcr-tool.ru | sh -s -- install stable export PATH="$HOME/.dcr/bin:$PATH" ``` ### Windows (PowerShell) ```powershell -irm https://ps1.dcr-tool.ru | iex -# or download then run: -# irm https://ps1.dcr-tool.ru -OutFile dcrup.ps1 -# powershell -File .\dcrup.ps1 self-install +& ([scriptblock]::Create((irm https://ps1.dcr-tool.ru))) self-install # $env:Path += ";$env:USERPROFILE\.dcr\bin" dcrup install stable ``` @@ -58,6 +55,8 @@ dcrup update dcrup list dcrup show dcrup which +dcrup uninstall 0.8.2 # remove one installed version +dcrup uninstall --all # remove all installed versions ``` Layout: `~/.dcr/toolchains//dcr` and `~/.dcr/bin/dcr` → active version.