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.repository;
7 
8 import vibe.vibe;
9 
10 import dubregistry.cache;
11 import std.digest.sha;
12 import std.typecons;
13 
14 
15 Repository getRepository(Json repinfo)
16 {
17 	auto ident = repinfo.toString();
18 	if( auto pr = ident in s_repositories )
19 		return *pr;
20 
21 	logDebug("Returning new repository: %s", ident);
22 	auto pf = repinfo.kind.get!string in s_repositoryFactories;
23 	enforce(pf, "Unknown repository type: "~repinfo.kind.get!string);
24 	auto rep = (*pf)(repinfo);
25 	s_repositories[ident] = rep;
26 	return rep;
27 }
28 
29 void addRepositoryFactory(string kind, RepositoryFactory factory)
30 {
31 	assert(kind !in s_repositoryFactories);
32 	s_repositoryFactories[kind] = factory;
33 }
34 
35 
36 alias RepositoryFactory = Repository delegate(Json);
37 
38 interface Repository {
39 	RefInfo[] getTags();
40 	RefInfo[] getBranches();
41 	void readFile(string commit_sha, Path path, scope void delegate(scope InputStream) reader);
42 	string getDownloadUrl(string tag_or_branch);
43 	void download(string tag_or_branch, scope void delegate(scope InputStream) del);
44 }
45 
46 struct RefInfo {
47 	string name;
48 	string sha;
49 	BsonDate date;
50 
51 	this(string name, string sha, SysTime date)
52 	{
53 		this.name = name;
54 		this.sha = sha;
55 		this.date = BsonDate(date);
56 	}
57 }
58 
59 package Json readJson(string url, bool sanitize = false, bool cache_priority = false)
60 {
61 	Json ret;
62 	logDiagnostic("Getting JSON response from %s", url);
63 	Exception ex;
64 	foreach (i; 0 .. 2) {
65 		try {
66 			downloadCached(url, (scope input){
67 				scope (failure) clearCacheEntry(url);
68 				auto text = input.readAllUTF8(sanitize);
69 				ret = parseJsonString(text);
70 			}, cache_priority);
71 			return ret;
72 		} catch (Exception e) {
73 			logDiagnostic("Failed to parse downloaded JSON document (attempt #%s): %s", i+1, e.msg);
74 			ex = e;
75 		}
76 	}
77 	throw new Exception(format("Failed to read JSON from %s: %s", url, ex.msg), __FILE__, __LINE__, ex);
78 }
79 
80 private {
81 	Repository[string] s_repositories;
82 	RepositoryFactory[string] s_repositoryFactories;
83 }