Skip to content

Instantly share code, notes, and snippets.

@frg
Created April 29, 2023 07:35
Show Gist options
  • Save frg/21ad912681a15cc693b32190dce88bc7 to your computer and use it in GitHub Desktop.
Save frg/21ad912681a15cc693b32190dce88bc7 to your computer and use it in GitHub Desktop.
Clone (or Pull) Bitbucket Cloud Repositories

Clone (or Pull) Bitbucket Cloud Repositories

This bash script is designed to synchronize repositories from Bitbucket Cloud to a local machine in an organized manner. Its primary purpose is to ensure that repositories are readily available locally when needed, rather than serving as a backup solution for the repositories. By cloning and updating repositories efficiently, the script streamlines access to the respositories in a workspace.

Usage

./sync_bitbucket_repos.sh \
    -u <username> \
    -p <app-password> \
    -w <workspace-id> \
    -b <branch1[,branch2,...]> \
    -d <output-directory> \
/
#!/bin/bash
usage() {
echo "Usage: $0 -u <bitbucket_username> -p <bitbucket_app_password> -w <workspace_id> -b <branch1[,branch2,...]> [-d <destination_directory>]"
exit 1
}
DESTINATION_DIR="repositories"
while getopts ":u:p:w:b:d:" opt; do
case $opt in
u)
BITBUCKET_USERNAME="$OPTARG"
;;
p)
BITBUCKET_APP_PASSWORD="$OPTARG"
;;
w)
WORKSPACE_ID="$OPTARG"
;;
b)
IFS=',' read -ra BRANCHES <<< "$OPTARG"
;;
d)
DESTINATION_DIR="$OPTARG"
;;
\?)
echo "Invalid option: -$OPTARG" >&2
usage
;;
:)
echo "Option -$OPTARG requires an argument." >&2
usage
;;
esac
done
if [ -z "$BITBUCKET_USERNAME" ] || [ -z "$BITBUCKET_APP_PASSWORD" ] || [ -z "$WORKSPACE_ID" ] || [ ${#BRANCHES[@]} -eq 0 ]; then
usage
fi
# Initialize the API URL and repositories variable
API_URL="https://api.bitbucket.org/2.0/repositories/$WORKSPACE_ID?pagelen=100"
REPOSITORIES=""
PAGE_NUMBER=1
# Iterate through the paginated API response
while [ -n "$API_URL" ]; do
echo "Fetching repositories from page $PAGE_NUMBER..."
# Get the current page of repositories
PAGE_RESPONSE=$(curl -s -u "$BITBUCKET_USERNAME:$BITBUCKET_APP_PASSWORD" "$API_URL")
# Extract the repositories and append them to the list
REPOSITORIES+=$(echo "$PAGE_RESPONSE" | jq -r '.values[] | "\(.project.key) \(.name) \(.links.clone[] | select(.name == "ssh") | .href)"')$'\n'
# Check for a "next" value in the response, indicating another page of results
API_URL=$(echo "$PAGE_RESPONSE" | jq -r 'if .next then .next else "" end')
# Increment the page number
PAGE_NUMBER=$((PAGE_NUMBER + 1))
done
REPO_COUNT=$(echo "$REPOSITORIES" | grep -c -v '^$')
# Check if no repositories are found
if [ $REPO_COUNT -eq 0 ]; then
echo "No repositories found in the specified workspace."
exit 0
fi
echo "Total repositories: $REPO_COUNT"
echo "Repositories:"
echo "$REPOSITORIES"
# Create the destination directory if it doesn't exist
mkdir -p "$DESTINATION_DIR"
# Iterate through the repositories and clone or pull them
while read -r PROJECT_KEY REPO_NAME REPO_URL; do
if [ -n "$REPO_URL" ]; then
# Convert project key to lowercase
PROJECT_KEY_LOWER=$(echo "$PROJECT_KEY" | tr '[:upper:]' '[:lower:]')
REPO_PATH="$DESTINATION_DIR/$PROJECT_KEY_LOWER/$REPO_NAME"
if [ -d "$REPO_PATH" ]; then
echo "Pulling the latest changes for $REPO_NAME"
cd "$REPO_PATH" || exit
git fetch
git pull || { echo "Failed to pull $REPO_NAME. Continuing with the next repository."; continue; }
else
echo "Cloning $REPO_NAME to $REPO_PATH"
mkdir -p "$DESTINATION_DIR/$PROJECT_KEY_LOWER" && cd "$DESTINATION_DIR/$PROJECT_KEY_LOWER" || exit
git clone "$REPO_URL" "$REPO_NAME" || { echo "Failed to clone $REPO_NAME. Continuing with the next repository."; continue; }
cd "$REPO_NAME" || exit
fi
# Check out the branches passed as arguments
for branch in "${BRANCHES[@]}"; do
if git show-ref --quiet "refs/remotes/origin/$branch"; then
echo "Checking out branch $branch"
git checkout "$branch"
git pull || { echo "Failed to pull $branch in $REPO_NAME. Continuing with the next branch."; continue; }
fi
done
cd ../../..
# Decrease the repository count and print the number of remaining repositories
REPO_COUNT=$((REPO_COUNT - 1))
echo "Repositories remaining: $REPO_COUNT"
fi
done <<< "$REPOSITORIES"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment