Add dev-mirror manager for npm, pip, cargo, go, gem, docker
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QKxGW1raAWaqeU8WdHsMsp
This commit is contained in:
Executable
+36
@@ -0,0 +1,36 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# omarchy:summary=Apply china or official registry profile to development tools
|
||||||
|
# omarchy:args=<china|official> [--target npm,pip,cargo,go,gem,docker]
|
||||||
|
# omarchy:examples=omarchycn dev-mirror apply china | omarchycn dev-mirror apply official --target npm,pip
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
source "$OMARCHY_PATH/cn/lib/dev-mirror.sh"
|
||||||
|
|
||||||
|
profile="${1:?usage: omarchycn dev-mirror apply <china|official> [--target a,b]}"
|
||||||
|
shift
|
||||||
|
|
||||||
|
if [[ $profile != "china" && $profile != "official" ]]; then
|
||||||
|
echo "Unknown profile: $profile (expected china or official)" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
targets=("${CN_DM_TARGETS[@]}")
|
||||||
|
if [[ ${1:-} == "--target" ]]; then
|
||||||
|
IFS=',' read -ra targets <<<"${2:?--target needs a comma-separated list}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
stamp=$(date +%Y%m%d-%H%M%S)
|
||||||
|
|
||||||
|
for target in "${targets[@]}"; do
|
||||||
|
if [[ ! " ${CN_DM_TARGETS[*]} " == *" $target "* ]]; then
|
||||||
|
echo "Unknown target: $target (known: ${CN_DM_TARGETS[*]})" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
url=$(cn_dm_url "$target" "$profile")
|
||||||
|
cn_dm_backup "$(cn_dm_config_file "$target")" "$stamp"
|
||||||
|
"cn_dm_set_$target" "$url"
|
||||||
|
echo "$target -> ${url:-<default>}"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "Backups (if any): $CN_DM_BACKUP_ROOT/$stamp"
|
||||||
Executable
+32
@@ -0,0 +1,32 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# omarchy:summary=Check reachability of each configured development registry
|
||||||
|
# omarchy:examples=omarchycn dev-mirror doctor
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
source "$OMARCHY_PATH/cn/lib/dev-mirror.sh"
|
||||||
|
|
||||||
|
failures=0
|
||||||
|
|
||||||
|
for target in "${CN_DM_TARGETS[@]}"; do
|
||||||
|
current=$("cn_dm_get_$target")
|
||||||
|
if [[ -z $current ]]; then
|
||||||
|
echo "INFO $target: using tool default"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Reduce to a probe-able https URL
|
||||||
|
probe="${current#sparse+}"
|
||||||
|
probe="${probe%%,*}"
|
||||||
|
if curl -sSf -o /dev/null -m 8 --connect-timeout 5 "$probe" 2>/dev/null; then
|
||||||
|
echo "PASS $target: $current"
|
||||||
|
elif curl -sS -o /dev/null -m 8 --connect-timeout 5 -w '%{http_code}' "$probe" 2>/dev/null | grep -qE '^[34]'; then
|
||||||
|
# Registry roots often answer 3xx/404 to bare GET while the service works
|
||||||
|
echo "PASS $target: $current"
|
||||||
|
else
|
||||||
|
echo "FAIL $target: $current unreachable"
|
||||||
|
failures=$((failures + 1))
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
exit $((failures > 0 ? 1 : 0))
|
||||||
Executable
+14
@@ -0,0 +1,14 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# omarchy:summary=Show configured registry for each development ecosystem
|
||||||
|
# omarchy:examples=omarchycn dev-mirror list
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
source "$OMARCHY_PATH/cn/lib/dev-mirror.sh"
|
||||||
|
|
||||||
|
printf '%-8s %-52s %s\n' "TARGET" "CURRENT" "CONFIG"
|
||||||
|
|
||||||
|
for target in "${CN_DM_TARGETS[@]}"; do
|
||||||
|
current=$("cn_dm_get_$target")
|
||||||
|
printf '%-8s %-52s %s\n' "$target" "${current:-<default>}" "$(cn_dm_config_file "$target")"
|
||||||
|
done
|
||||||
Executable
+20
@@ -0,0 +1,20 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# omarchy:summary=Point one development ecosystem at a custom registry URL
|
||||||
|
# omarchy:args=<target> <url>
|
||||||
|
# omarchy:examples=omarchycn dev-mirror set npm https://registry.example.com
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
source "$OMARCHY_PATH/cn/lib/dev-mirror.sh"
|
||||||
|
|
||||||
|
target="${1:?usage: omarchycn dev-mirror set <target> <url>}"
|
||||||
|
url="${2:?usage: omarchycn dev-mirror set <target> <url>}"
|
||||||
|
|
||||||
|
if [[ ! " ${CN_DM_TARGETS[*]} " == *" $target "* ]]; then
|
||||||
|
echo "Unknown target: $target (known: ${CN_DM_TARGETS[*]})" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
cn_dm_backup "$(cn_dm_config_file "$target")" "$(date +%Y%m%d-%H%M%S)"
|
||||||
|
"cn_dm_set_$target" "$url"
|
||||||
|
echo "$target -> $url"
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"npm": {
|
||||||
|
"china": "https://registry.npmmirror.com",
|
||||||
|
"official": "https://registry.npmjs.org/"
|
||||||
|
},
|
||||||
|
"pip": {
|
||||||
|
"china": "https://pypi.tuna.tsinghua.edu.cn/simple",
|
||||||
|
"official": "https://pypi.org/simple"
|
||||||
|
},
|
||||||
|
"cargo": {
|
||||||
|
"china": "sparse+https://rsproxy.cn/index/",
|
||||||
|
"official": "sparse+https://index.crates.io/"
|
||||||
|
},
|
||||||
|
"go": {
|
||||||
|
"china": "https://goproxy.cn,direct",
|
||||||
|
"official": "https://proxy.golang.org,direct"
|
||||||
|
},
|
||||||
|
"gem": {
|
||||||
|
"china": "https://mirrors.tuna.tsinghua.edu.cn/rubygems/",
|
||||||
|
"official": "https://rubygems.org/"
|
||||||
|
},
|
||||||
|
"docker": {
|
||||||
|
"china": "https://docker.m.daocloud.io",
|
||||||
|
"official": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,126 @@
|
|||||||
|
# shellcheck shell=bash
|
||||||
|
# Sourced helpers for omarchy-cn-dev-mirror-* commands
|
||||||
|
|
||||||
|
CN_DEV_MIRRORS_JSON="$OMARCHY_PATH/cn/dev-mirrors.json"
|
||||||
|
CN_DM_TARGETS=(npm pip cargo go gem docker)
|
||||||
|
CN_DM_BACKUP_ROOT="$HOME/.local/state/omarchycn/backups/dev-mirror"
|
||||||
|
|
||||||
|
cn_dm_url() {
|
||||||
|
jq -re --arg t "$1" --arg p "$2" '.[$t][$p]' "$CN_DEV_MIRRORS_JSON"
|
||||||
|
}
|
||||||
|
|
||||||
|
cn_dm_backup() {
|
||||||
|
local file="$1"
|
||||||
|
local stamp="$2"
|
||||||
|
|
||||||
|
if [[ -f $file ]]; then
|
||||||
|
mkdir -p "$CN_DM_BACKUP_ROOT/$stamp"
|
||||||
|
cp "$file" "$CN_DM_BACKUP_ROOT/$stamp/${file##*/}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Replace-or-append one key=value style line matched by a regex
|
||||||
|
cn_dm_set_line() {
|
||||||
|
local file="$1" match="$2" line="$3"
|
||||||
|
|
||||||
|
mkdir -p "${file%/*}"
|
||||||
|
touch "$file"
|
||||||
|
if grep -qE "$match" "$file"; then
|
||||||
|
sed -i -E "s|$match.*|$line|" "$file"
|
||||||
|
else
|
||||||
|
echo "$line" >> "$file"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
cn_dm_get_npm() { grep -sE '^registry=' "$HOME/.npmrc" | cut -d= -f2- || true; }
|
||||||
|
cn_dm_set_npm() { cn_dm_set_line "$HOME/.npmrc" '^registry=' "registry=$1"; }
|
||||||
|
|
||||||
|
cn_dm_get_pip() {
|
||||||
|
python3 - <<'EOF'
|
||||||
|
import configparser, os
|
||||||
|
c = configparser.ConfigParser()
|
||||||
|
c.read(os.path.expanduser("~/.config/pip/pip.conf"))
|
||||||
|
print(c.get("global", "index-url", fallback=""))
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
cn_dm_set_pip() {
|
||||||
|
CN_DM_PIP_URL="$1" python3 - <<'EOF'
|
||||||
|
import configparser, os
|
||||||
|
path = os.path.expanduser("~/.config/pip/pip.conf")
|
||||||
|
c = configparser.ConfigParser()
|
||||||
|
c.read(path)
|
||||||
|
if not c.has_section("global"):
|
||||||
|
c.add_section("global")
|
||||||
|
c.set("global", "index-url", os.environ["CN_DM_PIP_URL"])
|
||||||
|
os.makedirs(os.path.dirname(path), exist_ok=True)
|
||||||
|
with open(path, "w") as f:
|
||||||
|
c.write(f)
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
cn_dm_get_cargo() {
|
||||||
|
local f="$HOME/.cargo/config.toml"
|
||||||
|
grep -sA1 '^\[source\.omarchycn\]' "$f" | grep -sE '^registry' | cut -d\" -f2 || true
|
||||||
|
}
|
||||||
|
|
||||||
|
cn_dm_set_cargo() {
|
||||||
|
local url="$1" f="$HOME/.cargo/config.toml"
|
||||||
|
|
||||||
|
mkdir -p "${f%/*}"
|
||||||
|
touch "$f"
|
||||||
|
sed -i '/^# OmarchyCN dev-mirror begin$/,/^# OmarchyCN dev-mirror end$/d' "$f"
|
||||||
|
if [[ -n $url ]]; then
|
||||||
|
cat >> "$f" <<EOF
|
||||||
|
# OmarchyCN dev-mirror begin
|
||||||
|
[source.crates-io]
|
||||||
|
replace-with = "omarchycn"
|
||||||
|
|
||||||
|
[source.omarchycn]
|
||||||
|
registry = "$url"
|
||||||
|
# OmarchyCN dev-mirror end
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
cn_dm_get_go() { grep -sE '^GOPROXY=' "$HOME/.config/go/env" | cut -d= -f2- || true; }
|
||||||
|
cn_dm_set_go() { cn_dm_set_line "$HOME/.config/go/env" '^GOPROXY=' "GOPROXY=$1"; }
|
||||||
|
|
||||||
|
cn_dm_get_gem() { grep -sE '^- ' "$HOME/.gemrc" | head -1 | sed 's/^- //' || true; }
|
||||||
|
|
||||||
|
cn_dm_set_gem() {
|
||||||
|
cat > "$HOME/.gemrc" <<EOF
|
||||||
|
---
|
||||||
|
:sources:
|
||||||
|
- $1
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
cn_dm_get_docker() {
|
||||||
|
jq -re '."registry-mirrors"[0] // ""' /etc/docker/daemon.json 2>/dev/null || true
|
||||||
|
}
|
||||||
|
|
||||||
|
cn_dm_set_docker() {
|
||||||
|
local url="$1" current="{}"
|
||||||
|
|
||||||
|
if sudo test -f /etc/docker/daemon.json; then
|
||||||
|
current=$(sudo cat /etc/docker/daemon.json)
|
||||||
|
fi
|
||||||
|
if [[ -n $url ]]; then
|
||||||
|
jq --arg u "$url" '."registry-mirrors" = [$u]' <<<"$current" | sudo tee /etc/docker/daemon.json > /dev/null
|
||||||
|
else
|
||||||
|
jq 'del(."registry-mirrors")' <<<"$current" | sudo tee /etc/docker/daemon.json > /dev/null
|
||||||
|
fi
|
||||||
|
echo "docker: restart the docker daemon to take effect"
|
||||||
|
}
|
||||||
|
|
||||||
|
cn_dm_config_file() {
|
||||||
|
case "$1" in
|
||||||
|
npm) echo "$HOME/.npmrc" ;;
|
||||||
|
pip) echo "$HOME/.config/pip/pip.conf" ;;
|
||||||
|
cargo) echo "$HOME/.cargo/config.toml" ;;
|
||||||
|
go) echo "$HOME/.config/go/env" ;;
|
||||||
|
gem) echo "$HOME/.gemrc" ;;
|
||||||
|
docker) echo "/etc/docker/daemon.json" ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user