#!/usr/bin/env bash AWS=/usr/local/bin/aws basedir=$1 bucket=$2 repos_found=$basedir/*.git num_repos_found=0 completed=0 backup_log="${basedir}/gitbackup-log" mkdir -p "${backup_log}" echo "starting for: $basedir" get_rev_list () { : ' generates a rev list since the last checkpoint. provides a blank response if the checkpoint and the latest commit are one and the same output: "hash..hash2" return 0: successfully created a revlist 1: no revlist created ' # last checkpoint in repo local last_hash=$(git rev-list -n 1 --all) # first commit in repo, or hash of last checkpoint if ! $(git rev-list -n 1 CHECKPOINT &> /dev/null); then # first commit in repo local checkpoint_hash=$(git rev-list --all | tail -n 1) echo "${checkpoint_hash}" return 0 else local checkpoint_hash=$(git rev-list -n 1 CHECKPOINT) fi # if checkpoint and last hash are one and the same, offer nothing if [ "${checkpoint_hash}" = "${last_hash}" ]; then # we provide nothing back echo "" return 1 else echo "${checkpoint_hash}..${last_hash}" return 0 fi } create_bundle () { : ' Arguments: arg1: rev_list in proper revlist format hash..hash2 arg2: bundle name/path to create creates a bundle for a given revlist output: none returns: 0: created bundle 1: could not create bundle ' local rev_list=$1 local bundle_path_name=$2 if ! git bundle create "${bundle_path_name}" "${rev_list}" --all; then return 1 else return 0 fi } for repo in $repos_found; do let num_repos_found++ || true cd "${repo}" repobase=$(basename $repo) current_time=$(date +%s%N) slug=${repobase%%.*} tx_log="${backup_log}/${slug}.tx.log" last_time=$(touch ${tx_log} && tail -n1 "${tx_log}" | cut -d " " -f 1) last_time="${last_time:-0}" bundle_name="${last_time}-${current_time}-${slug}.bundle" bundle_tmp_path="/tmp/${bundle_name}" s3_base="s3://${bucket}" s3_uri="${s3_base}/${repobase}" rev_list=$(get_rev_list) if [ -z "${rev_list}" ]; then # we increase the counter, because not needing to update is ok echo "${slug} has no new commits, no bundle generated" let completed++ || true continue else if ! $(create_bundle "${rev_list}" "${bundle_tmp_path}"); then echo "${bundle_name} failed to be created" >&2 continue fi fi if ! $AWS s3 cp "${bundle_tmp_path}" "${s3_uri}/${bundle_name}" then echo "$bundle_name failed to upload S3" >&2 continue else # set checkpoint to the last hash in revlist checkpoint="${rev_list:42}" checkpoint=${checkpoint:-"${rev_list}"} git tag -f CHECKPOINT "${checkpoint}" # transaction log echo "${current_time} ${rev_list}" >> "${tx_log}" $AWS s3 cp "${tx_log}" "${s3_base}/logs/${slug}.tx.log" fi echo "${slug} backedup" let completed++ || true done echo "${completed} of ${num_repos_found} repos backed up"