from __future__ import print_function

from os import environ, remove
from os.path import join
from shutil import rmtree
from tempfile import mkdtemp
from httmock import HTTMock, response
from urllib.parse import parse_qsl, urlparse
from datetime import timedelta
from zipfile import ZipFile
from io import BytesIO
from mock import patch
from time import sleep

import unittest, json, os, sys

os.environ['GITHUB_TOKEN'] = ''
os.environ['DATABASE_URL'] = environ.get('DATABASE_URL', 'postgres:///hooked_on_sources')

from ..ci import (
    app, db_connect, db_cursor, db_queue, recreate_db, read_job, worker,
    pop_task_from_donequeue, pop_task_from_taskqueue, pop_task_from_duequeue,
    create_queued_job, TASK_QUEUE, DONE_QUEUE, DUE_QUEUE, MAGIC_OK_MESSAGE
    )

from ..jobs import JOB_TIMEOUT
from .. import compat
from . import FakeS3

class TestHook (unittest.TestCase):

    def setUp(self):
        '''
        '''
        recreate_db.recreate(app.config['DATABASE_URL'])

        self.output_dir = mkdtemp(prefix='TestHook-')
        self.database_url = app.config['DATABASE_URL']
        self.github_auth = app.config['GITHUB_AUTH']
        self.client = app.test_client()
        self.last_status_state = None
        self.last_status_message = None
        self.s3 = FakeS3()
    
    def tearDown(self):
        '''
        '''
        rmtree(self.output_dir)
        remove(self.s3._fake_keys)
        return
        
        with db_connect(self.database_url) as conn:
            with db_cursor(conn) as db:
                db.execute('TRUNCATE jobs')
                db.execute('TRUNCATE queue')
    
    def response_content(self, url, request):
        '''
        '''
        query = dict(parse_qsl(url.query))
        MHP = request.method, url.hostname, url.path
        GH, response_headers = 'api.github.com', {'Content-Type': 'application/json; charset=utf-8'}
        
        if MHP == ('GET', GH, '/repos/openaddresses/hooked-on-sources/contents/sources/us-ca-alameda_county.json') and query.get('ref', '').startswith('e91fbc'):
            data = '''{\r              "name": "us-ca-alameda_county.json",\r              "path": "sources/us-ca-alameda_county.json",\r              "sha": "c9cd0ed30256ae64d5924b03b0423346501b92d8",\r              "size": 745,\r              "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/contents/sources/us-ca-alameda_county.json?ref=e91fbc420f08890960f50f863626e1062f922522",\r              "html_url": "https://github.com/openaddresses/hooked-on-sources/blob/e91fbc420f08890960f50f863626e1062f922522/sources/us-ca-alameda_county.json",\r              "git_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/blobs/c9cd0ed30256ae64d5924b03b0423346501b92d8",\r              "download_url": "https://raw.githubusercontent.com/openaddresses/hooked-on-sources/e91fbc420f08890960f50f863626e1062f922522/sources/us-ca-alameda_county.json",\r              "type": "file",\r              "content": "ewogICAgImNvdmVyYWdlIjogewogICAgICAgICJVUyBDZW5zdXMiOiB7CiAg\\nICAgICAgICAgICJnZW9pZCI6ICIwNjAwMSIsCiAgICAgICAgICAgICJuYW1l\\nIjogIkFsYW1lZGEgQ291bnR5IiwKICAgICAgICAgICAgInN0YXRlIjogIkNh\\nbGlmb3JuaWEiCiAgICAgICAgfSwKICAgICAgICAiY291bnRyeSI6ICJ1cyIs\\nCiAgICAgICAgInN0YXRlIjogImNhIiwKICAgICAgICAiY291bnR5IjogIkFs\\nYW1lZGEiCiAgICB9LAogICAgImRhdGEiOiAiaHR0cHM6Ly9kYXRhLmFjZ292\\nLm9yZy9hcGkvZ2Vvc3BhdGlhbC84ZTRzLTdmNHY/bWV0aG9kPWV4cG9ydCZm\\nb3JtYXQ9T3JpZ2luYWwiLAogICAgImxpY2Vuc2UiOiAiaHR0cDovL3d3dy5h\\nY2dvdi5vcmcvYWNkYXRhL3Rlcm1zLmh0bSIsCiAgICAiYXR0cmlidXRpb24i\\nOiAiQWxhbWVkYSBDb3VudHkiLAogICAgInllYXIiOiAiIiwKICAgICJ0eXBl\\nIjogImh0dHAiLAogICAgImNvbXByZXNzaW9uIjogInppcCIsCiAgICAiY29u\\nZm9ybSI6IHsKICAgICAgICAibWVyZ2UiOiBbCiAgICAgICAgICAgICJmZWFu\\nbWUiLAogICAgICAgICAgICAiZmVhdHlwIgogICAgICAgIF0sCiAgICAgICAg\\nImxvbiI6ICJ4IiwKICAgICAgICAibGF0IjogInkiLAogICAgICAgICJudW1i\\nZXIiOiAic3RfbnVtIiwKICAgICAgICAic3RyZWV0IjogImF1dG9fc3RyZWV0\\nIiwKICAgICAgICAidHlwZSI6ICJzaGFwZWZpbGUiLAogICAgICAgICJwb3N0\\nY29kZSI6ICJ6aXBjb2RlIgogICAgfQp9Cg==\\n",\r              "encoding": "base64",\r              "_links": {\r                "self": "https://api.github.com/repos/openaddresses/hooked-on-sources/contents/sources/us-ca-alameda_county.json?ref=e91fbc420f08890960f50f863626e1062f922522",\r                "git": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/blobs/c9cd0ed30256ae64d5924b03b0423346501b92d8",\r                "html": "https://github.com/openaddresses/hooked-on-sources/blob/e91fbc420f08890960f50f863626e1062f922522/sources/us-ca-alameda_county.json"\r              }\r            }'''
            return response(200, data.encode('utf8'), headers=response_headers)
        
        if MHP == ('GET', GH, '/repos/openaddresses/hooked-on-sources/contents/sources/us-ca-san_francisco.json') and query.get('ref', '').startswith('ded44e'):
            data = '''{\r              "name": "us-ca-san_francisco.json",\r              "path": "sources/us-ca-san_francisco.json",\r              "sha": "cbf1f900ac072b6a2e728819a97e74bc772e79ff",\r              "size": 519,\r              "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/contents/sources/us-ca-san_francisco.json?ref=ded44ed5f1733bb93d84f94afe9383e2d47bbbaa",\r              "html_url": "https://github.com/openaddresses/hooked-on-sources/blob/ded44ed5f1733bb93d84f94afe9383e2d47bbbaa/sources/us-ca-san_francisco.json",\r              "git_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/blobs/cbf1f900ac072b6a2e728819a97e74bc772e79ff",\r              "download_url": "https://raw.githubusercontent.com/openaddresses/hooked-on-sources/ded44ed5f1733bb93d84f94afe9383e2d47bbbaa/sources/us-ca-san_francisco.json",\r              "type": "file",\r              "content": "ewogICAgImNvdmVyYWdlIjogewogICAgICAgICJjb3VudHJ5IjogInVzIiwK\\nICAgICAgICAic3RhdGUiOiAiY2EiLAogICAgICAgICJjaXR5IjogIlNhbiBG\\ncmFuY2lzY28iCiAgICB9LAogICAgImF0dHJpYnV0aW9uIjogIkNpdHkgb2Yg\\nU2FuIEZyYW5jaXNjbyIsCiAgICAiZGF0YSI6ICJodHRwczovL2RhdGEuc2Zn\\nb3Yub3JnL2Rvd25sb2FkL2t2ZWotdzVrYi9aSVBQRUQlMjBTSEFQRUZJTEUi\\nLAogICAgImxpY2Vuc2UiOiAiIiwKICAgICJ5ZWFyIjogIiIsCiAgICAidHlw\\nZSI6ICJodHRwIiwKICAgICJjb21wcmVzc2lvbiI6ICJ6aXAiLAogICAgImNv\\nbmZvcm0iOiB7Cgkic3BsaXQiOiAiQUREUkVTUyIsCiAgICAgICAgImxvbiI6\\nICJ4IiwKICAgICAgICAibGF0IjogInkiLAogICAgICAgICJudW1iZXIiOiAi\\nYXV0b19udW1iZXIiLAogICAgICAgICJzdHJlZXQiOiAiYXV0b19zdHJlZXQi\\nLAogICAgICAgICJ0eXBlIjogInNoYXBlZmlsZSIsCiAgICAgICAgInBvc3Rj\\nb2RlIjogInppcGNvZGUiCiAgICB9Cn0K\\n",\r              "encoding": "base64",\r              "_links": {\r                "self": "https://api.github.com/repos/openaddresses/hooked-on-sources/contents/sources/us-ca-san_francisco.json?ref=ded44ed5f1733bb93d84f94afe9383e2d47bbbaa",\r                "git": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/blobs/cbf1f900ac072b6a2e728819a97e74bc772e79ff",\r                "html": "https://github.com/openaddresses/hooked-on-sources/blob/ded44ed5f1733bb93d84f94afe9383e2d47bbbaa/sources/us-ca-san_francisco.json"\r              }\r            }'''
            return response(200, data.encode('utf8'), headers=response_headers)
        
        if MHP == ('GET', GH, '/repos/openaddresses/hooked-on-sources/contents/sources/us-ca-berkeley.json') and query.get('ref', '').startswith('ded44e'):
            data = '''{\r              "name": "us-ca-berkeley.json",\r              "path": "sources/us-ca-berkeley.json",\r              "sha": "16464c39b59b5a09c6526da3afa9a5f57caabcad",\r              "size": 779,\r              "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/contents/sources/us-ca-berkeley.json?ref=ded44ed5f1733bb93d84f94afe9383e2d47bbbaa",\r              "html_url": "https://github.com/openaddresses/hooked-on-sources/blob/ded44ed5f1733bb93d84f94afe9383e2d47bbbaa/sources/us-ca-berkeley.json",\r              "git_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/blobs/16464c39b59b5a09c6526da3afa9a5f57caabcad",\r              "download_url": "https://raw.githubusercontent.com/openaddresses/hooked-on-sources/ded44ed5f1733bb93d84f94afe9383e2d47bbbaa/sources/us-ca-berkeley.json",\r              "type": "file",\r              "content": "ewogICAgImNvdmVyYWdlIjogewogICAgICAgICJVUyBDZW5zdXMiOiB7CiAg\\nICAgICAgICAgICJnZW9pZCI6ICIwNjA2MDAwIiwKICAgICAgICAgICAgInBs\\nYWNlIjogIkJlcmtlbGV5IiwKICAgICAgICAgICAgInN0YXRlIjogIkNhbGlm\\nb3JuaWEiCiAgICAgICAgfSwKICAgICAgICAiY291bnRyeSI6ICJ1cyIsCiAg\\nICAgICAgInN0YXRlIjogImNhIiwKICAgICAgICAicGxhY2UiOiAiQmVya2Vs\\nZXkiCiAgICB9LAogICAgImF0dHJpYnV0aW9uIjogIkNpdHkgb2YgQmVya2Vs\\nZXkiLAogICAgImRhdGEiOiAiaHR0cDovL3d3dy5jaS5iZXJrZWxleS5jYS51\\ncy91cGxvYWRlZEZpbGVzL0lUL0dJUy9QYXJjZWxzLnppcCIsCiAgICAid2Vi\\nc2l0ZSI6ICJodHRwOi8vd3d3LmNpLmJlcmtlbGV5LmNhLnVzL2RhdGFjYXRh\\nbG9nLyIsCiAgICAidHlwZSI6ICJodHRwIiwKICAgICJjb21wcmVzc2lvbiI6\\nICJ6aXAiLAogICAgIm5vdGUiOiAiTWV0YWRhdGEgYXQgaHR0cDovL3d3dy5j\\naS5iZXJrZWxleS5jYS51cy91cGxvYWRlZEZpbGVzL0lUL0dJUy9QYXJjZWxz\\nLnNocCgxKS54bWwiLAogICAgImNvbmZvcm0iOiB7CiAgICAgICAgImxvbiI6\\nICJ4IiwKICAgICAgICAibGF0IjogInkiLAogICAgICAgICJudW1iZXIiOiAi\\nU3RyZWV0TnVtIiwKICAgICAgICAibWVyZ2UiOiBbIlN0cmVldE5hbWUiLCAi\\nU3RyZWV0U3VmeCIsICJEaXJlY3Rpb24iXSwKICAgICAgICAic3RyZWV0Ijog\\nImF1dG9fc3RyZWV0IiwKICAgICAgICAidHlwZSI6ICJzaGFwZWZpbGUtcG9s\\neWdvbiIKICAgIH0KfQo=\\n",\r              "encoding": "base64",\r              "_links": {\r                "self": "https://api.github.com/repos/openaddresses/hooked-on-sources/contents/sources/us-ca-berkeley.json?ref=ded44ed5f1733bb93d84f94afe9383e2d47bbbaa",\r                "git": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/blobs/16464c39b59b5a09c6526da3afa9a5f57caabcad",\r                "html": "https://github.com/openaddresses/hooked-on-sources/blob/ded44ed5f1733bb93d84f94afe9383e2d47bbbaa/sources/us-ca-berkeley.json"\r              }\r            }'''
            return response(200, data.encode('utf8'), headers=response_headers)
        
        if MHP == ('GET', GH, '/repos/openaddresses/hooked-on-sources/contents/sources/us-ca-santa_clara_county.json') and query.get('ref', '').startswith('e5f1dc'):
            data = '''{\r              "name": "us-ca-santa_clara_county.json",\r              "path": "sources/us-ca-santa_clara_county.json",\r              "sha": "84abff13dba318189f1f4d5c1605478127ceff5c",\r              "size": 908,\r              "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/contents/sources/us-ca-santa_clara_county.json?ref=e5f1dcae83ab1ef1f736b969da617311f7f11564",\r              "html_url": "https://github.com/openaddresses/hooked-on-sources/blob/e5f1dcae83ab1ef1f736b969da617311f7f11564/sources/us-ca-santa_clara_county.json",\r              "git_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/blobs/84abff13dba318189f1f4d5c1605478127ceff5c",\r              "download_url": "https://raw.githubusercontent.com/openaddresses/hooked-on-sources/e5f1dcae83ab1ef1f736b969da617311f7f11564/sources/us-ca-santa_clara_county.json",\r              "type": "file",\r              "content": "ewogICAgImNvdmVyYWdlIjogewogICAgICAgICJVUyBDZW5zdXMiOiB7Imdl\\nb2lkIjogIjA2MDg1IiwgIm5hbWUiOiAiU2FudGEgQ2xhcmEgQ291bnR5Iiwg\\nInN0YXRlIjogIkNhbGlmb3JuaWEifSwKICAgICAgICAiY291bnRyeSI6ICJ1\\ncyIsCiAgICAgICAgInN0YXRlIjogImNhIiwKICAgICAgICAiY291bnR5Ijog\\nIlNhbnRhIENsYXJhIgogICAgfSwKICAgICJjb25mb3JtIjogewogICAgICAg\\nICJ0eXBlIjogInNoYXBlZmlsZSIsCiAgICAgICAgInBvc3Rjb2RlIjogIlpJ\\nUENPREUiLAogICAgICAgICJjaXR5IjogIkNJVFkiLAogICAgICAgICJudW1i\\nZXIiOiAiSE9VU0VOVU1URSIsCiAgICAgICAgIm1lcmdlIjogWyJTVFJFRVRO\\nQU1FIiwgIlNUUkVFVFRZUEUiXSwKICAgICAgICAic3RyZWV0IjogImF1dG9f\\nc3RyZWV0IiwKICAgICAgICAibG9uIjogIngiLAogICAgICAgICJsYXQiOiAi\\neSIKICAgIH0sCiAgICAiYXR0cmlidXRpb24iOiAiU2FudGEgQ2xhcmEgQ291\\nbnR5IiwKICAgICJkYXRhIjogImh0dHBzOi8vZ2l0aHViLmNvbS9kYXRhZGVz\\nay91cy1jYS1zYW50YV9jbGFyYV9jb3VudHktZ2lzLXNocC9ibG9iL21hc3Rl\\nci9RNF9GWTE0X0FkZHJlc3NfUG9pbnQuemlwP3Jhdz10cnVlIiwKICAgICJ3\\nZWJzaXRlIjogImh0dHBzOi8vc2Z0cC5zY2Nnb3Yub3JnL2NvdXJpZXIvd2Vi\\nLzEwMDBAL3dtTG9naW4uaHRtbCIsCiAgICAidHlwZSI6ICJodHRwIiwKICAg\\nICJjb21wcmVzc2lvbiI6ICJ6aXAiLAogICAgIm5vdGUiOiAiRmlsZSBkb3du\\nbG9hZCBpcyBiZWhpbmQgYSByZWdpc3RyYXRpb24gd2FsbCBvbiBnb3Zlcm5t\\nZW50IHNpdGUgc28gdGhlIHppcCB3YXMgZG93bmxvYWRlZCBpbiBOb3ZlbWJl\\nciAyMDE0IGFuZCB1cGxvYWRlZCB0byBHaXRIdWIgZm9yIHB1YmxpYyBob3N0\\naW5nLiIKfQo=\\n",\r              "encoding": "base64",\r              "_links": {\r                "self": "https://api.github.com/repos/openaddresses/hooked-on-sources/contents/sources/us-ca-santa_clara_county.json?ref=e5f1dcae83ab1ef1f736b969da617311f7f11564",\r                "git": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/blobs/84abff13dba318189f1f4d5c1605478127ceff5c",\r                "html": "https://github.com/openaddresses/hooked-on-sources/blob/e5f1dcae83ab1ef1f736b969da617311f7f11564/sources/us-ca-santa_clara_county.json"\r              }\r            }'''
            return response(200, data.encode('utf8'), headers=response_headers)
        
        if MHP == ('GET', GH, '/repos/openaddresses/hooked-on-sources/contents/sources/us-ca-badjson_county.json') and query.get('ref', '').startswith('badjson'):
            data = '''{\r              "name": "us-ca-badjson_county.json",\r              "path": "sources/us-ca-badjson_county.json",\r              "sha": "c9cd0ed30256ae64d5924b03b0423346501b92d8",\r              "size": 745,\r              "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/contents/sources/us-ca-badjson_county.json?ref=badjson20f08890960f50f863626e1062f922522",\r              "html_url": "https://github.com/openaddresses/hooked-on-sources/blob/badjson20f08890960f50f863626e1062f922522/sources/us-ca-badjson_county.json",\r              "git_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/blobs/c9cd0ed30256ae64d5924b03b0423346501b92d8",\r              "download_url": "https://raw.githubusercontent.com/openaddresses/hooked-on-sources/badjson20f08890960f50f863626e1062f922522/sources/us-ca-badjson_county.json",\r              "type": "file",\r              "content": "ewogICAgImNvdmVyYWdlIjogewogICAgICAgICJVUyBDZW5zdXMiOiB7CiAgICAgICAgICAgICJnZW9pZCI6ICIwNjAwMSIsCiAgICAgICAgICAgICJuYW1lIjogIkFsYW1lZGEgQ291bnR5IiwKICAgICAgICAgICAgInN0YXRlIjogIkNhbGlmb3JuaWEiCiAgICAgICAgfSwKICAgICAgICAiY291bnRyeSI6ICJ1cyIsCiAgICAgICAgInN0YXRlIjogImNhIiwKICAgICAgICAiY291bnR5IjogIkFsYW1lZGEiCiAgICB9CiAgICAiZGF0YSI6ICJodHRwczovL2RhdGEuYWNnb3Yub3JnL2FwaS9nZW9zcGF0aWFsLzhlNHMtN2Y0dj9tZXRob2Q9ZXhwb3J0JmZvcm1hdD1PcmlnaW5hbCIsCiAgICAibGljZW5zZSI6ICJodHRwOi8vd3d3LmFjZ292Lm9yZy9hY2RhdGEvdGVybXMuaHRtIiwKICAgICJhdHRyaWJ1dGlvbiI6ICJBbGFtZWRhIENvdW50eSIsCiAgICAieWVhciI6ICIiLAogICAgInR5cGUiOiAiaHR0cCIsCiAgICAiY29tcHJlc3Npb24iOiAiemlwIiwKICAgICJjb25mb3JtIjogewogICAgICAgICJtZXJnZSI6IFsKICAgICAgICAgICAgImZlYW5tZSIsCiAgICAgICAgICAgICJmZWF0eXAiCiAgICAgICAgXSwKICAgICAgICAibG9uIjogIngiLAogICAgICAgICJsYXQiOiAieSIsCiAgICAgICAgIm51bWJlciI6ICJzdF9udW0iLAogICAgICAgICJzdHJlZXQiOiAiYXV0b19zdHJlZXQiLAogICAgICAgICJ0eXBlIjogInNoYXBlZmlsZSIsCiAgICAgICAgInBvc3Rjb2RlIjogInppcGNvZGUiCiAgICB9Cn0K",\r              "encoding": "base64",\r              "_links": {\r                "self": "https://api.github.com/repos/openaddresses/hooked-on-sources/contents/sources/us-ca-badjson_county.json?ref=badjson20f08890960f50f863626e1062f922522",\r                "git": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/blobs/c9cd0ed30256ae64d5924b03b0423346501b92d8",\r                "html": "https://github.com/openaddresses/hooked-on-sources/blob/badjson20f08890960f50f863626e1062f922522/sources/us-ca-badjson_county.json"\r              }\r            }'''
            return response(200, data.encode('utf8'), headers=response_headers)
        
        if MHP == ('GET', GH, '/repos/openaddresses/hooked-on-sources/contents/sources/us-ca-badutf8_county.json') and query.get('ref', '').startswith('badutf8'):
            data = '''{\r              "name": "us-ca-badutf8_county.json",\r              "path": "sources/us-ca-badutf8_county.json",\r              "sha": "c9cd0ed30256ae64d5924b03b0423346501b92d8",\r              "size": 745,\r              "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/contents/sources/us-ca-badutf8_county.json?ref=badutf820f08890960f50f863626e1062f922522",\r              "html_url": "https://github.com/openaddresses/hooked-on-sources/blob/badutf820f08890960f50f863626e1062f922522/sources/us-ca-badutf8_county.json",\r              "git_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/blobs/c9cd0ed30256ae64d5924b03b0423346501b92d8",\r              "download_url": "https://raw.githubusercontent.com/openaddresses/hooked-on-sources/badutf820f08890960f50f863626e1062f922522/sources/us-ca-badutf8_county.json",\r              "type": "file",\r              "content": "ewogICAgImNvdmVyYWdlIjogewogICAgICAgICJVUyBDZW5zdXMiOiB7CiAgICAgICAgICAgICJnZW9pZCI6ICIwNjAwMSIsCiAgICAgICAgICAgICJuYW1lIjogIkFsYW1lZGEgQ/Z1bnR5IiwKICAgICAgICAgICAgInN0YXRlIjogIkNhbGlmb3JuaWEiCiAgICAgICAgfSwKICAgICAgICAiY291bnRyeSI6ICJ1cyIsCiAgICAgICAgInN0YXRlIjogImNhIiwKICAgICAgICAiY291bnR5IjogIkFsYW1lZGEiCiAgICB9LAogICAgImRhdGEiOiAiaHR0cHM6Ly9kYXRhLmFjZ292Lm9yZy9hcGkvZ2Vvc3BhdGlhbC84ZTRzLTdmNHY/bWV0aG9kPWV4cG9ydCZmb3JtYXQ9T3JpZ2luYWwiLAogICAgImxpY2Vuc2UiOiAiaHR0cDovL3d3dy5hY2dvdi5vcmcvYWNkYXRhL3Rlcm1zLmh0bSIsCiAgICAiYXR0cmlidXRpb24iOiAiQWxhbWVkYSBDb3VudHkiLAogICAgInllYXIiOiAiIiwKICAgICJ0eXBlIjogImh0dHAiLAogICAgImNvbXByZXNzaW9uIjogInppcCIsCiAgICAiY29uZm9ybSI6IHsKICAgICAgICAibWVyZ2UiOiBbCiAgICAgICAgICAgICJmZWFubWUiLAogICAgICAgICAgICAiZmVhdHlwIgogICAgICAgIF0sCiAgICAgICAgImxvbiI6ICJ4IiwKICAgICAgICAibGF0IjogInkiLAogICAgICAgICJudW1iZXIiOiAic3RfbnVtIiwKICAgICAgICAic3RyZWV0IjogImF1dG9fc3RyZWV0IiwKICAgICAgICAidHlwZSI6ICJzaGFwZWZpbGUiLAogICAgICAgICJwb3N0Y29kZSI6ICJ6aXBjb2RlIgogICAgfQp9Cg==",\r              "encoding": "base64",\r              "_links": {\r                "self": "https://api.github.com/repos/openaddresses/hooked-on-sources/contents/sources/us-ca-badutf8_county.json?ref=badutf820f08890960f50f863626e1062f922522",\r                "git": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/blobs/c9cd0ed30256ae64d5924b03b0423346501b92d8",\r                "html": "https://github.com/openaddresses/hooked-on-sources/blob/badutf820f08890960f50f863626e1062f922522/sources/us-ca-badutf8_county.json"\r              }\r            }'''
            return response(200, data.encode('utf8'), headers=response_headers)
        
        if MHP == ('GET', GH, '/repos/daguar/openaddresses/contents/sources/us-ca-san_diego_county.json') and query.get('ref', '').startswith('f85074d'):
            data = '''{\r  "name": "us-ca-san_diego_county.json",\r  "path": "sources/us-ca-san_diego_county.json",\r  "sha": "0c7cf2f3e4cb5f0c07818a029e1decc9797ad3a1",\r  "size": 1119,\r  "url": "https://api.github.com/repos/daguar/openaddresses/contents/sources/us-ca-san_diego_county.json?ref=f85074d543622ef1fac7a80a059a50176f2a6e08",\r  "html_url": "https://github.com/daguar/openaddresses/blob/f85074d543622ef1fac7a80a059a50176f2a6e08/sources/us-ca-san_diego_county.json",\r  "git_url": "https://api.github.com/repos/daguar/openaddresses/git/blobs/0c7cf2f3e4cb5f0c07818a029e1decc9797ad3a1",\r  "download_url": "https://raw.githubusercontent.com/daguar/openaddresses/f85074d543622ef1fac7a80a059a50176f2a6e08/sources/us-ca-san_diego_county.json",\r  "type": "file",\r  "content": "ewogICAgImNvdmVyYWdlIjogewogICAgICAgICJVUyBDZW5zdXMiOiB7CiAg\\nICAgICAgICAiZ2VvaWQiOiAiMDYwNzMiLAogICAgICAgICAgIm5hbWUiOiAi\\nU2FuIERpZWdvIENvdW50eSIsCiAgICAgICAgICAic3RhdGUiOiAiQ2FsaWZv\\ncm5pYSIKICAgICAgICB9LAogICAgICAgICJjb3VudHJ5IjogInVzIiwKICAg\\nICAgICAic3RhdGUiOiAiY2EiLAogICAgICAgICJjb3VudHkiOiAiU2FuIERp\\nZWdvIgogICAgfSwKICAgICJhdHRyaWJ1dGlvbiI6ICJTYW4gRGllZ28gR2Vv\\nZ3JhcGhpYyBJbmZvcm1hdGlvbiBTb3VyY2UgLSBKUEEiLAogICAgImRhdGEi\\nOiAiaHR0cDovL3Jkdy5zYW5kYWcub3JnL2ZpbGVfc3RvcmUvQWRkcmVzcy9B\\nZGRyZXNzX0FQTi56aXAiLAogICAgImxpY2Vuc2UiOiAiaHR0cDovL3d3dy5z\\nYW5naXMub3JnL0xlZ2FsX05vdGljZS5odG0iLAogICAgIm5vdGUiOiAiTWV0\\nYWRhdGEgYXZhaWxhYmxlIGF0IGh0dHA6Ly9yZHcuc2FuZGFnLm9yZy9maWxl\\nX3N0b3JlJTVDQWRkcmVzcy9BZGRyZXNzX0FQTi5wZGYiLAogICAgIndlYnNp\\ndGUiOiAiaHR0cDovL3Jkdy5zYW5kYWcub3JnLyIsCiAgICAieWVhciI6ICIi\\nLAogICAgInR5cGUiOiAiaHR0cCIsCiAgICAiY29tcHJlc3Npb24iOiAiemlw\\nIiwKICAgICJjb25mb3JtIjogewogICAgICAgICJtZXJnZSI6IFsKICAgICAg\\nICAgICAgIkFERFJQRElSIiwKICAgICAgICAgICAgIkFERFJOQU1FIiwKICAg\\nICAgICAgICAgIkFERFJTRlgiLAogICAgICAgICAgICAiQUREUlBPU1REIgog\\nICAgICAgIF0sCiAgICAgICAgImxvbiI6ICJ4IiwKICAgICAgICAibGF0Ijog\\nInkiLAogICAgICAgICJhZHZhbmNlZF9tZXJnZSI6IHsKICAgICAgICAgICAg\\nImN1c3RvbV9udW1iZXIiOiB7CiAgICAgICAgICAgICAgICAic2VwYXJhdG9y\\nIjogIiAiLAogICAgICAgICAgICAgICAgImZpZWxkcyI6IFsiQUREUk5NQlIi\\nLCAiQUREUkZSQUMiXQogICAgICAgICAgICB9CiAgICAgICAgfSwKICAgICAg\\nICAibnVtYmVyIjogImN1c3RvbV9udW1iZXIiLAogICAgICAgICJzdHJlZXQi\\nOiAiYXV0b19zdHJlZXQiLAogICAgICAgICJ0eXBlIjogInNoYXBlZmlsZSIs\\nCiAgICAgICAgInBvc3Rjb2RlIjogImFkZHJ6aXAiCiAgICB9Cn0K\\n",\r  "encoding": "base64",\r  "_links": {\r    "self": "https://api.github.com/repos/daguar/openaddresses/contents/sources/us-ca-san_diego_county.json?ref=f85074d543622ef1fac7a80a059a50176f2a6e08",\r    "git": "https://api.github.com/repos/daguar/openaddresses/git/blobs/0c7cf2f3e4cb5f0c07818a029e1decc9797ad3a1",\r    "html": "https://github.com/daguar/openaddresses/blob/f85074d543622ef1fac7a80a059a50176f2a6e08/sources/us-ca-san_diego_county.json"\r  }\r}'''
            return response(200, data.encode('utf8'), headers=response_headers)
        
        if MHP == ('GET', GH, '/repos/openaddresses/openaddresses/contents/sources/us-ca-san_diego_county.json') and query.get('ref', '').startswith('bba8f70'):
            data = '''{\r  "name": "us-ca-san_diego_county.json",\r  "path": "sources/us-ca-san_diego_county.json",\r  "sha": "0c7cf2f3e4cb5f0c07818a029e1decc9797ad3a1",\r  "size": 1119,\r  "url": "https://api.github.com/repos/openaddresses/openaddresses/contents/sources/us-ca-san_diego_county.json?ref=bba8f709793f96750fed223d44ba373a92540b2a",\r  "html_url": "https://github.com/openaddresses/openaddresses/blob/bba8f709793f96750fed223d44ba373a92540b2a/sources/us-ca-san_diego_county.json",\r  "git_url": "https://api.github.com/repos/openaddresses/openaddresses/git/blobs/0c7cf2f3e4cb5f0c07818a029e1decc9797ad3a1",\r  "download_url": "https://raw.githubusercontent.com/openaddresses/openaddresses/bba8f709793f96750fed223d44ba373a92540b2a/sources/us-ca-san_diego_county.json",\r  "type": "file",\r  "content": "ewogICAgImNvdmVyYWdlIjogewogICAgICAgICJVUyBDZW5zdXMiOiB7CiAg\\nICAgICAgICAiZ2VvaWQiOiAiMDYwNzMiLAogICAgICAgICAgIm5hbWUiOiAi\\nU2FuIERpZWdvIENvdW50eSIsCiAgICAgICAgICAic3RhdGUiOiAiQ2FsaWZv\\ncm5pYSIKICAgICAgICB9LAogICAgICAgICJjb3VudHJ5IjogInVzIiwKICAg\\nICAgICAic3RhdGUiOiAiY2EiLAogICAgICAgICJjb3VudHkiOiAiU2FuIERp\\nZWdvIgogICAgfSwKICAgICJhdHRyaWJ1dGlvbiI6ICJTYW4gRGllZ28gR2Vv\\nZ3JhcGhpYyBJbmZvcm1hdGlvbiBTb3VyY2UgLSBKUEEiLAogICAgImRhdGEi\\nOiAiaHR0cDovL3Jkdy5zYW5kYWcub3JnL2ZpbGVfc3RvcmUvQWRkcmVzcy9B\\nZGRyZXNzX0FQTi56aXAiLAogICAgImxpY2Vuc2UiOiAiaHR0cDovL3d3dy5z\\nYW5naXMub3JnL0xlZ2FsX05vdGljZS5odG0iLAogICAgIm5vdGUiOiAiTWV0\\nYWRhdGEgYXZhaWxhYmxlIGF0IGh0dHA6Ly9yZHcuc2FuZGFnLm9yZy9maWxl\\nX3N0b3JlJTVDQWRkcmVzcy9BZGRyZXNzX0FQTi5wZGYiLAogICAgIndlYnNp\\ndGUiOiAiaHR0cDovL3Jkdy5zYW5kYWcub3JnLyIsCiAgICAieWVhciI6ICIi\\nLAogICAgInR5cGUiOiAiaHR0cCIsCiAgICAiY29tcHJlc3Npb24iOiAiemlw\\nIiwKICAgICJjb25mb3JtIjogewogICAgICAgICJtZXJnZSI6IFsKICAgICAg\\nICAgICAgIkFERFJQRElSIiwKICAgICAgICAgICAgIkFERFJOQU1FIiwKICAg\\nICAgICAgICAgIkFERFJTRlgiLAogICAgICAgICAgICAiQUREUlBPU1REIgog\\nICAgICAgIF0sCiAgICAgICAgImxvbiI6ICJ4IiwKICAgICAgICAibGF0Ijog\\nInkiLAogICAgICAgICJhZHZhbmNlZF9tZXJnZSI6IHsKICAgICAgICAgICAg\\nImN1c3RvbV9udW1iZXIiOiB7CiAgICAgICAgICAgICAgICAic2VwYXJhdG9y\\nIjogIiAiLAogICAgICAgICAgICAgICAgImZpZWxkcyI6IFsiQUREUk5NQlIi\\nLCAiQUREUkZSQUMiXQogICAgICAgICAgICB9CiAgICAgICAgfSwKICAgICAg\\nICAibnVtYmVyIjogImN1c3RvbV9udW1iZXIiLAogICAgICAgICJzdHJlZXQi\\nOiAiYXV0b19zdHJlZXQiLAogICAgICAgICJ0eXBlIjogInNoYXBlZmlsZSIs\\nCiAgICAgICAgInBvc3Rjb2RlIjogImFkZHJ6aXAiCiAgICB9Cn0K\\n",\r  "encoding": "base64",\r  "_links": {\r    "self": "https://api.github.com/repos/openaddresses/openaddresses/contents/sources/us-ca-san_diego_county.json?ref=bba8f709793f96750fed223d44ba373a92540b2a",\r    "git": "https://api.github.com/repos/openaddresses/openaddresses/git/blobs/0c7cf2f3e4cb5f0c07818a029e1decc9797ad3a1",\r    "html": "https://github.com/openaddresses/openaddresses/blob/bba8f709793f96750fed223d44ba373a92540b2a/sources/us-ca-san_diego_county.json"\r  }\r}'''
            return response(200, data.encode('utf8'), headers=response_headers)
        
        if MHP == ('GET', GH, '/repos/openaddresses/hooked-on-sources/compare/master...e5f1dcae83ab1ef1f736b969da617311f7f11564'):
            data = '''{\r  "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/compare/master...e5f1dcae83ab1ef1f736b969da617311f7f11564",\r  "html_url": "https://github.com/openaddresses/hooked-on-sources/compare/master...e5f1dcae83ab1ef1f736b969da617311f7f11564",\r  "permalink_url": "https://github.com/openaddresses/hooked-on-sources/compare/openaddresses:b450dcb...openaddresses:e5f1dca",\r  "diff_url": "https://github.com/openaddresses/hooked-on-sources/compare/master...e5f1dcae83ab1ef1f736b969da617311f7f11564.diff",\r  "patch_url": "https://github.com/openaddresses/hooked-on-sources/compare/master...e5f1dcae83ab1ef1f736b969da617311f7f11564.patch",\r  "base_commit": {\r    "sha": "b450dcbb6f4c61015b0a00290e984849f7d649de",\r    "commit": {\r      "author": {\r        "name": "Michal Migurski",\r        "email": "mike@teczno.com",\r        "date": "2015-04-27T01:29:59Z"\r      },\r      "committer": {\r        "name": "Michal Migurski",\r        "email": "mike@teczno.com",\r        "date": "2015-04-27T01:29:59Z"\r      },\r      "message": "Added Contra Costa county",\r      "tree": {\r        "sha": "f9e70a36019597c21c7a28bd16840588e6223a33",\r        "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/trees/f9e70a36019597c21c7a28bd16840588e6223a33"\r      },\r      "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/commits/b450dcbb6f4c61015b0a00290e984849f7d649de",\r      "comment_count": 0\r    },\r    "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/b450dcbb6f4c61015b0a00290e984849f7d649de",\r    "html_url": "https://github.com/openaddresses/hooked-on-sources/commit/b450dcbb6f4c61015b0a00290e984849f7d649de",\r    "comments_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/b450dcbb6f4c61015b0a00290e984849f7d649de/comments",\r    "author": {\r      "login": "migurski",\r      "id": 58730,\r      "avatar_url": "https://avatars.githubusercontent.com/u/58730?v=3",\r      "gravatar_id": "",\r      "url": "https://api.github.com/users/migurski",\r      "html_url": "https://github.com/migurski",\r      "followers_url": "https://api.github.com/users/migurski/followers",\r      "following_url": "https://api.github.com/users/migurski/following{/other_user}",\r      "gists_url": "https://api.github.com/users/migurski/gists{/gist_id}",\r      "starred_url": "https://api.github.com/users/migurski/starred{/owner}{/repo}",\r      "subscriptions_url": "https://api.github.com/users/migurski/subscriptions",\r      "organizations_url": "https://api.github.com/users/migurski/orgs",\r      "repos_url": "https://api.github.com/users/migurski/repos",\r      "events_url": "https://api.github.com/users/migurski/events{/privacy}",\r      "received_events_url": "https://api.github.com/users/migurski/received_events",\r      "type": "User",\r      "site_admin": false\r    },\r    "committer": {\r      "login": "migurski",\r      "id": 58730,\r      "avatar_url": "https://avatars.githubusercontent.com/u/58730?v=3",\r      "gravatar_id": "",\r      "url": "https://api.github.com/users/migurski",\r      "html_url": "https://github.com/migurski",\r      "followers_url": "https://api.github.com/users/migurski/followers",\r      "following_url": "https://api.github.com/users/migurski/following{/other_user}",\r      "gists_url": "https://api.github.com/users/migurski/gists{/gist_id}",\r      "starred_url": "https://api.github.com/users/migurski/starred{/owner}{/repo}",\r      "subscriptions_url": "https://api.github.com/users/migurski/subscriptions",\r      "organizations_url": "https://api.github.com/users/migurski/orgs",\r      "repos_url": "https://api.github.com/users/migurski/repos",\r      "events_url": "https://api.github.com/users/migurski/events{/privacy}",\r      "received_events_url": "https://api.github.com/users/migurski/received_events",\r      "type": "User",\r      "site_admin": false\r    },\r    "parents": [\r      {\r        "sha": "ded44ed5f1733bb93d84f94afe9383e2d47bbbaa",\r        "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/ded44ed5f1733bb93d84f94afe9383e2d47bbbaa",\r        "html_url": "https://github.com/openaddresses/hooked-on-sources/commit/ded44ed5f1733bb93d84f94afe9383e2d47bbbaa"\r      }\r    ]\r  },\r  "merge_base_commit": {\r    "sha": "ded44ed5f1733bb93d84f94afe9383e2d47bbbaa",\r    "commit": {\r      "author": {\r        "name": "Michal Migurski",\r        "email": "mike@teczno.com",\r        "date": "2015-04-26T00:25:55Z"\r      },\r      "committer": {\r        "name": "Michal Migurski",\r        "email": "mike@teczno.com",\r        "date": "2015-04-26T00:25:55Z"\r      },\r      "message": "Added Berkeley",\r      "tree": {\r        "sha": "9d6ac64ea358034e23fba121f3833790f47b5d76",\r        "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/trees/9d6ac64ea358034e23fba121f3833790f47b5d76"\r      },\r      "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/commits/ded44ed5f1733bb93d84f94afe9383e2d47bbbaa",\r      "comment_count": 0\r    },\r    "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/ded44ed5f1733bb93d84f94afe9383e2d47bbbaa",\r    "html_url": "https://github.com/openaddresses/hooked-on-sources/commit/ded44ed5f1733bb93d84f94afe9383e2d47bbbaa",\r    "comments_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/ded44ed5f1733bb93d84f94afe9383e2d47bbbaa/comments",\r    "author": {\r      "login": "migurski",\r      "id": 58730,\r      "avatar_url": "https://avatars.githubusercontent.com/u/58730?v=3",\r      "gravatar_id": "",\r      "url": "https://api.github.com/users/migurski",\r      "html_url": "https://github.com/migurski",\r      "followers_url": "https://api.github.com/users/migurski/followers",\r      "following_url": "https://api.github.com/users/migurski/following{/other_user}",\r      "gists_url": "https://api.github.com/users/migurski/gists{/gist_id}",\r      "starred_url": "https://api.github.com/users/migurski/starred{/owner}{/repo}",\r      "subscriptions_url": "https://api.github.com/users/migurski/subscriptions",\r      "organizations_url": "https://api.github.com/users/migurski/orgs",\r      "repos_url": "https://api.github.com/users/migurski/repos",\r      "events_url": "https://api.github.com/users/migurski/events{/privacy}",\r      "received_events_url": "https://api.github.com/users/migurski/received_events",\r      "type": "User",\r      "site_admin": false\r    },\r    "committer": {\r      "login": "migurski",\r      "id": 58730,\r      "avatar_url": "https://avatars.githubusercontent.com/u/58730?v=3",\r      "gravatar_id": "",\r      "url": "https://api.github.com/users/migurski",\r      "html_url": "https://github.com/migurski",\r      "followers_url": "https://api.github.com/users/migurski/followers",\r      "following_url": "https://api.github.com/users/migurski/following{/other_user}",\r      "gists_url": "https://api.github.com/users/migurski/gists{/gist_id}",\r      "starred_url": "https://api.github.com/users/migurski/starred{/owner}{/repo}",\r      "subscriptions_url": "https://api.github.com/users/migurski/subscriptions",\r      "organizations_url": "https://api.github.com/users/migurski/orgs",\r      "repos_url": "https://api.github.com/users/migurski/repos",\r      "events_url": "https://api.github.com/users/migurski/events{/privacy}",\r      "received_events_url": "https://api.github.com/users/migurski/received_events",\r      "type": "User",\r      "site_admin": false\r    },\r    "parents": [\r      {\r        "sha": "73a81c5b337bd393273a222f1cd191d7e634df51",\r        "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/73a81c5b337bd393273a222f1cd191d7e634df51",\r        "html_url": "https://github.com/openaddresses/hooked-on-sources/commit/73a81c5b337bd393273a222f1cd191d7e634df51"\r      }\r    ]\r  },\r  "status": "diverged",\r  "ahead_by": 3,\r  "behind_by": 1,\r  "total_commits": 3,\r  "commits": [\r    {\r      "sha": "b659130053b85cd3993b1a4653da1bf6231ec0b4",\r      "commit": {\r        "author": {\r          "name": "Michal Migurski",\r          "email": "mike@teczno.com",\r          "date": "2015-04-26T00:48:58Z"\r        },\r        "committer": {\r          "name": "Michal Migurski",\r          "email": "mike@teczno.com",\r          "date": "2015-04-26T00:48:58Z"\r        },\r        "message": "Added Santa Clara County",\r        "tree": {\r          "sha": "f0cd9b347f69397fcc79fcc434f077bf19af9520",\r          "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/trees/f0cd9b347f69397fcc79fcc434f077bf19af9520"\r        },\r        "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/commits/b659130053b85cd3993b1a4653da1bf6231ec0b4",\r        "comment_count": 0\r      },\r      "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/b659130053b85cd3993b1a4653da1bf6231ec0b4",\r      "html_url": "https://github.com/openaddresses/hooked-on-sources/commit/b659130053b85cd3993b1a4653da1bf6231ec0b4",\r      "comments_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/b659130053b85cd3993b1a4653da1bf6231ec0b4/comments",\r      "author": {\r        "login": "migurski",\r        "id": 58730,\r        "avatar_url": "https://avatars.githubusercontent.com/u/58730?v=3",\r        "gravatar_id": "",\r        "url": "https://api.github.com/users/migurski",\r        "html_url": "https://github.com/migurski",\r        "followers_url": "https://api.github.com/users/migurski/followers",\r        "following_url": "https://api.github.com/users/migurski/following{/other_user}",\r        "gists_url": "https://api.github.com/users/migurski/gists{/gist_id}",\r        "starred_url": "https://api.github.com/users/migurski/starred{/owner}{/repo}",\r        "subscriptions_url": "https://api.github.com/users/migurski/subscriptions",\r        "organizations_url": "https://api.github.com/users/migurski/orgs",\r        "repos_url": "https://api.github.com/users/migurski/repos",\r        "events_url": "https://api.github.com/users/migurski/events{/privacy}",\r        "received_events_url": "https://api.github.com/users/migurski/received_events",\r        "type": "User",\r        "site_admin": false\r      },\r      "committer": {\r        "login": "migurski",\r        "id": 58730,\r        "avatar_url": "https://avatars.githubusercontent.com/u/58730?v=3",\r        "gravatar_id": "",\r        "url": "https://api.github.com/users/migurski",\r        "html_url": "https://github.com/migurski",\r        "followers_url": "https://api.github.com/users/migurski/followers",\r        "following_url": "https://api.github.com/users/migurski/following{/other_user}",\r        "gists_url": "https://api.github.com/users/migurski/gists{/gist_id}",\r        "starred_url": "https://api.github.com/users/migurski/starred{/owner}{/repo}",\r        "subscriptions_url": "https://api.github.com/users/migurski/subscriptions",\r        "organizations_url": "https://api.github.com/users/migurski/orgs",\r        "repos_url": "https://api.github.com/users/migurski/repos",\r        "events_url": "https://api.github.com/users/migurski/events{/privacy}",\r        "received_events_url": "https://api.github.com/users/migurski/received_events",\r        "type": "User",\r        "site_admin": false\r      },\r      "parents": [\r        {\r          "sha": "ded44ed5f1733bb93d84f94afe9383e2d47bbbaa",\r          "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/ded44ed5f1733bb93d84f94afe9383e2d47bbbaa",\r          "html_url": "https://github.com/openaddresses/hooked-on-sources/commit/ded44ed5f1733bb93d84f94afe9383e2d47bbbaa"\r        }\r      ]\r    },\r    {\r      "sha": "0cbd51b8f6044e98c919dcabf93e3f4e1d58c035",\r      "commit": {\r        "author": {\r          "name": "Michal Migurski",\r          "email": "mike@teczno.com",\r          "date": "2015-04-26T00:52:39Z"\r        },\r        "committer": {\r          "name": "Michal Migurski",\r          "email": "mike@teczno.com",\r          "date": "2015-04-26T00:52:39Z"\r        },\r        "message": "Added Polish source",\r        "tree": {\r          "sha": "cf52bd865006bc0cd3deaba1b87a4d679a3410e0",\r          "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/trees/cf52bd865006bc0cd3deaba1b87a4d679a3410e0"\r        },\r        "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/commits/0cbd51b8f6044e98c919dcabf93e3f4e1d58c035",\r        "comment_count": 0\r      },\r      "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/0cbd51b8f6044e98c919dcabf93e3f4e1d58c035",\r      "html_url": "https://github.com/openaddresses/hooked-on-sources/commit/0cbd51b8f6044e98c919dcabf93e3f4e1d58c035",\r      "comments_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/0cbd51b8f6044e98c919dcabf93e3f4e1d58c035/comments",\r      "author": {\r        "login": "migurski",\r        "id": 58730,\r        "avatar_url": "https://avatars.githubusercontent.com/u/58730?v=3",\r        "gravatar_id": "",\r        "url": "https://api.github.com/users/migurski",\r        "html_url": "https://github.com/migurski",\r        "followers_url": "https://api.github.com/users/migurski/followers",\r        "following_url": "https://api.github.com/users/migurski/following{/other_user}",\r        "gists_url": "https://api.github.com/users/migurski/gists{/gist_id}",\r        "starred_url": "https://api.github.com/users/migurski/starred{/owner}{/repo}",\r        "subscriptions_url": "https://api.github.com/users/migurski/subscriptions",\r        "organizations_url": "https://api.github.com/users/migurski/orgs",\r        "repos_url": "https://api.github.com/users/migurski/repos",\r        "events_url": "https://api.github.com/users/migurski/events{/privacy}",\r        "received_events_url": "https://api.github.com/users/migurski/received_events",\r        "type": "User",\r        "site_admin": false\r      },\r      "committer": {\r        "login": "migurski",\r        "id": 58730,\r        "avatar_url": "https://avatars.githubusercontent.com/u/58730?v=3",\r        "gravatar_id": "",\r        "url": "https://api.github.com/users/migurski",\r        "html_url": "https://github.com/migurski",\r        "followers_url": "https://api.github.com/users/migurski/followers",\r        "following_url": "https://api.github.com/users/migurski/following{/other_user}",\r        "gists_url": "https://api.github.com/users/migurski/gists{/gist_id}",\r        "starred_url": "https://api.github.com/users/migurski/starred{/owner}{/repo}",\r        "subscriptions_url": "https://api.github.com/users/migurski/subscriptions",\r        "organizations_url": "https://api.github.com/users/migurski/orgs",\r        "repos_url": "https://api.github.com/users/migurski/repos",\r        "events_url": "https://api.github.com/users/migurski/events{/privacy}",\r        "received_events_url": "https://api.github.com/users/migurski/received_events",\r        "type": "User",\r        "site_admin": false\r      },\r      "parents": [\r        {\r          "sha": "b659130053b85cd3993b1a4653da1bf6231ec0b4",\r          "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/b659130053b85cd3993b1a4653da1bf6231ec0b4",\r          "html_url": "https://github.com/openaddresses/hooked-on-sources/commit/b659130053b85cd3993b1a4653da1bf6231ec0b4"\r        }\r      ]\r    },\r    {\r      "sha": "e5f1dcae83ab1ef1f736b969da617311f7f11564",\r      "commit": {\r        "author": {\r          "name": "Michal Migurski",\r          "email": "mike@teczno.com",\r          "date": "2015-04-26T00:52:46Z"\r        },\r        "committer": {\r          "name": "Michal Migurski",\r          "email": "mike@teczno.com",\r          "date": "2015-04-26T00:52:46Z"\r        },\r        "message": "Removed Polish source",\r        "tree": {\r          "sha": "f0cd9b347f69397fcc79fcc434f077bf19af9520",\r          "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/trees/f0cd9b347f69397fcc79fcc434f077bf19af9520"\r        },\r        "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/commits/e5f1dcae83ab1ef1f736b969da617311f7f11564",\r        "comment_count": 0\r      },\r      "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/e5f1dcae83ab1ef1f736b969da617311f7f11564",\r      "html_url": "https://github.com/openaddresses/hooked-on-sources/commit/e5f1dcae83ab1ef1f736b969da617311f7f11564",\r      "comments_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/e5f1dcae83ab1ef1f736b969da617311f7f11564/comments",\r      "author": {\r        "login": "migurski",\r        "id": 58730,\r        "avatar_url": "https://avatars.githubusercontent.com/u/58730?v=3",\r        "gravatar_id": "",\r        "url": "https://api.github.com/users/migurski",\r        "html_url": "https://github.com/migurski",\r        "followers_url": "https://api.github.com/users/migurski/followers",\r        "following_url": "https://api.github.com/users/migurski/following{/other_user}",\r        "gists_url": "https://api.github.com/users/migurski/gists{/gist_id}",\r        "starred_url": "https://api.github.com/users/migurski/starred{/owner}{/repo}",\r        "subscriptions_url": "https://api.github.com/users/migurski/subscriptions",\r        "organizations_url": "https://api.github.com/users/migurski/orgs",\r        "repos_url": "https://api.github.com/users/migurski/repos",\r        "events_url": "https://api.github.com/users/migurski/events{/privacy}",\r        "received_events_url": "https://api.github.com/users/migurski/received_events",\r        "type": "User",\r        "site_admin": false\r      },\r      "committer": {\r        "login": "migurski",\r        "id": 58730,\r        "avatar_url": "https://avatars.githubusercontent.com/u/58730?v=3",\r        "gravatar_id": "",\r        "url": "https://api.github.com/users/migurski",\r        "html_url": "https://github.com/migurski",\r        "followers_url": "https://api.github.com/users/migurski/followers",\r        "following_url": "https://api.github.com/users/migurski/following{/other_user}",\r        "gists_url": "https://api.github.com/users/migurski/gists{/gist_id}",\r        "starred_url": "https://api.github.com/users/migurski/starred{/owner}{/repo}",\r        "subscriptions_url": "https://api.github.com/users/migurski/subscriptions",\r        "organizations_url": "https://api.github.com/users/migurski/orgs",\r        "repos_url": "https://api.github.com/users/migurski/repos",\r        "events_url": "https://api.github.com/users/migurski/events{/privacy}",\r        "received_events_url": "https://api.github.com/users/migurski/received_events",\r        "type": "User",\r        "site_admin": false\r      },\r      "parents": [\r        {\r          "sha": "0cbd51b8f6044e98c919dcabf93e3f4e1d58c035",\r          "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/0cbd51b8f6044e98c919dcabf93e3f4e1d58c035",\r          "html_url": "https://github.com/openaddresses/hooked-on-sources/commit/0cbd51b8f6044e98c919dcabf93e3f4e1d58c035"\r        }\r      ]\r    }\r  ],\r  "files": [\r    {\r      "sha": "84abff13dba318189f1f4d5c1605478127ceff5c",\r      "filename": "sources/us-ca-santa_clara_county.json",\r      "status": "added",\r      "additions": 24,\r      "deletions": 0,\r      "changes": 24,\r      "blob_url": "https://github.com/openaddresses/hooked-on-sources/blob/e5f1dcae83ab1ef1f736b969da617311f7f11564/sources/us-ca-santa_clara_county.json",\r      "raw_url": "https://github.com/openaddresses/hooked-on-sources/raw/e5f1dcae83ab1ef1f736b969da617311f7f11564/sources/us-ca-santa_clara_county.json",\r      "contents_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/contents/sources/us-ca-santa_clara_county.json?ref=e5f1dcae83ab1ef1f736b969da617311f7f11564",\r      "patch": "@@ -0,0 +1,24 @@\\n+{\\n+    \\"coverage\\": {\\n+        \\"US Census\\": {\\"geoid\\": \\"06085\\", \\"name\\": \\"Santa Clara County\\", \\"state\\": \\"California\\"},\\n+        \\"country\\": \\"us\\",\\n+        \\"state\\": \\"ca\\",\\n+        \\"county\\": \\"Santa Clara\\"\\n+    },\\n+    \\"conform\\": {\\n+        \\"type\\": \\"shapefile\\",\\n+        \\"postcode\\": \\"ZIPCODE\\",\\n+        \\"city\\": \\"CITY\\",\\n+        \\"number\\": \\"HOUSENUMTE\\",\\n+        \\"merge\\": [\\"STREETNAME\\", \\"STREETTYPE\\"],\\n+        \\"street\\": \\"auto_street\\",\\n+        \\"lon\\": \\"x\\",\\n+        \\"lat\\": \\"y\\"\\n+    },\\n+    \\"attribution\\": \\"Santa Clara County\\",\\n+    \\"data\\": \\"https://github.com/datadesk/us-ca-santa_clara_county-gis-shp/blob/master/Q4_FY14_Address_Point.zip?raw=true\\",\\n+    \\"website\\": \\"https://sftp.sccgov.org/courier/web/1000@/wmLogin.html\\",\\n+    \\"type\\": \\"http\\",\\n+    \\"compression\\": \\"zip\\",\\n+    \\"note\\": \\"File download is behind a registration wall on government site so the zip was downloaded in November 2014 and uploaded to GitHub for public hosting.\\"\\n+}"\r    }\r  ]\r}'''
            return response(200, data.encode('utf8'), headers=response_headers)
        
        if MHP == ('GET', GH, '/repos/openaddresses/hooked-on-sources/compare/master...e91fbc420f08890960f50f863626e1062f922522'):
            data = '''{\r              "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/compare/master...e91fbc420f08890960f50f863626e1062f922522",\r              "html_url": "https://github.com/openaddresses/hooked-on-sources/compare/master...e91fbc420f08890960f50f863626e1062f922522",\r              "permalink_url": "https://github.com/openaddresses/hooked-on-sources/compare/openaddresses:ded44ed...openaddresses:e91fbc4",\r              "diff_url": "https://github.com/openaddresses/hooked-on-sources/compare/master...e91fbc420f08890960f50f863626e1062f922522.diff",\r              "patch_url": "https://github.com/openaddresses/hooked-on-sources/compare/master...e91fbc420f08890960f50f863626e1062f922522.patch",\r              "base_commit": {\r                "sha": "ded44ed5f1733bb93d84f94afe9383e2d47bbbaa",\r                "commit": {\r                  "author": {\r                    "name": "Michal Migurski",\r                    "email": "mike@teczno.com",\r                    "date": "2015-04-26T00:25:55Z"\r                  },\r                  "committer": {\r                    "name": "Michal Migurski",\r                    "email": "mike@teczno.com",\r                    "date": "2015-04-26T00:25:55Z"\r                  },\r                  "message": "Added Berkeley",\r                  "tree": {\r                    "sha": "9d6ac64ea358034e23fba121f3833790f47b5d76",\r                    "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/trees/9d6ac64ea358034e23fba121f3833790f47b5d76"\r                  },\r                  "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/commits/ded44ed5f1733bb93d84f94afe9383e2d47bbbaa",\r                  "comment_count": 0\r                },\r                "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/ded44ed5f1733bb93d84f94afe9383e2d47bbbaa",\r                "html_url": "https://github.com/openaddresses/hooked-on-sources/commit/ded44ed5f1733bb93d84f94afe9383e2d47bbbaa",\r                "comments_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/ded44ed5f1733bb93d84f94afe9383e2d47bbbaa/comments",\r                "author": {\r                  "login": "migurski",\r                  "id": 58730,\r                  "avatar_url": "https://avatars.githubusercontent.com/u/58730?v=3",\r                  "gravatar_id": "",\r                  "url": "https://api.github.com/users/migurski",\r                  "html_url": "https://github.com/migurski",\r                  "followers_url": "https://api.github.com/users/migurski/followers",\r                  "following_url": "https://api.github.com/users/migurski/following{/other_user}",\r                  "gists_url": "https://api.github.com/users/migurski/gists{/gist_id}",\r                  "starred_url": "https://api.github.com/users/migurski/starred{/owner}{/repo}",\r                  "subscriptions_url": "https://api.github.com/users/migurski/subscriptions",\r                  "organizations_url": "https://api.github.com/users/migurski/orgs",\r                  "repos_url": "https://api.github.com/users/migurski/repos",\r                  "events_url": "https://api.github.com/users/migurski/events{/privacy}",\r                  "received_events_url": "https://api.github.com/users/migurski/received_events",\r                  "type": "User",\r                  "site_admin": false\r                },\r                "committer": {\r                  "login": "migurski",\r                  "id": 58730,\r                  "avatar_url": "https://avatars.githubusercontent.com/u/58730?v=3",\r                  "gravatar_id": "",\r                  "url": "https://api.github.com/users/migurski",\r                  "html_url": "https://github.com/migurski",\r                  "followers_url": "https://api.github.com/users/migurski/followers",\r                  "following_url": "https://api.github.com/users/migurski/following{/other_user}",\r                  "gists_url": "https://api.github.com/users/migurski/gists{/gist_id}",\r                  "starred_url": "https://api.github.com/users/migurski/starred{/owner}{/repo}",\r                  "subscriptions_url": "https://api.github.com/users/migurski/subscriptions",\r                  "organizations_url": "https://api.github.com/users/migurski/orgs",\r                  "repos_url": "https://api.github.com/users/migurski/repos",\r                  "events_url": "https://api.github.com/users/migurski/events{/privacy}",\r                  "received_events_url": "https://api.github.com/users/migurski/received_events",\r                  "type": "User",\r                  "site_admin": false\r                },\r                "parents": [\r                  {\r                    "sha": "73a81c5b337bd393273a222f1cd191d7e634df51",\r                    "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/73a81c5b337bd393273a222f1cd191d7e634df51",\r                    "html_url": "https://github.com/openaddresses/hooked-on-sources/commit/73a81c5b337bd393273a222f1cd191d7e634df51"\r                  }\r                ]\r              },\r              "merge_base_commit": {\r                "sha": "e91fbc420f08890960f50f863626e1062f922522",\r                "commit": {\r                  "author": {\r                    "name": "Michal Migurski",\r                    "email": "mike@teczno.com",\r                    "date": "2015-04-26T00:16:12Z"\r                  },\r                  "committer": {\r                    "name": "Michal Migurski",\r                    "email": "mike@teczno.com",\r                    "date": "2015-04-26T00:16:12Z"\r                  },\r                  "message": "Added first source",\r                  "tree": {\r                    "sha": "f5e85249cee39d0e84ed936d31a9c08c1eaaa539",\r                    "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/trees/f5e85249cee39d0e84ed936d31a9c08c1eaaa539"\r                  },\r                  "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/commits/e91fbc420f08890960f50f863626e1062f922522",\r                  "comment_count": 0\r                },\r                "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/e91fbc420f08890960f50f863626e1062f922522",\r                "html_url": "https://github.com/openaddresses/hooked-on-sources/commit/e91fbc420f08890960f50f863626e1062f922522",\r                "comments_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/e91fbc420f08890960f50f863626e1062f922522/comments",\r                "author": {\r                  "login": "migurski",\r                  "id": 58730,\r                  "avatar_url": "https://avatars.githubusercontent.com/u/58730?v=3",\r                  "gravatar_id": "",\r                  "url": "https://api.github.com/users/migurski",\r                  "html_url": "https://github.com/migurski",\r                  "followers_url": "https://api.github.com/users/migurski/followers",\r                  "following_url": "https://api.github.com/users/migurski/following{/other_user}",\r                  "gists_url": "https://api.github.com/users/migurski/gists{/gist_id}",\r                  "starred_url": "https://api.github.com/users/migurski/starred{/owner}{/repo}",\r                  "subscriptions_url": "https://api.github.com/users/migurski/subscriptions",\r                  "organizations_url": "https://api.github.com/users/migurski/orgs",\r                  "repos_url": "https://api.github.com/users/migurski/repos",\r                  "events_url": "https://api.github.com/users/migurski/events{/privacy}",\r                  "received_events_url": "https://api.github.com/users/migurski/received_events",\r                  "type": "User",\r                  "site_admin": false\r                },\r                "committer": {\r                  "login": "migurski",\r                  "id": 58730,\r                  "avatar_url": "https://avatars.githubusercontent.com/u/58730?v=3",\r                  "gravatar_id": "",\r                  "url": "https://api.github.com/users/migurski",\r                  "html_url": "https://github.com/migurski",\r                  "followers_url": "https://api.github.com/users/migurski/followers",\r                  "following_url": "https://api.github.com/users/migurski/following{/other_user}",\r                  "gists_url": "https://api.github.com/users/migurski/gists{/gist_id}",\r                  "starred_url": "https://api.github.com/users/migurski/starred{/owner}{/repo}",\r                  "subscriptions_url": "https://api.github.com/users/migurski/subscriptions",\r                  "organizations_url": "https://api.github.com/users/migurski/orgs",\r                  "repos_url": "https://api.github.com/users/migurski/repos",\r                  "events_url": "https://api.github.com/users/migurski/events{/privacy}",\r                  "received_events_url": "https://api.github.com/users/migurski/received_events",\r                  "type": "User",\r                  "site_admin": false\r                },\r                "parents": [\r                  {\r                    "sha": "c52204fd40f17f9da243df09e6d1107d48768afd",\r                    "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/c52204fd40f17f9da243df09e6d1107d48768afd",\r                    "html_url": "https://github.com/openaddresses/hooked-on-sources/commit/c52204fd40f17f9da243df09e6d1107d48768afd"\r                  }\r                ]\r              },\r              "status": "behind",\r              "ahead_by": 0,\r              "behind_by": 2,\r              "total_commits": 0,\r              "commits": [\r\r              ],\r              "files": [\r\r              ]\r            }'''
            return response(200, data.encode('utf8'), headers=response_headers)
        
        if MHP == ('GET', GH, '/repos/openaddresses/hooked-on-sources/compare/master...ded44ed5f1733bb93d84f94afe9383e2d47bbbaa'):
            data = '''{\r              "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/compare/master...ded44ed5f1733bb93d84f94afe9383e2d47bbbaa",\r              "html_url": "https://github.com/openaddresses/hooked-on-sources/compare/master...ded44ed5f1733bb93d84f94afe9383e2d47bbbaa",\r              "permalink_url": "https://github.com/openaddresses/hooked-on-sources/compare/openaddresses:ded44ed...openaddresses:ded44ed",\r              "diff_url": "https://github.com/openaddresses/hooked-on-sources/compare/master...ded44ed5f1733bb93d84f94afe9383e2d47bbbaa.diff",\r              "patch_url": "https://github.com/openaddresses/hooked-on-sources/compare/master...ded44ed5f1733bb93d84f94afe9383e2d47bbbaa.patch",\r              "base_commit": {\r                "sha": "ded44ed5f1733bb93d84f94afe9383e2d47bbbaa",\r                "commit": {\r                  "author": {\r                    "name": "Michal Migurski",\r                    "email": "mike@teczno.com",\r                    "date": "2015-04-26T00:25:55Z"\r                  },\r                  "committer": {\r                    "name": "Michal Migurski",\r                    "email": "mike@teczno.com",\r                    "date": "2015-04-26T00:25:55Z"\r                  },\r                  "message": "Added Berkeley",\r                  "tree": {\r                    "sha": "9d6ac64ea358034e23fba121f3833790f47b5d76",\r                    "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/trees/9d6ac64ea358034e23fba121f3833790f47b5d76"\r                  },\r                  "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/commits/ded44ed5f1733bb93d84f94afe9383e2d47bbbaa",\r                  "comment_count": 0\r                },\r                "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/ded44ed5f1733bb93d84f94afe9383e2d47bbbaa",\r                "html_url": "https://github.com/openaddresses/hooked-on-sources/commit/ded44ed5f1733bb93d84f94afe9383e2d47bbbaa",\r                "comments_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/ded44ed5f1733bb93d84f94afe9383e2d47bbbaa/comments",\r                "author": {\r                  "login": "migurski",\r                  "id": 58730,\r                  "avatar_url": "https://avatars.githubusercontent.com/u/58730?v=3",\r                  "gravatar_id": "",\r                  "url": "https://api.github.com/users/migurski",\r                  "html_url": "https://github.com/migurski",\r                  "followers_url": "https://api.github.com/users/migurski/followers",\r                  "following_url": "https://api.github.com/users/migurski/following{/other_user}",\r                  "gists_url": "https://api.github.com/users/migurski/gists{/gist_id}",\r                  "starred_url": "https://api.github.com/users/migurski/starred{/owner}{/repo}",\r                  "subscriptions_url": "https://api.github.com/users/migurski/subscriptions",\r                  "organizations_url": "https://api.github.com/users/migurski/orgs",\r                  "repos_url": "https://api.github.com/users/migurski/repos",\r                  "events_url": "https://api.github.com/users/migurski/events{/privacy}",\r                  "received_events_url": "https://api.github.com/users/migurski/received_events",\r                  "type": "User",\r                  "site_admin": false\r                },\r                "committer": {\r                  "login": "migurski",\r                  "id": 58730,\r                  "avatar_url": "https://avatars.githubusercontent.com/u/58730?v=3",\r                  "gravatar_id": "",\r                  "url": "https://api.github.com/users/migurski",\r                  "html_url": "https://github.com/migurski",\r                  "followers_url": "https://api.github.com/users/migurski/followers",\r                  "following_url": "https://api.github.com/users/migurski/following{/other_user}",\r                  "gists_url": "https://api.github.com/users/migurski/gists{/gist_id}",\r                  "starred_url": "https://api.github.com/users/migurski/starred{/owner}{/repo}",\r                  "subscriptions_url": "https://api.github.com/users/migurski/subscriptions",\r                  "organizations_url": "https://api.github.com/users/migurski/orgs",\r                  "repos_url": "https://api.github.com/users/migurski/repos",\r                  "events_url": "https://api.github.com/users/migurski/events{/privacy}",\r                  "received_events_url": "https://api.github.com/users/migurski/received_events",\r                  "type": "User",\r                  "site_admin": false\r                },\r                "parents": [\r                  {\r                    "sha": "73a81c5b337bd393273a222f1cd191d7e634df51",\r                    "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/73a81c5b337bd393273a222f1cd191d7e634df51",\r                    "html_url": "https://github.com/openaddresses/hooked-on-sources/commit/73a81c5b337bd393273a222f1cd191d7e634df51"\r                  }\r                ]\r              },\r              "merge_base_commit": {\r                "sha": "ded44ed5f1733bb93d84f94afe9383e2d47bbbaa",\r                "commit": {\r                  "author": {\r                    "name": "Michal Migurski",\r                    "email": "mike@teczno.com",\r                    "date": "2015-04-26T00:25:55Z"\r                  },\r                  "committer": {\r                    "name": "Michal Migurski",\r                    "email": "mike@teczno.com",\r                    "date": "2015-04-26T00:25:55Z"\r                  },\r                  "message": "Added Berkeley",\r                  "tree": {\r                    "sha": "9d6ac64ea358034e23fba121f3833790f47b5d76",\r                    "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/trees/9d6ac64ea358034e23fba121f3833790f47b5d76"\r                  },\r                  "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/commits/ded44ed5f1733bb93d84f94afe9383e2d47bbbaa",\r                  "comment_count": 0\r                },\r                "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/ded44ed5f1733bb93d84f94afe9383e2d47bbbaa",\r                "html_url": "https://github.com/openaddresses/hooked-on-sources/commit/ded44ed5f1733bb93d84f94afe9383e2d47bbbaa",\r                "comments_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/ded44ed5f1733bb93d84f94afe9383e2d47bbbaa/comments",\r                "author": {\r                  "login": "migurski",\r                  "id": 58730,\r                  "avatar_url": "https://avatars.githubusercontent.com/u/58730?v=3",\r                  "gravatar_id": "",\r                  "url": "https://api.github.com/users/migurski",\r                  "html_url": "https://github.com/migurski",\r                  "followers_url": "https://api.github.com/users/migurski/followers",\r                  "following_url": "https://api.github.com/users/migurski/following{/other_user}",\r                  "gists_url": "https://api.github.com/users/migurski/gists{/gist_id}",\r                  "starred_url": "https://api.github.com/users/migurski/starred{/owner}{/repo}",\r                  "subscriptions_url": "https://api.github.com/users/migurski/subscriptions",\r                  "organizations_url": "https://api.github.com/users/migurski/orgs",\r                  "repos_url": "https://api.github.com/users/migurski/repos",\r                  "events_url": "https://api.github.com/users/migurski/events{/privacy}",\r                  "received_events_url": "https://api.github.com/users/migurski/received_events",\r                  "type": "User",\r                  "site_admin": false\r                },\r                "committer": {\r                  "login": "migurski",\r                  "id": 58730,\r                  "avatar_url": "https://avatars.githubusercontent.com/u/58730?v=3",\r                  "gravatar_id": "",\r                  "url": "https://api.github.com/users/migurski",\r                  "html_url": "https://github.com/migurski",\r                  "followers_url": "https://api.github.com/users/migurski/followers",\r                  "following_url": "https://api.github.com/users/migurski/following{/other_user}",\r                  "gists_url": "https://api.github.com/users/migurski/gists{/gist_id}",\r                  "starred_url": "https://api.github.com/users/migurski/starred{/owner}{/repo}",\r                  "subscriptions_url": "https://api.github.com/users/migurski/subscriptions",\r                  "organizations_url": "https://api.github.com/users/migurski/orgs",\r                  "repos_url": "https://api.github.com/users/migurski/repos",\r                  "events_url": "https://api.github.com/users/migurski/events{/privacy}",\r                  "received_events_url": "https://api.github.com/users/migurski/received_events",\r                  "type": "User",\r                  "site_admin": false\r                },\r                "parents": [\r                  {\r                    "sha": "73a81c5b337bd393273a222f1cd191d7e634df51",\r                    "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/73a81c5b337bd393273a222f1cd191d7e634df51",\r                    "html_url": "https://github.com/openaddresses/hooked-on-sources/commit/73a81c5b337bd393273a222f1cd191d7e634df51"\r                  }\r                ]\r              },\r              "status": "identical",\r              "ahead_by": 0,\r              "behind_by": 0,\r              "total_commits": 0,\r              "commits": [\r\r              ],\r              "files": [\r\r              ]\r            }'''
            return response(200, data.encode('utf8'), headers=response_headers)
        
        if MHP == ('GET', GH, '/repos/openaddresses/hooked-on-sources/compare/ded44ed5f1733bb93d84f94afe9383e2d47bbbaa...e5f1dcae83ab1ef1f736b969da617311f7f11564'):
            data = '''{\r  "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/compare/ded44ed5f1733bb93d84f94afe9383e2d47bbbaa...e5f1dcae83ab1ef1f736b969da617311f7f11564",\r  "html_url": "https://github.com/openaddresses/hooked-on-sources/compare/ded44ed5f1733bb93d84f94afe9383e2d47bbbaa...e5f1dcae83ab1ef1f736b969da617311f7f11564",\r  "permalink_url": "https://github.com/openaddresses/hooked-on-sources/compare/openaddresses:ded44ed...openaddresses:e5f1dca",\r  "diff_url": "https://github.com/openaddresses/hooked-on-sources/compare/ded44ed5f1733bb93d84f94afe9383e2d47bbbaa...e5f1dcae83ab1ef1f736b969da617311f7f11564.diff",\r  "patch_url": "https://github.com/openaddresses/hooked-on-sources/compare/ded44ed5f1733bb93d84f94afe9383e2d47bbbaa...e5f1dcae83ab1ef1f736b969da617311f7f11564.patch",\r  "base_commit": {\r    "sha": "ded44ed5f1733bb93d84f94afe9383e2d47bbbaa",\r    "commit": {\r      "author": {\r        "name": "Michal Migurski",\r        "email": "mike@teczno.com",\r        "date": "2015-04-26T00:25:55Z"\r      },\r      "committer": {\r        "name": "Michal Migurski",\r        "email": "mike@teczno.com",\r        "date": "2015-04-26T00:25:55Z"\r      },\r      "message": "Added Berkeley",\r      "tree": {\r        "sha": "9d6ac64ea358034e23fba121f3833790f47b5d76",\r        "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/trees/9d6ac64ea358034e23fba121f3833790f47b5d76"\r      },\r      "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/commits/ded44ed5f1733bb93d84f94afe9383e2d47bbbaa",\r      "comment_count": 0\r    },\r    "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/ded44ed5f1733bb93d84f94afe9383e2d47bbbaa",\r    "html_url": "https://github.com/openaddresses/hooked-on-sources/commit/ded44ed5f1733bb93d84f94afe9383e2d47bbbaa",\r    "comments_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/ded44ed5f1733bb93d84f94afe9383e2d47bbbaa/comments",\r    "author": {\r      "login": "migurski",\r      "id": 58730,\r      "avatar_url": "https://avatars.githubusercontent.com/u/58730?v=3",\r      "gravatar_id": "",\r      "url": "https://api.github.com/users/migurski",\r      "html_url": "https://github.com/migurski",\r      "followers_url": "https://api.github.com/users/migurski/followers",\r      "following_url": "https://api.github.com/users/migurski/following{/other_user}",\r      "gists_url": "https://api.github.com/users/migurski/gists{/gist_id}",\r      "starred_url": "https://api.github.com/users/migurski/starred{/owner}{/repo}",\r      "subscriptions_url": "https://api.github.com/users/migurski/subscriptions",\r      "organizations_url": "https://api.github.com/users/migurski/orgs",\r      "repos_url": "https://api.github.com/users/migurski/repos",\r      "events_url": "https://api.github.com/users/migurski/events{/privacy}",\r      "received_events_url": "https://api.github.com/users/migurski/received_events",\r      "type": "User",\r      "site_admin": false\r    },\r    "committer": {\r      "login": "migurski",\r      "id": 58730,\r      "avatar_url": "https://avatars.githubusercontent.com/u/58730?v=3",\r      "gravatar_id": "",\r      "url": "https://api.github.com/users/migurski",\r      "html_url": "https://github.com/migurski",\r      "followers_url": "https://api.github.com/users/migurski/followers",\r      "following_url": "https://api.github.com/users/migurski/following{/other_user}",\r      "gists_url": "https://api.github.com/users/migurski/gists{/gist_id}",\r      "starred_url": "https://api.github.com/users/migurski/starred{/owner}{/repo}",\r      "subscriptions_url": "https://api.github.com/users/migurski/subscriptions",\r      "organizations_url": "https://api.github.com/users/migurski/orgs",\r      "repos_url": "https://api.github.com/users/migurski/repos",\r      "events_url": "https://api.github.com/users/migurski/events{/privacy}",\r      "received_events_url": "https://api.github.com/users/migurski/received_events",\r      "type": "User",\r      "site_admin": false\r    },\r    "parents": [\r      {\r        "sha": "73a81c5b337bd393273a222f1cd191d7e634df51",\r        "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/73a81c5b337bd393273a222f1cd191d7e634df51",\r        "html_url": "https://github.com/openaddresses/hooked-on-sources/commit/73a81c5b337bd393273a222f1cd191d7e634df51"\r      }\r    ]\r  },\r  "merge_base_commit": {\r    "sha": "ded44ed5f1733bb93d84f94afe9383e2d47bbbaa",\r    "commit": {\r      "author": {\r        "name": "Michal Migurski",\r        "email": "mike@teczno.com",\r        "date": "2015-04-26T00:25:55Z"\r      },\r      "committer": {\r        "name": "Michal Migurski",\r        "email": "mike@teczno.com",\r        "date": "2015-04-26T00:25:55Z"\r      },\r      "message": "Added Berkeley",\r      "tree": {\r        "sha": "9d6ac64ea358034e23fba121f3833790f47b5d76",\r        "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/trees/9d6ac64ea358034e23fba121f3833790f47b5d76"\r      },\r      "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/commits/ded44ed5f1733bb93d84f94afe9383e2d47bbbaa",\r      "comment_count": 0\r    },\r    "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/ded44ed5f1733bb93d84f94afe9383e2d47bbbaa",\r    "html_url": "https://github.com/openaddresses/hooked-on-sources/commit/ded44ed5f1733bb93d84f94afe9383e2d47bbbaa",\r    "comments_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/ded44ed5f1733bb93d84f94afe9383e2d47bbbaa/comments",\r    "author": {\r      "login": "migurski",\r      "id": 58730,\r      "avatar_url": "https://avatars.githubusercontent.com/u/58730?v=3",\r      "gravatar_id": "",\r      "url": "https://api.github.com/users/migurski",\r      "html_url": "https://github.com/migurski",\r      "followers_url": "https://api.github.com/users/migurski/followers",\r      "following_url": "https://api.github.com/users/migurski/following{/other_user}",\r      "gists_url": "https://api.github.com/users/migurski/gists{/gist_id}",\r      "starred_url": "https://api.github.com/users/migurski/starred{/owner}{/repo}",\r      "subscriptions_url": "https://api.github.com/users/migurski/subscriptions",\r      "organizations_url": "https://api.github.com/users/migurski/orgs",\r      "repos_url": "https://api.github.com/users/migurski/repos",\r      "events_url": "https://api.github.com/users/migurski/events{/privacy}",\r      "received_events_url": "https://api.github.com/users/migurski/received_events",\r      "type": "User",\r      "site_admin": false\r    },\r    "committer": {\r      "login": "migurski",\r      "id": 58730,\r      "avatar_url": "https://avatars.githubusercontent.com/u/58730?v=3",\r      "gravatar_id": "",\r      "url": "https://api.github.com/users/migurski",\r      "html_url": "https://github.com/migurski",\r      "followers_url": "https://api.github.com/users/migurski/followers",\r      "following_url": "https://api.github.com/users/migurski/following{/other_user}",\r      "gists_url": "https://api.github.com/users/migurski/gists{/gist_id}",\r      "starred_url": "https://api.github.com/users/migurski/starred{/owner}{/repo}",\r      "subscriptions_url": "https://api.github.com/users/migurski/subscriptions",\r      "organizations_url": "https://api.github.com/users/migurski/orgs",\r      "repos_url": "https://api.github.com/users/migurski/repos",\r      "events_url": "https://api.github.com/users/migurski/events{/privacy}",\r      "received_events_url": "https://api.github.com/users/migurski/received_events",\r      "type": "User",\r      "site_admin": false\r    },\r    "parents": [\r      {\r        "sha": "73a81c5b337bd393273a222f1cd191d7e634df51",\r        "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/73a81c5b337bd393273a222f1cd191d7e634df51",\r        "html_url": "https://github.com/openaddresses/hooked-on-sources/commit/73a81c5b337bd393273a222f1cd191d7e634df51"\r      }\r    ]\r  },\r  "status": "ahead",\r  "ahead_by": 3,\r  "behind_by": 0,\r  "total_commits": 3,\r  "commits": [\r    {\r      "sha": "b659130053b85cd3993b1a4653da1bf6231ec0b4",\r      "commit": {\r        "author": {\r          "name": "Michal Migurski",\r          "email": "mike@teczno.com",\r          "date": "2015-04-26T00:48:58Z"\r        },\r        "committer": {\r          "name": "Michal Migurski",\r          "email": "mike@teczno.com",\r          "date": "2015-04-26T00:48:58Z"\r        },\r        "message": "Added Santa Clara County",\r        "tree": {\r          "sha": "f0cd9b347f69397fcc79fcc434f077bf19af9520",\r          "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/trees/f0cd9b347f69397fcc79fcc434f077bf19af9520"\r        },\r        "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/commits/b659130053b85cd3993b1a4653da1bf6231ec0b4",\r        "comment_count": 0\r      },\r      "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/b659130053b85cd3993b1a4653da1bf6231ec0b4",\r      "html_url": "https://github.com/openaddresses/hooked-on-sources/commit/b659130053b85cd3993b1a4653da1bf6231ec0b4",\r      "comments_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/b659130053b85cd3993b1a4653da1bf6231ec0b4/comments",\r      "author": {\r        "login": "migurski",\r        "id": 58730,\r        "avatar_url": "https://avatars.githubusercontent.com/u/58730?v=3",\r        "gravatar_id": "",\r        "url": "https://api.github.com/users/migurski",\r        "html_url": "https://github.com/migurski",\r        "followers_url": "https://api.github.com/users/migurski/followers",\r        "following_url": "https://api.github.com/users/migurski/following{/other_user}",\r        "gists_url": "https://api.github.com/users/migurski/gists{/gist_id}",\r        "starred_url": "https://api.github.com/users/migurski/starred{/owner}{/repo}",\r        "subscriptions_url": "https://api.github.com/users/migurski/subscriptions",\r        "organizations_url": "https://api.github.com/users/migurski/orgs",\r        "repos_url": "https://api.github.com/users/migurski/repos",\r        "events_url": "https://api.github.com/users/migurski/events{/privacy}",\r        "received_events_url": "https://api.github.com/users/migurski/received_events",\r        "type": "User",\r        "site_admin": false\r      },\r      "committer": {\r        "login": "migurski",\r        "id": 58730,\r        "avatar_url": "https://avatars.githubusercontent.com/u/58730?v=3",\r        "gravatar_id": "",\r        "url": "https://api.github.com/users/migurski",\r        "html_url": "https://github.com/migurski",\r        "followers_url": "https://api.github.com/users/migurski/followers",\r        "following_url": "https://api.github.com/users/migurski/following{/other_user}",\r        "gists_url": "https://api.github.com/users/migurski/gists{/gist_id}",\r        "starred_url": "https://api.github.com/users/migurski/starred{/owner}{/repo}",\r        "subscriptions_url": "https://api.github.com/users/migurski/subscriptions",\r        "organizations_url": "https://api.github.com/users/migurski/orgs",\r        "repos_url": "https://api.github.com/users/migurski/repos",\r        "events_url": "https://api.github.com/users/migurski/events{/privacy}",\r        "received_events_url": "https://api.github.com/users/migurski/received_events",\r        "type": "User",\r        "site_admin": false\r      },\r      "parents": [\r        {\r          "sha": "ded44ed5f1733bb93d84f94afe9383e2d47bbbaa",\r          "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/ded44ed5f1733bb93d84f94afe9383e2d47bbbaa",\r          "html_url": "https://github.com/openaddresses/hooked-on-sources/commit/ded44ed5f1733bb93d84f94afe9383e2d47bbbaa"\r        }\r      ]\r    },\r    {\r      "sha": "0cbd51b8f6044e98c919dcabf93e3f4e1d58c035",\r      "commit": {\r        "author": {\r          "name": "Michal Migurski",\r          "email": "mike@teczno.com",\r          "date": "2015-04-26T00:52:39Z"\r        },\r        "committer": {\r          "name": "Michal Migurski",\r          "email": "mike@teczno.com",\r          "date": "2015-04-26T00:52:39Z"\r        },\r        "message": "Added Polish source",\r        "tree": {\r          "sha": "cf52bd865006bc0cd3deaba1b87a4d679a3410e0",\r          "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/trees/cf52bd865006bc0cd3deaba1b87a4d679a3410e0"\r        },\r        "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/commits/0cbd51b8f6044e98c919dcabf93e3f4e1d58c035",\r        "comment_count": 0\r      },\r      "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/0cbd51b8f6044e98c919dcabf93e3f4e1d58c035",\r      "html_url": "https://github.com/openaddresses/hooked-on-sources/commit/0cbd51b8f6044e98c919dcabf93e3f4e1d58c035",\r      "comments_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/0cbd51b8f6044e98c919dcabf93e3f4e1d58c035/comments",\r      "author": {\r        "login": "migurski",\r        "id": 58730,\r        "avatar_url": "https://avatars.githubusercontent.com/u/58730?v=3",\r        "gravatar_id": "",\r        "url": "https://api.github.com/users/migurski",\r        "html_url": "https://github.com/migurski",\r        "followers_url": "https://api.github.com/users/migurski/followers",\r        "following_url": "https://api.github.com/users/migurski/following{/other_user}",\r        "gists_url": "https://api.github.com/users/migurski/gists{/gist_id}",\r        "starred_url": "https://api.github.com/users/migurski/starred{/owner}{/repo}",\r        "subscriptions_url": "https://api.github.com/users/migurski/subscriptions",\r        "organizations_url": "https://api.github.com/users/migurski/orgs",\r        "repos_url": "https://api.github.com/users/migurski/repos",\r        "events_url": "https://api.github.com/users/migurski/events{/privacy}",\r        "received_events_url": "https://api.github.com/users/migurski/received_events",\r        "type": "User",\r        "site_admin": false\r      },\r      "committer": {\r        "login": "migurski",\r        "id": 58730,\r        "avatar_url": "https://avatars.githubusercontent.com/u/58730?v=3",\r        "gravatar_id": "",\r        "url": "https://api.github.com/users/migurski",\r        "html_url": "https://github.com/migurski",\r        "followers_url": "https://api.github.com/users/migurski/followers",\r        "following_url": "https://api.github.com/users/migurski/following{/other_user}",\r        "gists_url": "https://api.github.com/users/migurski/gists{/gist_id}",\r        "starred_url": "https://api.github.com/users/migurski/starred{/owner}{/repo}",\r        "subscriptions_url": "https://api.github.com/users/migurski/subscriptions",\r        "organizations_url": "https://api.github.com/users/migurski/orgs",\r        "repos_url": "https://api.github.com/users/migurski/repos",\r        "events_url": "https://api.github.com/users/migurski/events{/privacy}",\r        "received_events_url": "https://api.github.com/users/migurski/received_events",\r        "type": "User",\r        "site_admin": false\r      },\r      "parents": [\r        {\r          "sha": "b659130053b85cd3993b1a4653da1bf6231ec0b4",\r          "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/b659130053b85cd3993b1a4653da1bf6231ec0b4",\r          "html_url": "https://github.com/openaddresses/hooked-on-sources/commit/b659130053b85cd3993b1a4653da1bf6231ec0b4"\r        }\r      ]\r    },\r    {\r      "sha": "e5f1dcae83ab1ef1f736b969da617311f7f11564",\r      "commit": {\r        "author": {\r          "name": "Michal Migurski",\r          "email": "mike@teczno.com",\r          "date": "2015-04-26T00:52:46Z"\r        },\r        "committer": {\r          "name": "Michal Migurski",\r          "email": "mike@teczno.com",\r          "date": "2015-04-26T00:52:46Z"\r        },\r        "message": "Removed Polish source",\r        "tree": {\r          "sha": "f0cd9b347f69397fcc79fcc434f077bf19af9520",\r          "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/trees/f0cd9b347f69397fcc79fcc434f077bf19af9520"\r        },\r        "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/commits/e5f1dcae83ab1ef1f736b969da617311f7f11564",\r        "comment_count": 0\r      },\r      "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/e5f1dcae83ab1ef1f736b969da617311f7f11564",\r      "html_url": "https://github.com/openaddresses/hooked-on-sources/commit/e5f1dcae83ab1ef1f736b969da617311f7f11564",\r      "comments_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/e5f1dcae83ab1ef1f736b969da617311f7f11564/comments",\r      "author": {\r        "login": "migurski",\r        "id": 58730,\r        "avatar_url": "https://avatars.githubusercontent.com/u/58730?v=3",\r        "gravatar_id": "",\r        "url": "https://api.github.com/users/migurski",\r        "html_url": "https://github.com/migurski",\r        "followers_url": "https://api.github.com/users/migurski/followers",\r        "following_url": "https://api.github.com/users/migurski/following{/other_user}",\r        "gists_url": "https://api.github.com/users/migurski/gists{/gist_id}",\r        "starred_url": "https://api.github.com/users/migurski/starred{/owner}{/repo}",\r        "subscriptions_url": "https://api.github.com/users/migurski/subscriptions",\r        "organizations_url": "https://api.github.com/users/migurski/orgs",\r        "repos_url": "https://api.github.com/users/migurski/repos",\r        "events_url": "https://api.github.com/users/migurski/events{/privacy}",\r        "received_events_url": "https://api.github.com/users/migurski/received_events",\r        "type": "User",\r        "site_admin": false\r      },\r      "committer": {\r        "login": "migurski",\r        "id": 58730,\r        "avatar_url": "https://avatars.githubusercontent.com/u/58730?v=3",\r        "gravatar_id": "",\r        "url": "https://api.github.com/users/migurski",\r        "html_url": "https://github.com/migurski",\r        "followers_url": "https://api.github.com/users/migurski/followers",\r        "following_url": "https://api.github.com/users/migurski/following{/other_user}",\r        "gists_url": "https://api.github.com/users/migurski/gists{/gist_id}",\r        "starred_url": "https://api.github.com/users/migurski/starred{/owner}{/repo}",\r        "subscriptions_url": "https://api.github.com/users/migurski/subscriptions",\r        "organizations_url": "https://api.github.com/users/migurski/orgs",\r        "repos_url": "https://api.github.com/users/migurski/repos",\r        "events_url": "https://api.github.com/users/migurski/events{/privacy}",\r        "received_events_url": "https://api.github.com/users/migurski/received_events",\r        "type": "User",\r        "site_admin": false\r      },\r      "parents": [\r        {\r          "sha": "0cbd51b8f6044e98c919dcabf93e3f4e1d58c035",\r          "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/0cbd51b8f6044e98c919dcabf93e3f4e1d58c035",\r          "html_url": "https://github.com/openaddresses/hooked-on-sources/commit/0cbd51b8f6044e98c919dcabf93e3f4e1d58c035"\r        }\r      ]\r    }\r  ],\r  "files": [\r    {\r      "sha": "84abff13dba318189f1f4d5c1605478127ceff5c",\r      "filename": "sources/us-ca-santa_clara_county.json",\r      "status": "added",\r      "additions": 24,\r      "deletions": 0,\r      "changes": 24,\r      "blob_url": "https://github.com/openaddresses/hooked-on-sources/blob/e5f1dcae83ab1ef1f736b969da617311f7f11564/sources/us-ca-santa_clara_county.json",\r      "raw_url": "https://github.com/openaddresses/hooked-on-sources/raw/e5f1dcae83ab1ef1f736b969da617311f7f11564/sources/us-ca-santa_clara_county.json",\r      "contents_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/contents/sources/us-ca-santa_clara_county.json?ref=e5f1dcae83ab1ef1f736b969da617311f7f11564",\r      "patch": "@@ -0,0 +1,24 @@\\n+{\\n+    \\"coverage\\": {\\n+        \\"US Census\\": {\\"geoid\\": \\"06085\\", \\"name\\": \\"Santa Clara County\\", \\"state\\": \\"California\\"},\\n+        \\"country\\": \\"us\\",\\n+        \\"state\\": \\"ca\\",\\n+        \\"county\\": \\"Santa Clara\\"\\n+    },\\n+    \\"conform\\": {\\n+        \\"type\\": \\"shapefile\\",\\n+        \\"postcode\\": \\"ZIPCODE\\",\\n+        \\"city\\": \\"CITY\\",\\n+        \\"number\\": \\"HOUSENUMTE\\",\\n+        \\"merge\\": [\\"STREETNAME\\", \\"STREETTYPE\\"],\\n+        \\"street\\": \\"auto_street\\",\\n+        \\"lon\\": \\"x\\",\\n+        \\"lat\\": \\"y\\"\\n+    },\\n+    \\"attribution\\": \\"Santa Clara County\\",\\n+    \\"data\\": \\"https://github.com/datadesk/us-ca-santa_clara_county-gis-shp/blob/master/Q4_FY14_Address_Point.zip?raw=true\\",\\n+    \\"website\\": \\"https://sftp.sccgov.org/courier/web/1000@/wmLogin.html\\",\\n+    \\"type\\": \\"http\\",\\n+    \\"compression\\": \\"zip\\",\\n+    \\"note\\": \\"File download is behind a registration wall on government site so the zip was downloaded in November 2014 and uploaded to GitHub for public hosting.\\"\\n+}"\r    }\r  ]\r}'''
            return response(200, data.encode('utf8'), headers=response_headers)
        
        if MHP == ('GET', GH, '/repos/openaddresses/hooked-on-sources/compare/master...3147668047a0bec6d481c0e42995f7c5e5eac637'):
            data = '''{\r  "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/compare/master...3147668047a0bec6d481c0e42995f7c5e5eac637",\r  "html_url": "https://github.com/openaddresses/hooked-on-sources/compare/master...3147668047a0bec6d481c0e42995f7c5e5eac637",\r  "permalink_url": "https://github.com/openaddresses/hooked-on-sources/compare/openaddresses:3147668...openaddresses:3147668",\r  "diff_url": "https://github.com/openaddresses/hooked-on-sources/compare/master...3147668047a0bec6d481c0e42995f7c5e5eac637.diff",\r  "patch_url": "https://github.com/openaddresses/hooked-on-sources/compare/master...3147668047a0bec6d481c0e42995f7c5e5eac637.patch",\r  "base_commit": {\r    "sha": "3147668047a0bec6d481c0e42995f7c5e5eac637",\r    "commit": {\r      "author": {\r        "name": "Michal Migurski",\r        "email": "mike@teczno.com",\r        "date": "2015-04-27T01:36:22Z"\r      },\r      "committer": {\r        "name": "Michal Migurski",\r        "email": "mike@teczno.com",\r        "date": "2015-04-27T01:36:22Z"\r      },\r      "message": "Empty commit",\r      "tree": {\r        "sha": "f9e70a36019597c21c7a28bd16840588e6223a33",\r        "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/trees/f9e70a36019597c21c7a28bd16840588e6223a33"\r      },\r      "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/commits/3147668047a0bec6d481c0e42995f7c5e5eac637",\r      "comment_count": 0\r    },\r    "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/3147668047a0bec6d481c0e42995f7c5e5eac637",\r    "html_url": "https://github.com/openaddresses/hooked-on-sources/commit/3147668047a0bec6d481c0e42995f7c5e5eac637",\r    "comments_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/3147668047a0bec6d481c0e42995f7c5e5eac637/comments",\r    "author": {\r      "login": "migurski",\r      "id": 58730,\r      "avatar_url": "https://avatars.githubusercontent.com/u/58730?v=3",\r      "gravatar_id": "",\r      "url": "https://api.github.com/users/migurski",\r      "html_url": "https://github.com/migurski",\r      "followers_url": "https://api.github.com/users/migurski/followers",\r      "following_url": "https://api.github.com/users/migurski/following{/other_user}",\r      "gists_url": "https://api.github.com/users/migurski/gists{/gist_id}",\r      "starred_url": "https://api.github.com/users/migurski/starred{/owner}{/repo}",\r      "subscriptions_url": "https://api.github.com/users/migurski/subscriptions",\r      "organizations_url": "https://api.github.com/users/migurski/orgs",\r      "repos_url": "https://api.github.com/users/migurski/repos",\r      "events_url": "https://api.github.com/users/migurski/events{/privacy}",\r      "received_events_url": "https://api.github.com/users/migurski/received_events",\r      "type": "User",\r      "site_admin": false\r    },\r    "committer": {\r      "login": "migurski",\r      "id": 58730,\r      "avatar_url": "https://avatars.githubusercontent.com/u/58730?v=3",\r      "gravatar_id": "",\r      "url": "https://api.github.com/users/migurski",\r      "html_url": "https://github.com/migurski",\r      "followers_url": "https://api.github.com/users/migurski/followers",\r      "following_url": "https://api.github.com/users/migurski/following{/other_user}",\r      "gists_url": "https://api.github.com/users/migurski/gists{/gist_id}",\r      "starred_url": "https://api.github.com/users/migurski/starred{/owner}{/repo}",\r      "subscriptions_url": "https://api.github.com/users/migurski/subscriptions",\r      "organizations_url": "https://api.github.com/users/migurski/orgs",\r      "repos_url": "https://api.github.com/users/migurski/repos",\r      "events_url": "https://api.github.com/users/migurski/events{/privacy}",\r      "received_events_url": "https://api.github.com/users/migurski/received_events",\r      "type": "User",\r      "site_admin": false\r    },\r    "parents": [\r      {\r        "sha": "b450dcbb6f4c61015b0a00290e984849f7d649de",\r        "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/b450dcbb6f4c61015b0a00290e984849f7d649de",\r        "html_url": "https://github.com/openaddresses/hooked-on-sources/commit/b450dcbb6f4c61015b0a00290e984849f7d649de"\r      }\r    ]\r  },\r  "merge_base_commit": {\r    "sha": "3147668047a0bec6d481c0e42995f7c5e5eac637",\r    "commit": {\r      "author": {\r        "name": "Michal Migurski",\r        "email": "mike@teczno.com",\r        "date": "2015-04-27T01:36:22Z"\r      },\r      "committer": {\r        "name": "Michal Migurski",\r        "email": "mike@teczno.com",\r        "date": "2015-04-27T01:36:22Z"\r      },\r      "message": "Empty commit",\r      "tree": {\r        "sha": "f9e70a36019597c21c7a28bd16840588e6223a33",\r        "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/trees/f9e70a36019597c21c7a28bd16840588e6223a33"\r      },\r      "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/commits/3147668047a0bec6d481c0e42995f7c5e5eac637",\r      "comment_count": 0\r    },\r    "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/3147668047a0bec6d481c0e42995f7c5e5eac637",\r    "html_url": "https://github.com/openaddresses/hooked-on-sources/commit/3147668047a0bec6d481c0e42995f7c5e5eac637",\r    "comments_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/3147668047a0bec6d481c0e42995f7c5e5eac637/comments",\r    "author": {\r      "login": "migurski",\r      "id": 58730,\r      "avatar_url": "https://avatars.githubusercontent.com/u/58730?v=3",\r      "gravatar_id": "",\r      "url": "https://api.github.com/users/migurski",\r      "html_url": "https://github.com/migurski",\r      "followers_url": "https://api.github.com/users/migurski/followers",\r      "following_url": "https://api.github.com/users/migurski/following{/other_user}",\r      "gists_url": "https://api.github.com/users/migurski/gists{/gist_id}",\r      "starred_url": "https://api.github.com/users/migurski/starred{/owner}{/repo}",\r      "subscriptions_url": "https://api.github.com/users/migurski/subscriptions",\r      "organizations_url": "https://api.github.com/users/migurski/orgs",\r      "repos_url": "https://api.github.com/users/migurski/repos",\r      "events_url": "https://api.github.com/users/migurski/events{/privacy}",\r      "received_events_url": "https://api.github.com/users/migurski/received_events",\r      "type": "User",\r      "site_admin": false\r    },\r    "committer": {\r      "login": "migurski",\r      "id": 58730,\r      "avatar_url": "https://avatars.githubusercontent.com/u/58730?v=3",\r      "gravatar_id": "",\r      "url": "https://api.github.com/users/migurski",\r      "html_url": "https://github.com/migurski",\r      "followers_url": "https://api.github.com/users/migurski/followers",\r      "following_url": "https://api.github.com/users/migurski/following{/other_user}",\r      "gists_url": "https://api.github.com/users/migurski/gists{/gist_id}",\r      "starred_url": "https://api.github.com/users/migurski/starred{/owner}{/repo}",\r      "subscriptions_url": "https://api.github.com/users/migurski/subscriptions",\r      "organizations_url": "https://api.github.com/users/migurski/orgs",\r      "repos_url": "https://api.github.com/users/migurski/repos",\r      "events_url": "https://api.github.com/users/migurski/events{/privacy}",\r      "received_events_url": "https://api.github.com/users/migurski/received_events",\r      "type": "User",\r      "site_admin": false\r    },\r    "parents": [\r      {\r        "sha": "b450dcbb6f4c61015b0a00290e984849f7d649de",\r        "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/b450dcbb6f4c61015b0a00290e984849f7d649de",\r        "html_url": "https://github.com/openaddresses/hooked-on-sources/commit/b450dcbb6f4c61015b0a00290e984849f7d649de"\r      }\r    ]\r  },\r  "status": "identical",\r  "ahead_by": 0,\r  "behind_by": 0,\r  "total_commits": 0,\r  "commits": [\r\r  ],\r  "files": [\r\r  ]\r}'''
            return response(200, data.encode('utf8'), headers=response_headers)
        
        if MHP == ('GET', GH, '/repos/openaddresses/hooked-on-sources/compare/master...badjson20f08890960f50f863626e1062f922522'):
            data = '''{\r              "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/compare/master...badjson20f08890960f50f863626e1062f922522",\r              "html_url": "https://github.com/openaddresses/hooked-on-sources/compare/master...badjson20f08890960f50f863626e1062f922522",\r              "permalink_url": "https://github.com/openaddresses/hooked-on-sources/compare/openaddresses:ded44ed...openaddresses:e91fbc4",\r              "diff_url": "https://github.com/openaddresses/hooked-on-sources/compare/master...badjson20f08890960f50f863626e1062f922522.diff",\r              "patch_url": "https://github.com/openaddresses/hooked-on-sources/compare/master...badjson20f08890960f50f863626e1062f922522.patch",\r              "base_commit": {\r                "sha": "ded44ed5f1733bb93d84f94afe9383e2d47bbbaa",\r                "commit": {\r                  "author": {\r                    "name": "Michal Migurski",\r                    "email": "mike@teczno.com",\r                    "date": "2015-04-26T00:25:55Z"\r                  },\r                  "committer": {\r                    "name": "Michal Migurski",\r                    "email": "mike@teczno.com",\r                    "date": "2015-04-26T00:25:55Z"\r                  },\r                  "message": "Added Berkeley",\r                  "tree": {\r                    "sha": "9d6ac64ea358034e23fba121f3833790f47b5d76",\r                    "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/trees/9d6ac64ea358034e23fba121f3833790f47b5d76"\r                  },\r                  "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/commits/ded44ed5f1733bb93d84f94afe9383e2d47bbbaa",\r                  "comment_count": 0\r                },\r                "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/ded44ed5f1733bb93d84f94afe9383e2d47bbbaa",\r                "html_url": "https://github.com/openaddresses/hooked-on-sources/commit/ded44ed5f1733bb93d84f94afe9383e2d47bbbaa",\r                "comments_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/ded44ed5f1733bb93d84f94afe9383e2d47bbbaa/comments",\r                "author": {\r                  "login": "migurski",\r                  "id": 58730,\r                  "avatar_url": "https://avatars.githubusercontent.com/u/58730?v=3",\r                  "gravatar_id": "",\r                  "url": "https://api.github.com/users/migurski",\r                  "html_url": "https://github.com/migurski",\r                  "followers_url": "https://api.github.com/users/migurski/followers",\r                  "following_url": "https://api.github.com/users/migurski/following{/other_user}",\r                  "gists_url": "https://api.github.com/users/migurski/gists{/gist_id}",\r                  "starred_url": "https://api.github.com/users/migurski/starred{/owner}{/repo}",\r                  "subscriptions_url": "https://api.github.com/users/migurski/subscriptions",\r                  "organizations_url": "https://api.github.com/users/migurski/orgs",\r                  "repos_url": "https://api.github.com/users/migurski/repos",\r                  "events_url": "https://api.github.com/users/migurski/events{/privacy}",\r                  "received_events_url": "https://api.github.com/users/migurski/received_events",\r                  "type": "User",\r                  "site_admin": false\r                },\r                "committer": {\r                  "login": "migurski",\r                  "id": 58730,\r                  "avatar_url": "https://avatars.githubusercontent.com/u/58730?v=3",\r                  "gravatar_id": "",\r                  "url": "https://api.github.com/users/migurski",\r                  "html_url": "https://github.com/migurski",\r                  "followers_url": "https://api.github.com/users/migurski/followers",\r                  "following_url": "https://api.github.com/users/migurski/following{/other_user}",\r                  "gists_url": "https://api.github.com/users/migurski/gists{/gist_id}",\r                  "starred_url": "https://api.github.com/users/migurski/starred{/owner}{/repo}",\r                  "subscriptions_url": "https://api.github.com/users/migurski/subscriptions",\r                  "organizations_url": "https://api.github.com/users/migurski/orgs",\r                  "repos_url": "https://api.github.com/users/migurski/repos",\r                  "events_url": "https://api.github.com/users/migurski/events{/privacy}",\r                  "received_events_url": "https://api.github.com/users/migurski/received_events",\r                  "type": "User",\r                  "site_admin": false\r                },\r                "parents": [\r                  {\r                    "sha": "73a81c5b337bd393273a222f1cd191d7e634df51",\r                    "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/73a81c5b337bd393273a222f1cd191d7e634df51",\r                    "html_url": "https://github.com/openaddresses/hooked-on-sources/commit/73a81c5b337bd393273a222f1cd191d7e634df51"\r                  }\r                ]\r              },\r              "merge_base_commit": {\r                "sha": "badjson20f08890960f50f863626e1062f922522",\r                "commit": {\r                  "author": {\r                    "name": "Michal Migurski",\r                    "email": "mike@teczno.com",\r                    "date": "2015-04-26T00:16:12Z"\r                  },\r                  "committer": {\r                    "name": "Michal Migurski",\r                    "email": "mike@teczno.com",\r                    "date": "2015-04-26T00:16:12Z"\r                  },\r                  "message": "Added first source",\r                  "tree": {\r                    "sha": "f5e85249cee39d0e84ed936d31a9c08c1eaaa539",\r                    "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/trees/f5e85249cee39d0e84ed936d31a9c08c1eaaa539"\r                  },\r                  "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/commits/badjson20f08890960f50f863626e1062f922522",\r                  "comment_count": 0\r                },\r                "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/badjson20f08890960f50f863626e1062f922522",\r                "html_url": "https://github.com/openaddresses/hooked-on-sources/commit/badjson20f08890960f50f863626e1062f922522",\r                "comments_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/badjson20f08890960f50f863626e1062f922522/comments",\r                "author": {\r                  "login": "migurski",\r                  "id": 58730,\r                  "avatar_url": "https://avatars.githubusercontent.com/u/58730?v=3",\r                  "gravatar_id": "",\r                  "url": "https://api.github.com/users/migurski",\r                  "html_url": "https://github.com/migurski",\r                  "followers_url": "https://api.github.com/users/migurski/followers",\r                  "following_url": "https://api.github.com/users/migurski/following{/other_user}",\r                  "gists_url": "https://api.github.com/users/migurski/gists{/gist_id}",\r                  "starred_url": "https://api.github.com/users/migurski/starred{/owner}{/repo}",\r                  "subscriptions_url": "https://api.github.com/users/migurski/subscriptions",\r                  "organizations_url": "https://api.github.com/users/migurski/orgs",\r                  "repos_url": "https://api.github.com/users/migurski/repos",\r                  "events_url": "https://api.github.com/users/migurski/events{/privacy}",\r                  "received_events_url": "https://api.github.com/users/migurski/received_events",\r                  "type": "User",\r                  "site_admin": false\r                },\r                "committer": {\r                  "login": "migurski",\r                  "id": 58730,\r                  "avatar_url": "https://avatars.githubusercontent.com/u/58730?v=3",\r                  "gravatar_id": "",\r                  "url": "https://api.github.com/users/migurski",\r                  "html_url": "https://github.com/migurski",\r                  "followers_url": "https://api.github.com/users/migurski/followers",\r                  "following_url": "https://api.github.com/users/migurski/following{/other_user}",\r                  "gists_url": "https://api.github.com/users/migurski/gists{/gist_id}",\r                  "starred_url": "https://api.github.com/users/migurski/starred{/owner}{/repo}",\r                  "subscriptions_url": "https://api.github.com/users/migurski/subscriptions",\r                  "organizations_url": "https://api.github.com/users/migurski/orgs",\r                  "repos_url": "https://api.github.com/users/migurski/repos",\r                  "events_url": "https://api.github.com/users/migurski/events{/privacy}",\r                  "received_events_url": "https://api.github.com/users/migurski/received_events",\r                  "type": "User",\r                  "site_admin": false\r                },\r                "parents": [\r                  {\r                    "sha": "c52204fd40f17f9da243df09e6d1107d48768afd",\r                    "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/c52204fd40f17f9da243df09e6d1107d48768afd",\r                    "html_url": "https://github.com/openaddresses/hooked-on-sources/commit/c52204fd40f17f9da243df09e6d1107d48768afd"\r                  }\r                ]\r              },\r              "status": "behind",\r              "ahead_by": 0,\r              "behind_by": 2,\r              "total_commits": 0,\r              "commits": [\r\r              ],\r              "files": [\r\r              ]\r            }'''
            return response(200, data.encode('utf8'), headers=response_headers)
        
        if MHP == ('GET', GH, '/repos/openaddresses/hooked-on-sources/compare/master...badutf820f08890960f50f863626e1062f922522'):
            data = '''{\r              "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/compare/master...badutf820f08890960f50f863626e1062f922522",\r              "html_url": "https://github.com/openaddresses/hooked-on-sources/compare/master...badutf820f08890960f50f863626e1062f922522",\r              "permalink_url": "https://github.com/openaddresses/hooked-on-sources/compare/openaddresses:ded44ed...openaddresses:e91fbc4",\r              "diff_url": "https://github.com/openaddresses/hooked-on-sources/compare/master...badutf820f08890960f50f863626e1062f922522.diff",\r              "patch_url": "https://github.com/openaddresses/hooked-on-sources/compare/master...badutf820f08890960f50f863626e1062f922522.patch",\r              "base_commit": {\r                "sha": "ded44ed5f1733bb93d84f94afe9383e2d47bbbaa",\r                "commit": {\r                  "author": {\r                    "name": "Michal Migurski",\r                    "email": "mike@teczno.com",\r                    "date": "2015-04-26T00:25:55Z"\r                  },\r                  "committer": {\r                    "name": "Michal Migurski",\r                    "email": "mike@teczno.com",\r                    "date": "2015-04-26T00:25:55Z"\r                  },\r                  "message": "Added Berkeley",\r                  "tree": {\r                    "sha": "9d6ac64ea358034e23fba121f3833790f47b5d76",\r                    "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/trees/9d6ac64ea358034e23fba121f3833790f47b5d76"\r                  },\r                  "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/commits/ded44ed5f1733bb93d84f94afe9383e2d47bbbaa",\r                  "comment_count": 0\r                },\r                "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/ded44ed5f1733bb93d84f94afe9383e2d47bbbaa",\r                "html_url": "https://github.com/openaddresses/hooked-on-sources/commit/ded44ed5f1733bb93d84f94afe9383e2d47bbbaa",\r                "comments_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/ded44ed5f1733bb93d84f94afe9383e2d47bbbaa/comments",\r                "author": {\r                  "login": "migurski",\r                  "id": 58730,\r                  "avatar_url": "https://avatars.githubusercontent.com/u/58730?v=3",\r                  "gravatar_id": "",\r                  "url": "https://api.github.com/users/migurski",\r                  "html_url": "https://github.com/migurski",\r                  "followers_url": "https://api.github.com/users/migurski/followers",\r                  "following_url": "https://api.github.com/users/migurski/following{/other_user}",\r                  "gists_url": "https://api.github.com/users/migurski/gists{/gist_id}",\r                  "starred_url": "https://api.github.com/users/migurski/starred{/owner}{/repo}",\r                  "subscriptions_url": "https://api.github.com/users/migurski/subscriptions",\r                  "organizations_url": "https://api.github.com/users/migurski/orgs",\r                  "repos_url": "https://api.github.com/users/migurski/repos",\r                  "events_url": "https://api.github.com/users/migurski/events{/privacy}",\r                  "received_events_url": "https://api.github.com/users/migurski/received_events",\r                  "type": "User",\r                  "site_admin": false\r                },\r                "committer": {\r                  "login": "migurski",\r                  "id": 58730,\r                  "avatar_url": "https://avatars.githubusercontent.com/u/58730?v=3",\r                  "gravatar_id": "",\r                  "url": "https://api.github.com/users/migurski",\r                  "html_url": "https://github.com/migurski",\r                  "followers_url": "https://api.github.com/users/migurski/followers",\r                  "following_url": "https://api.github.com/users/migurski/following{/other_user}",\r                  "gists_url": "https://api.github.com/users/migurski/gists{/gist_id}",\r                  "starred_url": "https://api.github.com/users/migurski/starred{/owner}{/repo}",\r                  "subscriptions_url": "https://api.github.com/users/migurski/subscriptions",\r                  "organizations_url": "https://api.github.com/users/migurski/orgs",\r                  "repos_url": "https://api.github.com/users/migurski/repos",\r                  "events_url": "https://api.github.com/users/migurski/events{/privacy}",\r                  "received_events_url": "https://api.github.com/users/migurski/received_events",\r                  "type": "User",\r                  "site_admin": false\r                },\r                "parents": [\r                  {\r                    "sha": "73a81c5b337bd393273a222f1cd191d7e634df51",\r                    "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/73a81c5b337bd393273a222f1cd191d7e634df51",\r                    "html_url": "https://github.com/openaddresses/hooked-on-sources/commit/73a81c5b337bd393273a222f1cd191d7e634df51"\r                  }\r                ]\r              },\r              "merge_base_commit": {\r                "sha": "badutf820f08890960f50f863626e1062f922522",\r                "commit": {\r                  "author": {\r                    "name": "Michal Migurski",\r                    "email": "mike@teczno.com",\r                    "date": "2015-04-26T00:16:12Z"\r                  },\r                  "committer": {\r                    "name": "Michal Migurski",\r                    "email": "mike@teczno.com",\r                    "date": "2015-04-26T00:16:12Z"\r                  },\r                  "message": "Added first source",\r                  "tree": {\r                    "sha": "f5e85249cee39d0e84ed936d31a9c08c1eaaa539",\r                    "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/trees/f5e85249cee39d0e84ed936d31a9c08c1eaaa539"\r                  },\r                  "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/commits/badutf820f08890960f50f863626e1062f922522",\r                  "comment_count": 0\r                },\r                "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/badutf820f08890960f50f863626e1062f922522",\r                "html_url": "https://github.com/openaddresses/hooked-on-sources/commit/badutf820f08890960f50f863626e1062f922522",\r                "comments_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/badutf820f08890960f50f863626e1062f922522/comments",\r                "author": {\r                  "login": "migurski",\r                  "id": 58730,\r                  "avatar_url": "https://avatars.githubusercontent.com/u/58730?v=3",\r                  "gravatar_id": "",\r                  "url": "https://api.github.com/users/migurski",\r                  "html_url": "https://github.com/migurski",\r                  "followers_url": "https://api.github.com/users/migurski/followers",\r                  "following_url": "https://api.github.com/users/migurski/following{/other_user}",\r                  "gists_url": "https://api.github.com/users/migurski/gists{/gist_id}",\r                  "starred_url": "https://api.github.com/users/migurski/starred{/owner}{/repo}",\r                  "subscriptions_url": "https://api.github.com/users/migurski/subscriptions",\r                  "organizations_url": "https://api.github.com/users/migurski/orgs",\r                  "repos_url": "https://api.github.com/users/migurski/repos",\r                  "events_url": "https://api.github.com/users/migurski/events{/privacy}",\r                  "received_events_url": "https://api.github.com/users/migurski/received_events",\r                  "type": "User",\r                  "site_admin": false\r                },\r                "committer": {\r                  "login": "migurski",\r                  "id": 58730,\r                  "avatar_url": "https://avatars.githubusercontent.com/u/58730?v=3",\r                  "gravatar_id": "",\r                  "url": "https://api.github.com/users/migurski",\r                  "html_url": "https://github.com/migurski",\r                  "followers_url": "https://api.github.com/users/migurski/followers",\r                  "following_url": "https://api.github.com/users/migurski/following{/other_user}",\r                  "gists_url": "https://api.github.com/users/migurski/gists{/gist_id}",\r                  "starred_url": "https://api.github.com/users/migurski/starred{/owner}{/repo}",\r                  "subscriptions_url": "https://api.github.com/users/migurski/subscriptions",\r                  "organizations_url": "https://api.github.com/users/migurski/orgs",\r                  "repos_url": "https://api.github.com/users/migurski/repos",\r                  "events_url": "https://api.github.com/users/migurski/events{/privacy}",\r                  "received_events_url": "https://api.github.com/users/migurski/received_events",\r                  "type": "User",\r                  "site_admin": false\r                },\r                "parents": [\r                  {\r                    "sha": "c52204fd40f17f9da243df09e6d1107d48768afd",\r                    "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits/c52204fd40f17f9da243df09e6d1107d48768afd",\r                    "html_url": "https://github.com/openaddresses/hooked-on-sources/commit/c52204fd40f17f9da243df09e6d1107d48768afd"\r                  }\r                ]\r              },\r              "status": "behind",\r              "ahead_by": 0,\r              "behind_by": 2,\r              "total_commits": 0,\r              "commits": [\r\r              ],\r              "files": [\r\r              ]\r            }'''
            return response(200, data.encode('utf8'), headers=response_headers)
        
        if MHP == ('GET', GH, '/repos/daguar/openaddresses/compare/97922c724541b0446ea2c022f9f200b9989f1a75...f85074d543622ef1fac7a80a059a50176f2a6e08'):
            data = '''{\r  "url": "https://api.github.com/repos/daguar/openaddresses/compare/97922c724541b0446ea2c022f9f200b9989f1a75...f85074d543622ef1fac7a80a059a50176f2a6e08",\r  "html_url": "https://github.com/daguar/openaddresses/compare/97922c724541b0446ea2c022f9f200b9989f1a75...f85074d543622ef1fac7a80a059a50176f2a6e08",\r  "permalink_url": "https://github.com/daguar/openaddresses/compare/daguar:97922c7...daguar:f85074d",\r  "diff_url": "https://github.com/daguar/openaddresses/compare/97922c724541b0446ea2c022f9f200b9989f1a75...f85074d543622ef1fac7a80a059a50176f2a6e08.diff",\r  "patch_url": "https://github.com/daguar/openaddresses/compare/97922c724541b0446ea2c022f9f200b9989f1a75...f85074d543622ef1fac7a80a059a50176f2a6e08.patch",\r  "base_commit": {\r    "sha": "97922c724541b0446ea2c022f9f200b9989f1a75",\r    "commit": {\r      "author": {\r        "name": "Ian Dees",\r        "email": "ian.dees@gmail.com",\r        "date": "2015-06-17T14:02:23Z"\r      },\r      "committer": {\r        "name": "Ian Dees",\r        "email": "ian.dees@gmail.com",\r        "date": "2015-06-17T14:02:23Z"\r      },\r      "message": "Merge pull request #1033 from openaddresses/s3\\n\\nUse s3 links",\r      "tree": {\r        "sha": "edb40a8c43a8668b30f50594cd0d8e42dad93dbc",\r        "url": "https://api.github.com/repos/daguar/openaddresses/git/trees/edb40a8c43a8668b30f50594cd0d8e42dad93dbc"\r      },\r      "url": "https://api.github.com/repos/daguar/openaddresses/git/commits/97922c724541b0446ea2c022f9f200b9989f1a75",\r      "comment_count": 0\r    },\r    "url": "https://api.github.com/repos/daguar/openaddresses/commits/97922c724541b0446ea2c022f9f200b9989f1a75",\r    "html_url": "https://github.com/daguar/openaddresses/commit/97922c724541b0446ea2c022f9f200b9989f1a75",\r    "comments_url": "https://api.github.com/repos/daguar/openaddresses/commits/97922c724541b0446ea2c022f9f200b9989f1a75/comments",\r    "author": {\r      "login": "iandees",\r      "id": 261584,\r      "avatar_url": "https://avatars.githubusercontent.com/u/261584?v=3",\r      "gravatar_id": "",\r      "url": "https://api.github.com/users/iandees",\r      "html_url": "https://github.com/iandees",\r      "followers_url": "https://api.github.com/users/iandees/followers",\r      "following_url": "https://api.github.com/users/iandees/following{/other_user}",\r      "gists_url": "https://api.github.com/users/iandees/gists{/gist_id}",\r      "starred_url": "https://api.github.com/users/iandees/starred{/owner}{/repo}",\r      "subscriptions_url": "https://api.github.com/users/iandees/subscriptions",\r      "organizations_url": "https://api.github.com/users/iandees/orgs",\r      "repos_url": "https://api.github.com/users/iandees/repos",\r      "events_url": "https://api.github.com/users/iandees/events{/privacy}",\r      "received_events_url": "https://api.github.com/users/iandees/received_events",\r      "type": "User",\r      "site_admin": false\r    },\r    "committer": {\r      "login": "iandees",\r      "id": 261584,\r      "avatar_url": "https://avatars.githubusercontent.com/u/261584?v=3",\r      "gravatar_id": "",\r      "url": "https://api.github.com/users/iandees",\r      "html_url": "https://github.com/iandees",\r      "followers_url": "https://api.github.com/users/iandees/followers",\r      "following_url": "https://api.github.com/users/iandees/following{/other_user}",\r      "gists_url": "https://api.github.com/users/iandees/gists{/gist_id}",\r      "starred_url": "https://api.github.com/users/iandees/starred{/owner}{/repo}",\r      "subscriptions_url": "https://api.github.com/users/iandees/subscriptions",\r      "organizations_url": "https://api.github.com/users/iandees/orgs",\r      "repos_url": "https://api.github.com/users/iandees/repos",\r      "events_url": "https://api.github.com/users/iandees/events{/privacy}",\r      "received_events_url": "https://api.github.com/users/iandees/received_events",\r      "type": "User",\r      "site_admin": false\r    },\r    "parents": [\r      {\r        "sha": "de49ae99caa9759dbe08e1aaa892e8bf72079fee",\r        "url": "https://api.github.com/repos/daguar/openaddresses/commits/de49ae99caa9759dbe08e1aaa892e8bf72079fee",\r        "html_url": "https://github.com/daguar/openaddresses/commit/de49ae99caa9759dbe08e1aaa892e8bf72079fee"\r      },\r      {\r        "sha": "3b80e6c555deb08a0a86251216c50106ed9a10b7",\r        "url": "https://api.github.com/repos/daguar/openaddresses/commits/3b80e6c555deb08a0a86251216c50106ed9a10b7",\r        "html_url": "https://github.com/daguar/openaddresses/commit/3b80e6c555deb08a0a86251216c50106ed9a10b7"\r      }\r    ]\r  },\r  "merge_base_commit": {\r    "sha": "97922c724541b0446ea2c022f9f200b9989f1a75",\r    "commit": {\r      "author": {\r        "name": "Ian Dees",\r        "email": "ian.dees@gmail.com",\r        "date": "2015-06-17T14:02:23Z"\r      },\r      "committer": {\r        "name": "Ian Dees",\r        "email": "ian.dees@gmail.com",\r        "date": "2015-06-17T14:02:23Z"\r      },\r      "message": "Merge pull request #1033 from openaddresses/s3\\n\\nUse s3 links",\r      "tree": {\r        "sha": "edb40a8c43a8668b30f50594cd0d8e42dad93dbc",\r        "url": "https://api.github.com/repos/daguar/openaddresses/git/trees/edb40a8c43a8668b30f50594cd0d8e42dad93dbc"\r      },\r      "url": "https://api.github.com/repos/daguar/openaddresses/git/commits/97922c724541b0446ea2c022f9f200b9989f1a75",\r      "comment_count": 0\r    },\r    "url": "https://api.github.com/repos/daguar/openaddresses/commits/97922c724541b0446ea2c022f9f200b9989f1a75",\r    "html_url": "https://github.com/daguar/openaddresses/commit/97922c724541b0446ea2c022f9f200b9989f1a75",\r    "comments_url": "https://api.github.com/repos/daguar/openaddresses/commits/97922c724541b0446ea2c022f9f200b9989f1a75/comments",\r    "author": {\r      "login": "iandees",\r      "id": 261584,\r      "avatar_url": "https://avatars.githubusercontent.com/u/261584?v=3",\r      "gravatar_id": "",\r      "url": "https://api.github.com/users/iandees",\r      "html_url": "https://github.com/iandees",\r      "followers_url": "https://api.github.com/users/iandees/followers",\r      "following_url": "https://api.github.com/users/iandees/following{/other_user}",\r      "gists_url": "https://api.github.com/users/iandees/gists{/gist_id}",\r      "starred_url": "https://api.github.com/users/iandees/starred{/owner}{/repo}",\r      "subscriptions_url": "https://api.github.com/users/iandees/subscriptions",\r      "organizations_url": "https://api.github.com/users/iandees/orgs",\r      "repos_url": "https://api.github.com/users/iandees/repos",\r      "events_url": "https://api.github.com/users/iandees/events{/privacy}",\r      "received_events_url": "https://api.github.com/users/iandees/received_events",\r      "type": "User",\r      "site_admin": false\r    },\r    "committer": {\r      "login": "iandees",\r      "id": 261584,\r      "avatar_url": "https://avatars.githubusercontent.com/u/261584?v=3",\r      "gravatar_id": "",\r      "url": "https://api.github.com/users/iandees",\r      "html_url": "https://github.com/iandees",\r      "followers_url": "https://api.github.com/users/iandees/followers",\r      "following_url": "https://api.github.com/users/iandees/following{/other_user}",\r      "gists_url": "https://api.github.com/users/iandees/gists{/gist_id}",\r      "starred_url": "https://api.github.com/users/iandees/starred{/owner}{/repo}",\r      "subscriptions_url": "https://api.github.com/users/iandees/subscriptions",\r      "organizations_url": "https://api.github.com/users/iandees/orgs",\r      "repos_url": "https://api.github.com/users/iandees/repos",\r      "events_url": "https://api.github.com/users/iandees/events{/privacy}",\r      "received_events_url": "https://api.github.com/users/iandees/received_events",\r      "type": "User",\r      "site_admin": false\r    },\r    "parents": [\r      {\r        "sha": "de49ae99caa9759dbe08e1aaa892e8bf72079fee",\r        "url": "https://api.github.com/repos/daguar/openaddresses/commits/de49ae99caa9759dbe08e1aaa892e8bf72079fee",\r        "html_url": "https://github.com/daguar/openaddresses/commit/de49ae99caa9759dbe08e1aaa892e8bf72079fee"\r      },\r      {\r        "sha": "3b80e6c555deb08a0a86251216c50106ed9a10b7",\r        "url": "https://api.github.com/repos/daguar/openaddresses/commits/3b80e6c555deb08a0a86251216c50106ed9a10b7",\r        "html_url": "https://github.com/daguar/openaddresses/commit/3b80e6c555deb08a0a86251216c50106ed9a10b7"\r      }\r    ]\r  },\r  "status": "ahead",\r  "ahead_by": 2,\r  "behind_by": 0,\r  "total_commits": 2,\r  "commits": [\r    {\r      "sha": "e1af73800eb25192099c4b1dd75bf0fbec3657fd",\r      "commit": {\r        "author": {\r          "name": "Dave Guarino",\r          "email": "dave@codeforamerica.org",\r          "date": "2015-06-21T19:45:12Z"\r        },\r        "committer": {\r          "name": "Dave Guarino",\r          "email": "dave@codeforamerica.org",\r          "date": "2015-06-21T19:45:12Z"\r        },\r        "message": "Update San Diego County coverage (rename as county, update as county, add source details)",\r        "tree": {\r          "sha": "adbabad72436d3082dbc32f4976ade5ad4e18966",\r          "url": "https://api.github.com/repos/daguar/openaddresses/git/trees/adbabad72436d3082dbc32f4976ade5ad4e18966"\r        },\r        "url": "https://api.github.com/repos/daguar/openaddresses/git/commits/e1af73800eb25192099c4b1dd75bf0fbec3657fd",\r        "comment_count": 0\r      },\r      "url": "https://api.github.com/repos/daguar/openaddresses/commits/e1af73800eb25192099c4b1dd75bf0fbec3657fd",\r      "html_url": "https://github.com/daguar/openaddresses/commit/e1af73800eb25192099c4b1dd75bf0fbec3657fd",\r      "comments_url": "https://api.github.com/repos/daguar/openaddresses/commits/e1af73800eb25192099c4b1dd75bf0fbec3657fd/comments",\r      "author": {\r        "login": "daguar",\r        "id": 994938,\r        "avatar_url": "https://avatars.githubusercontent.com/u/994938?v=3",\r        "gravatar_id": "",\r        "url": "https://api.github.com/users/daguar",\r        "html_url": "https://github.com/daguar",\r        "followers_url": "https://api.github.com/users/daguar/followers",\r        "following_url": "https://api.github.com/users/daguar/following{/other_user}",\r        "gists_url": "https://api.github.com/users/daguar/gists{/gist_id}",\r        "starred_url": "https://api.github.com/users/daguar/starred{/owner}{/repo}",\r        "subscriptions_url": "https://api.github.com/users/daguar/subscriptions",\r        "organizations_url": "https://api.github.com/users/daguar/orgs",\r        "repos_url": "https://api.github.com/users/daguar/repos",\r        "events_url": "https://api.github.com/users/daguar/events{/privacy}",\r        "received_events_url": "https://api.github.com/users/daguar/received_events",\r        "type": "User",\r        "site_admin": false\r      },\r      "committer": {\r        "login": "daguar",\r        "id": 994938,\r        "avatar_url": "https://avatars.githubusercontent.com/u/994938?v=3",\r        "gravatar_id": "",\r        "url": "https://api.github.com/users/daguar",\r        "html_url": "https://github.com/daguar",\r        "followers_url": "https://api.github.com/users/daguar/followers",\r        "following_url": "https://api.github.com/users/daguar/following{/other_user}",\r        "gists_url": "https://api.github.com/users/daguar/gists{/gist_id}",\r        "starred_url": "https://api.github.com/users/daguar/starred{/owner}{/repo}",\r        "subscriptions_url": "https://api.github.com/users/daguar/subscriptions",\r        "organizations_url": "https://api.github.com/users/daguar/orgs",\r        "repos_url": "https://api.github.com/users/daguar/repos",\r        "events_url": "https://api.github.com/users/daguar/events{/privacy}",\r        "received_events_url": "https://api.github.com/users/daguar/received_events",\r        "type": "User",\r        "site_admin": false\r      },\r      "parents": [\r        {\r          "sha": "97922c724541b0446ea2c022f9f200b9989f1a75",\r          "url": "https://api.github.com/repos/daguar/openaddresses/commits/97922c724541b0446ea2c022f9f200b9989f1a75",\r          "html_url": "https://github.com/daguar/openaddresses/commit/97922c724541b0446ea2c022f9f200b9989f1a75"\r        }\r      ]\r    },\r    {\r      "sha": "f85074d543622ef1fac7a80a059a50176f2a6e08",\r      "commit": {\r        "author": {\r          "name": "Dave Guarino",\r          "email": "dave@codeforamerica.org",\r          "date": "2015-06-21T20:07:58Z"\r        },\r        "committer": {\r          "name": "Dave Guarino",\r          "email": "dave@codeforamerica.org",\r          "date": "2015-06-21T20:07:58Z"\r        },\r        "message": "Fix San Diego County changes (key should be 'note' not 'notes')",\r        "tree": {\r          "sha": "9e6d99108995a58503407c104338e36c76cbbfe3",\r          "url": "https://api.github.com/repos/daguar/openaddresses/git/trees/9e6d99108995a58503407c104338e36c76cbbfe3"\r        },\r        "url": "https://api.github.com/repos/daguar/openaddresses/git/commits/f85074d543622ef1fac7a80a059a50176f2a6e08",\r        "comment_count": 0\r      },\r      "url": "https://api.github.com/repos/daguar/openaddresses/commits/f85074d543622ef1fac7a80a059a50176f2a6e08",\r      "html_url": "https://github.com/daguar/openaddresses/commit/f85074d543622ef1fac7a80a059a50176f2a6e08",\r      "comments_url": "https://api.github.com/repos/daguar/openaddresses/commits/f85074d543622ef1fac7a80a059a50176f2a6e08/comments",\r      "author": {\r        "login": "daguar",\r        "id": 994938,\r        "avatar_url": "https://avatars.githubusercontent.com/u/994938?v=3",\r        "gravatar_id": "",\r        "url": "https://api.github.com/users/daguar",\r        "html_url": "https://github.com/daguar",\r        "followers_url": "https://api.github.com/users/daguar/followers",\r        "following_url": "https://api.github.com/users/daguar/following{/other_user}",\r        "gists_url": "https://api.github.com/users/daguar/gists{/gist_id}",\r        "starred_url": "https://api.github.com/users/daguar/starred{/owner}{/repo}",\r        "subscriptions_url": "https://api.github.com/users/daguar/subscriptions",\r        "organizations_url": "https://api.github.com/users/daguar/orgs",\r        "repos_url": "https://api.github.com/users/daguar/repos",\r        "events_url": "https://api.github.com/users/daguar/events{/privacy}",\r        "received_events_url": "https://api.github.com/users/daguar/received_events",\r        "type": "User",\r        "site_admin": false\r      },\r      "committer": {\r        "login": "daguar",\r        "id": 994938,\r        "avatar_url": "https://avatars.githubusercontent.com/u/994938?v=3",\r        "gravatar_id": "",\r        "url": "https://api.github.com/users/daguar",\r        "html_url": "https://github.com/daguar",\r        "followers_url": "https://api.github.com/users/daguar/followers",\r        "following_url": "https://api.github.com/users/daguar/following{/other_user}",\r        "gists_url": "https://api.github.com/users/daguar/gists{/gist_id}",\r        "starred_url": "https://api.github.com/users/daguar/starred{/owner}{/repo}",\r        "subscriptions_url": "https://api.github.com/users/daguar/subscriptions",\r        "organizations_url": "https://api.github.com/users/daguar/orgs",\r        "repos_url": "https://api.github.com/users/daguar/repos",\r        "events_url": "https://api.github.com/users/daguar/events{/privacy}",\r        "received_events_url": "https://api.github.com/users/daguar/received_events",\r        "type": "User",\r        "site_admin": false\r      },\r      "parents": [\r        {\r          "sha": "e1af73800eb25192099c4b1dd75bf0fbec3657fd",\r          "url": "https://api.github.com/repos/daguar/openaddresses/commits/e1af73800eb25192099c4b1dd75bf0fbec3657fd",\r          "html_url": "https://github.com/daguar/openaddresses/commit/e1af73800eb25192099c4b1dd75bf0fbec3657fd"\r        }\r      ]\r    }\r  ],\r  "files": [\r    {\r      "sha": "0c7cf2f3e4cb5f0c07818a029e1decc9797ad3a1",\r      "filename": "sources/us-ca-san_diego_county.json",\r      "status": "renamed",\r      "additions": 10,\r      "deletions": 3,\r      "changes": 13,\r      "blob_url": "https://github.com/daguar/openaddresses/blob/f85074d543622ef1fac7a80a059a50176f2a6e08/sources/us-ca-san_diego_county.json",\r      "raw_url": "https://github.com/daguar/openaddresses/raw/f85074d543622ef1fac7a80a059a50176f2a6e08/sources/us-ca-san_diego_county.json",\r      "contents_url": "https://api.github.com/repos/daguar/openaddresses/contents/sources/us-ca-san_diego_county.json?ref=f85074d543622ef1fac7a80a059a50176f2a6e08",\r      "patch": "@@ -1,12 +1,19 @@\\n {\\n     \\"coverage\\": {\\n+        \\"US Census\\": {\\n+          \\"geoid\\": \\"06073\\",\\n+          \\"name\\": \\"San Diego County\\",\\n+          \\"state\\": \\"California\\"\\n+        },\\n         \\"country\\": \\"us\\",\\n         \\"state\\": \\"ca\\",\\n-        \\"city\\": \\"San Diego\\"\\n+        \\"county\\": \\"San Diego\\"\\n     },\\n-    \\"attribution\\": \\"City of San Diego\\",\\n+    \\"attribution\\": \\"San Diego Geographic Information Source - JPA\\",\\n     \\"data\\": \\"http://rdw.sandag.org/file_store/Address/Address_APN.zip\\",\\n-    \\"license\\": \\"http://rdw.sandag.org/\\",\\n+    \\"license\\": \\"http://www.sangis.org/Legal_Notice.htm\\",\\n+    \\"note\\": \\"Metadata available at http://rdw.sandag.org/file_store%5CAddress/Address_APN.pdf\\",\\n+    \\"website\\": \\"http://rdw.sandag.org/\\",\\n     \\"year\\": \\"\\",\\n     \\"type\\": \\"http\\",\\n     \\"compression\\": \\"zip\\",",\r      "previous_filename": "sources/us-ca-san_diego.json"\r    }\r  ]\r}'''
            return response(200, data.encode('utf8'), headers=response_headers)
        
        if MHP == ('GET', GH, '/repos/openaddresses/openaddresses/compare/master...bba8f709793f96750fed223d44ba373a92540b2a'):
            data = '''{\r  "url": "https://api.github.com/repos/openaddresses/openaddresses/compare/master...bba8f709793f96750fed223d44ba373a92540b2a",\r  "html_url": "https://github.com/openaddresses/openaddresses/compare/master...bba8f709793f96750fed223d44ba373a92540b2a",\r  "permalink_url": "https://github.com/openaddresses/openaddresses/compare/openaddresses:bba8f70...openaddresses:bba8f70",\r  "diff_url": "https://github.com/openaddresses/openaddresses/compare/master...bba8f709793f96750fed223d44ba373a92540b2a.diff",\r  "patch_url": "https://github.com/openaddresses/openaddresses/compare/master...bba8f709793f96750fed223d44ba373a92540b2a.patch",\r  "base_commit": {\r    "sha": "bba8f709793f96750fed223d44ba373a92540b2a",\r    "commit": {\r      "author": {\r        "name": "migurski",\r        "email": "mike-github@teczno.com",\r        "date": "2015-06-21T20:25:01Z"\r      },\r      "committer": {\r        "name": "migurski",\r        "email": "mike-github@teczno.com",\r        "date": "2015-06-21T20:25:01Z"\r      },\r      "message": "Merge pull request #1036 from daguar/fix-coverage-of-san-diego-county\\n\\nUpdate San Diego County coverage and details",\r      "tree": {\r        "sha": "6ba53187095d883ba698d230ab808021dfb9c4b4",\r        "url": "https://api.github.com/repos/openaddresses/openaddresses/git/trees/6ba53187095d883ba698d230ab808021dfb9c4b4"\r      },\r      "url": "https://api.github.com/repos/openaddresses/openaddresses/git/commits/bba8f709793f96750fed223d44ba373a92540b2a",\r      "comment_count": 0\r    },\r    "url": "https://api.github.com/repos/openaddresses/openaddresses/commits/bba8f709793f96750fed223d44ba373a92540b2a",\r    "html_url": "https://github.com/openaddresses/openaddresses/commit/bba8f709793f96750fed223d44ba373a92540b2a",\r    "comments_url": "https://api.github.com/repos/openaddresses/openaddresses/commits/bba8f709793f96750fed223d44ba373a92540b2a/comments",\r    "author": {\r      "login": "migurski",\r      "id": 58730,\r      "avatar_url": "https://avatars.githubusercontent.com/u/58730?v=3",\r      "gravatar_id": "",\r      "url": "https://api.github.com/users/migurski",\r      "html_url": "https://github.com/migurski",\r      "followers_url": "https://api.github.com/users/migurski/followers",\r      "following_url": "https://api.github.com/users/migurski/following{/other_user}",\r      "gists_url": "https://api.github.com/users/migurski/gists{/gist_id}",\r      "starred_url": "https://api.github.com/users/migurski/starred{/owner}{/repo}",\r      "subscriptions_url": "https://api.github.com/users/migurski/subscriptions",\r      "organizations_url": "https://api.github.com/users/migurski/orgs",\r      "repos_url": "https://api.github.com/users/migurski/repos",\r      "events_url": "https://api.github.com/users/migurski/events{/privacy}",\r      "received_events_url": "https://api.github.com/users/migurski/received_events",\r      "type": "User",\r      "site_admin": false\r    },\r    "committer": {\r      "login": "migurski",\r      "id": 58730,\r      "avatar_url": "https://avatars.githubusercontent.com/u/58730?v=3",\r      "gravatar_id": "",\r      "url": "https://api.github.com/users/migurski",\r      "html_url": "https://github.com/migurski",\r      "followers_url": "https://api.github.com/users/migurski/followers",\r      "following_url": "https://api.github.com/users/migurski/following{/other_user}",\r      "gists_url": "https://api.github.com/users/migurski/gists{/gist_id}",\r      "starred_url": "https://api.github.com/users/migurski/starred{/owner}{/repo}",\r      "subscriptions_url": "https://api.github.com/users/migurski/subscriptions",\r      "organizations_url": "https://api.github.com/users/migurski/orgs",\r      "repos_url": "https://api.github.com/users/migurski/repos",\r      "events_url": "https://api.github.com/users/migurski/events{/privacy}",\r      "received_events_url": "https://api.github.com/users/migurski/received_events",\r      "type": "User",\r      "site_admin": false\r    },\r    "parents": [\r      {\r        "sha": "6a7b18728673fc7621bb46ed1a445611f33324f9",\r        "url": "https://api.github.com/repos/openaddresses/openaddresses/commits/6a7b18728673fc7621bb46ed1a445611f33324f9",\r        "html_url": "https://github.com/openaddresses/openaddresses/commit/6a7b18728673fc7621bb46ed1a445611f33324f9"\r      },\r      {\r        "sha": "f85074d543622ef1fac7a80a059a50176f2a6e08",\r        "url": "https://api.github.com/repos/openaddresses/openaddresses/commits/f85074d543622ef1fac7a80a059a50176f2a6e08",\r        "html_url": "https://github.com/openaddresses/openaddresses/commit/f85074d543622ef1fac7a80a059a50176f2a6e08"\r      }\r    ]\r  },\r  "merge_base_commit": {\r    "sha": "bba8f709793f96750fed223d44ba373a92540b2a",\r    "commit": {\r      "author": {\r        "name": "migurski",\r        "email": "mike-github@teczno.com",\r        "date": "2015-06-21T20:25:01Z"\r      },\r      "committer": {\r        "name": "migurski",\r        "email": "mike-github@teczno.com",\r        "date": "2015-06-21T20:25:01Z"\r      },\r      "message": "Merge pull request #1036 from daguar/fix-coverage-of-san-diego-county\\n\\nUpdate San Diego County coverage and details",\r      "tree": {\r        "sha": "6ba53187095d883ba698d230ab808021dfb9c4b4",\r        "url": "https://api.github.com/repos/openaddresses/openaddresses/git/trees/6ba53187095d883ba698d230ab808021dfb9c4b4"\r      },\r      "url": "https://api.github.com/repos/openaddresses/openaddresses/git/commits/bba8f709793f96750fed223d44ba373a92540b2a",\r      "comment_count": 0\r    },\r    "url": "https://api.github.com/repos/openaddresses/openaddresses/commits/bba8f709793f96750fed223d44ba373a92540b2a",\r    "html_url": "https://github.com/openaddresses/openaddresses/commit/bba8f709793f96750fed223d44ba373a92540b2a",\r    "comments_url": "https://api.github.com/repos/openaddresses/openaddresses/commits/bba8f709793f96750fed223d44ba373a92540b2a/comments",\r    "author": {\r      "login": "migurski",\r      "id": 58730,\r      "avatar_url": "https://avatars.githubusercontent.com/u/58730?v=3",\r      "gravatar_id": "",\r      "url": "https://api.github.com/users/migurski",\r      "html_url": "https://github.com/migurski",\r      "followers_url": "https://api.github.com/users/migurski/followers",\r      "following_url": "https://api.github.com/users/migurski/following{/other_user}",\r      "gists_url": "https://api.github.com/users/migurski/gists{/gist_id}",\r      "starred_url": "https://api.github.com/users/migurski/starred{/owner}{/repo}",\r      "subscriptions_url": "https://api.github.com/users/migurski/subscriptions",\r      "organizations_url": "https://api.github.com/users/migurski/orgs",\r      "repos_url": "https://api.github.com/users/migurski/repos",\r      "events_url": "https://api.github.com/users/migurski/events{/privacy}",\r      "received_events_url": "https://api.github.com/users/migurski/received_events",\r      "type": "User",\r      "site_admin": false\r    },\r    "committer": {\r      "login": "migurski",\r      "id": 58730,\r      "avatar_url": "https://avatars.githubusercontent.com/u/58730?v=3",\r      "gravatar_id": "",\r      "url": "https://api.github.com/users/migurski",\r      "html_url": "https://github.com/migurski",\r      "followers_url": "https://api.github.com/users/migurski/followers",\r      "following_url": "https://api.github.com/users/migurski/following{/other_user}",\r      "gists_url": "https://api.github.com/users/migurski/gists{/gist_id}",\r      "starred_url": "https://api.github.com/users/migurski/starred{/owner}{/repo}",\r      "subscriptions_url": "https://api.github.com/users/migurski/subscriptions",\r      "organizations_url": "https://api.github.com/users/migurski/orgs",\r      "repos_url": "https://api.github.com/users/migurski/repos",\r      "events_url": "https://api.github.com/users/migurski/events{/privacy}",\r      "received_events_url": "https://api.github.com/users/migurski/received_events",\r      "type": "User",\r      "site_admin": false\r    },\r    "parents": [\r      {\r        "sha": "6a7b18728673fc7621bb46ed1a445611f33324f9",\r        "url": "https://api.github.com/repos/openaddresses/openaddresses/commits/6a7b18728673fc7621bb46ed1a445611f33324f9",\r        "html_url": "https://github.com/openaddresses/openaddresses/commit/6a7b18728673fc7621bb46ed1a445611f33324f9"\r      },\r      {\r        "sha": "f85074d543622ef1fac7a80a059a50176f2a6e08",\r        "url": "https://api.github.com/repos/openaddresses/openaddresses/commits/f85074d543622ef1fac7a80a059a50176f2a6e08",\r        "html_url": "https://github.com/openaddresses/openaddresses/commit/f85074d543622ef1fac7a80a059a50176f2a6e08"\r      }\r    ]\r  },\r  "status": "identical",\r  "ahead_by": 0,\r  "behind_by": 0,\r  "total_commits": 0,\r  "commits": [\r\r  ],\r  "files": [\r\r  ]\r}'''
            return response(200, data.encode('utf8'), headers=response_headers)
        
        if MHP == ('POST', GH, '/repos/openaddresses/hooked-on-sources/statuses/e5f1dcae83ab1ef1f736b969da617311f7f11564') \
        or MHP == ('POST', GH, '/repos/openaddresses/hooked-on-sources/statuses/e91fbc420f08890960f50f863626e1062f922522') \
        or MHP == ('POST', GH, '/repos/openaddresses/hooked-on-sources/statuses/ded44ed5f1733bb93d84f94afe9383e2d47bbbaa') \
        or MHP == ('POST', GH, '/repos/openaddresses/hooked-on-sources/statuses/3147668047a0bec6d481c0e42995f7c5e5eac637') \
        or MHP == ('POST', GH, '/repos/openaddresses/hooked-on-sources/statuses/badjson20f08890960f50f863626e1062f922522') \
        or MHP == ('POST', GH, '/repos/openaddresses/hooked-on-sources/statuses/badutf820f08890960f50f863626e1062f922522') \
        or MHP == ('POST', GH, '/repos/openaddresses/openaddresses/statuses/f85074d543622ef1fac7a80a059a50176f2a6e08') \
        or MHP == ('POST', GH, '/repos/openaddresses/openaddresses/statuses/bba8f709793f96750fed223d44ba373a92540b2a'):
            input = json.loads(request.body)
            self.last_status_state = input['state']
            self.last_status_message = input['description']
            self.assertEqual(input['context'], 'openaddresses/hooked')
            
            data = '''{{\r              "context": "openaddresses/hooked", \r              "created_at": "2015-04-26T23:45:39Z", \r              "creator": {{\r                "avatar_url": "https://avatars.githubusercontent.com/u/58730?v=3", \r                "events_url": "https://api.github.com/users/migurski/events{{/privacy}}", \r                "followers_url": "https://api.github.com/users/migurski/followers", \r                "following_url": "https://api.github.com/users/migurski/following{{/other_user}}", \r                "gists_url": "https://api.github.com/users/migurski/gists{{/gist_id}}", \r                "gravatar_id": "", \r                "html_url": "https://github.com/migurski", \r                "id": 58730, \r                "login": "migurski", \r                "organizations_url": "https://api.github.com/users/migurski/orgs", \r                "received_events_url": "https://api.github.com/users/migurski/received_events", \r                "repos_url": "https://api.github.com/users/migurski/repos", \r                "site_admin": false, \r                "starred_url": "https://api.github.com/users/migurski/starred{{/owner}}{{/repo}}", \r                "subscriptions_url": "https://api.github.com/users/migurski/subscriptions", \r                "type": "User", \r                "url": "https://api.github.com/users/migurski"\r              }}, \r              "description": "Checking ", \r              "id": 999999999, \r              "state": "{state}", \r              "target_url": null, \r              "updated_at": "2015-04-26T23:45:39Z", \r              "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/statuses/xxxxxxxxx"\r            }}'''
            return response(201, data.format(**input).encode('utf8'), headers=response_headers)
        
        print('Unknowable Request {} "{}"'.format(request.method, url.geturl()), file=sys.stderr)
        raise ValueError('Unknowable Request {} "{}"'.format(request.method, url.geturl()))

    def test_webhook_badjson_content(self):
        ''' Push a single commit with bad JSON source directly to master.
        '''
        data = '''{\r          "after": "badjson20f08890960f50f863626e1062f922522", \r          "base_ref": null, \r          "before": "c52204fd40f17f9da243df09e6d1107d48768afd", \r          "commits": [\r            {\r              "added": [\r                "sources/us-ca-badjson_county.json"\r              ], \r              "author": {\r                "email": "mike@teczno.com", \r                "name": "Michal Migurski", \r                "username": "migurski"\r              }, \r              "committer": {\r                "email": "mike@teczno.com", \r                "name": "Michal Migurski", \r                "username": "migurski"\r              }, \r              "distinct": true, \r              "id": "badjson20f08890960f50f863626e1062f922522", \r              "message": "Added first source", \r              "modified": [], \r              "removed": [], \r              "timestamp": "2015-04-25T17:16:12-07:00", \r              "url": "https://github.com/openaddresses/hooked-on-sources/commit/badjson20f08890960f50f863626e1062f922522"\r            }\r          ], \r          "compare": "https://github.com/openaddresses/hooked-on-sources/compare/c52204fd40f1...e91fbc420f08", \r          "created": false, \r          "deleted": false, \r          "forced": false, \r          "head_commit": {\r            "added": [\r              "sources/us-ca-badjson_county.json"\r            ], \r            "author": {\r              "email": "mike@teczno.com", \r              "name": "Michal Migurski", \r              "username": "migurski"\r            }, \r            "committer": {\r              "email": "mike@teczno.com", \r              "name": "Michal Migurski", \r              "username": "migurski"\r            }, \r            "distinct": true, \r            "id": "badjson20f08890960f50f863626e1062f922522", \r            "message": "Added first source", \r            "modified": [], \r            "removed": [], \r            "timestamp": "2015-04-25T17:16:12-07:00", \r            "url": "https://github.com/openaddresses/hooked-on-sources/commit/badjson20f08890960f50f863626e1062f922522"\r          }, \r          "organization": {\r            "avatar_url": "https://avatars.githubusercontent.com/u/6895392?v=3", \r            "description": "The free and open global address collection ", \r            "events_url": "https://api.github.com/orgs/openaddresses/events", \r            "id": 6895392, \r            "login": "openaddresses", \r            "members_url": "https://api.github.com/orgs/openaddresses/members{/member}", \r            "public_members_url": "https://api.github.com/orgs/openaddresses/public_members{/member}", \r            "repos_url": "https://api.github.com/orgs/openaddresses/repos", \r            "url": "https://api.github.com/orgs/openaddresses"\r          }, \r          "pusher": {\r            "email": "mike-github@teczno.com", \r            "name": "migurski"\r          }, \r          "ref": "refs/heads/master", \r          "repository": {\r            "archive_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/{archive_format}{/ref}", \r            "assignees_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/assignees{/user}", \r            "blobs_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/blobs{/sha}", \r            "branches_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/branches{/branch}", \r            "clone_url": "https://github.com/openaddresses/hooked-on-sources.git", \r            "collaborators_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/collaborators{/collaborator}", \r            "comments_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/comments{/number}", \r            "commits_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits{/sha}", \r            "compare_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/compare/{base}...{head}", \r            "contents_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/contents/{+path}", \r            "contributors_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/contributors", \r            "created_at": 1430006167, \r            "default_branch": "master", \r            "description": "Temporary repository for testing Github webhook features", \r            "downloads_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/downloads", \r            "events_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/events", \r            "fork": false, \r            "forks": 0, \r            "forks_count": 0, \r            "forks_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/forks", \r            "full_name": "openaddresses/hooked-on-sources", \r            "git_commits_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/commits{/sha}", \r            "git_refs_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/refs{/sha}", \r            "git_tags_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/tags{/sha}", \r            "git_url": "git://github.com/openaddresses/hooked-on-sources.git", \r            "has_downloads": true, \r            "has_issues": true, \r            "has_pages": false, \r            "has_wiki": true, \r            "homepage": null, \r            "hooks_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/hooks", \r            "html_url": "https://github.com/openaddresses/hooked-on-sources", \r            "id": 34590951, \r            "issue_comment_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/issues/comments{/number}", \r            "issue_events_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/issues/events{/number}", \r            "issues_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/issues{/number}", \r            "keys_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/keys{/key_id}", \r            "labels_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/labels{/name}", \r            "language": null, \r            "languages_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/languages", \r            "master_branch": "master", \r            "merges_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/merges", \r            "milestones_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/milestones{/number}", \r            "mirror_url": null, \r            "name": "hooked-on-sources", \r            "notifications_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/notifications{?since,all,participating}", \r            "open_issues": 0, \r            "open_issues_count": 0, \r            "organization": "openaddresses", \r            "owner": {\r              "email": "openaddresses@gmail.com", \r              "name": "openaddresses"\r            }, \r            "private": false, \r            "pulls_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/pulls{/number}", \r            "pushed_at": 1430007676, \r            "releases_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/releases{/id}", \r            "size": 0, \r            "ssh_url": "git@github.com:openaddresses/hooked-on-sources.git", \r            "stargazers": 0, \r            "stargazers_count": 0, \r            "stargazers_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/stargazers", \r            "statuses_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/statuses/{sha}", \r            "subscribers_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/subscribers", \r            "subscription_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/subscription", \r            "svn_url": "https://github.com/openaddresses/hooked-on-sources", \r            "tags_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/tags", \r            "teams_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/teams", \r            "trees_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/trees{/sha}", \r            "updated_at": "2015-04-25T23:56:07Z", \r            "url": "https://github.com/openaddresses/hooked-on-sources", \r            "watchers": 0, \r            "watchers_count": 0\r          }, \r          "sender": {\r            "avatar_url": "https://avatars.githubusercontent.com/u/58730?v=3", \r            "events_url": "https://api.github.com/users/migurski/events{/privacy}", \r            "followers_url": "https://api.github.com/users/migurski/followers", \r            "following_url": "https://api.github.com/users/migurski/following{/other_user}", \r            "gists_url": "https://api.github.com/users/migurski/gists{/gist_id}", \r            "gravatar_id": "", \r            "html_url": "https://github.com/migurski", \r            "id": 58730, \r            "login": "migurski", \r            "organizations_url": "https://api.github.com/users/migurski/orgs", \r            "received_events_url": "https://api.github.com/users/migurski/received_events", \r            "repos_url": "https://api.github.com/users/migurski/repos", \r            "site_admin": false, \r            "starred_url": "https://api.github.com/users/migurski/starred{/owner}{/repo}", \r            "subscriptions_url": "https://api.github.com/users/migurski/subscriptions", \r            "type": "User", \r            "url": "https://api.github.com/users/migurski"\r          }\r        }'''
        
        with HTTMock(self.response_content):
            posted = self.client.post('/hook', data=data)
        
        self.assertEqual(posted.status_code, 200)
        self.assertEqual(self.last_status_state, 'pending')
        self.assertTrue(b'us-ca-badjson_county' in posted.data, 'Bad JSON County source should be present in master commit')
        
        # Look for the task in the task queue.
        with db_connect(self.database_url) as conn, HTTMock(self.response_content):
            task_q = db_queue(conn, TASK_QUEUE)
            done_q = db_queue(conn, DONE_QUEUE)
            due_q = db_queue(conn, DUE_QUEUE)
            pop_task_from_taskqueue(self.s3, task_q, done_q, due_q, self.output_dir)
            pop_task_from_donequeue(done_q, self.github_auth)
            
        self.assertEquals(self.last_status_state, 'failure', 'Bad JSON should lead to failure')

    def test_webhook_badutf8_content(self):
        ''' Push a single commit with bad UTF8 source directly to master.
        '''
        data = '''{\r          "after": "badutf820f08890960f50f863626e1062f922522", \r          "base_ref": null, \r          "before": "c52204fd40f17f9da243df09e6d1107d48768afd", \r          "commits": [\r            {\r              "added": [\r                "sources/us-ca-badutf8_county.json"\r              ], \r              "author": {\r                "email": "mike@teczno.com", \r                "name": "Michal Migurski", \r                "username": "migurski"\r              }, \r              "committer": {\r                "email": "mike@teczno.com", \r                "name": "Michal Migurski", \r                "username": "migurski"\r              }, \r              "distinct": true, \r              "id": "badutf820f08890960f50f863626e1062f922522", \r              "message": "Added first source", \r              "modified": [], \r              "removed": [], \r              "timestamp": "2015-04-25T17:16:12-07:00", \r              "url": "https://github.com/openaddresses/hooked-on-sources/commit/badutf820f08890960f50f863626e1062f922522"\r            }\r          ], \r          "compare": "https://github.com/openaddresses/hooked-on-sources/compare/c52204fd40f1...e91fbc420f08", \r          "created": false, \r          "deleted": false, \r          "forced": false, \r          "head_commit": {\r            "added": [\r              "sources/us-ca-badutf8_county.json"\r            ], \r            "author": {\r              "email": "mike@teczno.com", \r              "name": "Michal Migurski", \r              "username": "migurski"\r            }, \r            "committer": {\r              "email": "mike@teczno.com", \r              "name": "Michal Migurski", \r              "username": "migurski"\r            }, \r            "distinct": true, \r            "id": "badutf820f08890960f50f863626e1062f922522", \r            "message": "Added first source", \r            "modified": [], \r            "removed": [], \r            "timestamp": "2015-04-25T17:16:12-07:00", \r            "url": "https://github.com/openaddresses/hooked-on-sources/commit/badutf820f08890960f50f863626e1062f922522"\r          }, \r          "organization": {\r            "avatar_url": "https://avatars.githubusercontent.com/u/6895392?v=3", \r            "description": "The free and open global address collection ", \r            "events_url": "https://api.github.com/orgs/openaddresses/events", \r            "id": 6895392, \r            "login": "openaddresses", \r            "members_url": "https://api.github.com/orgs/openaddresses/members{/member}", \r            "public_members_url": "https://api.github.com/orgs/openaddresses/public_members{/member}", \r            "repos_url": "https://api.github.com/orgs/openaddresses/repos", \r            "url": "https://api.github.com/orgs/openaddresses"\r          }, \r          "pusher": {\r            "email": "mike-github@teczno.com", \r            "name": "migurski"\r          }, \r          "ref": "refs/heads/master", \r          "repository": {\r            "archive_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/{archive_format}{/ref}", \r            "assignees_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/assignees{/user}", \r            "blobs_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/blobs{/sha}", \r            "branches_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/branches{/branch}", \r            "clone_url": "https://github.com/openaddresses/hooked-on-sources.git", \r            "collaborators_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/collaborators{/collaborator}", \r            "comments_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/comments{/number}", \r            "commits_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits{/sha}", \r            "compare_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/compare/{base}...{head}", \r            "contents_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/contents/{+path}", \r            "contributors_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/contributors", \r            "created_at": 1430006167, \r            "default_branch": "master", \r            "description": "Temporary repository for testing Github webhook features", \r            "downloads_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/downloads", \r            "events_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/events", \r            "fork": false, \r            "forks": 0, \r            "forks_count": 0, \r            "forks_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/forks", \r            "full_name": "openaddresses/hooked-on-sources", \r            "git_commits_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/commits{/sha}", \r            "git_refs_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/refs{/sha}", \r            "git_tags_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/tags{/sha}", \r            "git_url": "git://github.com/openaddresses/hooked-on-sources.git", \r            "has_downloads": true, \r            "has_issues": true, \r            "has_pages": false, \r            "has_wiki": true, \r            "homepage": null, \r            "hooks_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/hooks", \r            "html_url": "https://github.com/openaddresses/hooked-on-sources", \r            "id": 34590951, \r            "issue_comment_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/issues/comments{/number}", \r            "issue_events_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/issues/events{/number}", \r            "issues_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/issues{/number}", \r            "keys_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/keys{/key_id}", \r            "labels_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/labels{/name}", \r            "language": null, \r            "languages_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/languages", \r            "master_branch": "master", \r            "merges_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/merges", \r            "milestones_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/milestones{/number}", \r            "mirror_url": null, \r            "name": "hooked-on-sources", \r            "notifications_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/notifications{?since,all,participating}", \r            "open_issues": 0, \r            "open_issues_count": 0, \r            "organization": "openaddresses", \r            "owner": {\r              "email": "openaddresses@gmail.com", \r              "name": "openaddresses"\r            }, \r            "private": false, \r            "pulls_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/pulls{/number}", \r            "pushed_at": 1430007676, \r            "releases_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/releases{/id}", \r            "size": 0, \r            "ssh_url": "git@github.com:openaddresses/hooked-on-sources.git", \r            "stargazers": 0, \r            "stargazers_count": 0, \r            "stargazers_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/stargazers", \r            "statuses_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/statuses/{sha}", \r            "subscribers_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/subscribers", \r            "subscription_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/subscription", \r            "svn_url": "https://github.com/openaddresses/hooked-on-sources", \r            "tags_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/tags", \r            "teams_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/teams", \r            "trees_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/trees{/sha}", \r            "updated_at": "2015-04-25T23:56:07Z", \r            "url": "https://github.com/openaddresses/hooked-on-sources", \r            "watchers": 0, \r            "watchers_count": 0\r          }, \r          "sender": {\r            "avatar_url": "https://avatars.githubusercontent.com/u/58730?v=3", \r            "events_url": "https://api.github.com/users/migurski/events{/privacy}", \r            "followers_url": "https://api.github.com/users/migurski/followers", \r            "following_url": "https://api.github.com/users/migurski/following{/other_user}", \r            "gists_url": "https://api.github.com/users/migurski/gists{/gist_id}", \r            "gravatar_id": "", \r            "html_url": "https://github.com/migurski", \r            "id": 58730, \r            "login": "migurski", \r            "organizations_url": "https://api.github.com/users/migurski/orgs", \r            "received_events_url": "https://api.github.com/users/migurski/received_events", \r            "repos_url": "https://api.github.com/users/migurski/repos", \r            "site_admin": false, \r            "starred_url": "https://api.github.com/users/migurski/starred{/owner}{/repo}", \r            "subscriptions_url": "https://api.github.com/users/migurski/subscriptions", \r            "type": "User", \r            "url": "https://api.github.com/users/migurski"\r          }\r        }'''
        
        with HTTMock(self.response_content):
            posted = self.client.post('/hook', data=data)
        
        self.assertEqual(posted.status_code, 200)
        self.assertEqual(self.last_status_state, 'error')

    def test_webhook_one_master_commit(self):
        ''' Push a single commit with Alameda County source directly to master.
        '''
        data = '''{\r          "after": "e91fbc420f08890960f50f863626e1062f922522", \r          "base_ref": null, \r          "before": "c52204fd40f17f9da243df09e6d1107d48768afd", \r          "commits": [\r            {\r              "added": [\r                "sources/us-ca-alameda_county.json"\r              ], \r              "author": {\r                "email": "mike@teczno.com", \r                "name": "Michal Migurski", \r                "username": "migurski"\r              }, \r              "committer": {\r                "email": "mike@teczno.com", \r                "name": "Michal Migurski", \r                "username": "migurski"\r              }, \r              "distinct": true, \r              "id": "e91fbc420f08890960f50f863626e1062f922522", \r              "message": "Added first source", \r              "modified": [], \r              "removed": [], \r              "timestamp": "2015-04-25T17:16:12-07:00", \r              "url": "https://github.com/openaddresses/hooked-on-sources/commit/e91fbc420f08890960f50f863626e1062f922522"\r            }\r          ], \r          "compare": "https://github.com/openaddresses/hooked-on-sources/compare/c52204fd40f1...e91fbc420f08", \r          "created": false, \r          "deleted": false, \r          "forced": false, \r          "head_commit": {\r            "added": [\r              "sources/us-ca-alameda_county.json"\r            ], \r            "author": {\r              "email": "mike@teczno.com", \r              "name": "Michal Migurski", \r              "username": "migurski"\r            }, \r            "committer": {\r              "email": "mike@teczno.com", \r              "name": "Michal Migurski", \r              "username": "migurski"\r            }, \r            "distinct": true, \r            "id": "e91fbc420f08890960f50f863626e1062f922522", \r            "message": "Added first source", \r            "modified": [], \r            "removed": [], \r            "timestamp": "2015-04-25T17:16:12-07:00", \r            "url": "https://github.com/openaddresses/hooked-on-sources/commit/e91fbc420f08890960f50f863626e1062f922522"\r          }, \r          "organization": {\r            "avatar_url": "https://avatars.githubusercontent.com/u/6895392?v=3", \r            "description": "The free and open global address collection ", \r            "events_url": "https://api.github.com/orgs/openaddresses/events", \r            "id": 6895392, \r            "login": "openaddresses", \r            "members_url": "https://api.github.com/orgs/openaddresses/members{/member}", \r            "public_members_url": "https://api.github.com/orgs/openaddresses/public_members{/member}", \r            "repos_url": "https://api.github.com/orgs/openaddresses/repos", \r            "url": "https://api.github.com/orgs/openaddresses"\r          }, \r          "pusher": {\r            "email": "mike-github@teczno.com", \r            "name": "migurski"\r          }, \r          "ref": "refs/heads/master", \r          "repository": {\r            "archive_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/{archive_format}{/ref}", \r            "assignees_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/assignees{/user}", \r            "blobs_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/blobs{/sha}", \r            "branches_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/branches{/branch}", \r            "clone_url": "https://github.com/openaddresses/hooked-on-sources.git", \r            "collaborators_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/collaborators{/collaborator}", \r            "comments_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/comments{/number}", \r            "commits_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits{/sha}", \r            "compare_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/compare/{base}...{head}", \r            "contents_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/contents/{+path}", \r            "contributors_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/contributors", \r            "created_at": 1430006167, \r            "default_branch": "master", \r            "description": "Temporary repository for testing Github webhook features", \r            "downloads_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/downloads", \r            "events_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/events", \r            "fork": false, \r            "forks": 0, \r            "forks_count": 0, \r            "forks_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/forks", \r            "full_name": "openaddresses/hooked-on-sources", \r            "git_commits_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/commits{/sha}", \r            "git_refs_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/refs{/sha}", \r            "git_tags_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/tags{/sha}", \r            "git_url": "git://github.com/openaddresses/hooked-on-sources.git", \r            "has_downloads": true, \r            "has_issues": true, \r            "has_pages": false, \r            "has_wiki": true, \r            "homepage": null, \r            "hooks_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/hooks", \r            "html_url": "https://github.com/openaddresses/hooked-on-sources", \r            "id": 34590951, \r            "issue_comment_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/issues/comments{/number}", \r            "issue_events_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/issues/events{/number}", \r            "issues_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/issues{/number}", \r            "keys_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/keys{/key_id}", \r            "labels_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/labels{/name}", \r            "language": null, \r            "languages_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/languages", \r            "master_branch": "master", \r            "merges_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/merges", \r            "milestones_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/milestones{/number}", \r            "mirror_url": null, \r            "name": "hooked-on-sources", \r            "notifications_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/notifications{?since,all,participating}", \r            "open_issues": 0, \r            "open_issues_count": 0, \r            "organization": "openaddresses", \r            "owner": {\r              "email": "openaddresses@gmail.com", \r              "name": "openaddresses"\r            }, \r            "private": false, \r            "pulls_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/pulls{/number}", \r            "pushed_at": 1430007676, \r            "releases_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/releases{/id}", \r            "size": 0, \r            "ssh_url": "git@github.com:openaddresses/hooked-on-sources.git", \r            "stargazers": 0, \r            "stargazers_count": 0, \r            "stargazers_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/stargazers", \r            "statuses_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/statuses/{sha}", \r            "subscribers_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/subscribers", \r            "subscription_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/subscription", \r            "svn_url": "https://github.com/openaddresses/hooked-on-sources", \r            "tags_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/tags", \r            "teams_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/teams", \r            "trees_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/trees{/sha}", \r            "updated_at": "2015-04-25T23:56:07Z", \r            "url": "https://github.com/openaddresses/hooked-on-sources", \r            "watchers": 0, \r            "watchers_count": 0\r          }, \r          "sender": {\r            "avatar_url": "https://avatars.githubusercontent.com/u/58730?v=3", \r            "events_url": "https://api.github.com/users/migurski/events{/privacy}", \r            "followers_url": "https://api.github.com/users/migurski/followers", \r            "following_url": "https://api.github.com/users/migurski/following{/other_user}", \r            "gists_url": "https://api.github.com/users/migurski/gists{/gist_id}", \r            "gravatar_id": "", \r            "html_url": "https://github.com/migurski", \r            "id": 58730, \r            "login": "migurski", \r            "organizations_url": "https://api.github.com/users/migurski/orgs", \r            "received_events_url": "https://api.github.com/users/migurski/received_events", \r            "repos_url": "https://api.github.com/users/migurski/repos", \r            "site_admin": false, \r            "starred_url": "https://api.github.com/users/migurski/starred{/owner}{/repo}", \r            "subscriptions_url": "https://api.github.com/users/migurski/subscriptions", \r            "type": "User", \r            "url": "https://api.github.com/users/migurski"\r          }\r        }'''
        
        with HTTMock(self.response_content):
            posted = self.client.post('/hook', data=data)
        
        self.assertEqual(posted.status_code, 200)
        self.assertEqual(self.last_status_state, 'pending')
        self.assertTrue(b'us-ca-alameda_county' in posted.data, 'Alameda County source should be present in master commit')
        self.assertTrue(b'data.acgov.org' in posted.data, 'Alameda County domain name should be present in master commit')
        
        # Look for the task in the task queue.
        with db_connect(self.database_url) as conn:
            task = db_queue(conn, TASK_QUEUE).get()
            
        self.assertTrue('us-ca-alameda_county' in task.data['name'])
        
        # This is the JSON source payload, just make sure it parses.
        content = json.loads(task.data['content'])
        task.data['result'] = dict(message=MAGIC_OK_MESSAGE)
        task.data['run_id'] = -1
        
        # Put back a completion task to the done queue.
        with db_connect(self.database_url) as conn:
            db_queue(conn, DONE_QUEUE).put(task.data)
        
            # Handle completion task and check with Github.
            with HTTMock(self.response_content):
                pop_task_from_donequeue(db_queue(conn, DONE_QUEUE), self.github_auth)
        
            # Check that Github knows the job to have been completed successfully.
            self.assertEqual(self.last_status_state, 'success')

    def test_webhook_two_master_commits_early_fail(self):
        ''' Push two commits with San Francisco and Berkeley sources directly to master.
        '''
        data = '''{\r          "after": "ded44ed5f1733bb93d84f94afe9383e2d47bbbaa", \r          "base_ref": null, \r          "before": "e91fbc420f08890960f50f863626e1062f922522", \r          "commits": [\r            {\r              "added": [\r                "sources/us-ca-san_francisco.json"\r              ], \r              "author": {\r                "email": "mike@teczno.com", \r                "name": "Michal Migurski", \r                "username": "migurski"\r              }, \r              "committer": {\r                "email": "mike@teczno.com", \r                "name": "Michal Migurski", \r                "username": "migurski"\r              }, \r              "distinct": true, \r              "id": "73a81c5b337bd393273a222f1cd191d7e634df51", \r              "message": "Added SF", \r              "modified": [], \r              "removed": [], \r              "timestamp": "2015-04-25T17:25:45-07:00", \r              "url": "https://github.com/openaddresses/hooked-on-sources/commit/73a81c5b337bd393273a222f1cd191d7e634df51"\r            }, \r            {\r              "added": [\r                "sources/us-ca-berkeley.json"\r              ], \r              "author": {\r                "email": "mike@teczno.com", \r                "name": "Michal Migurski", \r                "username": "migurski"\r              }, \r              "committer": {\r                "email": "mike@teczno.com", \r                "name": "Michal Migurski", \r                "username": "migurski"\r              }, \r              "distinct": true, \r              "id": "ded44ed5f1733bb93d84f94afe9383e2d47bbbaa", \r              "message": "Added Berkeley", \r              "modified": [], \r              "removed": [], \r              "timestamp": "2015-04-25T17:25:55-07:00", \r              "url": "https://github.com/openaddresses/hooked-on-sources/commit/ded44ed5f1733bb93d84f94afe9383e2d47bbbaa"\r            }\r          ], \r          "compare": "https://github.com/openaddresses/hooked-on-sources/compare/e91fbc420f08...ded44ed5f173", \r          "created": false, \r          "deleted": false, \r          "forced": false, \r          "head_commit": {\r            "added": [\r              "sources/us-ca-berkeley.json"\r            ], \r            "author": {\r              "email": "mike@teczno.com", \r              "name": "Michal Migurski", \r              "username": "migurski"\r            }, \r            "committer": {\r              "email": "mike@teczno.com", \r              "name": "Michal Migurski", \r              "username": "migurski"\r            }, \r            "distinct": true, \r            "id": "ded44ed5f1733bb93d84f94afe9383e2d47bbbaa", \r            "message": "Added Berkeley", \r            "modified": [], \r            "removed": [], \r            "timestamp": "2015-04-25T17:25:55-07:00", \r            "url": "https://github.com/openaddresses/hooked-on-sources/commit/ded44ed5f1733bb93d84f94afe9383e2d47bbbaa"\r          }, \r          "organization": {\r            "avatar_url": "https://avatars.githubusercontent.com/u/6895392?v=3", \r            "description": "The free and open global address collection ", \r            "events_url": "https://api.github.com/orgs/openaddresses/events", \r            "id": 6895392, \r            "login": "openaddresses", \r            "members_url": "https://api.github.com/orgs/openaddresses/members{/member}", \r            "public_members_url": "https://api.github.com/orgs/openaddresses/public_members{/member}", \r            "repos_url": "https://api.github.com/orgs/openaddresses/repos", \r            "url": "https://api.github.com/orgs/openaddresses"\r          }, \r          "pusher": {\r            "email": "mike-github@teczno.com", \r            "name": "migurski"\r          }, \r          "ref": "refs/heads/master", \r          "repository": {\r            "archive_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/{archive_format}{/ref}", \r            "assignees_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/assignees{/user}", \r            "blobs_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/blobs{/sha}", \r            "branches_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/branches{/branch}", \r            "clone_url": "https://github.com/openaddresses/hooked-on-sources.git", \r            "collaborators_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/collaborators{/collaborator}", \r            "comments_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/comments{/number}", \r            "commits_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits{/sha}", \r            "compare_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/compare/{base}...{head}", \r            "contents_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/contents/{+path}", \r            "contributors_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/contributors", \r            "created_at": 1430006167, \r            "default_branch": "master", \r            "description": "Temporary repository for testing Github webhook features", \r            "downloads_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/downloads", \r            "events_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/events", \r            "fork": false, \r            "forks": 0, \r            "forks_count": 0, \r            "forks_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/forks", \r            "full_name": "openaddresses/hooked-on-sources", \r            "git_commits_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/commits{/sha}", \r            "git_refs_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/refs{/sha}", \r            "git_tags_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/tags{/sha}", \r            "git_url": "git://github.com/openaddresses/hooked-on-sources.git", \r            "has_downloads": true, \r            "has_issues": true, \r            "has_pages": false, \r            "has_wiki": true, \r            "homepage": null, \r            "hooks_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/hooks", \r            "html_url": "https://github.com/openaddresses/hooked-on-sources", \r            "id": 34590951, \r            "issue_comment_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/issues/comments{/number}", \r            "issue_events_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/issues/events{/number}", \r            "issues_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/issues{/number}", \r            "keys_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/keys{/key_id}", \r            "labels_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/labels{/name}", \r            "language": null, \r            "languages_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/languages", \r            "master_branch": "master", \r            "merges_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/merges", \r            "milestones_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/milestones{/number}", \r            "mirror_url": null, \r            "name": "hooked-on-sources", \r            "notifications_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/notifications{?since,all,participating}", \r            "open_issues": 0, \r            "open_issues_count": 0, \r            "organization": "openaddresses", \r            "owner": {\r              "email": "openaddresses@gmail.com", \r              "name": "openaddresses"\r            }, \r            "private": false, \r            "pulls_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/pulls{/number}", \r            "pushed_at": 1430007964, \r            "releases_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/releases{/id}", \r            "size": 0, \r            "ssh_url": "git@github.com:openaddresses/hooked-on-sources.git", \r            "stargazers": 0, \r            "stargazers_count": 0, \r            "stargazers_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/stargazers", \r            "statuses_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/statuses/{sha}", \r            "subscribers_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/subscribers", \r            "subscription_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/subscription", \r            "svn_url": "https://github.com/openaddresses/hooked-on-sources", \r            "tags_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/tags", \r            "teams_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/teams", \r            "trees_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/trees{/sha}", \r            "updated_at": "2015-04-25T23:56:07Z", \r            "url": "https://github.com/openaddresses/hooked-on-sources", \r            "watchers": 0, \r            "watchers_count": 0\r          }, \r          "sender": {\r            "avatar_url": "https://avatars.githubusercontent.com/u/58730?v=3", \r            "events_url": "https://api.github.com/users/migurski/events{/privacy}", \r            "followers_url": "https://api.github.com/users/migurski/followers", \r            "following_url": "https://api.github.com/users/migurski/following{/other_user}", \r            "gists_url": "https://api.github.com/users/migurski/gists{/gist_id}", \r            "gravatar_id": "", \r            "html_url": "https://github.com/migurski", \r            "id": 58730, \r            "login": "migurski", \r            "organizations_url": "https://api.github.com/users/migurski/orgs", \r            "received_events_url": "https://api.github.com/users/migurski/received_events", \r            "repos_url": "https://api.github.com/users/migurski/repos", \r            "site_admin": false, \r            "starred_url": "https://api.github.com/users/migurski/starred{/owner}{/repo}", \r            "subscriptions_url": "https://api.github.com/users/migurski/subscriptions", \r            "type": "User", \r            "url": "https://api.github.com/users/migurski"\r          }\r        }'''
        
        with HTTMock(self.response_content):
            posted = self.client.post('/hook', data=data)
        
        self.assertEqual(posted.status_code, 200)
        self.assertEqual(self.last_status_state, 'pending')
        self.assertTrue(b'us-ca-san_francisco' in posted.data, 'San Francisco source should be present in master commit')
        self.assertTrue(b'data.sfgov.org' in posted.data, 'San Francisco URL should be present in master commit')
        self.assertTrue(b'us-ca-berkeley' in posted.data, 'Berkeley source should be present in master commit')
        self.assertTrue(b'www.ci.berkeley.ca.us' in posted.data, 'Berkeley URL should be present in master commit')
        self.assertFalse(b'us-ca-alameda_county' in posted.data, 'Alameda County source should be absent from master commit')
        
        for message in ('Something went wrong', MAGIC_OK_MESSAGE):
            # Look for the task in the task queue.
            with db_connect(self.database_url) as conn:
                task = db_queue(conn, TASK_QUEUE).get()
            
            self.assertTrue('us-ca-san_francisco' in task.data['name'] or 'us-ca-berkeley' in task.data['name'])
        
            # This is the JSON source payload, just make sure it parses.
            content = json.loads(task.data['content'])
            task.data['result'] = dict(message=message)
            task.data['run_id'] = -1
        
            # Put back a completion task to the done queue.
            with db_connect(self.database_url) as conn:
                db_queue(conn, DONE_QUEUE).put(task.data)
        
                # Handle completion tasks and check with Github.
                with HTTMock(self.response_content):
                    pop_task_from_donequeue(db_queue(conn, DONE_QUEUE), self.github_auth)
                
                # Check that Github already knows the job to have been completed unsuccessfully.
                self.assertEqual(self.last_status_state, 'failure')
                self.assertTrue('Failed' in self.last_status_message)

    def test_webhook_two_master_commits_late_fail(self):
        ''' Push two commits with San Francisco and Berkeley sources directly to master.
        '''
        data = '''{\r          "after": "ded44ed5f1733bb93d84f94afe9383e2d47bbbaa", \r          "base_ref": null, \r          "before": "e91fbc420f08890960f50f863626e1062f922522", \r          "commits": [\r            {\r              "added": [\r                "sources/us-ca-san_francisco.json"\r              ], \r              "author": {\r                "email": "mike@teczno.com", \r                "name": "Michal Migurski", \r                "username": "migurski"\r              }, \r              "committer": {\r                "email": "mike@teczno.com", \r                "name": "Michal Migurski", \r                "username": "migurski"\r              }, \r              "distinct": true, \r              "id": "73a81c5b337bd393273a222f1cd191d7e634df51", \r              "message": "Added SF", \r              "modified": [], \r              "removed": [], \r              "timestamp": "2015-04-25T17:25:45-07:00", \r              "url": "https://github.com/openaddresses/hooked-on-sources/commit/73a81c5b337bd393273a222f1cd191d7e634df51"\r            }, \r            {\r              "added": [\r                "sources/us-ca-berkeley.json"\r              ], \r              "author": {\r                "email": "mike@teczno.com", \r                "name": "Michal Migurski", \r                "username": "migurski"\r              }, \r              "committer": {\r                "email": "mike@teczno.com", \r                "name": "Michal Migurski", \r                "username": "migurski"\r              }, \r              "distinct": true, \r              "id": "ded44ed5f1733bb93d84f94afe9383e2d47bbbaa", \r              "message": "Added Berkeley", \r              "modified": [], \r              "removed": [], \r              "timestamp": "2015-04-25T17:25:55-07:00", \r              "url": "https://github.com/openaddresses/hooked-on-sources/commit/ded44ed5f1733bb93d84f94afe9383e2d47bbbaa"\r            }\r          ], \r          "compare": "https://github.com/openaddresses/hooked-on-sources/compare/e91fbc420f08...ded44ed5f173", \r          "created": false, \r          "deleted": false, \r          "forced": false, \r          "head_commit": {\r            "added": [\r              "sources/us-ca-berkeley.json"\r            ], \r            "author": {\r              "email": "mike@teczno.com", \r              "name": "Michal Migurski", \r              "username": "migurski"\r            }, \r            "committer": {\r              "email": "mike@teczno.com", \r              "name": "Michal Migurski", \r              "username": "migurski"\r            }, \r            "distinct": true, \r            "id": "ded44ed5f1733bb93d84f94afe9383e2d47bbbaa", \r            "message": "Added Berkeley", \r            "modified": [], \r            "removed": [], \r            "timestamp": "2015-04-25T17:25:55-07:00", \r            "url": "https://github.com/openaddresses/hooked-on-sources/commit/ded44ed5f1733bb93d84f94afe9383e2d47bbbaa"\r          }, \r          "organization": {\r            "avatar_url": "https://avatars.githubusercontent.com/u/6895392?v=3", \r            "description": "The free and open global address collection ", \r            "events_url": "https://api.github.com/orgs/openaddresses/events", \r            "id": 6895392, \r            "login": "openaddresses", \r            "members_url": "https://api.github.com/orgs/openaddresses/members{/member}", \r            "public_members_url": "https://api.github.com/orgs/openaddresses/public_members{/member}", \r            "repos_url": "https://api.github.com/orgs/openaddresses/repos", \r            "url": "https://api.github.com/orgs/openaddresses"\r          }, \r          "pusher": {\r            "email": "mike-github@teczno.com", \r            "name": "migurski"\r          }, \r          "ref": "refs/heads/master", \r          "repository": {\r            "archive_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/{archive_format}{/ref}", \r            "assignees_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/assignees{/user}", \r            "blobs_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/blobs{/sha}", \r            "branches_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/branches{/branch}", \r            "clone_url": "https://github.com/openaddresses/hooked-on-sources.git", \r            "collaborators_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/collaborators{/collaborator}", \r            "comments_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/comments{/number}", \r            "commits_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits{/sha}", \r            "compare_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/compare/{base}...{head}", \r            "contents_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/contents/{+path}", \r            "contributors_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/contributors", \r            "created_at": 1430006167, \r            "default_branch": "master", \r            "description": "Temporary repository for testing Github webhook features", \r            "downloads_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/downloads", \r            "events_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/events", \r            "fork": false, \r            "forks": 0, \r            "forks_count": 0, \r            "forks_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/forks", \r            "full_name": "openaddresses/hooked-on-sources", \r            "git_commits_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/commits{/sha}", \r            "git_refs_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/refs{/sha}", \r            "git_tags_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/tags{/sha}", \r            "git_url": "git://github.com/openaddresses/hooked-on-sources.git", \r            "has_downloads": true, \r            "has_issues": true, \r            "has_pages": false, \r            "has_wiki": true, \r            "homepage": null, \r            "hooks_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/hooks", \r            "html_url": "https://github.com/openaddresses/hooked-on-sources", \r            "id": 34590951, \r            "issue_comment_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/issues/comments{/number}", \r            "issue_events_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/issues/events{/number}", \r            "issues_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/issues{/number}", \r            "keys_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/keys{/key_id}", \r            "labels_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/labels{/name}", \r            "language": null, \r            "languages_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/languages", \r            "master_branch": "master", \r            "merges_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/merges", \r            "milestones_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/milestones{/number}", \r            "mirror_url": null, \r            "name": "hooked-on-sources", \r            "notifications_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/notifications{?since,all,participating}", \r            "open_issues": 0, \r            "open_issues_count": 0, \r            "organization": "openaddresses", \r            "owner": {\r              "email": "openaddresses@gmail.com", \r              "name": "openaddresses"\r            }, \r            "private": false, \r            "pulls_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/pulls{/number}", \r            "pushed_at": 1430007964, \r            "releases_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/releases{/id}", \r            "size": 0, \r            "ssh_url": "git@github.com:openaddresses/hooked-on-sources.git", \r            "stargazers": 0, \r            "stargazers_count": 0, \r            "stargazers_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/stargazers", \r            "statuses_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/statuses/{sha}", \r            "subscribers_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/subscribers", \r            "subscription_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/subscription", \r            "svn_url": "https://github.com/openaddresses/hooked-on-sources", \r            "tags_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/tags", \r            "teams_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/teams", \r            "trees_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/trees{/sha}", \r            "updated_at": "2015-04-25T23:56:07Z", \r            "url": "https://github.com/openaddresses/hooked-on-sources", \r            "watchers": 0, \r            "watchers_count": 0\r          }, \r          "sender": {\r            "avatar_url": "https://avatars.githubusercontent.com/u/58730?v=3", \r            "events_url": "https://api.github.com/users/migurski/events{/privacy}", \r            "followers_url": "https://api.github.com/users/migurski/followers", \r            "following_url": "https://api.github.com/users/migurski/following{/other_user}", \r            "gists_url": "https://api.github.com/users/migurski/gists{/gist_id}", \r            "gravatar_id": "", \r            "html_url": "https://github.com/migurski", \r            "id": 58730, \r            "login": "migurski", \r            "organizations_url": "https://api.github.com/users/migurski/orgs", \r            "received_events_url": "https://api.github.com/users/migurski/received_events", \r            "repos_url": "https://api.github.com/users/migurski/repos", \r            "site_admin": false, \r            "starred_url": "https://api.github.com/users/migurski/starred{/owner}{/repo}", \r            "subscriptions_url": "https://api.github.com/users/migurski/subscriptions", \r            "type": "User", \r            "url": "https://api.github.com/users/migurski"\r          }\r        }'''
        
        with HTTMock(self.response_content):
            posted = self.client.post('/hook', data=data)
        
        self.assertEqual(posted.status_code, 200)
        self.assertEqual(self.last_status_state, 'pending')
        self.assertTrue(b'us-ca-san_francisco' in posted.data, 'San Francisco source should be present in master commit')
        self.assertTrue(b'data.sfgov.org' in posted.data, 'San Francisco URL should be present in master commit')
        self.assertTrue(b'us-ca-berkeley' in posted.data, 'Berkeley source should be present in master commit')
        self.assertTrue(b'www.ci.berkeley.ca.us' in posted.data, 'Berkeley URL should be present in master commit')
        self.assertFalse(b'us-ca-alameda_county' in posted.data, 'Alameda County source should be absent from master commit')
        
        for (index, message) in enumerate((MAGIC_OK_MESSAGE, 'Something went wrong')):
            # Look for the task in the task queue.
            with db_connect(self.database_url) as conn:
                task = db_queue(conn, TASK_QUEUE).get()
            
            self.assertTrue('us-ca-san_francisco' in task.data['name'] or 'us-ca-berkeley' in task.data['name'])
        
            # This is the JSON source payload, just make sure it parses.
            content = json.loads(task.data['content'])
            task.data['result'] = dict(message=message)
            task.data['run_id'] = -1
        
            # Put back a completion task to the done queue.
            with db_connect(self.database_url) as conn:
                db_queue(conn, DONE_QUEUE).put(task.data)
        
                # Handle completion tasks and check with Github.
                with HTTMock(self.response_content):
                    pop_task_from_donequeue(db_queue(conn, DONE_QUEUE), self.github_auth)
                
                if index == 0:
                    # Check that Github still thinks it's pending.
                    self.assertEqual(self.last_status_state, 'pending')
                else:
                    # Check that Github knows the job to have been completed unsuccessfully.
                    self.assertEqual(self.last_status_state, 'failure')
                    self.assertTrue('Failed' in self.last_status_message)

    def test_webhook_two_branch_commits(self):
        ''' Push two commits with addition and removal of Polish source to a branch.
        
            That branch includes a previously-added Santa Clara County source
            which should be checked.
        '''
        data = '''{\r          "ref": "refs/heads/branch",\r          "before": "b659130053b85cd3993b1a4653da1bf6231ec0b4",\r          "after": "e5f1dcae83ab1ef1f736b969da617311f7f11564",\r          "created": false,\r          "deleted": false,\r          "forced": false,\r          "base_ref": null,\r          "compare": "https://github.com/openaddresses/hooked-on-sources/compare/b659130053b8...e5f1dcae83ab",\r          "commits": [\r            {\r              "id": "0cbd51b8f6044e98c919dcabf93e3f4e1d58c035",\r              "distinct": true,\r              "message": "Added Polish source",\r              "timestamp": "2015-04-25T17:52:39-07:00",\r              "url": "https://github.com/openaddresses/hooked-on-sources/commit/0cbd51b8f6044e98c919dcabf93e3f4e1d58c035",\r              "author": {\r                "name": "Michal Migurski",\r                "email": "mike@teczno.com",\r                "username": "migurski"\r              },\r              "committer": {\r                "name": "Michal Migurski",\r                "email": "mike@teczno.com",\r                "username": "migurski"\r              },\r              "added": [\r                "sources/pl-dolnoslaskie.json"\r              ],\r              "removed": [\r\r              ],\r              "modified": [\r\r              ]\r            },\r            {\r              "id": "e5f1dcae83ab1ef1f736b969da617311f7f11564",\r              "distinct": true,\r              "message": "Removed Polish source",\r              "timestamp": "2015-04-25T17:52:46-07:00",\r              "url": "https://github.com/openaddresses/hooked-on-sources/commit/e5f1dcae83ab1ef1f736b969da617311f7f11564",\r              "author": {\r                "name": "Michal Migurski",\r                "email": "mike@teczno.com",\r                "username": "migurski"\r              },\r              "committer": {\r                "name": "Michal Migurski",\r                "email": "mike@teczno.com",\r                "username": "migurski"\r              },\r              "added": [\r\r              ],\r              "removed": [\r                "sources/pl-dolnoslaskie.json"\r              ],\r              "modified": [\r\r              ]\r            }\r          ],\r          "head_commit": {\r            "id": "e5f1dcae83ab1ef1f736b969da617311f7f11564",\r            "distinct": true,\r            "message": "Removed Polish source",\r            "timestamp": "2015-04-25T17:52:46-07:00",\r            "url": "https://github.com/openaddresses/hooked-on-sources/commit/e5f1dcae83ab1ef1f736b969da617311f7f11564",\r            "author": {\r              "name": "Michal Migurski",\r              "email": "mike@teczno.com",\r              "username": "migurski"\r            },\r            "committer": {\r              "name": "Michal Migurski",\r              "email": "mike@teczno.com",\r              "username": "migurski"\r            },\r            "added": [\r\r            ],\r            "removed": [\r              "sources/pl-dolnoslaskie.json"\r            ],\r            "modified": [\r\r            ]\r          },\r          "repository": {\r            "id": 34590951,\r            "name": "hooked-on-sources",\r            "full_name": "openaddresses/hooked-on-sources",\r            "owner": {\r              "name": "openaddresses",\r              "email": "openaddresses@gmail.com"\r            },\r            "private": false,\r            "html_url": "https://github.com/openaddresses/hooked-on-sources",\r            "description": "Temporary repository for testing Github webhook features",\r            "fork": false,\r            "url": "https://github.com/openaddresses/hooked-on-sources",\r            "forks_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/forks",\r            "keys_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/keys{/key_id}",\r            "collaborators_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/collaborators{/collaborator}",\r            "teams_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/teams",\r            "hooks_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/hooks",\r            "issue_events_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/issues/events{/number}",\r            "events_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/events",\r            "assignees_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/assignees{/user}",\r            "branches_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/branches{/branch}",\r            "tags_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/tags",\r            "blobs_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/blobs{/sha}",\r            "git_tags_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/tags{/sha}",\r            "git_refs_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/refs{/sha}",\r            "trees_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/trees{/sha}",\r            "statuses_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/statuses/{sha}",\r            "languages_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/languages",\r            "stargazers_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/stargazers",\r            "contributors_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/contributors",\r            "subscribers_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/subscribers",\r            "subscription_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/subscription",\r            "commits_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits{/sha}",\r            "git_commits_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/commits{/sha}",\r            "comments_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/comments{/number}",\r            "issue_comment_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/issues/comments{/number}",\r            "contents_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/contents/{+path}",\r            "compare_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/compare/{base}...{head}",\r            "merges_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/merges",\r            "archive_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/{archive_format}{/ref}",\r            "downloads_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/downloads",\r            "issues_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/issues{/number}",\r            "pulls_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/pulls{/number}",\r            "milestones_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/milestones{/number}",\r            "notifications_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/notifications{?since,all,participating}",\r            "labels_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/labels{/name}",\r            "releases_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/releases{/id}",\r            "created_at": 1430006167,\r            "updated_at": "2015-04-25T23:56:07Z",\r            "pushed_at": 1430009572,\r            "git_url": "git://github.com/openaddresses/hooked-on-sources.git",\r            "ssh_url": "git@github.com:openaddresses/hooked-on-sources.git",\r            "clone_url": "https://github.com/openaddresses/hooked-on-sources.git",\r            "svn_url": "https://github.com/openaddresses/hooked-on-sources",\r            "homepage": null,\r            "size": 0,\r            "stargazers_count": 0,\r            "watchers_count": 0,\r            "language": null,\r            "has_issues": true,\r            "has_downloads": true,\r            "has_wiki": true,\r            "has_pages": false,\r            "forks_count": 0,\r            "mirror_url": null,\r            "open_issues_count": 1,\r            "forks": 0,\r            "open_issues": 1,\r            "watchers": 0,\r            "default_branch": "master",\r            "stargazers": 0,\r            "master_branch": "master",\r            "organization": "openaddresses"\r          },\r          "pusher": {\r            "name": "migurski",\r            "email": "mike-github@teczno.com"\r          },\r          "organization": {\r            "login": "openaddresses",\r            "id": 6895392,\r            "url": "https://api.github.com/orgs/openaddresses",\r            "repos_url": "https://api.github.com/orgs/openaddresses/repos",\r            "events_url": "https://api.github.com/orgs/openaddresses/events",\r            "members_url": "https://api.github.com/orgs/openaddresses/members{/member}",\r            "public_members_url": "https://api.github.com/orgs/openaddresses/public_members{/member}",\r            "avatar_url": "https://avatars.githubusercontent.com/u/6895392?v=3",\r            "description": "The free and open global address collection "\r          },\r          "sender": {\r            "login": "migurski",\r            "id": 58730,\r            "avatar_url": "https://avatars.githubusercontent.com/u/58730?v=3",\r            "gravatar_id": "",\r            "url": "https://api.github.com/users/migurski",\r            "html_url": "https://github.com/migurski",\r            "followers_url": "https://api.github.com/users/migurski/followers",\r            "following_url": "https://api.github.com/users/migurski/following{/other_user}",\r            "gists_url": "https://api.github.com/users/migurski/gists{/gist_id}",\r            "starred_url": "https://api.github.com/users/migurski/starred{/owner}{/repo}",\r            "subscriptions_url": "https://api.github.com/users/migurski/subscriptions",\r            "organizations_url": "https://api.github.com/users/migurski/orgs",\r            "repos_url": "https://api.github.com/users/migurski/repos",\r            "events_url": "https://api.github.com/users/migurski/events{/privacy}",\r            "received_events_url": "https://api.github.com/users/migurski/received_events",\r            "type": "User",\r            "site_admin": false\r          }\r        }'''
        
        with patch('openaddr.ci.add_files_to_queue') as add_files_to_queue:
            def job_queue_fails(*args, **kwargs):
                raise Exception('Nope')

            add_files_to_queue.side_effect = job_queue_fails

            with HTTMock(self.response_content):
                posted = self.client.post('/hook', data=data)
        
        self.assertEqual(posted.status_code, 500)
        self.assertEqual(self.last_status_state, 'error')
        self.assertTrue('us-ca-santa_clara_county' in self.last_status_message, 'Santa Clara County source should be present in error message')
        self.assertTrue(b'us-ca-santa_clara_county' in posted.data, 'Santa Clara County source should be present in branch commit')
        self.assertTrue(b'sftp.sccgov.org' in posted.data, 'Santa Clara County URL should be present in branch commit')
        self.assertFalse(b'us-ca-contra_costa_county' in posted.data, 'Contra Costa County should be absent from branch commit')
        self.assertFalse(b'pl-dolnoslaskie' in posted.data, 'Polish source should be absent from branch commit')
        self.assertFalse(b'us-ca-san_francisco' in posted.data, 'San Francisco source should be absent from branch commit')
        self.assertFalse(b'us-ca-berkeley' in posted.data, 'Berkeley source should be absent from branch commit')
        
        # Verify that queued job was never created.
        last_job_url = json.loads(posted.data.decode('utf8')).get('url')
        
        self.assertEqual(last_job_url, None)
        self.assertEqual(self.last_status_state, 'error')

    def test_webhook_empty_master_commit(self):
        ''' Push one empty commit directly to master.
        '''
        data = '''{\r  "ref": "refs/heads/master",\r  "before": "b450dcbb6f4c61015b0a00290e984849f7d649de",\r  "after": "3147668047a0bec6d481c0e42995f7c5e5eac637",\r  "created": false,\r  "deleted": false,\r  "forced": false,\r  "base_ref": null,\r  "compare": "https://github.com/openaddresses/hooked-on-sources/compare/b450dcbb6f4c...3147668047a0",\r  "commits": [\r    {\r      "id": "3147668047a0bec6d481c0e42995f7c5e5eac637",\r      "distinct": true,\r      "message": "Empty commit",\r      "timestamp": "2015-04-26T18:36:22-07:00",\r      "url": "https://github.com/openaddresses/hooked-on-sources/commit/3147668047a0bec6d481c0e42995f7c5e5eac637",\r      "author": {\r        "name": "Michal Migurski",\r        "email": "mike@teczno.com",\r        "username": "migurski"\r      },\r      "committer": {\r        "name": "Michal Migurski",\r        "email": "mike@teczno.com",\r        "username": "migurski"\r      },\r      "added": [\r\r      ],\r      "removed": [\r\r      ],\r      "modified": [\r\r      ]\r    }\r  ],\r  "head_commit": {\r    "id": "3147668047a0bec6d481c0e42995f7c5e5eac637",\r    "distinct": true,\r    "message": "Empty commit",\r    "timestamp": "2015-04-26T18:36:22-07:00",\r    "url": "https://github.com/openaddresses/hooked-on-sources/commit/3147668047a0bec6d481c0e42995f7c5e5eac637",\r    "author": {\r      "name": "Michal Migurski",\r      "email": "mike@teczno.com",\r      "username": "migurski"\r    },\r    "committer": {\r      "name": "Michal Migurski",\r      "email": "mike@teczno.com",\r      "username": "migurski"\r    },\r    "added": [\r\r    ],\r    "removed": [\r\r    ],\r    "modified": [\r\r    ]\r  },\r  "repository": {\r    "id": 34590951,\r    "name": "hooked-on-sources",\r    "full_name": "openaddresses/hooked-on-sources",\r    "owner": {\r      "name": "openaddresses",\r      "email": "openaddresses@gmail.com"\r    },\r    "private": false,\r    "html_url": "https://github.com/openaddresses/hooked-on-sources",\r    "description": "Temporary repository for testing Github webhook features",\r    "fork": false,\r    "url": "https://github.com/openaddresses/hooked-on-sources",\r    "forks_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/forks",\r    "keys_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/keys{/key_id}",\r    "collaborators_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/collaborators{/collaborator}",\r    "teams_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/teams",\r    "hooks_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/hooks",\r    "issue_events_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/issues/events{/number}",\r    "events_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/events",\r    "assignees_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/assignees{/user}",\r    "branches_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/branches{/branch}",\r    "tags_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/tags",\r    "blobs_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/blobs{/sha}",\r    "git_tags_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/tags{/sha}",\r    "git_refs_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/refs{/sha}",\r    "trees_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/trees{/sha}",\r    "statuses_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/statuses/{sha}",\r    "languages_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/languages",\r    "stargazers_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/stargazers",\r    "contributors_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/contributors",\r    "subscribers_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/subscribers",\r    "subscription_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/subscription",\r    "commits_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/commits{/sha}",\r    "git_commits_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/git/commits{/sha}",\r    "comments_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/comments{/number}",\r    "issue_comment_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/issues/comments{/number}",\r    "contents_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/contents/{+path}",\r    "compare_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/compare/{base}...{head}",\r    "merges_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/merges",\r    "archive_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/{archive_format}{/ref}",\r    "downloads_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/downloads",\r    "issues_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/issues{/number}",\r    "pulls_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/pulls{/number}",\r    "milestones_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/milestones{/number}",\r    "notifications_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/notifications{?since,all,participating}",\r    "labels_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/labels{/name}",\r    "releases_url": "https://api.github.com/repos/openaddresses/hooked-on-sources/releases{/id}",\r    "created_at": 1430006167,\r    "updated_at": "2015-04-25T23:56:07Z",\r    "pushed_at": 1430098587,\r    "git_url": "git://github.com/openaddresses/hooked-on-sources.git",\r    "ssh_url": "git@github.com:openaddresses/hooked-on-sources.git",\r    "clone_url": "https://github.com/openaddresses/hooked-on-sources.git",\r    "svn_url": "https://github.com/openaddresses/hooked-on-sources",\r    "homepage": null,\r    "size": 0,\r    "stargazers_count": 0,\r    "watchers_count": 0,\r    "language": null,\r    "has_issues": true,\r    "has_downloads": true,\r    "has_wiki": true,\r    "has_pages": false,\r    "forks_count": 0,\r    "mirror_url": null,\r    "open_issues_count": 1,\r    "forks": 0,\r    "open_issues": 1,\r    "watchers": 0,\r    "default_branch": "master",\r    "stargazers": 0,\r    "master_branch": "master",\r    "organization": "openaddresses"\r  },\r  "pusher": {\r    "name": "migurski",\r    "email": "mike-github@teczno.com"\r  },\r  "organization": {\r    "login": "openaddresses",\r    "id": 6895392,\r    "url": "https://api.github.com/orgs/openaddresses",\r    "repos_url": "https://api.github.com/orgs/openaddresses/repos",\r    "events_url": "https://api.github.com/orgs/openaddresses/events",\r    "members_url": "https://api.github.com/orgs/openaddresses/members{/member}",\r    "public_members_url": "https://api.github.com/orgs/openaddresses/public_members{/member}",\r    "avatar_url": "https://avatars.githubusercontent.com/u/6895392?v=3",\r    "description": "The free and open global address collection "\r  },\r  "sender": {\r    "login": "migurski",\r    "id": 58730,\r    "avatar_url": "https://avatars.githubusercontent.com/u/58730?v=3",\r    "gravatar_id": "",\r    "url": "https://api.github.com/users/migurski",\r    "html_url": "https://github.com/migurski",\r    "followers_url": "https://api.github.com/users/migurski/followers",\r    "following_url": "https://api.github.com/users/migurski/following{/other_user}",\r    "gists_url": "https://api.github.com/users/migurski/gists{/gist_id}",\r    "starred_url": "https://api.github.com/users/migurski/starred{/owner}{/repo}",\r    "subscriptions_url": "https://api.github.com/users/migurski/subscriptions",\r    "organizations_url": "https://api.github.com/users/migurski/orgs",\r    "repos_url": "https://api.github.com/users/migurski/repos",\r    "events_url": "https://api.github.com/users/migurski/events{/privacy}",\r    "received_events_url": "https://api.github.com/users/migurski/received_events",\r    "type": "User",\r    "site_admin": false\r  }\r}'''
        
        with HTTMock(self.response_content):
            posted = self.client.post('/hook', data=data)
        
        self.assertEqual(posted.status_code, 200)
        self.assertEqual(self.last_status_state, 'success')
        self.assertFalse(b'us-ca-contra_costa_county' in posted.data, 'Contra Costa County should be absent from master commit')
        self.assertFalse(b'us-ca-san_francisco' in posted.data, 'San Francisco source should be absent from master commit')
        self.assertFalse(b'us-ca-berkeley' in posted.data, 'Berkeley source should be absent from master commit')
    
    def test_webhook_delete_branch(self):
        ''' Delete a branch.
        '''
        data = '''{\r  "ref": "refs/heads/whitespace",\r  "before": "237a09603386664658fba6bcc843044a2ede79fb",\r  "after": "0000000000000000000000000000000000000000",\r  "created": false,\r  "deleted": true,\r  "forced": true,\r  "base_ref": null,\r  "compare": "https://github.com/openaddresses/openaddresses/compare/237a09603386...000000000000",\r  "commits": [\r\r  ],\r  "head_commit": null,\r  "repository": {\r    "id": 16594532,\r    "name": "openaddresses",\r    "full_name": "openaddresses/openaddresses",\r    "owner": {\r      "name": "openaddresses",\r      "email": "openaddresses@gmail.com"\r    },\r    "private": false,\r    "html_url": "https://github.com/openaddresses/openaddresses",\r    "description": "A repository of address data.",\r    "fork": false,\r    "url": "https://github.com/openaddresses/openaddresses",\r    "forks_url": "https://api.github.com/repos/openaddresses/openaddresses/forks",\r    "keys_url": "https://api.github.com/repos/openaddresses/openaddresses/keys{/key_id}",\r    "collaborators_url": "https://api.github.com/repos/openaddresses/openaddresses/collaborators{/collaborator}",\r    "teams_url": "https://api.github.com/repos/openaddresses/openaddresses/teams",\r    "hooks_url": "https://api.github.com/repos/openaddresses/openaddresses/hooks",\r    "issue_events_url": "https://api.github.com/repos/openaddresses/openaddresses/issues/events{/number}",\r    "events_url": "https://api.github.com/repos/openaddresses/openaddresses/events",\r    "assignees_url": "https://api.github.com/repos/openaddresses/openaddresses/assignees{/user}",\r    "branches_url": "https://api.github.com/repos/openaddresses/openaddresses/branches{/branch}",\r    "tags_url": "https://api.github.com/repos/openaddresses/openaddresses/tags",\r    "blobs_url": "https://api.github.com/repos/openaddresses/openaddresses/git/blobs{/sha}",\r    "git_tags_url": "https://api.github.com/repos/openaddresses/openaddresses/git/tags{/sha}",\r    "git_refs_url": "https://api.github.com/repos/openaddresses/openaddresses/git/refs{/sha}",\r    "trees_url": "https://api.github.com/repos/openaddresses/openaddresses/git/trees{/sha}",\r    "statuses_url": "https://api.github.com/repos/openaddresses/openaddresses/statuses/{sha}",\r    "languages_url": "https://api.github.com/repos/openaddresses/openaddresses/languages",\r    "stargazers_url": "https://api.github.com/repos/openaddresses/openaddresses/stargazers",\r    "contributors_url": "https://api.github.com/repos/openaddresses/openaddresses/contributors",\r    "subscribers_url": "https://api.github.com/repos/openaddresses/openaddresses/subscribers",\r    "subscription_url": "https://api.github.com/repos/openaddresses/openaddresses/subscription",\r    "commits_url": "https://api.github.com/repos/openaddresses/openaddresses/commits{/sha}",\r    "git_commits_url": "https://api.github.com/repos/openaddresses/openaddresses/git/commits{/sha}",\r    "comments_url": "https://api.github.com/repos/openaddresses/openaddresses/comments{/number}",\r    "issue_comment_url": "https://api.github.com/repos/openaddresses/openaddresses/issues/comments{/number}",\r    "contents_url": "https://api.github.com/repos/openaddresses/openaddresses/contents/{+path}",\r    "compare_url": "https://api.github.com/repos/openaddresses/openaddresses/compare/{base}...{head}",\r    "merges_url": "https://api.github.com/repos/openaddresses/openaddresses/merges",\r    "archive_url": "https://api.github.com/repos/openaddresses/openaddresses/{archive_format}{/ref}",\r    "downloads_url": "https://api.github.com/repos/openaddresses/openaddresses/downloads",\r    "issues_url": "https://api.github.com/repos/openaddresses/openaddresses/issues{/number}",\r    "pulls_url": "https://api.github.com/repos/openaddresses/openaddresses/pulls{/number}",\r    "milestones_url": "https://api.github.com/repos/openaddresses/openaddresses/milestones{/number}",\r    "notifications_url": "https://api.github.com/repos/openaddresses/openaddresses/notifications{?since,all,participating}",\r    "labels_url": "https://api.github.com/repos/openaddresses/openaddresses/labels{/name}",\r    "releases_url": "https://api.github.com/repos/openaddresses/openaddresses/releases{/id}",\r    "created_at": 1391722160,\r    "updated_at": "2015-06-11T11:42:47Z",\r    "pushed_at": 1434506471,\r    "git_url": "git://github.com/openaddresses/openaddresses.git",\r    "ssh_url": "git@github.com:openaddresses/openaddresses.git",\r    "clone_url": "https://github.com/openaddresses/openaddresses.git",\r    "svn_url": "https://github.com/openaddresses/openaddresses",\r    "homepage": "http://openaddresses.io/",\r    "size": 9790,\r    "stargazers_count": 275,\r    "watchers_count": 275,\r    "language": "JavaScript",\r    "has_issues": true,\r    "has_downloads": true,\r    "has_wiki": true,\r    "has_pages": false,\r    "forks_count": 313,\r    "mirror_url": null,\r    "open_issues_count": 214,\r    "forks": 313,\r    "open_issues": 214,\r    "watchers": 275,\r    "default_branch": "master",\r    "stargazers": 275,\r    "master_branch": "master",\r    "organization": "openaddresses"\r  },\r  "pusher": {\r    "name": "ingalls",\r    "email": "nick@mapbox.com"\r  },\r  "organization": {\r    "login": "openaddresses",\r    "id": 6895392,\r    "url": "https://api.github.com/orgs/openaddresses",\r    "repos_url": "https://api.github.com/orgs/openaddresses/repos",\r    "events_url": "https://api.github.com/orgs/openaddresses/events",\r    "members_url": "https://api.github.com/orgs/openaddresses/members{/member}",\r    "public_members_url": "https://api.github.com/orgs/openaddresses/public_members{/member}",\r    "avatar_url": "https://avatars.githubusercontent.com/u/6895392?v=3",\r    "description": "The free and open global address collection "\r  },\r  "sender": {\r    "login": "ingalls",\r    "id": 1297009,\r    "avatar_url": "https://avatars.githubusercontent.com/u/1297009?v=3",\r    "gravatar_id": "",\r    "url": "https://api.github.com/users/ingalls",\r    "html_url": "https://github.com/ingalls",\r    "followers_url": "https://api.github.com/users/ingalls/followers",\r    "following_url": "https://api.github.com/users/ingalls/following{/other_user}",\r    "gists_url": "https://api.github.com/users/ingalls/gists{/gist_id}",\r    "starred_url": "https://api.github.com/users/ingalls/starred{/owner}{/repo}",\r    "subscriptions_url": "https://api.github.com/users/ingalls/subscriptions",\r    "organizations_url": "https://api.github.com/users/ingalls/orgs",\r    "repos_url": "https://api.github.com/users/ingalls/repos",\r    "events_url": "https://api.github.com/users/ingalls/events{/privacy}",\r    "received_events_url": "https://api.github.com/users/ingalls/received_events",\r    "type": "User",\r    "site_admin": false\r  }\r}'''
        
        with HTTMock(self.response_content):
            posted = self.client.post('/hook', data=data)
        
        self.assertEqual(posted.status_code, 200)
        self.assertEqual(self.last_status_state, None, 'Status should not exist for a deleted branch push')
    
    def test_webhook_pull_request(self):
        ''' Pull request from an outside contributor.
        '''
        data = '''{\r  "action": "synchronize",\r  "number": 1036,\r  "pull_request": {\r    "url": "https://api.github.com/repos/openaddresses/openaddresses/pulls/1036",\r    "id": 38189539,\r    "html_url": "https://github.com/openaddresses/openaddresses/pull/1036",\r    "diff_url": "https://github.com/openaddresses/openaddresses/pull/1036.diff",\r    "patch_url": "https://github.com/openaddresses/openaddresses/pull/1036.patch",\r    "issue_url": "https://api.github.com/repos/openaddresses/openaddresses/issues/1036",\r    "number": 1036,\r    "state": "open",\r    "locked": false,\r    "title": "Update San Diego County coverage and details",\r    "user": {\r      "login": "daguar",\r      "id": 994938,\r      "avatar_url": "https://avatars.githubusercontent.com/u/994938?v=3",\r      "gravatar_id": "",\r      "url": "https://api.github.com/users/daguar",\r      "html_url": "https://github.com/daguar",\r      "followers_url": "https://api.github.com/users/daguar/followers",\r      "following_url": "https://api.github.com/users/daguar/following{/other_user}",\r      "gists_url": "https://api.github.com/users/daguar/gists{/gist_id}",\r      "starred_url": "https://api.github.com/users/daguar/starred{/owner}{/repo}",\r      "subscriptions_url": "https://api.github.com/users/daguar/subscriptions",\r      "organizations_url": "https://api.github.com/users/daguar/orgs",\r      "repos_url": "https://api.github.com/users/daguar/repos",\r      "events_url": "https://api.github.com/users/daguar/events{/privacy}",\r      "received_events_url": "https://api.github.com/users/daguar/received_events",\r      "type": "User",\r      "site_admin": false\r    },\r    "body": "This PR improves the San Diego data source:\\r\\n\\r\\n- Corrected source to say that the data covers the _county_ of San Diego (rather just than the city)\\r\\n(per the [metadata file](http://rdw.sandag.org/file_store%5CAddress/Address_APN.pdf), `ADDRJUR` specifies the jurisdiction within the county [city or unincorporated area name] )\\r\\n- Renamed file to denote county coverage\\r\\n- Added US Census coverage data (eg, geoid)\\r\\n- Corrected attribution\\r\\n- Added link to specific license/terms\\r\\n- Added link to metadata in the notes field\\r\\n\\r\\ncc @palewire since he did a little San Diego work in #743 that had changes related to this but which were not merged\\r\\n",\r    "created_at": "2015-06-21T19:51:13Z",\r    "updated_at": "2015-06-21T20:08:05Z",\r    "closed_at": null,\r    "merged_at": null,\r    "merge_commit_sha": "71c0a042df03abed0ea1f6000182e2904fdd1749",\r    "assignee": null,\r    "milestone": null,\r    "commits_url": "https://api.github.com/repos/openaddresses/openaddresses/pulls/1036/commits",\r    "review_comments_url": "https://api.github.com/repos/openaddresses/openaddresses/pulls/1036/comments",\r    "review_comment_url": "https://api.github.com/repos/openaddresses/openaddresses/pulls/comments{/number}",\r    "comments_url": "https://api.github.com/repos/openaddresses/openaddresses/issues/1036/comments",\r    "statuses_url": "https://api.github.com/repos/openaddresses/openaddresses/statuses/f85074d543622ef1fac7a80a059a50176f2a6e08",\r    "head": {\r      "label": "daguar:fix-coverage-of-san-diego-county",\r      "ref": "fix-coverage-of-san-diego-county",\r      "sha": "f85074d543622ef1fac7a80a059a50176f2a6e08",\r      "user": {\r        "login": "daguar",\r        "id": 994938,\r        "avatar_url": "https://avatars.githubusercontent.com/u/994938?v=3",\r        "gravatar_id": "",\r        "url": "https://api.github.com/users/daguar",\r        "html_url": "https://github.com/daguar",\r        "followers_url": "https://api.github.com/users/daguar/followers",\r        "following_url": "https://api.github.com/users/daguar/following{/other_user}",\r        "gists_url": "https://api.github.com/users/daguar/gists{/gist_id}",\r        "starred_url": "https://api.github.com/users/daguar/starred{/owner}{/repo}",\r        "subscriptions_url": "https://api.github.com/users/daguar/subscriptions",\r        "organizations_url": "https://api.github.com/users/daguar/orgs",\r        "repos_url": "https://api.github.com/users/daguar/repos",\r        "events_url": "https://api.github.com/users/daguar/events{/privacy}",\r        "received_events_url": "https://api.github.com/users/daguar/received_events",\r        "type": "User",\r        "site_admin": false\r      },\r      "repo": {\r        "id": 24661971,\r        "name": "openaddresses",\r        "full_name": "daguar/openaddresses",\r        "owner": {\r          "login": "daguar",\r          "id": 994938,\r          "avatar_url": "https://avatars.githubusercontent.com/u/994938?v=3",\r          "gravatar_id": "",\r          "url": "https://api.github.com/users/daguar",\r          "html_url": "https://github.com/daguar",\r          "followers_url": "https://api.github.com/users/daguar/followers",\r          "following_url": "https://api.github.com/users/daguar/following{/other_user}",\r          "gists_url": "https://api.github.com/users/daguar/gists{/gist_id}",\r          "starred_url": "https://api.github.com/users/daguar/starred{/owner}{/repo}",\r          "subscriptions_url": "https://api.github.com/users/daguar/subscriptions",\r          "organizations_url": "https://api.github.com/users/daguar/orgs",\r          "repos_url": "https://api.github.com/users/daguar/repos",\r          "events_url": "https://api.github.com/users/daguar/events{/privacy}",\r          "received_events_url": "https://api.github.com/users/daguar/received_events",\r          "type": "User",\r          "site_admin": false\r        },\r        "private": false,\r        "html_url": "https://github.com/daguar/openaddresses",\r        "description": "A repository of address data.",\r        "fork": true,\r        "url": "https://api.github.com/repos/daguar/openaddresses",\r        "forks_url": "https://api.github.com/repos/daguar/openaddresses/forks",\r        "keys_url": "https://api.github.com/repos/daguar/openaddresses/keys{/key_id}",\r        "collaborators_url": "https://api.github.com/repos/daguar/openaddresses/collaborators{/collaborator}",\r        "teams_url": "https://api.github.com/repos/daguar/openaddresses/teams",\r        "hooks_url": "https://api.github.com/repos/daguar/openaddresses/hooks",\r        "issue_events_url": "https://api.github.com/repos/daguar/openaddresses/issues/events{/number}",\r        "events_url": "https://api.github.com/repos/daguar/openaddresses/events",\r        "assignees_url": "https://api.github.com/repos/daguar/openaddresses/assignees{/user}",\r        "branches_url": "https://api.github.com/repos/daguar/openaddresses/branches{/branch}",\r        "tags_url": "https://api.github.com/repos/daguar/openaddresses/tags",\r        "blobs_url": "https://api.github.com/repos/daguar/openaddresses/git/blobs{/sha}",\r        "git_tags_url": "https://api.github.com/repos/daguar/openaddresses/git/tags{/sha}",\r        "git_refs_url": "https://api.github.com/repos/daguar/openaddresses/git/refs{/sha}",\r        "trees_url": "https://api.github.com/repos/daguar/openaddresses/git/trees{/sha}",\r        "statuses_url": "https://api.github.com/repos/daguar/openaddresses/statuses/{sha}",\r        "languages_url": "https://api.github.com/repos/daguar/openaddresses/languages",\r        "stargazers_url": "https://api.github.com/repos/daguar/openaddresses/stargazers",\r        "contributors_url": "https://api.github.com/repos/daguar/openaddresses/contributors",\r        "subscribers_url": "https://api.github.com/repos/daguar/openaddresses/subscribers",\r        "subscription_url": "https://api.github.com/repos/daguar/openaddresses/subscription",\r        "commits_url": "https://api.github.com/repos/daguar/openaddresses/commits{/sha}",\r        "git_commits_url": "https://api.github.com/repos/daguar/openaddresses/git/commits{/sha}",\r        "comments_url": "https://api.github.com/repos/daguar/openaddresses/comments{/number}",\r        "issue_comment_url": "https://api.github.com/repos/daguar/openaddresses/issues/comments{/number}",\r        "contents_url": "https://api.github.com/repos/daguar/openaddresses/contents/{+path}",\r        "compare_url": "https://api.github.com/repos/daguar/openaddresses/compare/{base}...{head}",\r        "merges_url": "https://api.github.com/repos/daguar/openaddresses/merges",\r        "archive_url": "https://api.github.com/repos/daguar/openaddresses/{archive_format}{/ref}",\r        "downloads_url": "https://api.github.com/repos/daguar/openaddresses/downloads",\r        "issues_url": "https://api.github.com/repos/daguar/openaddresses/issues{/number}",\r        "pulls_url": "https://api.github.com/repos/daguar/openaddresses/pulls{/number}",\r        "milestones_url": "https://api.github.com/repos/daguar/openaddresses/milestones{/number}",\r        "notifications_url": "https://api.github.com/repos/daguar/openaddresses/notifications{?since,all,participating}",\r        "labels_url": "https://api.github.com/repos/daguar/openaddresses/labels{/name}",\r        "releases_url": "https://api.github.com/repos/daguar/openaddresses/releases{/id}",\r        "created_at": "2014-10-01T01:31:54Z",\r        "updated_at": "2015-06-21T19:26:06Z",\r        "pushed_at": "2015-06-21T20:08:05Z",\r        "git_url": "git://github.com/daguar/openaddresses.git",\r        "ssh_url": "git@github.com:daguar/openaddresses.git",\r        "clone_url": "https://github.com/daguar/openaddresses.git",\r        "svn_url": "https://github.com/daguar/openaddresses",\r        "homepage": "http://openaddresses.io/",\r        "size": 2988,\r        "stargazers_count": 1,\r        "watchers_count": 1,\r        "language": "JavaScript",\r        "has_issues": false,\r        "has_downloads": true,\r        "has_wiki": true,\r        "has_pages": false,\r        "forks_count": 0,\r        "mirror_url": null,\r        "open_issues_count": 0,\r        "forks": 0,\r        "open_issues": 0,\r        "watchers": 1,\r        "default_branch": "master"\r      }\r    },\r    "base": {\r      "label": "openaddresses:master",\r      "ref": "master",\r      "sha": "97922c724541b0446ea2c022f9f200b9989f1a75",\r      "user": {\r        "login": "openaddresses",\r        "id": 6895392,\r        "avatar_url": "https://avatars.githubusercontent.com/u/6895392?v=3",\r        "gravatar_id": "",\r        "url": "https://api.github.com/users/openaddresses",\r        "html_url": "https://github.com/openaddresses",\r        "followers_url": "https://api.github.com/users/openaddresses/followers",\r        "following_url": "https://api.github.com/users/openaddresses/following{/other_user}",\r        "gists_url": "https://api.github.com/users/openaddresses/gists{/gist_id}",\r        "starred_url": "https://api.github.com/users/openaddresses/starred{/owner}{/repo}",\r        "subscriptions_url": "https://api.github.com/users/openaddresses/subscriptions",\r        "organizations_url": "https://api.github.com/users/openaddresses/orgs",\r        "repos_url": "https://api.github.com/users/openaddresses/repos",\r        "events_url": "https://api.github.com/users/openaddresses/events{/privacy}",\r        "received_events_url": "https://api.github.com/users/openaddresses/received_events",\r        "type": "Organization",\r        "site_admin": false\r      },\r      "repo": {\r        "id": 16594532,\r        "name": "openaddresses",\r        "full_name": "openaddresses/openaddresses",\r        "owner": {\r          "login": "openaddresses",\r          "id": 6895392,\r          "avatar_url": "https://avatars.githubusercontent.com/u/6895392?v=3",\r          "gravatar_id": "",\r          "url": "https://api.github.com/users/openaddresses",\r          "html_url": "https://github.com/openaddresses",\r          "followers_url": "https://api.github.com/users/openaddresses/followers",\r          "following_url": "https://api.github.com/users/openaddresses/following{/other_user}",\r          "gists_url": "https://api.github.com/users/openaddresses/gists{/gist_id}",\r          "starred_url": "https://api.github.com/users/openaddresses/starred{/owner}{/repo}",\r          "subscriptions_url": "https://api.github.com/users/openaddresses/subscriptions",\r          "organizations_url": "https://api.github.com/users/openaddresses/orgs",\r          "repos_url": "https://api.github.com/users/openaddresses/repos",\r          "events_url": "https://api.github.com/users/openaddresses/events{/privacy}",\r          "received_events_url": "https://api.github.com/users/openaddresses/received_events",\r          "type": "Organization",\r          "site_admin": false\r        },\r        "private": false,\r        "html_url": "https://github.com/openaddresses/openaddresses",\r        "description": "A repository of address data.",\r        "fork": false,\r        "url": "https://api.github.com/repos/openaddresses/openaddresses",\r        "forks_url": "https://api.github.com/repos/openaddresses/openaddresses/forks",\r        "keys_url": "https://api.github.com/repos/openaddresses/openaddresses/keys{/key_id}",\r        "collaborators_url": "https://api.github.com/repos/openaddresses/openaddresses/collaborators{/collaborator}",\r        "teams_url": "https://api.github.com/repos/openaddresses/openaddresses/teams",\r        "hooks_url": "https://api.github.com/repos/openaddresses/openaddresses/hooks",\r        "issue_events_url": "https://api.github.com/repos/openaddresses/openaddresses/issues/events{/number}",\r        "events_url": "https://api.github.com/repos/openaddresses/openaddresses/events",\r        "assignees_url": "https://api.github.com/repos/openaddresses/openaddresses/assignees{/user}",\r        "branches_url": "https://api.github.com/repos/openaddresses/openaddresses/branches{/branch}",\r        "tags_url": "https://api.github.com/repos/openaddresses/openaddresses/tags",\r        "blobs_url": "https://api.github.com/repos/openaddresses/openaddresses/git/blobs{/sha}",\r        "git_tags_url": "https://api.github.com/repos/openaddresses/openaddresses/git/tags{/sha}",\r        "git_refs_url": "https://api.github.com/repos/openaddresses/openaddresses/git/refs{/sha}",\r        "trees_url": "https://api.github.com/repos/openaddresses/openaddresses/git/trees{/sha}",\r        "statuses_url": "https://api.github.com/repos/openaddresses/openaddresses/statuses/{sha}",\r        "languages_url": "https://api.github.com/repos/openaddresses/openaddresses/languages",\r        "stargazers_url": "https://api.github.com/repos/openaddresses/openaddresses/stargazers",\r        "contributors_url": "https://api.github.com/repos/openaddresses/openaddresses/contributors",\r        "subscribers_url": "https://api.github.com/repos/openaddresses/openaddresses/subscribers",\r        "subscription_url": "https://api.github.com/repos/openaddresses/openaddresses/subscription",\r        "commits_url": "https://api.github.com/repos/openaddresses/openaddresses/commits{/sha}",\r        "git_commits_url": "https://api.github.com/repos/openaddresses/openaddresses/git/commits{/sha}",\r        "comments_url": "https://api.github.com/repos/openaddresses/openaddresses/comments{/number}",\r        "issue_comment_url": "https://api.github.com/repos/openaddresses/openaddresses/issues/comments{/number}",\r        "contents_url": "https://api.github.com/repos/openaddresses/openaddresses/contents/{+path}",\r        "compare_url": "https://api.github.com/repos/openaddresses/openaddresses/compare/{base}...{head}",\r        "merges_url": "https://api.github.com/repos/openaddresses/openaddresses/merges",\r        "archive_url": "https://api.github.com/repos/openaddresses/openaddresses/{archive_format}{/ref}",\r        "downloads_url": "https://api.github.com/repos/openaddresses/openaddresses/downloads",\r        "issues_url": "https://api.github.com/repos/openaddresses/openaddresses/issues{/number}",\r        "pulls_url": "https://api.github.com/repos/openaddresses/openaddresses/pulls{/number}",\r        "milestones_url": "https://api.github.com/repos/openaddresses/openaddresses/milestones{/number}",\r        "notifications_url": "https://api.github.com/repos/openaddresses/openaddresses/notifications{?since,all,participating}",\r        "labels_url": "https://api.github.com/repos/openaddresses/openaddresses/labels{/name}",\r        "releases_url": "https://api.github.com/repos/openaddresses/openaddresses/releases{/id}",\r        "created_at": "2014-02-06T21:29:20Z",\r        "updated_at": "2015-06-18T09:14:44Z",\r        "pushed_at": "2015-06-21T20:08:06Z",\r        "git_url": "git://github.com/openaddresses/openaddresses.git",\r        "ssh_url": "git@github.com:openaddresses/openaddresses.git",\r        "clone_url": "https://github.com/openaddresses/openaddresses.git",\r        "svn_url": "https://github.com/openaddresses/openaddresses",\r        "homepage": "http://openaddresses.io/",\r        "size": 10029,\r        "stargazers_count": 276,\r        "watchers_count": 276,\r        "language": "JavaScript",\r        "has_issues": true,\r        "has_downloads": true,\r        "has_wiki": true,\r        "has_pages": false,\r        "forks_count": 315,\r        "mirror_url": null,\r        "open_issues_count": 219,\r        "forks": 315,\r        "open_issues": 219,\r        "watchers": 276,\r        "default_branch": "master"\r      }\r    },\r    "_links": {\r      "self": {\r        "href": "https://api.github.com/repos/openaddresses/openaddresses/pulls/1036"\r      },\r      "html": {\r        "href": "https://github.com/openaddresses/openaddresses/pull/1036"\r      },\r      "issue": {\r        "href": "https://api.github.com/repos/openaddresses/openaddresses/issues/1036"\r      },\r      "comments": {\r        "href": "https://api.github.com/repos/openaddresses/openaddresses/issues/1036/comments"\r      },\r      "review_comments": {\r        "href": "https://api.github.com/repos/openaddresses/openaddresses/pulls/1036/comments"\r      },\r      "review_comment": {\r        "href": "https://api.github.com/repos/openaddresses/openaddresses/pulls/comments{/number}"\r      },\r      "commits": {\r        "href": "https://api.github.com/repos/openaddresses/openaddresses/pulls/1036/commits"\r      },\r      "statuses": {\r        "href": "https://api.github.com/repos/openaddresses/openaddresses/statuses/f85074d543622ef1fac7a80a059a50176f2a6e08"\r      }\r    },\r    "merged": false,\r    "mergeable": null,\r    "mergeable_state": "unknown",\r    "merged_by": null,\r    "comments": 2,\r    "review_comments": 0,\r    "commits": 2,\r    "additions": 10,\r    "deletions": 3,\r    "changed_files": 1\r  },\r  "repository": {\r    "id": 16594532,\r    "name": "openaddresses",\r    "full_name": "openaddresses/openaddresses",\r    "owner": {\r      "login": "openaddresses",\r      "id": 6895392,\r      "avatar_url": "https://avatars.githubusercontent.com/u/6895392?v=3",\r      "gravatar_id": "",\r      "url": "https://api.github.com/users/openaddresses",\r      "html_url": "https://github.com/openaddresses",\r      "followers_url": "https://api.github.com/users/openaddresses/followers",\r      "following_url": "https://api.github.com/users/openaddresses/following{/other_user}",\r      "gists_url": "https://api.github.com/users/openaddresses/gists{/gist_id}",\r      "starred_url": "https://api.github.com/users/openaddresses/starred{/owner}{/repo}",\r      "subscriptions_url": "https://api.github.com/users/openaddresses/subscriptions",\r      "organizations_url": "https://api.github.com/users/openaddresses/orgs",\r      "repos_url": "https://api.github.com/users/openaddresses/repos",\r      "events_url": "https://api.github.com/users/openaddresses/events{/privacy}",\r      "received_events_url": "https://api.github.com/users/openaddresses/received_events",\r      "type": "Organization",\r      "site_admin": false\r    },\r    "private": false,\r    "html_url": "https://github.com/openaddresses/openaddresses",\r    "description": "A repository of address data.",\r    "fork": false,\r    "url": "https://api.github.com/repos/openaddresses/openaddresses",\r    "forks_url": "https://api.github.com/repos/openaddresses/openaddresses/forks",\r    "keys_url": "https://api.github.com/repos/openaddresses/openaddresses/keys{/key_id}",\r    "collaborators_url": "https://api.github.com/repos/openaddresses/openaddresses/collaborators{/collaborator}",\r    "teams_url": "https://api.github.com/repos/openaddresses/openaddresses/teams",\r    "hooks_url": "https://api.github.com/repos/openaddresses/openaddresses/hooks",\r    "issue_events_url": "https://api.github.com/repos/openaddresses/openaddresses/issues/events{/number}",\r    "events_url": "https://api.github.com/repos/openaddresses/openaddresses/events",\r    "assignees_url": "https://api.github.com/repos/openaddresses/openaddresses/assignees{/user}",\r    "branches_url": "https://api.github.com/repos/openaddresses/openaddresses/branches{/branch}",\r    "tags_url": "https://api.github.com/repos/openaddresses/openaddresses/tags",\r    "blobs_url": "https://api.github.com/repos/openaddresses/openaddresses/git/blobs{/sha}",\r    "git_tags_url": "https://api.github.com/repos/openaddresses/openaddresses/git/tags{/sha}",\r    "git_refs_url": "https://api.github.com/repos/openaddresses/openaddresses/git/refs{/sha}",\r    "trees_url": "https://api.github.com/repos/openaddresses/openaddresses/git/trees{/sha}",\r    "statuses_url": "https://api.github.com/repos/openaddresses/openaddresses/statuses/{sha}",\r    "languages_url": "https://api.github.com/repos/openaddresses/openaddresses/languages",\r    "stargazers_url": "https://api.github.com/repos/openaddresses/openaddresses/stargazers",\r    "contributors_url": "https://api.github.com/repos/openaddresses/openaddresses/contributors",\r    "subscribers_url": "https://api.github.com/repos/openaddresses/openaddresses/subscribers",\r    "subscription_url": "https://api.github.com/repos/openaddresses/openaddresses/subscription",\r    "commits_url": "https://api.github.com/repos/openaddresses/openaddresses/commits{/sha}",\r    "git_commits_url": "https://api.github.com/repos/openaddresses/openaddresses/git/commits{/sha}",\r    "comments_url": "https://api.github.com/repos/openaddresses/openaddresses/comments{/number}",\r    "issue_comment_url": "https://api.github.com/repos/openaddresses/openaddresses/issues/comments{/number}",\r    "contents_url": "https://api.github.com/repos/openaddresses/openaddresses/contents/{+path}",\r    "compare_url": "https://api.github.com/repos/openaddresses/openaddresses/compare/{base}...{head}",\r    "merges_url": "https://api.github.com/repos/openaddresses/openaddresses/merges",\r    "archive_url": "https://api.github.com/repos/openaddresses/openaddresses/{archive_format}{/ref}",\r    "downloads_url": "https://api.github.com/repos/openaddresses/openaddresses/downloads",\r    "issues_url": "https://api.github.com/repos/openaddresses/openaddresses/issues{/number}",\r    "pulls_url": "https://api.github.com/repos/openaddresses/openaddresses/pulls{/number}",\r    "milestones_url": "https://api.github.com/repos/openaddresses/openaddresses/milestones{/number}",\r    "notifications_url": "https://api.github.com/repos/openaddresses/openaddresses/notifications{?since,all,participating}",\r    "labels_url": "https://api.github.com/repos/openaddresses/openaddresses/labels{/name}",\r    "releases_url": "https://api.github.com/repos/openaddresses/openaddresses/releases{/id}",\r    "created_at": "2014-02-06T21:29:20Z",\r    "updated_at": "2015-06-18T09:14:44Z",\r    "pushed_at": "2015-06-21T20:08:06Z",\r    "git_url": "git://github.com/openaddresses/openaddresses.git",\r    "ssh_url": "git@github.com:openaddresses/openaddresses.git",\r    "clone_url": "https://github.com/openaddresses/openaddresses.git",\r    "svn_url": "https://github.com/openaddresses/openaddresses",\r    "homepage": "http://openaddresses.io/",\r    "size": 10029,\r    "stargazers_count": 276,\r    "watchers_count": 276,\r    "language": "JavaScript",\r    "has_issues": true,\r    "has_downloads": true,\r    "has_wiki": true,\r    "has_pages": false,\r    "forks_count": 315,\r    "mirror_url": null,\r    "open_issues_count": 219,\r    "forks": 315,\r    "open_issues": 219,\r    "watchers": 276,\r    "default_branch": "master"\r  },\r  "organization": {\r    "login": "openaddresses",\r    "id": 6895392,\r    "url": "https://api.github.com/orgs/openaddresses",\r    "repos_url": "https://api.github.com/orgs/openaddresses/repos",\r    "events_url": "https://api.github.com/orgs/openaddresses/events",\r    "members_url": "https://api.github.com/orgs/openaddresses/members{/member}",\r    "public_members_url": "https://api.github.com/orgs/openaddresses/public_members{/member}",\r    "avatar_url": "https://avatars.githubusercontent.com/u/6895392?v=3",\r    "description": "The free and open global address collection "\r  },\r  "sender": {\r    "login": "daguar",\r    "id": 994938,\r    "avatar_url": "https://avatars.githubusercontent.com/u/994938?v=3",\r    "gravatar_id": "",\r    "url": "https://api.github.com/users/daguar",\r    "html_url": "https://github.com/daguar",\r    "followers_url": "https://api.github.com/users/daguar/followers",\r    "following_url": "https://api.github.com/users/daguar/following{/other_user}",\r    "gists_url": "https://api.github.com/users/daguar/gists{/gist_id}",\r    "starred_url": "https://api.github.com/users/daguar/starred{/owner}{/repo}",\r    "subscriptions_url": "https://api.github.com/users/daguar/subscriptions",\r    "organizations_url": "https://api.github.com/users/daguar/orgs",\r    "repos_url": "https://api.github.com/users/daguar/repos",\r    "events_url": "https://api.github.com/users/daguar/events{/privacy}",\r    "received_events_url": "https://api.github.com/users/daguar/received_events",\r    "type": "User",\r    "site_admin": false\r  }\r}\r'''
        
        with HTTMock(self.response_content):
            posted = self.client.post('/hook', data=data)
        
        self.assertEqual(posted.status_code, 200)
        self.assertEqual(self.last_status_state, 'pending', 'Status should be pending for a valid pull request')
        
        # Look for the task in the task queue.
        with db_connect(self.database_url) as conn:
            task_queue = db_queue(conn, TASK_QUEUE)
            task_count = len(task_queue)
            task = task_queue.get()
            
        self.assertEqual(task_count, 1, 'There should be exactly one task in the queue')
        self.assertEqual(task.data['name'], 'sources/us-ca-san_diego_county.json', 'San Diego should be there')
        self.assertEqual(task.data['file_id'], '0c7cf2f3e4cb5f0c07818a029e1decc9797ad3a1')
    
    def test_webhook_remove_existing_file(self):
        ''' Update with removal of an existing file.
        '''
        data = '''{\r  "ref": "refs/heads/master",\r  "before": "6a7b18728673fc7621bb46ed1a445611f33324f9",\r  "after": "bba8f709793f96750fed223d44ba373a92540b2a",\r  "created": false,\r  "deleted": false,\r  "forced": false,\r  "base_ref": null,\r  "compare": "https://github.com/openaddresses/openaddresses/compare/6a7b18728673...bba8f709793f",\r  "commits": [\r    {\r      "id": "e1af73800eb25192099c4b1dd75bf0fbec3657fd",\r      "distinct": true,\r      "message": "Update San Diego County coverage (rename as county, update as county, add source details)",\r      "timestamp": "2015-06-21T12:45:12-07:00",\r      "url": "https://github.com/openaddresses/openaddresses/commit/e1af73800eb25192099c4b1dd75bf0fbec3657fd",\r      "author": {\r        "name": "Dave Guarino",\r        "email": "dave@codeforamerica.org",\r        "username": "daguar"\r      },\r      "committer": {\r        "name": "Dave Guarino",\r        "email": "dave@codeforamerica.org",\r        "username": "daguar"\r      },\r      "added": [\r        "sources/us-ca-san_diego_county.json"\r      ],\r      "removed": [\r        "sources/us-ca-san_diego.json"\r      ],\r      "modified": [\r\r      ]\r    },\r    {\r      "id": "f85074d543622ef1fac7a80a059a50176f2a6e08",\r      "distinct": true,\r      "message": "Fix San Diego County changes (key should be 'note' not 'notes')",\r      "timestamp": "2015-06-21T13:07:58-07:00",\r      "url": "https://github.com/openaddresses/openaddresses/commit/f85074d543622ef1fac7a80a059a50176f2a6e08",\r      "author": {\r        "name": "Dave Guarino",\r        "email": "dave@codeforamerica.org",\r        "username": "daguar"\r      },\r      "committer": {\r        "name": "Dave Guarino",\r        "email": "dave@codeforamerica.org",\r        "username": "daguar"\r      },\r      "added": [\r\r      ],\r      "removed": [\r\r      ],\r      "modified": [\r        "sources/us-ca-san_diego_county.json"\r      ]\r    },\r    {\r      "id": "bba8f709793f96750fed223d44ba373a92540b2a",\r      "distinct": true,\r      "message": "Merge pull request #1036 from daguar/fix-coverage-of-san-diego-county\\n\\nUpdate San Diego County coverage and details",\r      "timestamp": "2015-06-21T13:25:01-07:00",\r      "url": "https://github.com/openaddresses/openaddresses/commit/bba8f709793f96750fed223d44ba373a92540b2a",\r      "author": {\r        "name": "migurski",\r        "email": "mike-github@teczno.com",\r        "username": "migurski"\r      },\r      "committer": {\r        "name": "migurski",\r        "email": "mike-github@teczno.com",\r        "username": "migurski"\r      },\r      "added": [\r        "sources/us-ca-san_diego_county.json"\r      ],\r      "removed": [\r        "sources/us-ca-san_diego.json"\r      ],\r      "modified": [\r\r      ]\r    }\r  ],\r  "head_commit": {\r    "id": "bba8f709793f96750fed223d44ba373a92540b2a",\r    "distinct": true,\r    "message": "Merge pull request #1036 from daguar/fix-coverage-of-san-diego-county\\n\\nUpdate San Diego County coverage and details",\r    "timestamp": "2015-06-21T13:25:01-07:00",\r    "url": "https://github.com/openaddresses/openaddresses/commit/bba8f709793f96750fed223d44ba373a92540b2a",\r    "author": {\r      "name": "migurski",\r      "email": "mike-github@teczno.com",\r      "username": "migurski"\r    },\r    "committer": {\r      "name": "migurski",\r      "email": "mike-github@teczno.com",\r      "username": "migurski"\r    },\r    "added": [\r      "sources/us-ca-san_diego_county.json"\r    ],\r    "removed": [\r      "sources/us-ca-san_diego.json"\r    ],\r    "modified": [\r\r    ]\r  },\r  "repository": {\r    "id": 16594532,\r    "name": "openaddresses",\r    "full_name": "openaddresses/openaddresses",\r    "owner": {\r      "name": "openaddresses",\r      "email": "openaddresses@gmail.com"\r    },\r    "private": false,\r    "html_url": "https://github.com/openaddresses/openaddresses",\r    "description": "A repository of address data.",\r    "fork": false,\r    "url": "https://github.com/openaddresses/openaddresses",\r    "forks_url": "https://api.github.com/repos/openaddresses/openaddresses/forks",\r    "keys_url": "https://api.github.com/repos/openaddresses/openaddresses/keys{/key_id}",\r    "collaborators_url": "https://api.github.com/repos/openaddresses/openaddresses/collaborators{/collaborator}",\r    "teams_url": "https://api.github.com/repos/openaddresses/openaddresses/teams",\r    "hooks_url": "https://api.github.com/repos/openaddresses/openaddresses/hooks",\r    "issue_events_url": "https://api.github.com/repos/openaddresses/openaddresses/issues/events{/number}",\r    "events_url": "https://api.github.com/repos/openaddresses/openaddresses/events",\r    "assignees_url": "https://api.github.com/repos/openaddresses/openaddresses/assignees{/user}",\r    "branches_url": "https://api.github.com/repos/openaddresses/openaddresses/branches{/branch}",\r    "tags_url": "https://api.github.com/repos/openaddresses/openaddresses/tags",\r    "blobs_url": "https://api.github.com/repos/openaddresses/openaddresses/git/blobs{/sha}",\r    "git_tags_url": "https://api.github.com/repos/openaddresses/openaddresses/git/tags{/sha}",\r    "git_refs_url": "https://api.github.com/repos/openaddresses/openaddresses/git/refs{/sha}",\r    "trees_url": "https://api.github.com/repos/openaddresses/openaddresses/git/trees{/sha}",\r    "statuses_url": "https://api.github.com/repos/openaddresses/openaddresses/statuses/{sha}",\r    "languages_url": "https://api.github.com/repos/openaddresses/openaddresses/languages",\r    "stargazers_url": "https://api.github.com/repos/openaddresses/openaddresses/stargazers",\r    "contributors_url": "https://api.github.com/repos/openaddresses/openaddresses/contributors",\r    "subscribers_url": "https://api.github.com/repos/openaddresses/openaddresses/subscribers",\r    "subscription_url": "https://api.github.com/repos/openaddresses/openaddresses/subscription",\r    "commits_url": "https://api.github.com/repos/openaddresses/openaddresses/commits{/sha}",\r    "git_commits_url": "https://api.github.com/repos/openaddresses/openaddresses/git/commits{/sha}",\r    "comments_url": "https://api.github.com/repos/openaddresses/openaddresses/comments{/number}",\r    "issue_comment_url": "https://api.github.com/repos/openaddresses/openaddresses/issues/comments{/number}",\r    "contents_url": "https://api.github.com/repos/openaddresses/openaddresses/contents/{+path}",\r    "compare_url": "https://api.github.com/repos/openaddresses/openaddresses/compare/{base}...{head}",\r    "merges_url": "https://api.github.com/repos/openaddresses/openaddresses/merges",\r    "archive_url": "https://api.github.com/repos/openaddresses/openaddresses/{archive_format}{/ref}",\r    "downloads_url": "https://api.github.com/repos/openaddresses/openaddresses/downloads",\r    "issues_url": "https://api.github.com/repos/openaddresses/openaddresses/issues{/number}",\r    "pulls_url": "https://api.github.com/repos/openaddresses/openaddresses/pulls{/number}",\r    "milestones_url": "https://api.github.com/repos/openaddresses/openaddresses/milestones{/number}",\r    "notifications_url": "https://api.github.com/repos/openaddresses/openaddresses/notifications{?since,all,participating}",\r    "labels_url": "https://api.github.com/repos/openaddresses/openaddresses/labels{/name}",\r    "releases_url": "https://api.github.com/repos/openaddresses/openaddresses/releases{/id}",\r    "created_at": 1391722160,\r    "updated_at": "2015-06-18T09:14:44Z",\r    "pushed_at": 1434918301,\r    "git_url": "git://github.com/openaddresses/openaddresses.git",\r    "ssh_url": "git@github.com:openaddresses/openaddresses.git",\r    "clone_url": "https://github.com/openaddresses/openaddresses.git",\r    "svn_url": "https://github.com/openaddresses/openaddresses",\r    "homepage": "http://openaddresses.io/",\r    "size": 10029,\r    "stargazers_count": 276,\r    "watchers_count": 276,\r    "language": "JavaScript",\r    "has_issues": true,\r    "has_downloads": true,\r    "has_wiki": true,\r    "has_pages": false,\r    "forks_count": 315,\r    "mirror_url": null,\r    "open_issues_count": 216,\r    "forks": 315,\r    "open_issues": 216,\r    "watchers": 276,\r    "default_branch": "master",\r    "stargazers": 276,\r    "master_branch": "master",\r    "organization": "openaddresses"\r  },\r  "pusher": {\r    "name": "migurski",\r    "email": "mike-github@teczno.com"\r  },\r  "organization": {\r    "login": "openaddresses",\r    "id": 6895392,\r    "url": "https://api.github.com/orgs/openaddresses",\r    "repos_url": "https://api.github.com/orgs/openaddresses/repos",\r    "events_url": "https://api.github.com/orgs/openaddresses/events",\r    "members_url": "https://api.github.com/orgs/openaddresses/members{/member}",\r    "public_members_url": "https://api.github.com/orgs/openaddresses/public_members{/member}",\r    "avatar_url": "https://avatars.githubusercontent.com/u/6895392?v=3",\r    "description": "The free and open global address collection "\r  },\r  "sender": {\r    "login": "migurski",\r    "id": 58730,\r    "avatar_url": "https://avatars.githubusercontent.com/u/58730?v=3",\r    "gravatar_id": "",\r    "url": "https://api.github.com/users/migurski",\r    "html_url": "https://github.com/migurski",\r    "followers_url": "https://api.github.com/users/migurski/followers",\r    "following_url": "https://api.github.com/users/migurski/following{/other_user}",\r    "gists_url": "https://api.github.com/users/migurski/gists{/gist_id}",\r    "starred_url": "https://api.github.com/users/migurski/starred{/owner}{/repo}",\r    "subscriptions_url": "https://api.github.com/users/migurski/subscriptions",\r    "organizations_url": "https://api.github.com/users/migurski/orgs",\r    "repos_url": "https://api.github.com/users/migurski/repos",\r    "events_url": "https://api.github.com/users/migurski/events{/privacy}",\r    "received_events_url": "https://api.github.com/users/migurski/received_events",\r    "type": "User",\r    "site_admin": false\r  }\r}'''
        
        with HTTMock(self.response_content):
            posted = self.client.post('/hook', data=data)
        
        self.assertEqual(posted.status_code, 200)
        self.assertEqual(self.last_status_state, 'pending', 'Status should be pending for a valid pull request')
        
        # Look for the task in the task queue.
        with db_connect(self.database_url) as conn:
            task_queue = db_queue(conn, TASK_QUEUE)
            task_count = len(task_queue)
            task = task_queue.get()
            
        self.assertEqual(task_count, 1, 'There should be exactly one task in the queue')
        self.assertEqual(task.data['name'], 'sources/us-ca-san_diego_county.json', 'San Diego should be there')
        self.assertEqual(task.data['file_id'], '0c7cf2f3e4cb5f0c07818a029e1decc9797ad3a1')
    
class TestRuns (unittest.TestCase):

    def setUp(self):
        '''
        '''
        recreate_db.recreate(os.environ['DATABASE_URL'])
        self.database_url = os.environ['DATABASE_URL']
        self.output_dir = mkdtemp(prefix='TestRuns-')
        self.s3 = FakeS3()
        
        self.github_auth = 'Fake', 'Auth'
        self.fake_job_template_url = 'http://example.com/{id}'
        self.fake_status_url = 'http://api.github.com/repos/openaddresses/fake-sources/statuses/ff9900'
        self.last_status_state = None
    
    def tearDown(self):
        '''
        '''
        rmtree(self.output_dir)
        remove(self.s3._fake_keys)
        return
        
        with db_connect(self.database_url) as conn:
            with db_cursor(conn) as db:
                db.execute('TRUNCATE jobs')
                db.execute('TRUNCATE queue')
    
    def response_content(self, url, request):
        '''
        '''
        query = dict(parse_qsl(url.query))
        MHP = request.method, url.hostname, url.path
        GH, response_headers = 'api.github.com', {'Content-Type': 'application/json; charset=utf-8'}
        
        if MHP == ('POST', GH, '/repos/openaddresses/fake-sources/statuses/ff9900'):
            input = json.loads(request.body)
            self.last_status_state = input['state']
            self.last_status_message = input['description']
            self.assertEqual(input['context'], 'openaddresses/hooked')
            
            data = '''{{\r              "context": "openaddresses/hooked", \r              "created_at": "2015-04-26T23:45:39Z", \r              "creator": {{\r                "avatar_url": "https://avatars.githubusercontent.com/u/58730?v=3", \r                "events_url": "https://api.github.com/users/migurski/events{{/privacy}}", \r                "followers_url": "https://api.github.com/users/migurski/followers", \r                "following_url": "https://api.github.com/users/migurski/following{{/other_user}}", \r                "gists_url": "https://api.github.com/users/migurski/gists{{/gist_id}}", \r                "gravatar_id": "", \r                "html_url": "https://github.com/migurski", \r                "id": 58730, \r                "login": "migurski", \r                "organizations_url": "https://api.github.com/users/migurski/orgs", \r                "received_events_url": "https://api.github.com/users/migurski/received_events", \r                "repos_url": "https://api.github.com/users/migurski/repos", \r                "site_admin": false, \r                "starred_url": "https://api.github.com/users/migurski/starred{{/owner}}{{/repo}}", \r                "subscriptions_url": "https://api.github.com/users/migurski/subscriptions", \r                "type": "User", \r                "url": "https://api.github.com/users/migurski"\r              }}, \r              "description": "Checking ", \r              "id": 999999999, \r              "state": "{state}", \r              "target_url": null, \r              "updated_at": "2015-04-26T23:45:39Z", \r              "url": "https://api.github.com/repos/openaddresses/hooked-on-sources/statuses/xxxxxxxxx"\r            }}'''
            return response(201, data.format(**input).encode('utf8'), headers=response_headers)
        
        print('Unknowable Request {} "{}"'.format(request.method, url.geturl()), file=sys.stderr)
        raise ValueError('Unknowable Request {} "{}"'.format(request.method, url.geturl()))

    @patch('openaddr.jobs.JOB_TIMEOUT', new=timedelta(seconds=1))
    @patch('openaddr.ci.DUETASK_DELAY', new=timedelta(seconds=1))
    @patch('openaddr.ci.worker.do_work')
    def test_working_run(self, do_work):
        '''
        '''
        source = '''{
            "coverage": { "US Census": {"geoid": "0653000", "place": "Oakland city", "state": "California"} },
            "data": "http://data.openoakland.org/sites/default/files/OakParcelsGeo2013_0.zip"
            }'''
        
        source_id, source_path = '0xDEADBEEF', 'sources/us-ca-oakland.json'
        
        def returns_plausible_result(s3, run_id, source_name, content, output_dir):
            return dict(message=MAGIC_OK_MESSAGE, output={"source": "user_input.txt"})
        
        do_work.side_effect = returns_plausible_result

        # Do the work.
        with db_connect(self.database_url) as conn, HTTMock(self.response_content):
            task_Q = db_queue(conn, TASK_QUEUE)
            done_Q = db_queue(conn, DONE_QUEUE)
            due_Q = db_queue(conn, DUE_QUEUE)

            files = {source_path: (source, source_id)}
            job_id = create_queued_job(task_Q, files, self.fake_job_template_url, self.fake_status_url)
            pop_task_from_taskqueue(self.s3, task_Q, done_Q, due_Q, self.output_dir)
            self.assertEqual(self.last_status_state, None, 'Should be nothing yet')
            
            # Work done! 
            pop_task_from_donequeue(done_Q, self.github_auth)
            self.assertEqual(self.last_status_state, 'success', 'Should be "success" now')

            # Should do nothing, because no Due task is yet scheduled.
            pop_task_from_duequeue(due_Q, self.github_auth)
            self.assertEqual(self.last_status_state, 'success', 'Should be unchanged')

            sleep(2.1)
            
            # Should do nothing, because Due task data will be found in runs table.
            pop_task_from_duequeue(due_Q, self.github_auth)
            self.assertEqual(self.last_status_state, 'success', 'Should be unchanged')
            
            # Find a record of this run.
            with done_Q as db:
                db.execute('SELECT source_path, source_id, source_data FROM runs')
                ((db_source_path, db_source_id, db_source_data), ) = db.fetchall()
                self.assertEqual(db_source_path, source_path)
                self.assertEqual(db_source_id, source_id)
                self.assertTrue(bytes(db_source_data).decode('utf8').startswith('{'))
     
    @patch('openaddr.jobs.JOB_TIMEOUT', new=timedelta(seconds=2))
    @patch('openaddr.ci.DUETASK_DELAY', new=timedelta(seconds=1))
    @patch('openaddr.compat.check_output')
    def test_failing_run(self, check_output):
        '''
        '''
        def raises_unexpected_error(cmd, timeout=None):
            raise NotImplementedError('Everything is ruined.')

        check_output.side_effect = raises_unexpected_error

        source = '''{
            "coverage": { "US Census": {"geoid": "0653000", "place": "Oakland city", "state": "California"} },
            "data": "http://data.openoakland.org/sites/default/files/OakParcelsGeo2013_0.zip"
            }'''
        
        source_id, source_path = '0xDEADBEEF', 'sources/us-ca-oakland.json'
        
        with db_connect(self.database_url) as conn, HTTMock(self.response_content):
            task_Q = db_queue(conn, TASK_QUEUE)
            done_Q = db_queue(conn, DONE_QUEUE)
            due_Q = db_queue(conn, DUE_QUEUE)

            files = {source_path: (source, source_id)}
            job_id = create_queued_job(task_Q, files, self.fake_job_template_url, self.fake_status_url)
        
            # Bad things will happen and the job will fail.
            with self.assertRaises(NotImplementedError) as e:
                pop_task_from_taskqueue(self.s3, task_Q, done_Q, due_Q, self.output_dir)

            # Should do nothing, because a Done task was never sent.
            pop_task_from_donequeue(done_Q, None)
            self.assertEqual(self.last_status_state, None, 'Should be nothing yet')

            # Should do nothing, because no Due task is yet scheduled.
            pop_task_from_duequeue(due_Q, None)
            self.assertEqual(self.last_status_state, None, 'Should be nothing yet')
            
            # Check for result
            with db_cursor(conn) as db:
                job_status, _, _, _, _ = read_job(db, job_id)
                self.assertEquals(job_status, None, 'Status should be null at this early stage')

            sleep(2.1)
            
            # Now handle the later due task
            # Unclear why it's necessary to hit the due queue twice here?
            pop_task_from_duequeue(due_Q, None)
            pop_task_from_duequeue(due_Q, None)
            self.assertEqual(self.last_status_state, 'failure', 'Should be "failure" now')
            
            # Check for result
            with db_cursor(conn) as db:
                job_status, _, _, _, _ = read_job(db, job_id)
                self.assertEquals(job_status, False, 'Status should be false after unexpected error')
            
            # Find a record of this run.
            with done_Q as db:
                db.execute('SELECT source_path, source_id, source_data FROM runs')
                ((db_source_path, db_source_id, db_source_data), ) = db.fetchall()
                self.assertEqual(db_source_path, source_path)
                self.assertEqual(db_source_id, source_id)
                self.assertTrue(bytes(db_source_data).decode('utf8').startswith('{'))
     
    @patch('openaddr.jobs.JOB_TIMEOUT', new=timedelta(seconds=1))
    @patch('openaddr.ci.DUETASK_DELAY', new=timedelta(seconds=1))
    @patch('openaddr.ci.worker.do_work')
    def test_overdue_run(self, do_work):
        '''
        '''
        def returns_plausible_result(s3, run_id, source_name, content, output_dir):
            return dict(message=MAGIC_OK_MESSAGE, output={"source": "user_input.txt"})

        do_work.side_effect = returns_plausible_result

        source = '''{
            "coverage": { "US Census": {"geoid": "0653000", "place": "Oakland city", "state": "California"} },
            "data": "http://data.openoakland.org/sites/default/files/OakParcelsGeo2013_0.zip"
            }'''
        
        source_id, source_path = '0xDEADBEEF', 'sources/us-ca-oakland.json'
        
        with db_connect(self.database_url) as conn, HTTMock(self.response_content):
            task_Q = db_queue(conn, TASK_QUEUE)
            done_Q = db_queue(conn, DONE_QUEUE)
            due_Q = db_queue(conn, DUE_QUEUE)

            files = {source_path: (source, source_id)}
            job_id = create_queued_job(task_Q, files, self.fake_job_template_url, self.fake_status_url)
            pop_task_from_taskqueue(self.s3, task_Q, done_Q, due_Q, self.output_dir)

            # Should do nothing, because no Due task is yet scheduled.
            pop_task_from_duequeue(due_Q, None)
            self.assertEqual(self.last_status_state, None, 'Should be nothing yet')

            sleep(2.1)
            
            # Handle the due task
            pop_task_from_duequeue(due_Q, None)
            self.assertEqual(self.last_status_state, 'failure', 'Should be "failure" now')
            
            # Check for result
            with db_cursor(conn) as db:
                job_status, _, _, _, _ = read_job(db, job_id)
                self.assertEquals(job_status, False, 'Status should be false since it took so long')

            # The job eventually completes, but it's too late
            pop_task_from_donequeue(done_Q, None)
            self.assertEqual(self.last_status_state, 'failure', 'Should be unchanged')
            
            # Check for result
            with db_cursor(conn) as db:
                job_status, _, _, _, _ = read_job(db, job_id)
                self.assertEquals(job_status, False, 'Status should still be false no matter what')
            
            # Find a record of this run.
            with done_Q as db:
                db.execute('SELECT source_path, source_id, source_data FROM runs')
                ((db_source_path, db_source_id, db_source_data), ) = db.fetchall()
                self.assertEqual(db_source_path, source_path)
                self.assertEqual(db_source_id, source_id)
                self.assertTrue(bytes(db_source_data).decode('utf8').startswith('{'))
     
