nixos-config/scripts/sync-bazar-to-local-git-repos.sh
2025-05-18 23:46:41 +03:00

197 lines
8.8 KiB
Bash
Executable file

#!/usr/bin/env bash
CODE_DIR="~/Code"
eval expanded_code_dir="$CODE_DIR"
mkdir -p "$expanded_code_dir"
# API URL
API_URL="https://lab.mrflos.pw/?api/forms/5/entries"
echo "Fetching repository information from $API_URL..."
json_data=$(curl -s "$API_URL")
if [ $? -ne 0 ]; then
echo "Error: Failed to fetch data from the API at $API_URL."
exit 1
fi
if [ -z "$json_data" ]; then
echo "Error: Fetched JSON data is empty from $API_URL."
exit 1
fi
# Get all top-level keys (repository entry names) from the JSON
# The `keys_unsorted[]` jq function extracts all keys as an array.
# `jq -r '. | keys_unsorted[]'` prints each key on a new line.
repo_keys=$(echo "$json_data" | jq -r '. | keys_unsorted[]')
if [ $? -ne 0 ] || [ -z "$repo_keys" ]; then
echo "Error: Could not extract repository keys from JSON or JSON is not in the expected format (object)."
echo "Fetched JSON data (first 500 chars): $(echo "$json_data" | head -c 500)"
exit 1
fi
echo "Found repository keys to process:"
echo "$repo_keys"
echo "---"
# Loop through each repository key
while IFS= read -r REPO_KEY; do
if [ -z "$REPO_KEY" ]; then
continue # Skip empty lines if any
fi
echo ""
echo "Processing repository entry: $REPO_KEY"
echo "--------------------------------------------------"
# Use jq to parse repository URL and branch for the current REPO_KEY
repo_url=$(echo "$json_data" | jq -r --arg key "$REPO_KEY" '.[$key].bf_repo_git')
branch_name=$(echo "$json_data" | jq -r --arg key "$REPO_KEY" '.[$key].bf_branch')
# Validate that repo_url and branch_name were found and are not null or empty
if [ "$repo_url" == "null" ] || [ -z "$repo_url" ]; then
echo "Error: Could not parse bf_repo_git for key '$REPO_KEY'. Skipping this entry."
echo " JSON for this key (bf_repo_git): $(echo "$json_data" | jq --arg key "$REPO_KEY" '.[$key].bf_repo_git')"
continue
fi
if [ "$branch_name" == "null" ] || [ -z "$branch_name" ]; then
echo "Error: Could not parse bf_branch for key '$REPO_KEY'. Skipping this entry."
echo " JSON for this key (bf_branch): $(echo "$json_data" | jq --arg key "$REPO_KEY" '.[$key].bf_branch')"
continue
fi
echo " Repository URL: $repo_url"
echo " Branch: $branch_name"
# Extract repository name from the URL to use as the folder name.
repo_folder_name=$(basename "$repo_url" .git)
# Define the full path to the local repository
local_repo_path="$expanded_code_dir/$repo_folder_name"
echo " Local repository path: $local_repo_path"
# Check if the repository directory exists
if [ ! -d "$local_repo_path" ]; then
echo " Repository folder '$repo_folder_name' does not exist locally. Cloning..."
# Try to clone the specific branch directly
git clone --branch "$branch_name" "$repo_url" "$local_repo_path"
clone_status=$?
if [ $clone_status -ne 0 ]; then
echo " Warning: Initial clone with branch '$branch_name' failed. Trying to clone default branch then checkout..."
# If specific branch clone fails, clone default and then try to checkout the branch
git clone "$repo_url" "$local_repo_path"
if [ $? -ne 0 ]; then
echo " Error: Git clone (default branch) failed for $repo_url. Skipping this repository."
continue
fi
cd "$local_repo_path" || { echo " Error: Failed to cd into '$local_repo_path' after clone. Skipping."; continue; }
echo " Checking out branch '$branch_name'..."
git checkout "$branch_name"
if [ $? -ne 0 ]; then
echo " Warning: Failed to checkout branch '$branch_name' after cloning. The branch might not exist remotely or there was another issue."
echo " Staying on default branch: $(git rev-parse --abbrev-ref HEAD)"
else
echo " Successfully checked out branch '$branch_name'."
fi
else
cd "$local_repo_path" || { echo " Error: Failed to cd into '$local_repo_path' after clone. Skipping."; continue; }
echo " Successfully cloned and on branch '$branch_name'."
fi
else
echo " Repository folder '$repo_folder_name' already exists. Fetching and updating..."
cd "$local_repo_path" || { echo " Error: Failed to cd into existing '$local_repo_path'. Skipping."; continue; }
echo " Current directory: $(pwd)"
echo " Currently on branch: $(git rev-parse --abbrev-ref HEAD)"
# Stash any local changes before switching branches or pulling
echo " Stashing local changes if any..."
git stash push -m "autostash_before_update_$(date +%s)_$REPO_KEY" > /dev/null 2>&1
echo " Fetching all remotes and pruning..."
git fetch --all --prune
if [ $? -ne 0 ]; then
echo " Error: Git fetch failed for $repo_folder_name. Attempting to restore stash."
git stash pop > /dev/null 2>&1 # Attempt to restore stashed changes
continue # Skip to the next repository
fi
current_branch_in_repo=$(git rev-parse --abbrev-ref HEAD)
# Check if the desired branch exists locally or remotely
if ! git show-ref --verify --quiet refs/heads/"$branch_name" && ! git show-ref --verify --quiet refs/remotes/origin/"$branch_name"; then
echo " Warning: Branch '$branch_name' not found locally or on remote 'origin' for $repo_folder_name. Staying on branch '$current_branch_in_repo'."
# If the target branch doesn't exist at all, pull the current one.
if [ "$current_branch_in_repo" != "HEAD" ]; then # Ensure it's not a detached HEAD
echo " Pulling latest changes for current branch '$current_branch_in_repo'..."
git pull origin "$current_branch_in_repo"
if [ $? -ne 0 ]; then
echo " Error: Git pull failed for branch '$current_branch_in_repo' in $repo_folder_name. Attempting to restore stash."
fi
else
echo " Warning: Repository is in a detached HEAD state. Cannot pull without a specific branch."
fi
else
# Desired branch exists either locally or remotely. Try to switch and pull.
if [ "$current_branch_in_repo" != "$branch_name" ]; then
echo " Switching to branch '$branch_name'..."
git checkout "$branch_name"
if [ $? -ne 0 ]; then
# If checkout fails (e.g., local branch exists but no remote tracking, or new branch from remote failed)
# Try to create it from remote if it exists there
if git show-ref --verify --quiet refs/remotes/origin/"$branch_name"; then
echo " Attempting to checkout '$branch_name' tracking 'origin/$branch_name'..."
git checkout -b "$branch_name" "origin/$branch_name"
if [ $? -ne 0 ]; then
echo " Error: Could not switch to or create branch '$branch_name'. Pulling current branch '$current_branch_in_repo'."
if [ "$current_branch_in_repo" != "HEAD" ]; then
git pull origin "$current_branch_in_repo"
fi
else
echo " Successfully on branch '$branch_name'. Pulling..."
git pull
fi
else
echo " Error: Could not switch to branch '$branch_name'. Pulling current branch '$current_branch_in_repo'."
if [ "$current_branch_in_repo" != "HEAD" ]; then
git pull origin "$current_branch_in_repo"
fi
fi
else
echo " Successfully on branch '$branch_name'. Pulling..."
git pull
fi
else
echo " Already on branch '$branch_name'. Pulling..."
git pull
fi
if [ $? -ne 0 ] && [ "$(git rev-parse --abbrev-ref HEAD)" == "$branch_name" ]; then # Check if pull failed on the target branch
echo " Error: Git pull failed for branch '$branch_name' in $repo_folder_name. Attempting to restore stash."
fi
fi
# Attempt to reapply stashed changes
echo " Attempting to reapply stashed changes..."
if ! git stash pop > /dev/null 2>&1; then
# Check if there was anything to pop
stash_count=$(git stash list | wc -l)
if [ "$stash_count" -gt 0 ]; then
echo " Warning: Could not automatically reapply stashed changes for $repo_folder_name. You may have a stash entry to resolve manually (git stash list)."
else
echo " No stashed changes to reapply."
fi
else
echo " Stashed changes (if any) reapplied successfully."
fi
fi
echo " Process for '$REPO_KEY' completed."
echo "--------------------------------------------------"
# Return to the main code directory to avoid issues with relative paths in the loop
cd "$expanded_code_dir" || { echo "FATAL: Could not cd back to $expanded_code_dir. Exiting."; exit 1; }
done <<< "$repo_keys"
echo ""
echo "All repositories processed."