-
Notifications
You must be signed in to change notification settings - Fork 6
feat: install.sh for cli #502
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,311 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #!/usr/bin/env bash | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| set -euo pipefail | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # --- config --- | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| REPO="relaystr/ndk" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| BIN_NAME="ndk" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| INSTALL_DIR="${NDK_INSTALL_DIR:-$HOME/.local/bin}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| VERSION="${NDK_VERSION:-latest}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| PRERELEASE="${NDK_PRERELEASE:-0}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| INSTALL_MODE="${NDK_INSTALL_MODE:-user}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| USER_LIB_DIR="${NDK_USER_LIB_DIR:-$HOME/.local/lib}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| SYSTEM_BIN_DIR="${NDK_SYSTEM_BIN_DIR:-/usr/bin}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| SYSTEM_LIB_DIR="${NDK_SYSTEM_LIB_DIR:-/usr/lib}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # --- helpers --- | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| info() { echo -e "\033[1;34minfo\033[0m $*"; } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ok() { echo -e "\033[1;32m ok \033[0m $*"; } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| err() { echo -e "\033[1;31merror\033[0m $*" >&2; exit 1; } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| need() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| command -v "$1" &>/dev/null || err "required tool not found: $1" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| is_truthy() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| case "$1" in | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 1 | true | TRUE | yes | YES) return 0 ;; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| *) return 1 ;; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| esac | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # --- detect platform --- | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| detect_target() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| local os arch | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| os="$(uname -s)" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| arch="$(uname -m)" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| case "$os" in | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Linux) os="linux" ;; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Darwin) os="macos" ;; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| *) err "unsupported OS: $os" ;; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| esac | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| case "$arch" in | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| x86_64) arch="x64" ;; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| aarch64 | arm64) arch="arm64" ;; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| *) err "unsupported architecture: $arch" ;; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| esac | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo "${os}-${arch}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # --- resolve version/tag --- | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| resolve_tag() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| local use_prerelease="0" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| local tag | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| case "$VERSION" in | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| latest-pre | latest-prerelease) use_prerelease="1" ;; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| latest) is_truthy "$PRERELEASE" && use_prerelease="1" ;; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| esac | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if [ "$VERSION" = "latest" ] || [ "$VERSION" = "latest-pre" ] || [ "$VERSION" = "latest-prerelease" ]; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| need curl | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if [ "$use_prerelease" = "1" ]; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| tag=$( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| curl -fsSL "https://api.github.com/repos/${REPO}/releases" \ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| | awk ' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| BEGIN { tag=""; draft=0; found="" } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /"tag_name":/ { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (tag == "") { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| tag = $0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sub(/^.*"tag_name":[[:space:]]*"/, "", tag) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sub(/".*$/, "", tag) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /"draft":/ { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| draft = ($0 ~ /true/) ? 1 : 0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /"prerelease":/ { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if ($0 ~ /true/ && draft == 0 && tag != "") { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (found == "") { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| found = tag | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| tag="" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| draft=0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| END { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (found != "") { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| print found | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [ -n "$tag" ] || err "could not determine latest pre-release version" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| tag=$( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| curl -fsSL "https://api.github.com/repos/${REPO}/releases/latest" \ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| | grep '"tag_name"' \ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| | sed -E 's/.*"([^"]+)".*/\1/' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [ -n "$tag" ] || err "could not determine latest version" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if [[ "$VERSION" =~ ^v[0-9] ]]; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| tag="$VERSION" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| tag="v${VERSION}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo "$tag" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| get_release_json() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| local tag="$1" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if curl -fsSL "https://api.github.com/repos/${REPO}/releases/tags/${tag}"; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return 0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if [[ "$tag" =~ ^v ]]; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| curl -fsSL "https://api.github.com/repos/${REPO}/releases/tags/${tag#v}" \ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| || err "could not fetch release metadata for tag: ${tag}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| curl -fsSL "https://api.github.com/repos/${REPO}/releases/tags/v${tag}" \ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| || err "could not fetch release metadata for tag: ${tag}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| resolve_release_asset() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| local release_json="$1" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| local target="$2" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| printf "%s\n" "$release_json" | awk -v target="$target" ' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| BEGIN { name="" } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /"name":/ { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (name == "") { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| name = $0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sub(/^.*"name":[[:space:]]*"/, "", name) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sub(/".*$/, "", name) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| next | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /"browser_download_url":/ { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (name != "") { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| url = $0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sub(/^.*"browser_download_url":[[:space:]]*"/, "", url) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sub(/".*$/, "", url) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (name ~ ("-" target "\\.(tar\\.gz|tgz)$")) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| print name "\t" url | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| exit | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| name = "" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+136
to
+157
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🌐 Web query:
💡 Result: The GitHub Releases API response JSON structure includes an 'assets' array in release objects (e.g., from GET /repos/{owner}/{repo}/releases, GET /repos/{owner}/{repo}/releases/{release_id}). Official documentation does not specify any guaranteed order for the elements in this array. No sorting criteria (such as by ID, name, created_at, or upload order) is documented. In practice, it is likely unordered or sorted by creation time or ID (ascending), as is common for database-backed lists without explicit sorting, but this is not guaranteed and may vary. For reliable ordering, clients should sort the array themselves if order matters. Note that the dedicated List release assets endpoint (GET /repos/{owner}/{repo}/releases/{release_id}/assets) supports pagination but also lacks documented sort order. Citations:
🏁 Script executed: # Let's also create a minimal test to trace through the AWK logic
cat > /tmp/test_awk.sh << 'EOF'
#!/bin/bash
# Sample GitHub Releases API response (simplified)
release_json='
{
"id": 123,
"tag_name": "v1.0.0",
"name": "Release v1.0.0",
"assets": [
{
"id": 456,
"name": "my-tool-linux-amd64.tar.gz",
"browser_download_url": "https://example.com/my-tool-linux-amd64.tar.gz"
},
{
"id": 789,
"name": "my-tool-darwin-arm64.tar.gz",
"browser_download_url": "https://example.com/my-tool-darwin-arm64.tar.gz"
}
]
}
'
target="linux-amd64"
echo "=== Testing ORIGINAL code ==="
printf "%s\n" "$release_json" | awk -v target="$target" '
BEGIN { name="" }
/"name":/ {
if (name == "") {
name = $0
sub(/^.*"name":[[:space:]]*"/, "", name)
sub(/".*$/, "", name)
}
next
}
/"browser_download_url":/ {
if (name != "") {
url = $0
sub(/^.*"browser_download_url":[[:space:]]*"/, "", url)
sub(/".*$/, "", url)
if (name ~ ("-" target "\\.(tar\\.gz|tgz)$")) {
print name "\t" url
exit
}
}
name = ""
}
'
echo ""
echo "=== Testing SUGGESTED FIX ==="
printf "%s\n" "$release_json" | awk -v target="$target" '
BEGIN { in_assets=0; name="" }
/"assets":[[:space:]]*\[/ { in_assets=1; next }
in_assets && /^[[:space:]]*\],?$/ { exit }
!in_assets { next }
/"name":/ {
if (name == "") {
name = $0
sub(/^.*"name":[[:space:]]*"/, "", name)
sub(/".*$/, "", name)
}
next
}
/"browser_download_url":/ {
if (name != "") {
url = $0
sub(/^.*"browser_download_url":[[:space:]]*"/, "", url)
sub(/".*$/, "", url)
if (name ~ ("-" target "\\.(tar\\.gz|tgz)$")) {
print name "\t" url
exit
}
}
name = ""
}
'
EOF
bash /tmp/test_awk.sh
EOFRepository: relaystr/ndk Length of output: 252 🏁 Script executed: # Corrected test script
release_json='
{
"id": 123,
"tag_name": "v1.0.0",
"name": "Release v1.0.0",
"assets": [
{
"id": 456,
"name": "my-tool-linux-amd64.tar.gz",
"browser_download_url": "https://example.com/my-tool-linux-amd64.tar.gz"
},
{
"id": 789,
"name": "my-tool-darwin-arm64.tar.gz",
"browser_download_url": "https://example.com/my-tool-darwin-arm64.tar.gz"
}
]
}
'
target="linux-amd64"
echo "=== ORIGINAL CODE (from install.sh lines 136-157) ==="
printf "%s\n" "$release_json" | awk -v target="$target" '
BEGIN { name="" }
/"name":/ {
if (name == "") {
name = $0
sub(/^.*"name":[[:space:]]*"/, "", name)
sub(/".*$/, "", name)
}
next
}
/"browser_download_url":/ {
if (name != "") {
url = $0
sub(/^.*"browser_download_url":[[:space:]]*"/, "", url)
sub(/".*$/, "", url)
if (name ~ ("-" target "\\.(tar\\.gz|tgz)$")) {
print name "\t" url
exit
}
}
name = ""
}
'
echo "(Exit code: $?)"
echo ""
echo "=== SUGGESTED FIX ==="
printf "%s\n" "$release_json" | awk -v target="$target" '
BEGIN { in_assets=0; name="" }
/"assets":[[:space:]]*\[/ { in_assets=1; next }
in_assets && /^[[:space:]]*\],?$/ { exit }
!in_assets { next }
/"name":/ {
if (name == "") {
name = $0
sub(/^.*"name":[[:space:]]*"/, "", name)
sub(/".*$/, "", name)
}
next
}
/"browser_download_url":/ {
if (name != "") {
url = $0
sub(/^.*"browser_download_url":[[:space:]]*"/, "", url)
sub(/".*$/, "", url)
if (name ~ ("-" target "\\.(tar\\.gz|tgz)$")) {
print name "\t" url
exit
}
}
name = ""
}
'
echo "(Exit code: $?)"Repository: relaystr/ndk Length of output: 236 The first release asset is never selectable. Line 138 captures the release-level Suggested fix- printf "%s\n" "$release_json" | awk -v target="$target" '
- BEGIN { name="" }
+ printf "%s\n" "$release_json" | awk -v target="$target" '
+ BEGIN { in_assets=0; name="" }
+ /"assets":[[:space:]]*\[/ { in_assets=1; next }
+ in_assets && /^[[:space:]]*\],?$/ { exit }
+ !in_assets { next }
/"name":/ {📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| check_sudo_needed() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| local path parent | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for path in "$@"; do | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if [ -e "$path" ]; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [ -w "$path" ] || return 0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| parent="$(dirname "$path")" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [ -w "$parent" ] || return 0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| done | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return 1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| run_priv() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if [ "${USE_SUDO:-0}" = "1" ]; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sudo "$@" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "$@" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| parse_args() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| while [ $# -gt 0 ]; do | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| case "$1" in | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| --system) INSTALL_MODE="system" ;; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| --user) INSTALL_MODE="user" ;; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| -h | --help) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cat <<EOF | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Usage: install.sh [--user|--system] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Install mode (Linux): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| --user Install to user paths (default): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - binary: NDK_INSTALL_DIR (default: ~/.local/bin) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - libs: NDK_USER_LIB_DIR (default: ~/.local/lib) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| --system Install to system paths: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - binary: NDK_SYSTEM_BIN_DIR (default: /usr/bin) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| - libs: NDK_SYSTEM_LIB_DIR (default: /usr/lib) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Env vars: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| NDK_VERSION Version or tag. Also supports latest, latest-pre. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| NDK_PRERELEASE When truthy and NDK_VERSION=latest, picks latest pre-release. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| NDK_INSTALL_MODE user|system (Linux) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| EOF | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| exit 0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ;; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| *) err "unknown argument: $1" ;; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| esac | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| shift | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| done | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # --- main --- | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| main() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| parse_args "$@" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| need curl | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| need tar | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| local target tag release_json asset_name download_url tmp_dir extract_dir | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| local bin_src lib_src lib_installed | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+219
to
+220
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: cd /tmp && git ls-files | grep -E "install\.sh$"Repository: relaystr/ndk Length of output: 124 🏁 Script executed: head -250 install.sh | tail -50Repository: relaystr/ndk Length of output: 1866 🏁 Script executed: # Let's examine the trap setup and main function structure
sed -n '200,250p' install.shRepository: relaystr/ndk Length of output: 1877 🏁 Script executed: # Check how main() is called
grep -n "^main\|^.*main(" install.sh | head -20Repository: relaystr/ndk Length of output: 82 🏁 Script executed: # Look for other trap definitions
grep -n "trap" install.shRepository: relaystr/ndk Length of output: 95 🏁 Script executed: # Check script structure and sourcing
head -50 install.shRepository: relaystr/ndk Length of output: 1220 🏁 Script executed: # Check if there's any cleanup at the end of main() before return
sed -n '208,320p' install.sh | tail -50Repository: relaystr/ndk Length of output: 1555 🏁 Script executed: # Look for the actual end of main() function
awk '/^main\(\) {/,/^}/ {print NR": "$0}' install.sh | tail -30Repository: relaystr/ndk Length of output: 1093 🏁 Script executed: # Let's verify the trap behavior with a test to confirm the bug
cat > /tmp/trap_test.sh << 'EOF'
#!/bin/bash
test_local_trap() {
local tmp_dir
tmp_dir="$(mktemp -d)"
echo "Created temp dir: $tmp_dir"
trap 'rm -rf "${tmp_dir:-}"' EXIT
# Function returns, tmp_dir goes out of scope
}
test_global_trap() {
TMP_DIR=""
TMP_DIR="$(mktemp -d)"
echo "Created global temp dir: $TMP_DIR"
trap 'rm -rf "${TMP_DIR:-}"' EXIT
}
echo "Testing local variable trap:"
test_local_trap
echo "After function returns"
ls /tmp/tmp.* 2>/dev/null || echo "No temp dirs left (bug not present)"
# Clean up for next test
trap - EXIT
echo ""
echo "Testing global variable trap:"
test_global_trap
EOF
chmod +x /tmp/trap_test.sh
bash /tmp/trap_test.shRepository: relaystr/ndk Length of output: 221 🏁 Script executed: # Verify the script is called at the end (line 313)
tail -5 install.shRepository: relaystr/ndk Length of output: 85 🏁 Script executed: # Check if temp dirs from the test still exist
ls -la /tmp/tmp.* 2>&1 | head -20Repository: relaystr/ndk Length of output: 162 🏁 Script executed: # Verify the proposed fix approach works correctly by checking the global scope
grep -n "SYSTEM_LIB_DIR\|^[A-Z_]*=" install.sh | head -15Repository: relaystr/ndk Length of output: 796 Temporary directory cleanup fails due to local variable going out of scope when When Declare Proposed fix SYSTEM_LIB_DIR="${NDK_SYSTEM_LIB_DIR:-/usr/lib}"
+TMP_DIR=""
main() {
parse_args "$@"
need curl
need tar
- local target tag release_json asset_name download_url tmp_dir extract_dir
+ local target tag release_json asset_name download_url extract_dir
local bin_src lib_src lib_installed
target="$(detect_target)"
tag="$(resolve_tag)"
release_json="$(get_release_json "$tag")"
IFS=$'\t' read -r asset_name download_url <<< "$(resolve_release_asset "$release_json" "$target")"
[ -n "${asset_name:-}" ] || err "could not find archive asset matching '*-${target}.tar.gz' (or .tgz) for tag ${tag}"
[ -n "${download_url:-}" ] || err "could not determine asset download URL for tag ${tag}"
info "installing ${BIN_NAME} ${tag} (${target})"
info "from ${asset_name}"
- tmp_dir="$(mktemp -d)"
- extract_dir="${tmp_dir}/extract"
- trap 'rm -rf "${tmp_dir:-}"' EXIT
+ TMP_DIR="$(mktemp -d)"
+ extract_dir="${TMP_DIR}/extract"
+ trap 'rm -rf "${TMP_DIR:-}"' EXIT
mkdir -p "$extract_dir"
- curl -fsSL --progress-bar "$download_url" -o "${tmp_dir}/${asset_name}" \
+ curl -fsSL --progress-bar "$download_url" -o "${TMP_DIR}/${asset_name}" \
|| err "download failed — check that release asset exists: ${download_url}"
- tar -xzf "${tmp_dir}/${asset_name}" -C "$extract_dir" \
+ tar -xzf "${TMP_DIR}/${asset_name}" -C "$extract_dir" \
|| err "failed to extract archive: ${asset_name}"📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| target="$(detect_target)" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| tag="$(resolve_tag)" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| release_json="$(get_release_json "$tag")" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| IFS=$'\t' read -r asset_name download_url <<< "$(resolve_release_asset "$release_json" "$target")" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [ -n "${asset_name:-}" ] || err "could not find archive asset matching '*-${target}.tar.gz' (or .tgz) for tag ${tag}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [ -n "${download_url:-}" ] || err "could not determine asset download URL for tag ${tag}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| info "installing ${BIN_NAME} ${tag} (${target})" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| info "from ${asset_name}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| tmp_dir="$(mktemp -d)" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| extract_dir="${tmp_dir}/extract" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| trap 'rm -rf "${tmp_dir:-}"' EXIT | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| mkdir -p "$extract_dir" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| curl -fsSL --progress-bar "$download_url" -o "${tmp_dir}/${asset_name}" \ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| || err "download failed — check that release asset exists: ${download_url}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| tar -xzf "${tmp_dir}/${asset_name}" -C "$extract_dir" \ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| || err "failed to extract archive: ${asset_name}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+238
to
+242
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Downloaded artifact is extracted and executed without integrity verification. The installer currently trusts network-delivered assets before extraction and execution. Add checksum/signature verification first (and fail closed) to reduce supply-chain risk. 💡 Proposed hardening direction+ # Verify archive integrity before extraction/execution.
+ # Example: require a sidecar checksum asset and validate here.
+ # (Use sha256sum/shasum depending on platform.)
+ # err if checksum is unavailable or mismatched.
+ # Reject unsafe tar paths before extraction.
+ tar -tzf "${TMP_DIR}/${asset_name}" \
+ | awk '($0 ~ /^\//) || ($0 ~ /(^|\/)\.\.(\/|$)/) { bad=1 } END { exit bad }' \
+ || err "archive contains unsafe paths"Also applies to: 246-250 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| bin_src="${extract_dir}/bin/${BIN_NAME}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [ -f "$bin_src" ] || err "archive does not contain expected binary: bin/${BIN_NAME}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| chmod +x "$bin_src" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # quick sanity check (make bundled libs discoverable before install) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # not all builds implement --version, so accept --help or default invocation too | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if ! LD_LIBRARY_PATH="${extract_dir}/lib:${LD_LIBRARY_PATH:-}" "$bin_src" --version &>/dev/null; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if ! LD_LIBRARY_PATH="${extract_dir}/lib:${LD_LIBRARY_PATH:-}" "$bin_src" --help &>/dev/null; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| LD_LIBRARY_PATH="${extract_dir}/lib:${LD_LIBRARY_PATH:-}" "$bin_src" &>/dev/null \ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| || err "downloaded binary failed to run — wrong platform?" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if [ "${target#linux-}" != "$target" ] && [ "$INSTALL_MODE" = "system" ]; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| USE_SUDO="0" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if [ "$(id -u)" -ne 0 ] && check_sudo_needed "$SYSTEM_BIN_DIR" "$SYSTEM_LIB_DIR"; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| need sudo | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| USE_SUDO="1" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| run_priv mkdir -p "$SYSTEM_BIN_DIR" "$SYSTEM_LIB_DIR" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| run_priv install -m 0755 "$bin_src" "${SYSTEM_BIN_DIR}/${BIN_NAME}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| lib_installed="0" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for lib_src in "${extract_dir}/lib"/*; do | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [ -f "$lib_src" ] || continue | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| run_priv install -m 0644 "$lib_src" "${SYSTEM_LIB_DIR}/$(basename "$lib_src")" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| lib_installed="1" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| done | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [ "$lib_installed" = "1" ] || err "archive does not contain shared libraries under lib/" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| run_priv ldconfig || true | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ok "${BIN_NAME} installed to ${SYSTEM_BIN_DIR}/${BIN_NAME}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ok "shared libraries installed to ${SYSTEM_LIB_DIR}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+258
to
+281
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
If users pass 💡 Proposed fix target="$(detect_target)"
+ if [ "$INSTALL_MODE" = "system" ] && [ "${target#linux-}" = "$target" ]; then
+ err "--system install mode is only supported on Linux"
+ fi
tag="$(resolve_tag)"
release_json="$(get_release_json "$tag")"🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # user install (default) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| mkdir -p "$INSTALL_DIR" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| mkdir -p "$USER_LIB_DIR" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| install -m 0755 "$bin_src" "${INSTALL_DIR}/${BIN_NAME}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| lib_installed="0" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for lib_src in "${extract_dir}/lib"/*; do | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [ -f "$lib_src" ] || continue | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| install -m 0644 "$lib_src" "${USER_LIB_DIR}/$(basename "$lib_src")" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| lib_installed="1" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| done | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [ "$lib_installed" = "1" ] || err "archive does not contain shared libraries under lib/" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ok "${BIN_NAME} installed to ${INSTALL_DIR}/${BIN_NAME}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ok "shared libraries installed to ${USER_LIB_DIR}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # PATH hint | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if ! echo "$PATH" | grep -q "$INSTALL_DIR"; then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo "" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo " Add this to your shell profile (~/.bashrc / ~/.zshrc):" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo "" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo " export PATH=\"\$PATH:${INSTALL_DIR}\"" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| echo "" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| main "$@" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: relaystr/ndk
Length of output: 226
🏁 Script executed:
fd -t f -name "install.sh"Repository: relaystr/ndk
Length of output: 286
🏁 Script executed:
Repository: relaystr/ndk
Length of output: 68
🏁 Script executed:
cat -n ./install.sh | head -220Repository: relaystr/ndk
Length of output: 6982
🏁 Script executed:
Repository: relaystr/ndk
Length of output: 4081
Add validation for
NDK_INSTALL_MODEenvironment variable.INSTALL_MODEcan be set from the environment to an invalid value and will silently fall back to the defaultuserinstall mode instead of rejecting it. Add validation inparse_args()to ensure only valid values (userorsystem) are accepted.Suggested fix
parse_args() { while [ $# -gt 0 ]; do case "$1" in --system) INSTALL_MODE="system" ;; --user) INSTALL_MODE="user" ;; -h | --help) cat <<EOF Usage: install.sh [--user|--system] Install mode (Linux): --user Install to user paths (default): - binary: NDK_INSTALL_DIR (default: ~/.local/bin) - libs: NDK_USER_LIB_DIR (default: ~/.local/lib) --system Install to system paths: - binary: NDK_SYSTEM_BIN_DIR (default: /usr/bin) - libs: NDK_SYSTEM_LIB_DIR (default: /usr/lib) Env vars: NDK_VERSION Version or tag. Also supports latest, latest-pre. NDK_PRERELEASE When truthy and NDK_VERSION=latest, picks latest pre-release. NDK_INSTALL_MODE user|system (Linux) EOF exit 0 ;; *) err "unknown argument: $1" ;; esac shift done + + case "$INSTALL_MODE" in + user|system) ;; + *) err "invalid install mode: ${INSTALL_MODE} (expected 'user' or 'system')" ;; + esac }📝 Committable suggestion
🤖 Prompt for AI Agents