class TestWorker (unittest.TestCase):

    def setUp(self):
        '''
        '''
        recreate_db.recreate(os.environ['DATABASE_URL'])
        self.database_url = os.environ['DATABASE_URL']
        self.output_dir = mkdtemp(prefix='TestWorker-')
        self.s3 = FakeS3()
    
    def tearDown(self):
        '''
        '''
        rmtree(self.output_dir)
        remove(self.s3._fake_keys)
        return
        
        with db_connect(self.database_url) as conn:
            with db_cursor(conn) as db:
                db.execute('TRUNCATE jobs')
                db.execute('TRUNCATE queue')
    
    @patch('tempfile.mkdtemp')
    @patch('openaddr.compat.check_output')
    def test_happy_worker(self, check_output, mkdtemp):
        '''
        '''
        def does_what_its_told(cmd, timeout=None):
            index_path = '{id}/out/user_input/index.json'.format(**task_data)
            index_filename = os.path.join(self.output_dir, index_path)
            index_dirname = os.path.dirname(index_filename)
            os.makedirs(index_dirname)
            
            with open(index_filename, 'w') as file:
                file.write('''[ ["source", "cache", "sample", "geometry type", "address count", "version", "fingerprint", "cache time", "processed", "process time", "output"], ["user_input.txt", "cache.zip", "sample.json", "Point", 62384, null, "6c4852b8c7b0f1c7dd9af289289fb70f", "0:00:01.345149", "out.csv", "0:00:33.808682", "output.txt"] ]''')
            
            for name in ('cache.zip', 'sample.json', 'out.csv', 'output.txt'):
                with open(os.path.join(index_dirname, name), 'w') as file:
                    file.write('Yo')
            
            return index_filename
        
        def same_tempdir_every_time(prefix, dir):
            os.mkdir(join(dir, 'work'))
            return join(dir, 'work')
        
        task_data = dict(id='0xDEADBEEF', content='{ }', name='Dead Beef', url=None)
        check_output.side_effect = does_what_its_told
        mkdtemp.side_effect = same_tempdir_every_time
        
        job_id, content = task_data['id'], task_data['content']
        result = worker.do_work(self.s3, -1, 'so/happy', content, self.output_dir)
        
        check_output.assert_called_with((
            'openaddr-process-one', '-l',
            os.path.join(self.output_dir, 'work/logfile.txt'),
            os.path.join(self.output_dir, 'work/user_input.txt'),
            os.path.join(self.output_dir, 'work/out')
            ),
            timeout=JOB_TIMEOUT.seconds + JOB_TIMEOUT.days * 86400)
        
        self.assertEqual(result['message'], MAGIC_OK_MESSAGE)
        self.assertEqual(result['result_code'], 0)

        self.assertTrue(result['output']['cache'].endswith('/cache.zip'))
        self.assertTrue(result['output']['sample'].endswith('/sample.json'))
        self.assertTrue(result['output']['output'].endswith('/output.txt'))
        self.assertTrue(result['output']['processed'].endswith('/so/happy.zip'))
        
        zip_path = urlparse(result['output']['processed']).path
        zip_bytes = self.s3._read_fake_key(zip_path)
        zip_file = ZipFile(BytesIO(zip_bytes), mode='r')
        
        self.assertTrue('so/happy.csv' in zip_file.namelist())
        self.assertTrue('so/happy.vrt' in zip_file.namelist())
    
    @patch('tempfile.mkdtemp')
    @patch('openaddr.compat.check_output')
    def test_angry_worker(self, check_output, mkdtemp):
        '''
        '''
        def raises_called_process_error(cmd, timeout=None):
            raise compat.CalledProcessError(1, cmd, 'Everything is ruined.\n')
        
        def same_tempdir_every_time(prefix, dir):
            os.mkdir(join(dir, 'work'))
            return join(dir, 'work')
        
        task_data = dict(id='0xDEADBEEF', content='{ }', name='Dead Beef', url=None)
        check_output.side_effect = raises_called_process_error
        mkdtemp.side_effect = same_tempdir_every_time
        
        job_id, content = task_data['id'], task_data['content']
        result = worker.do_work(self.s3, -1, 'angry', content, self.output_dir)
        
        check_output.assert_called_with((
            'openaddr-process-one', '-l',
            os.path.join(self.output_dir, 'work/logfile.txt'),
            os.path.join(self.output_dir, 'work/user_input.txt'),
            os.path.join(self.output_dir, 'work/out')
            ),
            timeout=JOB_TIMEOUT.seconds + JOB_TIMEOUT.days * 86400)
        
        self.assertEqual(result['message'], 'Something went wrong in openaddr-process-one')
        self.assertEqual(result['result_stdout'], 'Everything is ruined.\n')
        self.assertEqual(result['result_code'], 1)

if __name__ == '__main__':
    unittest.main()
