#!/bin/bash set -euo pipefail IFS=$'\n\t' # ╭─────────────────────────────────────╮ # │ CONFIGURATION │ # ╰─────────────────────────────────────╮ REPO_PATH=$(git rev-parse --show-toplevel 2>/dev/null) || error "Not inside a Git repository" REPO_NAME=$(basename "$REPO_PATH") GITFIELD_DIR="$REPO_PATH/.gitfield" LOG_FILE="$GITFIELD_DIR/pushed.log" GITFIELD_MD="$REPO_PATH/GITFIELD.md" TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S') SCRIPT_VERSION="1.0" # URLs for each platform (derived from existing scripts) GITHUB_URL="https://github.com/mrhavens/$REPO_NAME" GITLAB_URL="https://gitlab.com/mrhavens/$REPO_NAME" BITBUCKET_URL="https://bitbucket.org/thefoldwithin/$REPO_NAME" RADICLE_PROJECT_ID="z45QC21eWL1F43VSbnV9AZbCZrHQJ" RADICLE_URL="https://app.radicle.xyz/nodes/ash.radicle.garden/rad:$RADICLE_PROJECT_ID" # ╭─────────────────────────────────────╮ # │ LOGGING UTILS │ # ╰─────────────────────────────────────╮ info() { echo -e "\e[1;34m[INFO]\e[0m $*" >&2; } warn() { echo -e "\e[1;33m[WARN]\e[0m $*" >&2; } error() { echo -e "\e[1;31m[ERROR]\e[0m $*" >&2; exit 1; } # ╭─────────────────────────────────────╮ # │ SCRIPT LOOKUP FUNCTION │ # ╰─────────────────────────────────────╮ find_script() { local script_name=$1 local search_paths=( "$HOME/.local/gitfieldbin" "$HOME/.local/bin" "$HOME/.local/gitfield" "$HOME/.local/bin/gitfield" "$HOME/.local/bin/gitfieldbin" ) for path in "${search_paths[@]}"; do if [ -f "$path/$script_name" ]; then if [ -x "$path/$script_name" ]; then # Log to stderr to avoid capturing in command substitution if [[ "$path" != "$HOME"* ]]; then info "Using script: \e[1;31m$path/$script_name\e[0m (outside home directory)" else info "Using script: $path/$script_name" fi echo "$path/$script_name" return 0 else warn "Found $path/$script_name but it is not executable" fi fi done error "Script $script_name not found in any search path" } # ╭─────────────────────────────────────╮ # │ INITIAL SETUP │ # ╰─────────────────────────────────────╮ # Ensure .gitfield directory exists mkdir -p "$GITFIELD_DIR" # Initialize log file if it doesn't exist if [ ! -f "$LOG_FILE" ]; then echo "# Push Log for $REPO_NAME" > "$LOG_FILE" echo "# Generated by gitfield-sync" >> "$LOG_FILE" echo "" >> "$LOG_FILE" fi # ╭─────────────────────────────────────╮ # │ GENERATE GITFIELD.MD │ # ╰─────────────────────────────────────╮ generate_gitfield_md() { info "Generating $GITFIELD_MD..." cat > "$GITFIELD_MD" <> "$LOG_FILE" info "Logged push to $LOG_FILE: [$timestamp] $platform: $url" } # ╭─────────────────────────────────────╮ # │ EXECUTE PUSH SCRIPT │ # ╰─────────────────────────────────────╮ execute_push() { local script_name=$1 local platform=$2 local url=$3 local script_path script_path=$(find_script "$script_name") || error "Failed to find $script_name" info "Executing $platform push with script: $script_path" if [ -x "$script_path" ]; then # Change to repo root to ensure consistent execution context pushd "$REPO_PATH" >/dev/null "$script_path" || warn "Execution of $script_path failed, continuing..." # Log the URL after successful push log_url "$platform" "$url" # Add and commit any new files generated by the script git add . || warn "Nothing to add after $script_path" git commit -m "Post-$platform sync at $TIMESTAMP" || warn "No changes to commit after $script_path" popd >/dev/null else error "Script $script_path is not executable" fi } # ╭─────────────────────────────────────╮ # │ RECURSIVE PUSH LOOP │ # ╰─────────────────────────────────────╮ run_push_cycle() { local cycle_number=$1 info "Starting push cycle $cycle_number..." # Push to each platform in order execute_push "gitfield-radicle" "Radicle" "$RADICLE_URL" execute_push "gitfield-gitlab" "GitLab" "$GITLAB_URL" execute_push "gitfield-bitbucket" "Bitbucket" "$BITBUCKET_URL" execute_push "gitfield-github" "GitHub" "$GITHUB_URL" } # ╭─────────────────────────────────────╮ # │ MAIN EXECUTION │ # ╰─────────────────────────────────────╮ info "Starting gitfield-sync for $REPO_NAME..." # Ensure the repository is initialized if [ ! -d "$REPO_PATH/.git" ]; then pushd "$REPO_PATH" >/dev/null git init git add . git commit -m "Initial commit" || warn "Nothing to commit" popd >/dev/null fi # Run the first push cycle run_push_cycle 1 # Generate GITFIELD.md after the first cycle generate_gitfield_md # Run the second push cycle to include GITFIELD.md run_push_cycle 2 # Run the third push cycle for final metadata sync run_push_cycle 3 info "✅ gitfield-sync completed successfully." info "🔗 View logs: $LOG_FILE" info "🔗 View multi-repo manifest: $GITFIELD_MD"