public
Last active

Mirror all my github repositories and gists

  • Download Gist
github_mirror.py
Python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
#!/usr/bin/env python
# See http://stackoverflow.com/questions/3581031/backup-mirror-github-repositories/13917251#13917251
# You can find the latest version of this script at
# https://gist.github.com/4319265
import os
import sys
import json
import urllib
import subprocess
 
__version__ = '0.2'
__author__ = 'Marius Gedminas <marius@gedmin.as>'
__url__ = 'https://gist.github.com/4319265'
 
# configuration
username = 'mgedmin'
backup_dir = os.path.expanduser('~/github')
gist_backup_dir = os.path.expanduser('~/github/gists')
 
# helpers
def ensure_dir(dir):
if not os.path.isdir(dir):
os.makedirs(dir)
 
def get_github_list(url):
response = urllib.urlopen(url + '?per_page=100')
if response.info().getheader('Link'):
print >> sys.stderr, "error: pagination is not supported yet"
return json.load(response)
 
def info(*args):
print(" ".join(map(str, args)))
sys.stdout.flush()
 
def backup(git_url, dir):
if os.path.exists(dir):
subprocess.call(['git', 'fetch'], cwd=dir)
else:
subprocess.call(['git', 'clone', '--mirror', git_url])
 
def update_description(git_dir, description):
with open(os.path.join(git_dir, 'description'), 'w') as f:
f.write(description.encode('UTF-8') + '\n')
 
def update_cloneurl(git_dir, cloneurl):
with open(os.path.join(git_dir, 'cloneurl'), 'w') as f:
f.write(cloneurl + '\n')
 
# action
ensure_dir(gist_backup_dir)
os.chdir(gist_backup_dir)
for gist in get_github_list('https://api.github.com/users/%s/gists' % username):
dir = gist['id'] + '.git'
description = gist['description'] or "(no description)"
info("+", "gists/" + gist['id'], "-", description.partition('\n')[0])
backup(gist['git_pull_url'], dir)
update_description(dir, description + '\n\n' + gist['html_url'])
update_cloneurl(dir, gist['git_push_url'])
 
# help me catch silly errors
gist = None
del gist
 
ensure_dir(backup_dir)
os.chdir(backup_dir)
for repo in get_github_list('https://api.github.com/users/%s/repos' % username):
dir = repo['name'] + '.git'
description = repo['description'] or "(no description)"
info("+", repo['full_name'])
backup(repo['git_url'], dir)
update_description(dir, description + '\n\n' + repo['html_url'])
update_cloneurl(dir, repo['ssh_url'])

Update: use git clone --mirror, so we get bare repositories and direct refs for all the branches.

Update: mirror gists as well.

Thanks, this is really handy, have created a minor fork if you wanted to merge the changes in - simply allows the exclusion of specific repos - https://gist.github.com/bentasker/6567069

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.