|
|
@@ -1,19 +1,32 @@
|
|
|
#!/usr/bin/env bash
|
|
|
set -euo pipefail
|
|
|
|
|
|
-REPO_URL="${REPO_URL:-https://github.com/christianlempa/boilerplates.git}"
|
|
|
-BRANCH="${BRANCH:-main}"
|
|
|
+REPO_OWNER="christianlempa"
|
|
|
+REPO_NAME="boilerplates"
|
|
|
+VERSION="${VERSION:-latest}"
|
|
|
TARGET_DIR="${TARGET_DIR:-$HOME/boilerplates}"
|
|
|
|
|
|
usage() {
|
|
|
cat <<USAGE
|
|
|
-Usage: install.sh [--path DIR] [--repo URL] [--branch BRANCH]
|
|
|
+Usage: install.sh [OPTIONS]
|
|
|
+
|
|
|
+Install the boilerplates CLI from GitHub releases.
|
|
|
|
|
|
Options:
|
|
|
- --path DIR Installation directory (default: \"$HOME/boilerplates\")
|
|
|
- --repo URL Git repository URL (default: $REPO_URL)
|
|
|
- --branch NAME Git branch or tag to checkout (default: $BRANCH)
|
|
|
- -h, --help Show this message
|
|
|
+ --path DIR Installation directory (default: "$HOME/boilerplates")
|
|
|
+ --version VER Version to install (default: "latest")
|
|
|
+ Examples: latest, v1.0.0, v0.0.1
|
|
|
+ -h, --help Show this message
|
|
|
+
|
|
|
+Examples:
|
|
|
+ # Install latest version
|
|
|
+ curl -fsSL https://raw.githubusercontent.com/christianlempa/boilerplates/main/scripts/install.sh | bash
|
|
|
+
|
|
|
+ # Install specific version
|
|
|
+ curl -fsSL https://raw.githubusercontent.com/christianlempa/boilerplates/main/scripts/install.sh | bash -s -- --version v1.0.0
|
|
|
+
|
|
|
+ # Install to custom directory
|
|
|
+ curl -fsSL https://raw.githubusercontent.com/christianlempa/boilerplates/main/scripts/install.sh | bash -s -- --path ~/my-boilerplates
|
|
|
USAGE
|
|
|
}
|
|
|
|
|
|
@@ -42,14 +55,9 @@ parse_args() {
|
|
|
TARGET_DIR="$2"
|
|
|
shift 2
|
|
|
;;
|
|
|
- --repo)
|
|
|
- [[ $# -lt 2 ]] && error "--repo requires a value"
|
|
|
- REPO_URL="$2"
|
|
|
- shift 2
|
|
|
- ;;
|
|
|
- --branch)
|
|
|
- [[ $# -lt 2 ]] && error "--branch requires a value"
|
|
|
- BRANCH="$2"
|
|
|
+ --version)
|
|
|
+ [[ $# -lt 2 ]] && error "--version requires a value"
|
|
|
+ VERSION="$2"
|
|
|
shift 2
|
|
|
;;
|
|
|
-h|--help)
|
|
|
@@ -70,34 +78,89 @@ print(os.path.abspath(os.path.expanduser(sys.argv[1])))
|
|
|
PY
|
|
|
}
|
|
|
|
|
|
-update_repo() {
|
|
|
- log "Updating existing repository at $TARGET_DIR"
|
|
|
- git -C "$TARGET_DIR" fetch --tags origin "$BRANCH"
|
|
|
- git -C "$TARGET_DIR" checkout "$BRANCH"
|
|
|
- git -C "$TARGET_DIR" pull --ff-only origin "$BRANCH"
|
|
|
-}
|
|
|
-
|
|
|
-clone_repo() {
|
|
|
- log "Cloning $REPO_URL into $TARGET_DIR"
|
|
|
- git clone --branch "$BRANCH" "$REPO_URL" "$TARGET_DIR"
|
|
|
+get_latest_release() {
|
|
|
+ local api_url="https://api.github.com/repos/$REPO_OWNER/$REPO_NAME/releases/latest"
|
|
|
+ local release_tag
|
|
|
+
|
|
|
+ log "Fetching latest release information..."
|
|
|
+
|
|
|
+ if command -v curl >/dev/null 2>&1; then
|
|
|
+ release_tag=$(curl -fsSL "$api_url" | grep '"tag_name":' | sed -E 's/.*"tag_name": "([^"]+)".*/\1/')
|
|
|
+ elif command -v wget >/dev/null 2>&1; then
|
|
|
+ release_tag=$(wget -qO- "$api_url" | grep '"tag_name":' | sed -E 's/.*"tag_name": "([^"]+)".*/\1/')
|
|
|
+ else
|
|
|
+ error "Neither curl nor wget found. Please install one of them."
|
|
|
+ fi
|
|
|
+
|
|
|
+ if [[ -z "$release_tag" ]]; then
|
|
|
+ error "Failed to fetch latest release tag"
|
|
|
+ fi
|
|
|
+
|
|
|
+ echo "$release_tag"
|
|
|
}
|
|
|
|
|
|
-ensure_repo() {
|
|
|
- if [[ -d "$TARGET_DIR/.git" ]]; then
|
|
|
- local current_remote
|
|
|
- if current_remote=$(git -C "$TARGET_DIR" remote get-url origin 2>/dev/null); then
|
|
|
- if [[ "$current_remote" != "$REPO_URL" ]]; then
|
|
|
- log "Updating origin remote to $REPO_URL"
|
|
|
- git -C "$TARGET_DIR" remote set-url origin "$REPO_URL"
|
|
|
- fi
|
|
|
- fi
|
|
|
- update_repo
|
|
|
- elif [[ -e "$TARGET_DIR" ]]; then
|
|
|
- error "Target path $TARGET_DIR exists but is not a git repository"
|
|
|
+download_release() {
|
|
|
+ local version="$1"
|
|
|
+ local download_url
|
|
|
+
|
|
|
+ # If version is "latest", resolve it to the actual version tag
|
|
|
+ if [[ "$version" == "latest" ]]; then
|
|
|
+ version=$(get_latest_release)
|
|
|
+ log "Latest version is $version"
|
|
|
+ fi
|
|
|
+
|
|
|
+ # Ensure version has 'v' prefix for GitHub releases
|
|
|
+ if [[ ! "$version" =~ ^v ]]; then
|
|
|
+ version="v$version"
|
|
|
+ fi
|
|
|
+
|
|
|
+ download_url="https://github.com/$REPO_OWNER/$REPO_NAME/archive/refs/tags/$version.tar.gz"
|
|
|
+
|
|
|
+ log "Downloading release $version..."
|
|
|
+ log "URL: $download_url"
|
|
|
+
|
|
|
+ local temp_dir
|
|
|
+ temp_dir=$(mktemp -d)
|
|
|
+ trap 'rm -rf "$temp_dir"' EXIT
|
|
|
+
|
|
|
+ local archive_file="$temp_dir/boilerplates.tar.gz"
|
|
|
+
|
|
|
+ if command -v curl >/dev/null 2>&1; then
|
|
|
+ curl -fsSL -o "$archive_file" "$download_url" || error "Failed to download release"
|
|
|
+ elif command -v wget >/dev/null 2>&1; then
|
|
|
+ wget -qO "$archive_file" "$download_url" || error "Failed to download release"
|
|
|
else
|
|
|
- mkdir -p "$(dirname "$TARGET_DIR")"
|
|
|
- clone_repo
|
|
|
+ error "Neither curl nor wget found. Please install one of them."
|
|
|
+ fi
|
|
|
+
|
|
|
+ log "Extracting release..."
|
|
|
+
|
|
|
+ # Remove existing installation if present
|
|
|
+ if [[ -d "$TARGET_DIR" ]]; then
|
|
|
+ log "Removing existing installation at $TARGET_DIR"
|
|
|
+ rm -rf "$TARGET_DIR"
|
|
|
fi
|
|
|
+
|
|
|
+ # Create parent directory
|
|
|
+ mkdir -p "$(dirname "$TARGET_DIR")"
|
|
|
+
|
|
|
+ # Extract with strip-components to remove the top-level directory
|
|
|
+ tar -xzf "$archive_file" -C "$(dirname "$TARGET_DIR")"
|
|
|
+
|
|
|
+ # Rename extracted directory to target name
|
|
|
+ local extracted_dir
|
|
|
+ extracted_dir=$(dirname "$TARGET_DIR")/"$REPO_NAME-${version#v}"
|
|
|
+
|
|
|
+ if [[ ! -d "$extracted_dir" ]]; then
|
|
|
+ error "Extraction failed: expected directory $extracted_dir not found"
|
|
|
+ fi
|
|
|
+
|
|
|
+ mv "$extracted_dir" "$TARGET_DIR"
|
|
|
+
|
|
|
+ log "Release extracted to $TARGET_DIR"
|
|
|
+
|
|
|
+ # Store version info
|
|
|
+ echo "$version" > "$TARGET_DIR/.installed-version"
|
|
|
}
|
|
|
|
|
|
ensure_pipx() {
|
|
|
@@ -129,30 +192,56 @@ pipx_install() {
|
|
|
"${PIPX_CMD}" install --editable --force "$TARGET_DIR"
|
|
|
}
|
|
|
|
|
|
+check_current_version() {
|
|
|
+ if [[ -f "$TARGET_DIR/.installed-version" ]]; then
|
|
|
+ cat "$TARGET_DIR/.installed-version"
|
|
|
+ else
|
|
|
+ echo "unknown"
|
|
|
+ fi
|
|
|
+}
|
|
|
+
|
|
|
main() {
|
|
|
parse_args "$@"
|
|
|
- require_command git
|
|
|
require_command python3
|
|
|
+ require_command tar
|
|
|
|
|
|
TARGET_DIR="$(make_absolute_path)"
|
|
|
+
|
|
|
+ # Check if already installed
|
|
|
+ local current_version
|
|
|
+ current_version=$(check_current_version)
|
|
|
+
|
|
|
+ if [[ "$current_version" != "unknown" ]]; then
|
|
|
+ log "Currently installed version: $current_version"
|
|
|
+ fi
|
|
|
|
|
|
- ensure_repo
|
|
|
+ download_release "$VERSION"
|
|
|
ensure_pipx
|
|
|
pipx_install
|
|
|
|
|
|
local pipx_info
|
|
|
pipx_info=$("${PIPX_CMD}" list --short 2>/dev/null | grep -E '^boilerplates' || echo "boilerplates (not detected)")
|
|
|
+
|
|
|
+ local installed_version
|
|
|
+ installed_version=$(check_current_version)
|
|
|
|
|
|
cat <<EOF2
|
|
|
|
|
|
-Installation complete.
|
|
|
-Repository: $TARGET_DIR
|
|
|
+✓ Installation complete!
|
|
|
+
|
|
|
+Version: $installed_version
|
|
|
+Location: $TARGET_DIR
|
|
|
pipx environment: $pipx_info
|
|
|
|
|
|
To use the CLI:
|
|
|
boilerplate --help
|
|
|
+ boilerplate --version
|
|
|
+
|
|
|
+To update to the latest version:
|
|
|
+ curl -fsSL https://raw.githubusercontent.com/$REPO_OWNER/$REPO_NAME/main/scripts/install.sh | bash
|
|
|
|
|
|
-Re-run this script anytime to fetch the latest changes and refresh dependencies.
|
|
|
+To install a specific version:
|
|
|
+ curl -fsSL https://raw.githubusercontent.com/$REPO_OWNER/$REPO_NAME/main/scripts/install.sh | bash -s -- --version v1.0.0
|
|
|
EOF2
|
|
|
}
|
|
|
|