1 /**
2 	Copyright: © 2013 rejectedsoftware e.K.
3 	License: Subject to the terms of the GNU GPLv3 license, as written in the included LICENSE.txt file.
4 	Authors: Sönke Ludwig
5 */
6 module dubregistry.repositories.github;
7 
8 import dubregistry.cache;
9 import dubregistry.repositories.repository;
10 import std.string : startsWith;
11 import std.typecons;
12 import vibe.core.log;
13 import vibe.core.stream;
14 import vibe.data.json;
15 import vibe.inet.url;
16 
17 
18 class GithubRepository : Repository {
19 	private {
20 		string m_owner;
21 		string m_project;
22 		string m_authUser;
23 		string m_authPassword;
24 	}
25 
26 	static void register(string user, string password)
27 	{
28 		Repository factory(Json info){
29 			return new GithubRepository(info.owner.get!string, info.project.get!string, user, password);
30 		}
31 		addRepositoryFactory("github", &factory);
32 	}
33 
34 	this(string owner, string project, string auth_user, string auth_password)
35 	{
36 		m_owner = owner;
37 		m_project = project;
38 		m_authUser = auth_user;
39 		m_authPassword = auth_password;
40 	}
41 
42 	RefInfo[] getTags()
43 	{
44 		import std.datetime : SysTime;
45 
46 		Json tags;
47 		try tags = readJson(getAPIURLPrefix()~"/repos/"~m_owner~"/"~m_project~"/tags");
48 		catch( Exception e ) { throw new Exception("Failed to get tags: "~e.msg); }
49 		RefInfo[] ret;
50 		foreach_reverse (tag; tags) {
51 			try {
52 				auto tagname = tag.name.get!string;
53 				Json commit = readJson(getAPIURLPrefix()~"/repos/"~m_owner~"/"~m_project~"/commits/"~tag.commit.sha.get!string, true, true);
54 				ret ~= RefInfo(tagname, tag.commit.sha.get!string, SysTime.fromISOExtString(commit.commit.committer.date.get!string));
55 				logDebug("Found tag for %s/%s: %s", m_owner, m_project, tagname);
56 			} catch( Exception e ){
57 				throw new Exception("Failed to process tag "~tag.name.get!string~": "~e.msg);
58 			}
59 		}
60 		return ret;
61 	}
62 
63 	RefInfo[] getBranches()
64 	{
65 		import std.datetime : SysTime;
66 
67 		Json branches = readJson(getAPIURLPrefix()~"/repos/"~m_owner~"/"~m_project~"/branches");
68 		RefInfo[] ret;
69 		foreach_reverse( branch; branches ){
70 			auto branchname = branch.name.get!string;
71 			Json commit = readJson(getAPIURLPrefix()~"/repos/"~m_owner~"/"~m_project~"/commits/"~branch.commit.sha.get!string, true, true);
72 			ret ~= RefInfo(branchname, branch.commit.sha.get!string, SysTime.fromISOExtString(commit.commit.committer.date.get!string));
73 			logDebug("Found branch for %s/%s: %s", m_owner, m_project, branchname);
74 		}
75 		return ret;
76 	}
77 
78 	void readFile(string commit_sha, Path path, scope void delegate(scope InputStream) reader)
79 	{
80 		assert(path.absolute, "Passed relative path to readFile.");
81 		auto url = getContentURLPrefix()~"/"~m_owner~"/"~m_project~"/"~commit_sha~path.toString();
82 		downloadCached(url, (scope input) {
83 			reader(input);
84 		}, true);
85 	}
86 
87 	string getDownloadUrl(string ver)
88 	{
89 		if( ver.startsWith("~") ) ver = ver[1 .. $];
90 		else ver = ver;
91 		return "https://github.com/"~m_owner~"/"~m_project~"/archive/"~ver~".zip";
92 	}
93 
94 	private string getAPIURLPrefix() {
95 		if (m_authUser.length) return "https://"~m_authUser~":"~m_authPassword~"@api.github.com";
96 		else return "https://api.github.com";
97 	}
98 
99 	private string getContentURLPrefix() {
100 		return "http://raw.github.com";
101 	}
102 }