#!/usr/bin/python2 # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 """ Copyright (c) 2013 Alberto Ruiz All rights reserved. Hacked up to work for freedesktop.org by Ray Strode Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Pioneers of the Inevitable, Songbird, nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """ import codecs import os import os.path import sys import requests import subprocess import shlex import ConfigParser import xml.etree.ElementTree as et import smtplib from email.mime.text import MIMEText import tempfile import json ORGANIZATION="freedesktop" name_maps = {"gtk+": "gtk", "libxml++": "libxmlmm"} class GitHub: def __init__ (self): config = ConfigParser.ConfigParser() try: config.read(os.path.expanduser('/etc/github-mirror/mirror.cfg')) self.user = config.get('Github', 'user') self.pw = config.get('Github', 'password') except ConfigParser.NoSectionError: raise Exception ("~/.gitmirrorrc non existant or missing [Github] section with user and password keys") except ConfigParser.NoOptionError: raise Exception ("~/.gitmirrorrc misses user or/and password keys in the [Github] section") def check_if_repo_exists (self, name): rq = requests.get('https://api.github.com/repos/'+ORGANIZATION+'/'+name, auth=(self.user, self.pw)) if rq.status_code != 200: return False return True def create_github_repo (self, name): if self.check_if_repo_exists (name): return try: description_file = codecs.open('description', encoding='utf-8') description = description_file.read().replace('\n', ' ').rstrip() description_file.close() except: description = '' payload = json.dumps({ 'name': self.normalize_name(name), 'description': description, 'has_wiki': False, 'has_issues': False }) rq = requests.post('https://api.github.com/orgs/'+ORGANIZATION+'/repos', auth=(self.user, self.pw), data=payload) if rq.status_code == 201: return raise Exception("There was an error attempting to create the repo %s in github:\n\nStatus: %d\nText:\n%s" % (name, rq.status_code, rq.text)) def normalize_name (self, name): if name in name_maps.keys(): return name_maps[name] if "+" in name: raise Exception("%s has a '+' character in it which is unsupported by Github.\nYou have to add it to the exception maps in the post-update hook." % name) return name def get_repo_name (): repo_namespace = os.getcwd ().split("/")[-2] if repo_namespace == "git": repo_namespace = None repo_parts = "".join(os.getcwd ().split("/git/")[1:]).split('/') if repo_namespace and repo_parts[1].startswith(repo_namespace + '-'): repo_parts[1] = repo_parts[1].replace(repo_namespace + '-', '', 1) elif repo_namespace and repo_parts[1] == repo_namespace + ".git": repo_parts.remove(repo_parts[1]) elif repo_namespace and repo_parts[1] == repo_namespace: repo_parts.remove(repo_parts[1]) if repo_parts[-1] == ".git": repo_parts = repo_parts[:-1] repo_name = "-".join(repo_parts) if repo_name.endswith(".git"): repo_name = repo_name[0:-4] return repo_name def main (): gh = GitHub () repo_name = get_repo_name () github_name = gh.normalize_name (repo_name) if not gh.check_if_repo_exists(repo_name) and os.path.exists("git-daemon-export-ok"): gh.create_github_repo (repo_name) try: out = tempfile.NamedTemporaryFile (prefix="github",suffix="std") err = tempfile.NamedTemporaryFile (prefix="github",suffix="err") command = 'git push --force --no-verify --prune git@github.com:%s/%s refs/heads/*:refs/heads/*' % (ORGANIZATION, github_name) subprocess.check_call(shlex.split(command), stderr=err, stdout=out) command = 'git push --force --no-verify --prune git@github.com:%s/%s refs/tags/*:refs/tags/*' % (ORGANIZATION, github_name) subprocess.check_call(shlex.split(command), stderr=err, stdout=out) command = 'git push --force --no-verify --prune git@github.com:%s/%s refs/notes/*:refs/notes/*' % (ORGANIZATION, github_name) subprocess.check_call(shlex.split(command), stderr=err, stdout=out) out.close() err.close() except subprocess.CalledProcessError: out = open(out.name, "r") err = open(err.name, "r") raise Exception("Error trying to push branch %s\nSTDOUT:\n%s\nSTDERR\n%s" % (repo_name, out.read(), err.read())) if __name__ == "__main__": try: main () except Exception as e: msg = MIMEText(str(e)) msg['Subject'] = "[GITHUB HOOK] ERROR trying to push %s" % os.getcwd () msg['From'] = "noreply@freedesktop.org" msg['To'] = "halfline+fdo-github-mirror@freedesktop.org" msg['X-FDO-SERVICE'] = "github-mirror" server = smtplib.SMTP("localhost") server.sendmail (msg['From'], msg['To'], msg.as_string()) server.quit ()