Skip to content

Instantly share code, notes, and snippets.

@xenithorb
Last active May 14, 2017 11:57
Show Gist options
  • Save xenithorb/bd0be10e105ef160826e1c0902bae3f1 to your computer and use it in GitHub Desktop.
Save xenithorb/bd0be10e105ef160826e1c0902bae3f1 to your computer and use it in GitHub Desktop.
A helper script for python-github-backup that also handles backing up github gists
#!/bin/bash
#
# github-backup.sh: A helper script for python-github-backup that also
# handles backing up github gists
#
# Author: Mike Goodwin
# Date: 20170429
#
# Usage Example:
#
# This would download all repos and gists and install a virtual
# env for python-github-backup
#
# ./github-backup.sh -o <outdir> -t <token> -rgis
#
#
# For a new token, see: https://github.com/settings/tokens/new
GH_TOKEN="${GH_TOKEN}" # Set token here or export GH_TOKEN or -t <token>
API="https://api.github.com"
VENV_DIR="${HOME}/virtualenvs/github-backup"
DEPS=(
"github-backup"
"python"
"virtualenv"
"pyvenv"
"curl"
)
json_parse() {
env python <(
cat <<-EOF
import json
import sys
a = json.loads(sys.stdin.read())
if type(a) is not list:
a = [a]
print('%s' % '\n'.join([s['${1}'] for s in a]))
EOF
)
}
curl_gh_api() {
curl -sH "Authorization: token ${GH_TOKEN}" "${API}/${1}"
}
github_back() {
[[ "${1}" == "org" ]] &&
local o="-O --repositories" d="$2" u="$3"
[[ "${1}" == "user" ]] &&
local o='--all' d="$2" u="$3"
(( PREFER_SSH )) && local PREFER_SSH='--prefer-ssh'
github-backup -iFP ${o} ${PREFER_SSH} -t "${GH_TOKEN}" -o "${d}" "${u}"
}
while getopts ":sirt:go:" opt; do
found_opts=1
case "${opt}" in
o) OUTDIR="${OPTARG%/}" ;;
s) PREFER_SSH=1 ;;
t) GH_TOKEN="${OPTARG}" ;;
g) DO_GISTS=1 ;;
i) DO_VENVINSTALL=1 ;;
r) DO_REPOS=1 ;;
\?) echo "Invalid option: -${OPTARG}" >&2; exit 1 ;;
:) echo "Error, argument required: -${OPTARG}" >&2; exit 1 ;;
esac
done
if [[ ! "$OUTDIR" ]] && ((found_opts)); then
echo "Error: -o <outdir> is REQUIRED"; exit 1
fi
if [[ ! "$GH_TOKEN" ]] && ((found_opts)); then
echo "Error: -t <token> is missing"
fi
((!found_opts)) && { echo "Missing some options"; exit 1; }
PY_VER=$( env python --version 2>&1 | awk 'BEGIN{FS="[ .]"} {print $2}' )
[[ "$PY_VER" == "2" ]] && DEPS=( "${DEPS[@]/pyvenv}" ); VENV_CMD=virtualenv
[[ "$PY_VER" == "3" ]] && DEPS=( "${DEPS[@]/virtualenv}" ); VENV_CMD=pyvenv
if ! command -v github-backup &>/dev/null; then
if ((DO_VENVINSTALL)); then
VENV_ACTIVATE="${VENV_DIR}/bin/activate"
[[ ! -d "${VENV_DIR%/*}" ]] && mkdir -p "${VENV_DIR%/*}"
if [[ ! -f "${VENV_ACTIVATE}" ]]; then
$VENV_CMD "$VENV_DIR"
fi
if [[ ! -x "${VENV_DIR}/bin/github-backup" ]]; then
# shellcheck source=/dev/null
source "${VENV_ACTIVATE}"
pip install --upgrade github-backup
fi
fi
if [[ -x "${VENV_DIR}/bin/github-backup" ]]; then
# shellcheck source=/dev/null
source "${VENV_ACTIVATE}"
fi
fi
# Find deps
for cmd in "${DEPS[@]}"; do
if [[ "$cmd" ]]; then
if ! command -v "${cmd}" >/dev/null 2>&1; then
if [[ "$cmd" == "github-backup" ]]; then
echo "Missing: $cmd, perhaps try -i ?"
else
echo "Missing: $cmd, please install to continue."
fi
exit 1
fi
fi
done
GH_USER_JSON=$( curl_gh_api user )
GH_MSG_TEST=$( json_parse message <<< "$GH_USER_JSON" 2>/dev/null )
[[ "${GH_MSG_TEST}" ]] && { echo "${GH_MSG_TEST}"; exit 1; }
GH_USER=$( json_parse login <<< "$GH_USER_JSON" )
if ((DO_REPOS)); then
readarray -t ORGS < <( curl_gh_api user/orgs | json_parse login )
USER_DIR="${OUTDIR}/users/${GH_USER}"
ORGS_DIR="${OUTDIR}/orgs"
[[ ! -d "${USER_DIR}" ]] && mkdir -p "${USER_DIR}" #./users/xenith
github_back user "${USER_DIR}" "${GH_USER}"
for org in "${ORGS[@]}"; do
[[ ! -d "${org}" ]] && mkdir -p "${ORGS_DIR}/${org}"
github_back org "${ORGS_DIR}/${org}" "${org}"
done
fi
if ((DO_GISTS)); then
GISTS_JSON=$( curl_gh_api gists )
readarray -t GISTS_REPO_URL < <( json_parse git_pull_url <<< "${GISTS_JSON}" )
readarray -t GISTS_DESC < <( json_parse description <<< "${GISTS_JSON}" )
readarray -t GISTS_ID < <( json_parse id <<< "${GISTS_JSON}" )
GIST_DIR="${OUTDIR}/users/${GH_USER}/gists"
[[ ! -d "${GIST_DIR}" ]] && mkdir -p "$GIST_DIR"
pushd "$GIST_DIR" &>/dev/null
for i in "${!GISTS_REPO_URL[@]}"; do
if [[ ! -d "${GISTS_ID[i]}" ]]; then
((PREFER_SSH)) && GISTS_REPO_URL[$i]=$( sed -r 's|^https://|git@|; s|/(.*)|:\1|' <<< "${GISTS_REPO_URL[i]}" )
mkdir "${GISTS_ID[i]}"
git clone "${GISTS_REPO_URL[i]}" "${GISTS_ID[i]}/repo"
else
pushd "${GISTS_ID[i]}/repo" &>/dev/null
echo -n "$PWD: "
git pull --rebase --autostash
popd &>/dev/null
fi
echo "${GISTS_ID[i]}: ${GISTS_DESC[i]}" > "${GISTS_ID[i]}/description"
done
popd &>/dev/null
fi
@xenithorb
Copy link
Author

xenithorb commented May 3, 2017

Usage Example:

#  This would download all repos and gists and install a virtual 
#  env for python-github-backup

./github-backup.sh -o <outdir> -t <token> -rgis 

Yields the following file structure:

/<outdir>
├── orgs
│   ├── org-1 
│   │   ├── last_update
│   │   └── repositories
│   │       ├── repo-1
│   │       ├── repo-2 
│   │       └── repo-3
│   └── org-2 
│       ├── last_update
│       └── repositories
│           ├── repo-1
│           ├── repo-2
│           └── repo-3
|
└── users
    └── username1
        ├── account
        │   ├── starred.json
        │   └── watched.json
        ├── gists
        │   ├── 03ba08ec4faec2449072139f89ef108d
        │   ├── 06e9ca089432b731da6a50767506b043
        │   ├── 0dc5e8304a6e42a293feb01ac1f50a10
        │   └── fe93512746099e2173e5d7f12e7c2527
        ├── last_update
        └── repositories
            ├── repo-1
            ├── repo-2
            └── repo-3 

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment