updated makefiles and added dependency installation for ODIN
CI / Detect changed paths (pull_request) Failing after 1s
CI / Infra unit tests, vet, and preview (pull_request) Has been skipped
CI / Odin unit tests and build (pull_request) Has been skipped
CI / API unit tests and lint (pull_request) Has been skipped

This commit was merged in pull request #3.
This commit is contained in:
2026-09-02 11:37:29 -06:00
parent 920fcd6a1a
commit 9e6cb03b8a
5 changed files with 186 additions and 9 deletions
+151
View File
@@ -0,0 +1,151 @@
#!/usr/bin/env bash
# Search Codeberg, GitHub, and GitLab for an Odin dependency and add it
# as a git submodule under gui/lib/local/. Run via `make -C gui add-dep`.
#
# Usage: add_dep.sh <dependency-name>
#
# Requires: curl, jq
# Optional: fzf (interactive selector; falls back to numbered menu)
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
GUI_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
ROOT_DIR="$(cd "${GUI_DIR}/.." && pwd)"
LIB_DIR="${GUI_DIR}/lib/local"
# ---- Args ------------------------------------------------------------------
if [[ $# -lt 1 ]]; then
echo "Usage: $0 <dependency-name>" >&2
exit 1
fi
QUERY="$1"
# ---- Helpers ---------------------------------------------------------------
TMPDIR_WORK="$(mktemp -d)"
trap 'rm -rf "${TMPDIR_WORK}"' EXIT
RESULTS="${TMPDIR_WORK}/results"
touch "$RESULTS"
search_codeberg() {
local url
url="https://codeberg.org/api/v1/repos/search?q=$(printf '%s' "$QUERY" | jq -sRr @uri)&limit=10"
local data
data=$(curl -sf --max-time 10 "$url" 2>/dev/null) || return 0
printf '%s' "$data" | jq -r '.data[]? | [.owner.username, .name, "codeberg", (.description // "")] | @tsv' 2>/dev/null \
| while IFS=$'\t' read -r owner name _ desc; do
printf '%s\t%s\t%s\t%s\n' "$owner" "$name" "codeberg" "$desc"
done >> "$RESULTS"
}
search_github() {
local url
url="https://api.github.com/search/repositories?q=$(printf '%s' "$QUERY" | jq -sRr @uri)&per_page=10"
local data
data=$(curl -sf --max-time 10 -H "Accept: application/vnd.github+json" "$url" 2>/dev/null) || return 0
printf '%s' "$data" | jq -r '.items[]? | [.owner.login, .name, "github", (.description // "")] | @tsv' 2>/dev/null \
| while IFS=$'\t' read -r owner name _ desc; do
printf '%s\t%s\t%s\t%s\n' "$owner" "$name" "github" "$desc"
done >> "$RESULTS"
}
search_gitlab() {
local url
url="https://gitlab.com/api/v4/projects?search=$(printf '%s' "$QUERY" | jq -sRr @uri)&per_page=10"
local data
data=$(curl -sf --max-time 10 "$url" 2>/dev/null) || return 0
printf '%s' "$data" | jq -r '.[]? | [.namespace.full_path, .name, "gitlab", (.description // "")] | @tsv' 2>/dev/null \
| while IFS=$'\t' read -r owner name _ desc; do
printf '%s\t%s\t%s\t%s\n' "$owner" "$name" "gitlab" "$desc"
done >> "$RESULTS"
}
# ---- Search (Codeberg → GitHub → GitLab) -----------------------------------
echo "Searching for '${QUERY}'..." >&2
search_codeberg
search_github
search_gitlab
TOTAL=$(wc -l < "$RESULTS" | tr -d ' ')
if [[ "$TOTAL" -eq 0 ]]; then
echo "No results found for '${QUERY}' on Codeberg, GitHub, or GitLab." >&2
exit 1
fi
# ---- Select ----------------------------------------------------------------
SELECTED=""
if command -v fzf >/dev/null 2>&1; then
SELECTED=$(while IFS=$'\t' read -r owner name forge desc; do
printf '%-20s %-30s [%s] %s\n' "$owner" "$name" "$forge" "$desc"
done < "$RESULTS" \
| fzf --prompt="Select dependency > " \
--header="${TOTAL} result(s) for '${QUERY}'" \
--height=40% \
--reverse)
else
echo "" >&2
echo "Results for '${QUERY}':" >&2
echo "---" >&2
IDX=0
while IFS=$'\t' read -r owner name forge desc; do
IDX=$((IDX + 1))
printf ' %2d) %-20s %-30s [%s] %s\n' "$IDX" "$owner" "$name" "$forge" "$desc" >&2
done < "$RESULTS"
echo "---" >&2
printf 'Select [1-%d]: ' "$TOTAL" >&2
read -r CHOICE
if ! [[ "$CHOICE" =~ ^[0-9]+$ ]] || [[ "$CHOICE" -lt 1 ]] || [[ "$CHOICE" -gt "$TOTAL" ]]; then
echo "Invalid selection." >&2
exit 1
fi
SELECTED=$(sed -n "${CHOICE}p" "$RESULTS")
fi
if [[ -z "$SELECTED" ]]; then
echo "No selection made." >&2
exit 1
fi
# ---- Parse & Add -----------------------------------------------------------
ENTRYowner=$(printf '%s' "$SELECTED" | cut -f1)
ENTRYname=$(printf '%s' "$SELECTED" | cut -f2)
ENTRYforge=$(printf '%s' "$SELECTED" | cut -f3)
case "$ENTRYforge" in
codeberg) URL="https://codeberg.org/${ENTRYowner}/${ENTRYname}.git" ;;
github) URL="https://github.com/${ENTRYowner}/${ENTRYname}.git" ;;
gitlab) URL="https://gitlab.com/${ENTRYowner}/${ENTRYname}.git" ;;
esac
MODULE_PATH="lib/local/${ENTRYname}"
# Check for name collisions (same dir, different repo).
if [[ -d "${GUI_DIR}/${MODULE_PATH}" ]]; then
EXISTING=$(git -C "${ROOT_DIR}" config --get "submodule.${MODULE_PATH}.url" 2>/dev/null || true)
if [[ -n "$EXISTING" ]]; then
echo "Dependency '${ENTRYname}' is already installed from ${EXISTING}." >&2
exit 1
fi
echo "Error: '${MODULE_PATH}' already exists but is not a submodule." >&2
exit 1
fi
echo "Adding ${ENTRYowner}/${ENTRYname} (${ENTRYforge}) as submodule..." >&2
mkdir -p "${LIB_DIR}"
git -C "${ROOT_DIR}" submodule add "$URL" "$MODULE_PATH"
echo "" >&2
echo "Done — added ${ENTRYowner}/${ENTRYname} from ${ENTRYforge}" >&2
echo " path: ${MODULE_PATH}" >&2
echo " The Makefile's -collection:lib=lib/local will pick it up automatically." >&2