#!/usr/bin/env python

import argparse
import commands
import json
import os
import re
import urllib2

def get_repos(user=None, url=None):
    if not user and not url:
        raise ValueError('Need either user or url')
    if user and not url:
        url = 'https://api.github.com/users/%s/repos' % user

    try:
        apidata = urllib2.urlopen(url)
    except urllib2.HTTPError, e:
        print ' * GitHub API error: %d %s' % (e.code, e.msg)
        return []
    repos = json.loads(apidata.read())

    if 'Link' in apidata.info():
        links = apidata.info()['Link']
        pm = re.search('<(http[^>]+)>;\s*rel="next"', links)
        if pm:
            next = pm.group(1)
            repos.extend(get_repos(url=next))

    return repos

def command(cmd):
    s, o = commands.getstatusoutput(cmd)
    if s != 0:
        for line in o.split('\n'):
            print '   * ' + line
        return
    lines = o.split('\n')
    for line in lines:
        if line.find('FETCH_HEAD') >= 0:
            continue
        if line.find('->') >= 0:
            print line

def git_fetch(repo):
    print ' . Fetching %s' % repo
    command('cd %s ; git remote update -p' % repo)

def git_clone(repo):
    print ' + Cloning %s' % repo
    if args.checkout:
        mirror = ''
    else:
        mirror = '--mirror'
    command('git clone %s %s' % (mirror, repo))

def backup_all(user):
    print 'Backing up %s' % user
    repos = get_repos(user)
    for repo in repos:
        local = repo['name']
        if not args.checkout:
            local = local + '.git'

        if args.ssh:
            url = repo['ssh_url']
        else:
            url = repo['clone_url']

        if os.path.exists(local):
            git_fetch(local)
        else:
            git_clone(url)

parser = argparse.ArgumentParser()
parser.add_argument('users', help='A user to back up repos for', metavar='USER', nargs='+')
parser.add_argument('-s', '--ssh', help='Clone using SSH instead of anonymous HTTPS', action='store_true')
parser.add_argument('-c', '--checkout', help='Clone to a regular repository instead of a bare one', action='store_true')
parser.parse_args()
args = parser.parse_args()

for user in args.users:
    backup_all(user)

