Created
February 10, 2014 10:26
-
-
Save scottwarren/8913568 to your computer and use it in GitHub Desktop.
simple "package" of all required files for: https://www.github.com/michael/github/
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Underscore.js 1.4.2 | |
// http://underscorejs.org | |
// (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc. | |
// Underscore may be freely distributed under the MIT license. | |
(function(){var e=this,t=e._,n={},r=Array.prototype,i=Object.prototype,s=Function.prototype,o=r.push,u=r.slice,a=r.concat,f=r.unshift,l=i.toString,c=i.hasOwnProperty,h=r.forEach,p=r.map,d=r.reduce,v=r.reduceRight,m=r.filter,g=r.every,y=r.some,b=r.indexOf,w=r.lastIndexOf,E=Array.isArray,S=Object.keys,x=s.bind,T=function(e){if(e instanceof T)return e;if(!(this instanceof T))return new T(e);this._wrapped=e};typeof exports!="undefined"?(typeof module!="undefined"&&module.exports&&(exports=module.exports=T),exports._=T):e._=T,T.VERSION="1.4.2";var N=T.each=T.forEach=function(e,t,r){if(e==null)return;if(h&&e.forEach===h)e.forEach(t,r);else if(e.length===+e.length){for(var i=0,s=e.length;i<s;i++)if(t.call(r,e[i],i,e)===n)return}else for(var o in e)if(T.has(e,o)&&t.call(r,e[o],o,e)===n)return};T.map=T.collect=function(e,t,n){var r=[];return e==null?r:p&&e.map===p?e.map(t,n):(N(e,function(e,i,s){r[r.length]=t.call(n,e,i,s)}),r)},T.reduce=T.foldl=T.inject=function(e,t,n,r){var i=arguments.length>2;e==null&&(e=[]);if(d&&e.reduce===d)return r&&(t=T.bind(t,r)),i?e.reduce(t,n):e.reduce(t);N(e,function(e,s,o){i?n=t.call(r,n,e,s,o):(n=e,i=!0)});if(!i)throw new TypeError("Reduce of empty array with no initial value");return n},T.reduceRight=T.foldr=function(e,t,n,r){var i=arguments.length>2;e==null&&(e=[]);if(v&&e.reduceRight===v)return r&&(t=T.bind(t,r)),arguments.length>2?e.reduceRight(t,n):e.reduceRight(t);var s=e.length;if(s!==+s){var o=T.keys(e);s=o.length}N(e,function(u,a,f){a=o?o[--s]:--s,i?n=t.call(r,n,e[a],a,f):(n=e[a],i=!0)});if(!i)throw new TypeError("Reduce of empty array with no initial value");return n},T.find=T.detect=function(e,t,n){var r;return C(e,function(e,i,s){if(t.call(n,e,i,s))return r=e,!0}),r},T.filter=T.select=function(e,t,n){var r=[];return e==null?r:m&&e.filter===m?e.filter(t,n):(N(e,function(e,i,s){t.call(n,e,i,s)&&(r[r.length]=e)}),r)},T.reject=function(e,t,n){var r=[];return e==null?r:(N(e,function(e,i,s){t.call(n,e,i,s)||(r[r.length]=e)}),r)},T.every=T.all=function(e,t,r){t||(t=T.identity);var i=!0;return e==null?i:g&&e.every===g?e.every(t,r):(N(e,function(e,s,o){if(!(i=i&&t.call(r,e,s,o)))return n}),!!i)};var C=T.some=T.any=function(e,t,r){t||(t=T.identity);var i=!1;return e==null?i:y&&e.some===y?e.some(t,r):(N(e,function(e,s,o){if(i||(i=t.call(r,e,s,o)))return n}),!!i)};T.contains=T.include=function(e,t){var n=!1;return e==null?n:b&&e.indexOf===b?e.indexOf(t)!=-1:(n=C(e,function(e){return e===t}),n)},T.invoke=function(e,t){var n=u.call(arguments,2);return T.map(e,function(e){return(T.isFunction(t)?t:e[t]).apply(e,n)})},T.pluck=function(e,t){return T.map(e,function(e){return e[t]})},T.where=function(e,t){return T.isEmpty(t)?[]:T.filter(e,function(e){for(var n in t)if(t[n]!==e[n])return!1;return!0})},T.max=function(e,t,n){if(!t&&T.isArray(e)&&e[0]===+e[0]&&e.length<65535)return Math.max.apply(Math,e);if(!t&&T.isEmpty(e))return-Infinity;var r={computed:-Infinity};return N(e,function(e,i,s){var o=t?t.call(n,e,i,s):e;o>=r.computed&&(r={value:e,computed:o})}),r.value},T.min=function(e,t,n){if(!t&&T.isArray(e)&&e[0]===+e[0]&&e.length<65535)return Math.min.apply(Math,e);if(!t&&T.isEmpty(e))return Infinity;var r={computed:Infinity};return N(e,function(e,i,s){var o=t?t.call(n,e,i,s):e;o<r.computed&&(r={value:e,computed:o})}),r.value},T.shuffle=function(e){var t,n=0,r=[];return N(e,function(e){t=T.random(n++),r[n-1]=r[t],r[t]=e}),r};var k=function(e){return T.isFunction(e)?e:function(t){return t[e]}};T.sortBy=function(e,t,n){var r=k(t);return T.pluck(T.map(e,function(e,t,i){return{value:e,index:t,criteria:r.call(n,e,t,i)}}).sort(function(e,t){var n=e.criteria,r=t.criteria;if(n!==r){if(n>r||n===void 0)return 1;if(n<r||r===void 0)return-1}return e.index<t.index?-1:1}),"value")};var L=function(e,t,n,r){var i={},s=k(t);return N(e,function(t,o){var u=s.call(n,t,o,e);r(i,u,t)}),i};T.groupBy=function(e,t,n){return L(e,t,n,function(e,t,n){(T.has(e,t)?e[t]:e[t]=[]).push(n)})},T.countBy=function(e,t,n){return L(e,t,n,function(e,t,n){T.has(e,t)||(e[t]=0),e[t]++})},T.sortedIndex=function(e,t,n,r){n=n==null?T.identity:k(n);var i=n.call(r,t),s=0,o=e.length;while(s<o){var u=s+o>>>1;n.call(r,e[u])<i?s=u+1:o=u}return s},T.toArray=function(e){return e?e.length===+e.length?u.call(e):T.values(e):[]},T.size=function(e){return e.length===+e.length?e.length:T.keys(e).length},T.first=T.head=T.take=function(e,t,n){return t!=null&&!n?u.call(e,0,t):e[0]},T.initial=function(e,t,n){return u.call(e,0,e.length-(t==null||n?1:t))},T.last=function(e,t,n){return t!=null&&!n?u.call(e,Math.max(e.length-t,0)):e[e.length-1]},T.rest=T.tail=T.drop=function(e,t,n){return u.call(e,t==null||n?1:t)},T.compact=function(e){return T.filter(e,function(e){return!!e})};var A=function(e,t,n){return N(e,function(e){T.isArray(e)?t?o.apply(n,e):A(e,t,n):n.push(e)}),n};T.flatten=function(e,t){return A(e,t,[])},T.without=function(e){return T.difference(e,u.call(arguments,1))},T.uniq=T.unique=function(e,t,n,r){var i=n?T.map(e,n,r):e,s=[],o=[];return N(i,function(n,r){if(t?!r||o[o.length-1]!==n:!T.contains(o,n))o.push(n),s.push(e[r])}),s},T.union=function(){return T.uniq(a.apply(r,arguments))},T.intersection=function(e){var t=u.call(arguments,1);return T.filter(T.uniq(e),function(e){return T.every(t,function(t){return T.indexOf(t,e)>=0})})},T.difference=function(e){var t=a.apply(r,u.call(arguments,1));return T.filter(e,function(e){return!T.contains(t,e)})},T.zip=function(){var e=u.call(arguments),t=T.max(T.pluck(e,"length")),n=new Array(t);for(var r=0;r<t;r++)n[r]=T.pluck(e,""+r);return n},T.object=function(e,t){var n={};for(var r=0,i=e.length;r<i;r++)t?n[e[r]]=t[r]:n[e[r][0]]=e[r][1];return n},T.indexOf=function(e,t,n){if(e==null)return-1;var r=0,i=e.length;if(n){if(typeof n!="number")return r=T.sortedIndex(e,t),e[r]===t?r:-1;r=n<0?Math.max(0,i+n):n}if(b&&e.indexOf===b)return e.indexOf(t,n);for(;r<i;r++)if(e[r]===t)return r;return-1},T.lastIndexOf=function(e,t,n){if(e==null)return-1;var r=n!=null;if(w&&e.lastIndexOf===w)return r?e.lastIndexOf(t,n):e.lastIndexOf(t);var i=r?n:e.length;while(i--)if(e[i]===t)return i;return-1},T.range=function(e,t,n){arguments.length<=1&&(t=e||0,e=0),n=arguments[2]||1;var r=Math.max(Math.ceil((t-e)/n),0),i=0,s=new Array(r);while(i<r)s[i++]=e,e+=n;return s};var O=function(){};T.bind=function(t,n){var r,i;if(t.bind===x&&x)return x.apply(t,u.call(arguments,1));if(!T.isFunction(t))throw new TypeError;return i=u.call(arguments,2),r=function(){if(this instanceof r){O.prototype=t.prototype;var e=new O,s=t.apply(e,i.concat(u.call(arguments)));return Object(s)===s?s:e}return t.apply(n,i.concat(u.call(arguments)))}},T.bindAll=function(e){var t=u.call(arguments,1);return t.length==0&&(t=T.functions(e)),N(t,function(t){e[t]=T.bind(e[t],e)}),e},T.memoize=function(e,t){var n={};return t||(t=T.identity),function(){var r=t.apply(this,arguments);return T.has(n,r)?n[r]:n[r]=e.apply(this,arguments)}},T.delay=function(e,t){var n=u.call(arguments,2);return setTimeout(function(){return e.apply(null,n)},t)},T.defer=function(e){return T.delay.apply(T,[e,1].concat(u.call(arguments,1)))},T.throttle=function(e,t){var n,r,i,s,o,u,a=T.debounce(function(){o=s=!1},t);return function(){n=this,r=arguments;var f=function(){i=null,o&&(u=e.apply(n,r)),a()};return i||(i=setTimeout(f,t)),s?o=!0:(s=!0,u=e.apply(n,r)),a(),u}},T.debounce=function(e,t,n){var r,i;return function(){var s=this,o=arguments,u=function(){r=null,n||(i=e.apply(s,o))},a=n&&!r;return clearTimeout(r),r=setTimeout(u,t),a&&(i=e.apply(s,o)),i}},T.once=function(e){var t=!1,n;return function(){return t?n:(t=!0,n=e.apply(this,arguments),e=null,n)}},T.wrap=function(e,t){return function(){var n=[e];return o.apply(n,arguments),t.apply(this,n)}},T.compose=function(){var e=arguments;return function(){var t=arguments;for(var n=e.length-1;n>=0;n--)t=[e[n].apply(this,t)];return t[0]}},T.after=function(e,t){return e<=0?t():function(){if(--e<1)return t.apply(this,arguments)}},T.keys=S||function(e){if(e!==Object(e))throw new TypeError("Invalid object");var t=[];for(var n in e)T.has(e,n)&&(t[t.length]=n);return t},T.values=function(e){var t=[];for(var n in e)T.has(e,n)&&t.push(e[n]);return t},T.pairs=function(e){var t=[];for(var n in e)T.has(e,n)&&t.push([n,e[n]]);return t},T.invert=function(e){var t={};for(var n in e)T.has(e,n)&&(t[e[n]]=n);return t},T.functions=T.methods=function(e){var t=[];for(var n in e)T.isFunction(e[n])&&t.push(n);return t.sort()},T.extend=function(e){return N(u.call(arguments,1),function(t){for(var n in t)e[n]=t[n]}),e},T.pick=function(e){var t={},n=a.apply(r,u.call(arguments,1));return N(n,function(n){n in e&&(t[n]=e[n])}),t},T.omit=function(e){var t={},n=a.apply(r,u.call(arguments,1));for(var i in e)T.contains(n,i)||(t[i]=e[i]);return t},T.defaults=function(e){return N(u.call(arguments,1),function(t){for(var n in t)e[n]==null&&(e[n]=t[n])}),e},T.clone=function(e){return T.isObject(e)?T.isArray(e)?e.slice():T.extend({},e):e},T.tap=function(e,t){return t(e),e};var M=function(e,t,n,r){if(e===t)return e!==0||1/e==1/t;if(e==null||t==null)return e===t;e instanceof T&&(e=e._wrapped),t instanceof T&&(t=t._wrapped);var i=l.call(e);if(i!=l.call(t))return!1;switch(i){case"[object String]":return e==String(t);case"[object Number]":return e!=+e?t!=+t:e==0?1/e==1/t:e==+t;case"[object Date]":case"[object Boolean]":return+e==+t;case"[object RegExp]":return e.source==t.source&&e.global==t.global&&e.multiline==t.multiline&&e.ignoreCase==t.ignoreCase}if(typeof e!="object"||typeof t!="object")return!1;var s=n.length;while(s--)if(n[s]==e)return r[s]==t;n.push(e),r.push(t);var o=0,u=!0;if(i=="[object Array]"){o=e.length,u=o==t.length;if(u)while(o--)if(!(u=M(e[o],t[o],n,r)))break}else{var a=e.constructor,f=t.constructor;if(a!==f&&!(T.isFunction(a)&&a instanceof a&&T.isFunction(f)&&f instanceof f))return!1;for(var c in e)if(T.has(e,c)){o++;if(!(u=T.has(t,c)&&M(e[c],t[c],n,r)))break}if(u){for(c in t)if(T.has(t,c)&&!(o--))break;u=!o}}return n.pop(),r.pop(),u};T.isEqual=function(e,t){return M(e,t,[],[])},T.isEmpty=function(e){if(e==null)return!0;if(T.isArray(e)||T.isString(e))return e.length===0;for(var t in e)if(T.has(e,t))return!1;return!0},T.isElement=function(e){return!!e&&e.nodeType===1},T.isArray=E||function(e){return l.call(e)=="[object Array]"},T.isObject=function(e){return e===Object(e)},N(["Arguments","Function","String","Number","Date","RegExp"],function(e){T["is"+e]=function(t){return l.call(t)=="[object "+e+"]"}}),T.isArguments(arguments)||(T.isArguments=function(e){return!!e&&!!T.has(e,"callee")}),typeof /./!="function"&&(T.isFunction=function(e){return typeof e=="function"}),T.isFinite=function(e){return T.isNumber(e)&&isFinite(e)},T.isNaN=function(e){return T.isNumber(e)&&e!=+e},T.isBoolean=function(e){return e===!0||e===!1||l.call(e)=="[object Boolean]"},T.isNull=function(e){return e===null},T.isUndefined=function(e){return e===void 0},T.has=function(e,t){return c.call(e,t)},T.noConflict=function(){return e._=t,this},T.identity=function(e){return e},T.times=function(e,t,n){for(var r=0;r<e;r++)t.call(n,r)},T.random=function(e,t){return t==null&&(t=e,e=0),e+(0|Math.random()*(t-e+1))};var _={escape:{"&":"&","<":"<",">":">",'"':""","'":"'","/":"/"}};_.unescape=T.invert(_.escape);var D={escape:new RegExp("["+T.keys(_.escape).join("")+"]","g"),unescape:new RegExp("("+T.keys(_.unescape).join("|")+")","g")};T.each(["escape","unescape"],function(e){T[e]=function(t){return t==null?"":(""+t).replace(D[e],function(t){return _[e][t]})}}),T.result=function(e,t){if(e==null)return null;var n=e[t];return T.isFunction(n)?n.call(e):n},T.mixin=function(e){N(T.functions(e),function(t){var n=T[t]=e[t];T.prototype[t]=function(){var e=[this._wrapped];return o.apply(e,arguments),F.call(this,n.apply(T,e))}})};var P=0;T.uniqueId=function(e){var t=P++;return e?e+t:t},T.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var H=/(.)^/,B={"'":"'","\\":"\\","\r":"r","\n":"n"," ":"t","\u2028":"u2028","\u2029":"u2029"},j=/\\|'|\r|\n|\t|\u2028|\u2029/g;T.template=function(e,t,n){n=T.defaults({},n,T.templateSettings);var r=new RegExp([(n.escape||H).source,(n.interpolate||H).source,(n.evaluate||H).source].join("|")+"|$","g"),i=0,s="__p+='";e.replace(r,function(t,n,r,o,u){s+=e.slice(i,u).replace(j,function(e){return"\\"+B[e]}),s+=n?"'+\n((__t=("+n+"))==null?'':_.escape(__t))+\n'":r?"'+\n((__t=("+r+"))==null?'':__t)+\n'":o?"';\n"+o+"\n__p+='":"",i=u+t.length}),s+="';\n",n.variable||(s="with(obj||{}){\n"+s+"}\n"),s="var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};\n"+s+"return __p;\n";try{var o=new Function(n.variable||"obj","_",s)}catch(u){throw u.source=s,u}if(t)return o(t,T);var a=function(e){return o.call(this,e,T)};return a.source="function("+(n.variable||"obj")+"){\n"+s+"}",a},T.chain=function(e){return T(e).chain()};var F=function(e){return this._chain?T(e).chain():e};T.mixin(T),N(["pop","push","reverse","shift","sort","splice","unshift"],function(e){var t=r[e];T.prototype[e]=function(){var n=this._wrapped;return t.apply(n,arguments),(e=="shift"||e=="splice")&&n.length===0&&delete n[0],F.call(this,n)}}),N(["concat","join","slice"],function(e){var t=r[e];T.prototype[e]=function(){return F.call(this,t.apply(this._wrapped,arguments))}}),T.extend(T.prototype,{chain:function(){return this._chain=!0,this},value:function(){return this._wrapped}})}).call(this); | |
// This code was written by Tyler Akins and has been placed in the | |
// public domain. It would be nice if you left this header intact. | |
// Base64 code from Tyler Akins -- http://rumkin.com | |
var Base64 = (function () { | |
var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; | |
var obj = { | |
/** | |
* Encodes a string in base64 | |
* @param {String} input The string to encode in base64. | |
*/ | |
encode: function (input) { | |
var output = ""; | |
var chr1, chr2, chr3; | |
var enc1, enc2, enc3, enc4; | |
var i = 0; | |
do { | |
chr1 = input.charCodeAt(i++); | |
chr2 = input.charCodeAt(i++); | |
chr3 = input.charCodeAt(i++); | |
enc1 = chr1 >> 2; | |
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); | |
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); | |
enc4 = chr3 & 63; | |
if (isNaN(chr2)) { | |
enc3 = enc4 = 64; | |
} else if (isNaN(chr3)) { | |
enc4 = 64; | |
} | |
output = output + keyStr.charAt(enc1) + keyStr.charAt(enc2) + | |
keyStr.charAt(enc3) + keyStr.charAt(enc4); | |
} while (i < input.length); | |
return output; | |
}, | |
/** | |
* Decodes a base64 string. | |
* @param {String} input The string to decode. | |
*/ | |
decode: function (input) { | |
var output = ""; | |
var chr1, chr2, chr3; | |
var enc1, enc2, enc3, enc4; | |
var i = 0; | |
// remove all characters that are not A-Z, a-z, 0-9, +, /, or = | |
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ""); | |
do { | |
enc1 = keyStr.indexOf(input.charAt(i++)); | |
enc2 = keyStr.indexOf(input.charAt(i++)); | |
enc3 = keyStr.indexOf(input.charAt(i++)); | |
enc4 = keyStr.indexOf(input.charAt(i++)); | |
chr1 = (enc1 << 2) | (enc2 >> 4); | |
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); | |
chr3 = ((enc3 & 3) << 6) | enc4; | |
output = output + String.fromCharCode(chr1); | |
if (enc3 != 64) { | |
output = output + String.fromCharCode(chr2); | |
} | |
if (enc4 != 64) { | |
output = output + String.fromCharCode(chr3); | |
} | |
} while (i < input.length); | |
return output; | |
} | |
}; | |
return obj; | |
})(); | |
if (typeof exports !== 'undefined') { | |
// Github = exports; | |
module.exports = Base64; | |
} else { | |
window.Base64 = Base64; | |
} | |
// Github.js 0.9.0 | |
// (c) 2013 Michael Aufreiter, Development Seed | |
// Github.js is freely distributable under the MIT license. | |
// For all details and documentation: | |
// http://substance.io/michael/github | |
(function() { | |
// Initial Setup | |
// ------------- | |
var XMLHttpRequest, Base64, _; | |
if (typeof exports !== 'undefined') { | |
XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest; | |
_ = require('underscore'); | |
Base64 = require('./lib/base64.js'); | |
}else{ | |
_ = window._; | |
Base64 = window.Base64; | |
} | |
//prefer native XMLHttpRequest always | |
if (typeof window !== 'undefined' && typeof window.XMLHttpRequest !== 'undefined'){ | |
XMLHttpRequest = window.XMLHttpRequest; | |
} | |
var API_URL = 'https://api.github.com'; | |
var Github = function(options) { | |
// HTTP Request Abstraction | |
// ======= | |
// | |
// I'm not proud of this and neither should you be if you were responsible for the XMLHttpRequest spec. | |
function _request(method, path, data, cb, raw, sync) { | |
function getURL() { | |
var url = path.indexOf('//') >= 0 ? path : API_URL + path; | |
return url + ((/\?/).test(url) ? "&" : "?") + (new Date()).getTime(); | |
} | |
var xhr = new XMLHttpRequest(); | |
if (!raw) {xhr.dataType = "json";} | |
xhr.open(method, getURL(), !sync); | |
if (!sync) { | |
xhr.onreadystatechange = function () { | |
if (this.readyState == 4) { | |
if (this.status >= 200 && this.status < 300 || this.status === 304) { | |
cb(null, raw ? this.responseText : this.responseText ? JSON.parse(this.responseText) : true, this); | |
} else { | |
cb({path: path, request: this, error: this.status}); | |
} | |
} | |
} | |
}; | |
xhr.setRequestHeader('Accept','application/vnd.github.raw+json'); | |
xhr.setRequestHeader('Content-Type','application/json;charset=UTF-8'); | |
if ((options.token) || (options.username && options.password)) { | |
xhr.setRequestHeader('Authorization', options.token | |
? 'token '+ options.token | |
: 'Basic ' + Base64.encode(options.username + ':' + options.password) | |
); | |
} | |
data ? xhr.send(JSON.stringify(data)) : xhr.send(); | |
if (sync) return xhr.response; | |
} | |
function _requestAllPages(path, cb) { | |
var results = []; | |
(function iterate() { | |
_request("GET", path, null, function(err, res, xhr) { | |
if (err) { | |
return cb(err); | |
} | |
results.push.apply(results, res); | |
var links = (xhr.getResponseHeader('link') || '').split(/\s*,\s*/g), | |
next = _.find(links, function(link) { return /rel="next"/.test(link); }); | |
if (next) { | |
next = (/<(.*)>/.exec(next) || [])[1]; | |
} | |
if (!next) { | |
cb(err, results); | |
} else { | |
path = next; | |
iterate(); | |
} | |
}); | |
})(); | |
} | |
// User API | |
// ======= | |
Github.User = function() { | |
this.repos = function(cb) { | |
// Github does not always honor the 1000 limit so we want to iterate over the data set. | |
_requestAllPages("/user/repos?type=all&per_page=1000&sort=updated", function(err, res) { | |
cb(err, res); | |
}); | |
}; | |
// List user organizations | |
// ------- | |
this.orgs = function(cb) { | |
_request("GET", "/user/orgs", null, function(err, res) { | |
cb(err, res); | |
}); | |
}; | |
// List authenticated user's gists | |
// ------- | |
this.gists = function(cb) { | |
_request("GET", "/gists", null, function(err, res) { | |
cb(err,res); | |
}); | |
}; | |
// List authenticated user's unread notifications | |
// ------- | |
this.notifications = function(cb) { | |
_request("GET", "/notifications", null, function(err, res) { | |
cb(err,res); | |
}); | |
}; | |
// Show user information | |
// ------- | |
this.show = function(username, cb) { | |
var command = username ? "/users/"+username : "/user"; | |
_request("GET", command, null, function(err, res) { | |
cb(err, res); | |
}); | |
}; | |
// List user repositories | |
// ------- | |
this.userRepos = function(username, cb) { | |
// Github does not always honor the 1000 limit so we want to iterate over the data set. | |
_requestAllPages("/users/"+username+"/repos?type=all&per_page=1000&sort=updated", function(err, res) { | |
cb(err, res); | |
}); | |
}; | |
// List a user's gists | |
// ------- | |
this.userGists = function(username, cb) { | |
_request("GET", "/users/"+username+"/gists", null, function(err, res) { | |
cb(err,res); | |
}); | |
}; | |
// List organization repositories | |
// ------- | |
this.orgRepos = function(orgname, cb) { | |
// Github does not always honor the 1000 limit so we want to iterate over the data set. | |
_requestAllPages("/orgs/"+orgname+"/repos?type=all&&page_num=1000&sort=updated&direction=desc", function(err, res) { | |
cb(err, res); | |
}); | |
}; | |
// Follow user | |
// ------- | |
this.follow = function(username, cb) { | |
_request("PUT", "/user/following/"+username, null, function(err, res) { | |
cb(err, res); | |
}); | |
}; | |
// Unfollow user | |
// ------- | |
this.unfollow = function(username, cb) { | |
_request("DELETE", "/user/following/"+username, null, function(err, res) { | |
cb(err, res); | |
}); | |
}; | |
}; | |
// Repository API | |
// ======= | |
Github.Repository = function(options) { | |
var repo = options.name; | |
var user = options.user; | |
var that = this; | |
var repoPath = "/repos/" + user + "/" + repo; | |
var currentTree = { | |
"branch": null, | |
"sha": null | |
}; | |
// Uses the cache if branch has not been changed | |
// ------- | |
function updateTree(branch, cb) { | |
if (branch === currentTree.branch && currentTree.sha) return cb(null, currentTree.sha); | |
that.getRef("heads/"+branch, function(err, sha) { | |
currentTree.branch = branch; | |
currentTree.sha = sha; | |
cb(err, sha); | |
}); | |
} | |
// Get a particular reference | |
// ------- | |
this.getRef = function(ref, cb) { | |
_request("GET", repoPath + "/git/refs/" + ref, null, function(err, res) { | |
if (err) return cb(err); | |
cb(null, res.object.sha); | |
}); | |
}; | |
// Create a new reference | |
// -------- | |
// | |
// { | |
// "ref": "refs/heads/my-new-branch-name", | |
// "sha": "827efc6d56897b048c772eb4087f854f46256132" | |
// } | |
this.createRef = function(options, cb) { | |
_request("POST", repoPath + "/git/refs", options, cb); | |
}; | |
// Delete a reference | |
// -------- | |
// | |
// repo.deleteRef('heads/gh-pages') | |
// repo.deleteRef('tags/v1.0') | |
this.deleteRef = function(ref, cb) { | |
_request("DELETE", repoPath + "/git/refs/"+ref, options, cb); | |
}; | |
// Create a repo | |
// ------- | |
this.createRepo = function(options, cb) { | |
_request("POST", "/user/repos", options, cb); | |
}; | |
// Delete a repo | |
// -------- | |
this.deleteRepo = function(cb) { | |
_request("DELETE", repoPath, options, cb); | |
}; | |
// List all tags of a repository | |
// ------- | |
this.listTags = function(cb) { | |
_request("GET", repoPath + "/tags", null, function(err, tags) { | |
if (err) return cb(err); | |
cb(null, tags); | |
}); | |
}; | |
// List all pull requests of a respository | |
// ------- | |
this.listPulls = function(state, cb) { | |
_request("GET", repoPath + "/pulls" + (state ? '?state=' + state : ''), null, function(err, pulls) { | |
if (err) return cb(err); | |
cb(null, pulls); | |
}); | |
}; | |
// Gets details for a specific pull request | |
// ------- | |
this.getPull = function(number, cb) { | |
_request("GET", repoPath + "/pulls/" + number, null, function(err, pull) { | |
if (err) return cb(err); | |
cb(null, pull); | |
}); | |
}; | |
// Retrieve the changes made between base and head | |
// ------- | |
this.compare = function(base, head, cb) { | |
_request("GET", repoPath + "/compare/" + base + "..." + head, null, function(err, diff) { | |
if (err) return cb(err); | |
cb(null, diff); | |
}); | |
}; | |
// List all branches of a repository | |
// ------- | |
this.listBranches = function(cb) { | |
_request("GET", repoPath + "/git/refs/heads", null, function(err, heads) { | |
if (err) return cb(err); | |
cb(null, _.map(heads, function(head) { return _.last(head.ref.split('/')); })); | |
}); | |
}; | |
// Retrieve the contents of a blob | |
// ------- | |
this.getBlob = function(sha, cb) { | |
_request("GET", repoPath + "/git/blobs/" + sha, null, cb, 'raw'); | |
}; | |
// For a given file path, get the corresponding sha (blob for files, tree for dirs) | |
// ------- | |
this.getSha = function(branch, path, cb) { | |
// Just use head if path is empty | |
if (path === "") return that.getRef("heads/"+branch, cb); | |
that.getTree(branch+"?recursive=true", function(err, tree) { | |
if (err) return cb(err); | |
var file = _.select(tree, function(file) { | |
return file.path === path; | |
})[0]; | |
cb(null, file ? file.sha : null); | |
}); | |
}; | |
// Retrieve the tree a commit points to | |
// ------- | |
this.getTree = function(tree, cb) { | |
_request("GET", repoPath + "/git/trees/"+tree, null, function(err, res) { | |
if (err) return cb(err); | |
cb(null, res.tree); | |
}); | |
}; | |
// Post a new blob object, getting a blob SHA back | |
// ------- | |
this.postBlob = function(content, cb) { | |
if (typeof(content) === "string") { | |
content = { | |
"content": content, | |
"encoding": "utf-8" | |
}; | |
} | |
_request("POST", repoPath + "/git/blobs", content, function(err, res) { | |
if (err) return cb(err); | |
cb(null, res.sha); | |
}); | |
}; | |
// Update an existing tree adding a new blob object getting a tree SHA back | |
// ------- | |
this.updateTree = function(baseTree, path, blob, cb) { | |
var data = { | |
"base_tree": baseTree, | |
"tree": [ | |
{ | |
"path": path, | |
"mode": "100644", | |
"type": "blob", | |
"sha": blob | |
} | |
] | |
}; | |
_request("POST", repoPath + "/git/trees", data, function(err, res) { | |
if (err) return cb(err); | |
cb(null, res.sha); | |
}); | |
}; | |
// Post a new tree object having a file path pointer replaced | |
// with a new blob SHA getting a tree SHA back | |
// ------- | |
this.postTree = function(tree, cb) { | |
_request("POST", repoPath + "/git/trees", { "tree": tree }, function(err, res) { | |
if (err) return cb(err); | |
cb(null, res.sha); | |
}); | |
}; | |
// Create a new commit object with the current commit SHA as the parent | |
// and the new tree SHA, getting a commit SHA back | |
// ------- | |
this.commit = function(parent, tree, message, cb) { | |
var data = { | |
"message": message, | |
"author": { | |
"name": options.username | |
}, | |
"parents": [ | |
parent | |
], | |
"tree": tree | |
}; | |
_request("POST", repoPath + "/git/commits", data, function(err, res) { | |
currentTree.sha = res.sha; // update latest commit | |
if (err) return cb(err); | |
cb(null, res.sha); | |
}); | |
}; | |
// Update the reference of your head to point to the new commit SHA | |
// ------- | |
this.updateHead = function(head, commit, cb) { | |
_request("PATCH", repoPath + "/git/refs/heads/" + head, { "sha": commit }, function(err, res) { | |
cb(err); | |
}); | |
}; | |
// Show repository information | |
// ------- | |
this.show = function(cb) { | |
_request("GET", repoPath, null, cb); | |
}; | |
// Get contents | |
// -------- | |
this.contents = function(branch, path, cb, sync) { | |
return _request("GET", repoPath + "/contents?ref=" + branch + (path ? "&path=" + path : ""), null, cb, 'raw', sync); | |
}; | |
// Fork repository | |
// ------- | |
this.fork = function(cb) { | |
_request("POST", repoPath + "/forks", null, cb); | |
}; | |
// Branch repository | |
// -------- | |
this.branch = function(oldBranch,newBranch,cb) { | |
if(arguments.length === 2 && typeof arguments[1] === "function") { | |
cb = newBranch; | |
newBranch = oldBranch; | |
oldBranch = "master"; | |
} | |
this.getRef("heads/" + oldBranch, function(err,ref) { | |
if(err && cb) return cb(err); | |
that.createRef({ | |
ref: "refs/heads/" + newBranch, | |
sha: ref | |
},cb); | |
}); | |
} | |
// Create pull request | |
// -------- | |
this.createPullRequest = function(options, cb) { | |
_request("POST", repoPath + "/pulls", options, cb); | |
}; | |
// List hooks | |
// -------- | |
this.listHooks = function(cb) { | |
_request("GET", repoPath + "/hooks", null, cb); | |
}; | |
// Get a hook | |
// -------- | |
this.getHook = function(id, cb) { | |
_request("GET", repoPath + "/hooks/" + id, null, cb); | |
}; | |
// Create a hook | |
// -------- | |
this.createHook = function(options, cb) { | |
_request("POST", repoPath + "/hooks", options, cb); | |
}; | |
// Edit a hook | |
// -------- | |
this.editHook = function(id, options, cb) { | |
_request("PATCH", repoPath + "/hooks/" + id, options, cb); | |
}; | |
// Delete a hook | |
// -------- | |
this.deleteHook = function(id, cb) { | |
_request("DELETE", repoPath + "/hooks/" + id, null, cb); | |
}; | |
// Read file at given path | |
// ------- | |
this.read = function(branch, path, cb) { | |
that.getSha(branch, path, function(err, sha) { | |
if (!sha) return cb("not found", null); | |
that.getBlob(sha, function(err, content) { | |
cb(err, content, sha); | |
}); | |
}); | |
}; | |
// Remove a file from the tree | |
// ------- | |
this.remove = function(branch, path, cb) { | |
updateTree(branch, function(err, latestCommit) { | |
that.getTree(latestCommit+"?recursive=true", function(err, tree) { | |
// Update Tree | |
var newTree = _.reject(tree, function(ref) { return ref.path === path; }); | |
_.each(newTree, function(ref) { | |
if (ref.type === "tree") delete ref.sha; | |
}); | |
that.postTree(newTree, function(err, rootTree) { | |
that.commit(latestCommit, rootTree, 'Deleted '+path , function(err, commit) { | |
that.updateHead(branch, commit, function(err) { | |
cb(err); | |
}); | |
}); | |
}); | |
}); | |
}); | |
}; | |
// Delete a file from the tree | |
// ------- | |
this.delete = function(branch, path, cb) { | |
that.getSha(branch, path, function(err, sha) { | |
if (!sha) return cb("not found", null); | |
var delPath = repoPath + "/contents/" + path; | |
var params = { | |
"message": "Deleted " + path, | |
"sha": sha | |
}; | |
delPath += "?message=" + encodeURIComponent(params.message); | |
delPath += "&sha=" + encodeURIComponent(params.sha); | |
_request("DELETE", delPath, null, cb); | |
}) | |
} | |
// Move a file to a new location | |
// ------- | |
this.move = function(branch, path, newPath, cb) { | |
updateTree(branch, function(err, latestCommit) { | |
that.getTree(latestCommit+"?recursive=true", function(err, tree) { | |
// Update Tree | |
_.each(tree, function(ref) { | |
if (ref.path === path) ref.path = newPath; | |
if (ref.type === "tree") delete ref.sha; | |
}); | |
that.postTree(tree, function(err, rootTree) { | |
that.commit(latestCommit, rootTree, 'Deleted '+path , function(err, commit) { | |
that.updateHead(branch, commit, function(err) { | |
cb(err); | |
}); | |
}); | |
}); | |
}); | |
}); | |
}; | |
// Write file contents to a given branch and path | |
// ------- | |
this.write = function(branch, path, content, message, cb) { | |
updateTree(branch, function(err, latestCommit) { | |
if (err) return cb(err); | |
that.postBlob(content, function(err, blob) { | |
if (err) return cb(err); | |
that.updateTree(latestCommit, path, blob, function(err, tree) { | |
if (err) return cb(err); | |
that.commit(latestCommit, tree, message, function(err, commit) { | |
if (err) return cb(err); | |
that.updateHead(branch, commit, cb); | |
}); | |
}); | |
}); | |
}); | |
}; | |
// List commits on a repository. Takes an object of optional paramaters: | |
// sha: SHA or branch to start listing commits from | |
// path: Only commits containing this file path will be returned | |
// since: ISO 8601 date - only commits after this date will be returned | |
// until: ISO 8601 date - only commits before this date will be returned | |
// ------- | |
this.getCommits = function(options, cb) { | |
options = options || {}; | |
var url = repoPath + "/commits"; | |
var params = []; | |
if (options.sha) { | |
params.push("sha=" + encodeURIComponent(options.sha)); | |
} | |
if (options.path) { | |
params.push("path=" + encodeURIComponent(options.path)); | |
} | |
if (options.since) { | |
var since = options.since; | |
if (since.constructor === Date) { | |
since = since.toISOString(); | |
} | |
params.push("since=" + encodeURIComponent(since)); | |
} | |
if (options.until) { | |
var until = options.until; | |
if (until.constructor === Date) { | |
until = until.toISOString(); | |
} | |
params.push("until=" + encodeURIComponent(until)); | |
} | |
if (params.length > 0) { | |
url += "?" + params.join("&"); | |
} | |
_request("GET", url, null, cb); | |
}; | |
}; | |
// Gists API | |
// ======= | |
Github.Gist = function(options) { | |
var id = options.id; | |
var gistPath = "/gists/"+id; | |
// Read the gist | |
// -------- | |
this.read = function(cb) { | |
_request("GET", gistPath, null, function(err, gist) { | |
cb(err, gist); | |
}); | |
}; | |
// Create the gist | |
// -------- | |
// { | |
// "description": "the description for this gist", | |
// "public": true, | |
// "files": { | |
// "file1.txt": { | |
// "content": "String file contents" | |
// } | |
// } | |
// } | |
this.create = function(options, cb){ | |
_request("POST","/gists", options, cb); | |
}; | |
// Delete the gist | |
// -------- | |
this.delete = function(cb) { | |
_request("DELETE", gistPath, null, function(err,res) { | |
cb(err,res); | |
}); | |
}; | |
// Fork a gist | |
// -------- | |
this.fork = function(cb) { | |
_request("POST", gistPath+"/fork", null, function(err,res) { | |
cb(err,res); | |
}); | |
}; | |
// Update a gist with the new stuff | |
// -------- | |
this.update = function(options, cb) { | |
_request("PATCH", gistPath, options, function(err,res) { | |
cb(err,res); | |
}); | |
}; | |
// Star a gist | |
// -------- | |
this.star = function(cb) { | |
_request("PUT", gistPath+"/star", null, function(err,res) { | |
cb(err,res); | |
}); | |
}; | |
// Untar a gist | |
// -------- | |
this.unstar = function(cb) { | |
_request("DELETE", gistPath+"/star", null, function(err,res) { | |
cb(err,res); | |
}); | |
}; | |
// Check if a gist is starred | |
// -------- | |
this.isStarred = function(cb) { | |
_request("GET", gistPath+"/star", null, function(err,res) { | |
cb(err,res); | |
}); | |
}; | |
}; | |
// Issues API | |
// ========== | |
Github.Issue = function(options) { | |
var path = "/repos/" + options.user + "/" + options.repo + "/issues"; | |
this.list = function(options, cb) { | |
_request("GET", path, options, function(err, res) { | |
cb(err,res) | |
}); | |
}; | |
}; | |
// Top Level API | |
// ------- | |
this.getIssues = function(user, repo) { | |
return new Github.Issue({user: user, repo: repo}); | |
}; | |
this.getRepo = function(user, repo) { | |
return new Github.Repository({user: user, name: repo}); | |
}; | |
this.getUser = function() { | |
return new Github.User(); | |
}; | |
this.getGist = function(id) { | |
return new Github.Gist({id: id}); | |
}; | |
}; | |
if (typeof exports !== 'undefined') { | |
// Github = exports; | |
module.exports = Github; | |
} else { | |
window.Github = Github; | |
} | |
}).call(this); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment