-
Notifications
You must be signed in to change notification settings - Fork 7
/
github.js
29 lines (29 loc) · 11.9 KB
/
github.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
(function(){'use strict';var XMLHttpRequest,btoa;if(typeof exports!=='undefined'){XMLHttpRequest=require('xmlhttprequest').XMLHttpRequest;if(typeof btoa==='undefined'){btoa=require('btoa');}}else{btoa=window.btoa;}
if(typeof window!=='undefined'&&typeof window.XMLHttpRequest!=='undefined'){XMLHttpRequest=window.XMLHttpRequest;}
var Github=function(options){var API_URL=options.apiUrl||'https://api.github.com';function _request(method,path,data,cb,raw,sync){function getURL(){var url=path.indexOf('//')>=0?path:API_URL+ path;url+=((/\?/).test(url)?'&':'?');if(data&&typeof data==="object"&&['GET','HEAD'].indexOf(method)>-1){url+='&'+ Object.keys(data).map(function(k){return k+'='+ data[k];}).join('&');}
return url+'&'+(new Date()).getTime();}
var xhr=new XMLHttpRequest();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});}}};}
if(!raw){xhr.dataType='json';xhr.setRequestHeader('Accept','application/vnd.github.v3+json');}else{xhr.setRequestHeader('Accept','application/vnd.github.v3.raw+json');}
xhr.setRequestHeader('Content-Type','application/json;charset=UTF-8');if((options.token)||(options.username&&options.password)){var authorization=options.token?'token '+ options.token:'Basic '+ btoa(options.username+':'+ options.password);xhr.setRequestHeader('Authorization',authorization);}
if(data){xhr.send(JSON.stringify(data));}else{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=null;links.forEach(function(link){next=/rel="next"/.test(link)?link:next;});if(next){next=(/<(.*)>/.exec(next)||[])[1];}
if(!next){cb(err,results);}else{path=next;iterate();}});})();}
Github.User=function(){this.repos=function(cb){_requestAllPages('/user/repos?type=all&per_page=1000&sort=updated',function(err,res){cb(err,res);});};this.orgs=function(cb){_request("GET",'/user/orgs',null,function(err,res){cb(err,res);});};this.gists=function(cb){_request("GET",'/gists',null,function(err,res){cb(err,res);});};this.notifications=function(cb){_request("GET",'/notifications',null,function(err,res){cb(err,res);});};this.show=function(username,cb){var command=username?'/users/'+ username:'/user';_request('GET',command,null,function(err,res){cb(err,res);});};this.userRepos=function(username,cb){_requestAllPages('/users/'+ username+'/repos?type=all&per_page=1000&sort=updated',function(err,res){cb(err,res);});};this.userGists=function(username,cb){_request('GET','/users/'+ username+'/gists',null,function(err,res){cb(err,res);});};this.orgRepos=function(orgname,cb){_requestAllPages('/orgs/'+ orgname+'/repos?type=all&&page_num=1000&sort=updated&direction=desc',function(err,res){cb(err,res);});};this.follow=function(username,cb){_request('PUT','/user/following/'+ username,null,function(err,res){cb(err,res);});};this.unfollow=function(username,cb){_request('DELETE','/user/following/'+ username,null,function(err,res){cb(err,res);});};this.createRepo=function(options,cb){_request('POST','/user/repos',options,cb);};};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};this.deleteRepo=function(cb){_request('DELETE',repoPath,options,cb);};function updateTree(branch,cb){if(branch===currentTree.branch&¤tTree.sha){return cb(null,currentTree.sha);}
that.getRef('heads/'+ branch,function(err,sha){currentTree.branch=branch;currentTree.sha=sha;cb(err,sha);});}
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);});};this.createRef=function(options,cb){_request('POST',repoPath+'/git/refs',options,cb);};this.deleteRef=function(ref,cb){_request('DELETE',repoPath+'/git/refs/'+ ref,options,cb);};this.createRepo=function(options,cb){_request('POST','/user/repos',options,cb);};this.deleteRepo=function(cb){_request('DELETE',repoPath,options,cb);};this.listTags=function(cb){_request('GET',repoPath+'/tags',null,function(err,tags){if(err){return cb(err);}
cb(null,tags);});};this.listPulls=function(state,cb){_request('GET',repoPath+"/pulls"+(state?'?state='+ state:''),null,function(err,pulls){if(err)return cb(err);cb(null,pulls);});};this.getPull=function(number,cb){_request("GET",repoPath+"/pulls/"+ number,null,function(err,pull){if(err)return cb(err);cb(null,pull);});};this.compare=function(base,head,cb){_request("GET",repoPath+"/compare/"+ base+"..."+ head,null,function(err,diff){if(err)return cb(err);cb(null,diff);});};this.listBranches=function(cb){_request("GET",repoPath+"/git/refs/heads",null,function(err,heads){if(err)return cb(err);cb(null,heads.map(function(head){var headParts=head.ref.split('/');return headParts[headParts.length- 1];}));});};this.getBlob=function(sha,cb){_request("GET",repoPath+"/git/blobs/"+ sha,null,cb,'raw');};this.getCommit=function(branch,sha,cb){_request("GET",repoPath+"/git/commits/"+sha,null,function(err,commit){if(err)return cb(err);cb(null,commit);});};this.getSha=function(branch,path,cb){if(!path||path==="")return that.getRef("heads/"+branch,cb);_request("GET",repoPath+"/contents/"+ path+(branch?"?ref="+ branch:""),null,function(err,pathContent){if(err)return cb(err);cb(null,pathContent.sha);});};this.getTree=function(tree,cb){_request("GET",repoPath+"/git/trees/"+tree,null,function(err,res){if(err)return cb(err);cb(null,res.tree);});};this.postBlob=function(content,cb){if(typeof(content)==="string"){content={"content":content,"encoding":"utf-8"};}else{content={"content":btoa(String.fromCharCode.apply(null,new Uint8Array(content))),"encoding":"base64"};}
_request("POST",repoPath+"/git/blobs",content,function(err,res){if(err)return cb(err);cb(null,res.sha);});};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);});};this.postTree=function(tree,cb){_request("POST",repoPath+"/git/trees",{"tree":tree},function(err,res){if(err)return cb(err);cb(null,res.sha);});};this.commit=function(parent,tree,message,cb){var user=new Github.User();user.show(null,function(err,userData){if(err)return cb(err);var data={"message":message,"author":{"name":options.user,"email":userData.email},"parents":[parent],"tree":tree};_request("POST",repoPath+"/git/commits",data,function(err,res){if(err)return cb(err);currentTree.sha=res.sha;cb(null,res.sha);});});};this.updateHead=function(head,commit,cb){_request("PATCH",repoPath+"/git/refs/heads/"+ head,{"sha":commit},function(err){cb(err);});};this.show=function(cb){_request("GET",repoPath,null,cb);};this.contributors=function(cb,retry){retry=retry||1000;var self=this;_request("GET",repoPath+"/stats/contributors",null,function(err,data,response){if(err)return cb(err);if(response.status===202){setTimeout(function(){self.contributors(cb,retry);},retry);}else{cb(err,data);}});};this.contents=function(ref,path,cb){path=encodeURI(path);_request("GET",repoPath+"/contents"+(path?"/"+ path:""),{ref:ref},cb);};this.fork=function(cb){_request("POST",repoPath+"/forks",null,cb);};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);});};this.createPullRequest=function(options,cb){_request("POST",repoPath+"/pulls",options,cb);};this.listHooks=function(cb){_request("GET",repoPath+"/hooks",null,cb);};this.getHook=function(id,cb){_request("GET",repoPath+"/hooks/"+ id,null,cb);};this.createHook=function(options,cb){_request("POST",repoPath+"/hooks",options,cb);};this.editHook=function(id,options,cb){_request("PATCH",repoPath+"/hooks/"+ id,options,cb);};this.deleteHook=function(id,cb){_request("DELETE",repoPath+"/hooks/"+ id,null,cb);};this.read=function(branch,path,cb){_request("GET",repoPath+"/contents/"+encodeURI(path)+(branch?"?ref="+ branch:""),null,function(err,obj){if(err&&err.error===404)return cb("not found",null,null);if(err)return cb(err);cb(null,obj);},true);};this.remove=function(branch,path,cb){that.getSha(branch,path,function(err,sha){if(err)return cb(err);_request("DELETE",repoPath+"/contents/"+ path,{message:path+" is removed",sha:sha,branch:branch},cb);});};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);delPath+='&branch='+ encodeURIComponent(branch);_request("DELETE",delPath,null,cb);});};this.move=function(branch,path,newPath,cb){updateTree(branch,function(err,latestCommit){that.getTree(latestCommit+"?recursive=true",function(err,tree){tree.forEach(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);});});});});});};this.write=function(branch,path,content,message,cb){that.getSha(branch,encodeURI(path),function(err,sha){if(err&&err.error!==404)return cb(err);_request("PUT",repoPath+"/contents/"+ encodeURI(path),{message:message,content:btoa(content),branch:branch,sha:sha},cb);});};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(options.page){params.push("page="+ options.page);}
if(options.perpage){params.push("per_page="+ options.perpage);}
if(params.length>0){url+="?"+ params.join("&");}
_request("GET",url,null,cb);};};Github.Gist=function(options){var id=options.id;var gistPath="/gists/"+id;this.read=function(cb){_request("GET",gistPath,null,function(err,gist){cb(err,gist);});};this.create=function(options,cb){_request("POST","/gists",options,cb);};this.delete=function(cb){_request("DELETE",gistPath,null,function(err,res){cb(err,res);});};this.fork=function(cb){_request("POST",gistPath+"/fork",null,function(err,res){cb(err,res);});};this.update=function(options,cb){_request("PATCH",gistPath,options,function(err,res){cb(err,res);});};this.star=function(cb){_request("PUT",gistPath+"/star",null,function(err,res){cb(err,res);});};this.unstar=function(cb){_request("DELETE",gistPath+"/star",null,function(err,res){cb(err,res);});};this.isStarred=function(cb){_request("GET",gistPath+"/star",null,function(err,res){cb(err,res);});};};Github.Issue=function(options){var path="/repos/"+ options.user+"/"+ options.repo+"/issues";this.list=function(options,cb){var query=[];for(var key in options){if(options.hasOwnProperty(key)){query.push(encodeURIComponent(key)+"="+ encodeURIComponent(options[key]));}}
_requestAllPages(path+'?'+ query.join("&"),cb);};};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'){module.exports=Github;}else{window.Github=Github;}}).call(this);