Last active
June 2, 2026 07:03
-
-
Save pascaljp/f3f7a70e2b845445ff286e5637eddde3 to your computer and use it in GitHub Desktop.
pascaljp/personal private repository bootstrap installer
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/sh | |
| set -eu | |
| REPO_URL="${PERSONAL_REPO_URL:-git@github.com:pascaljp/personal.git}" | |
| REPO_REF="${PERSONAL_REF:-main}" | |
| REPO_DIR="${PERSONAL_REPO_DIR:-${HOME}/.local/share/pascaljp/personal}" | |
| log() { | |
| echo "==> $*" | |
| } | |
| have() { | |
| command -v "$1" >/dev/null 2>&1 | |
| } | |
| run_sudo() { | |
| if [ "$(id -u)" -eq 0 ]; then | |
| "$@" | |
| return | |
| fi | |
| if have sudo; then | |
| sudo "$@" | |
| return | |
| fi | |
| echo "sudo is required to install missing packages. Install sudo or run as root, then rerun this script." >&2 | |
| exit 2 | |
| } | |
| install_homebrew() { | |
| if have brew; then | |
| return | |
| fi | |
| if ! have curl; then | |
| echo "curl is required to install Homebrew on macOS." >&2 | |
| exit 2 | |
| fi | |
| log "Installing Homebrew" | |
| NONINTERACTIVE=1 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" | |
| if [ -x /opt/homebrew/bin/brew ]; then | |
| eval "$(/opt/homebrew/bin/brew shellenv)" | |
| elif [ -x /usr/local/bin/brew ]; then | |
| eval "$(/usr/local/bin/brew shellenv)" | |
| fi | |
| } | |
| install_macos_packages() { | |
| packages="" | |
| have git || packages="${packages} git" | |
| have bash || packages="${packages} bash" | |
| if [ -z "$packages" ]; then | |
| return | |
| fi | |
| install_homebrew | |
| log "Installing missing macOS packages:${packages}" | |
| # shellcheck disable=SC2086 | |
| brew install $packages | |
| } | |
| linux_install_command() { | |
| if have apt-get; then | |
| echo "apt" | |
| elif have dnf; then | |
| echo "dnf" | |
| elif have yum; then | |
| echo "yum" | |
| elif have pacman; then | |
| echo "pacman" | |
| elif have zypper; then | |
| echo "zypper" | |
| elif have apk; then | |
| echo "apk" | |
| else | |
| echo "" | |
| fi | |
| } | |
| install_linux_packages() { | |
| packages="" | |
| have git || packages="${packages} git" | |
| have bash || packages="${packages} bash" | |
| if [ -z "$packages" ]; then | |
| return | |
| fi | |
| manager="$(linux_install_command)" | |
| if [ -z "$manager" ]; then | |
| echo "Could not find a supported Linux package manager. Install git and bash manually, then rerun this script." >&2 | |
| exit 2 | |
| fi | |
| log "Installing missing Linux packages with ${manager}:${packages}" | |
| case "$manager" in | |
| apt) | |
| run_sudo apt-get update | |
| # shellcheck disable=SC2086 | |
| run_sudo apt-get install -y $packages | |
| ;; | |
| dnf) | |
| # shellcheck disable=SC2086 | |
| run_sudo dnf install -y $packages | |
| ;; | |
| yum) | |
| # shellcheck disable=SC2086 | |
| run_sudo yum install -y $packages | |
| ;; | |
| pacman) | |
| # shellcheck disable=SC2086 | |
| run_sudo pacman -Sy --needed --noconfirm $packages | |
| ;; | |
| zypper) | |
| # shellcheck disable=SC2086 | |
| run_sudo zypper --non-interactive install $packages | |
| ;; | |
| apk) | |
| # shellcheck disable=SC2086 | |
| run_sudo apk add $packages | |
| ;; | |
| esac | |
| } | |
| ensure_basic_tools() { | |
| if have git && have bash; then | |
| return | |
| fi | |
| case "$(uname -s)" in | |
| Darwin) | |
| install_macos_packages | |
| ;; | |
| Linux) | |
| install_linux_packages | |
| ;; | |
| *) | |
| echo "Unsupported OS: $(uname -s). Install git and bash manually, then rerun this script." >&2 | |
| exit 2 | |
| ;; | |
| esac | |
| if ! have git || ! have bash; then | |
| echo "Failed to install git or bash. Install them manually, then rerun this script." >&2 | |
| exit 2 | |
| fi | |
| } | |
| ensure_clean_existing_checkout() { | |
| if [ ! -d "${REPO_DIR}/.git" ]; then | |
| return | |
| fi | |
| if ! git -C "$REPO_DIR" diff --quiet || ! git -C "$REPO_DIR" diff --cached --quiet; then | |
| echo "Existing checkout has local changes: ${REPO_DIR}" >&2 | |
| echo "Commit, stash, or inspect those changes before rerunning this installer." >&2 | |
| exit 2 | |
| fi | |
| } | |
| clone_or_update_repo() { | |
| if [ -d "${REPO_DIR}/.git" ]; then | |
| log "Updating ${REPO_DIR}" | |
| ensure_clean_existing_checkout | |
| git -C "$REPO_DIR" remote set-url origin "$REPO_URL" | |
| git -C "$REPO_DIR" fetch origin "$REPO_REF" | |
| if git -C "$REPO_DIR" show-ref --verify --quiet "refs/heads/${REPO_REF}"; then | |
| git -C "$REPO_DIR" checkout "$REPO_REF" | |
| else | |
| git -C "$REPO_DIR" checkout -b "$REPO_REF" "origin/${REPO_REF}" | |
| fi | |
| current_head="$(git -C "$REPO_DIR" rev-parse HEAD)" | |
| remote_head="$(git -C "$REPO_DIR" rev-parse "origin/${REPO_REF}")" | |
| if [ "$current_head" = "$remote_head" ]; then | |
| return | |
| fi | |
| if git -C "$REPO_DIR" merge-base --is-ancestor "$current_head" "$remote_head"; then | |
| git -C "$REPO_DIR" merge --ff-only "origin/${REPO_REF}" | |
| return | |
| fi | |
| cat >&2 <<EOF | |
| Existing checkout has local commits or has diverged from origin: ${REPO_DIR} | |
| Inspect the checkout manually before rerunning this installer. | |
| EOF | |
| exit 2 | |
| fi | |
| if [ -e "$REPO_DIR" ]; then | |
| echo "Target path exists but is not a git checkout: ${REPO_DIR}" >&2 | |
| echo "Move it aside or set PERSONAL_REPO_DIR to another path, then rerun this installer." >&2 | |
| exit 2 | |
| fi | |
| log "Cloning private repository into ${REPO_DIR}" | |
| mkdir -p "$(dirname "$REPO_DIR")" | |
| if ! git clone --branch "$REPO_REF" "$REPO_URL" "$REPO_DIR"; then | |
| cat >&2 <<EOF | |
| Failed to clone ${REPO_URL}. | |
| This repository is private. Configure GitHub SSH access for this machine, then rerun: | |
| ssh -T git@github.com | |
| Alternatively set PERSONAL_REPO_URL to another authenticated clone URL. | |
| EOF | |
| exit 2 | |
| fi | |
| } | |
| ensure_basic_tools | |
| clone_or_update_repo | |
| log "Running repository bootstrap" | |
| bash "${REPO_DIR}/scripts/bootstrap-home.sh" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment