From 0b51df49966e5c9c14568646ad9966131b1f0baa Mon Sep 17 00:00:00 2001 From: Florian Schmitt Date: Sun, 18 May 2025 23:46:10 +0300 Subject: [PATCH] feat(scripts): sync from bazar --- scripts/sync-bazar-to-local-git-repos.sh | 197 +++++++++++++++++++++++ 1 file changed, 197 insertions(+) create mode 100755 scripts/sync-bazar-to-local-git-repos.sh diff --git a/scripts/sync-bazar-to-local-git-repos.sh b/scripts/sync-bazar-to-local-git-repos.sh new file mode 100755 index 0000000..e7dc9c3 --- /dev/null +++ b/scripts/sync-bazar-to-local-git-repos.sh @@ -0,0 +1,197 @@ +#!/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."