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 }
44 
45 struct RefInfo {
46 	string name;
47 	string sha;
48 	BsonDate date;
49 
50 	this(string name, string sha, SysTime date)
51 	{
52 		this.name = name;
53 		this.sha = sha;
54 		this.date = BsonDate(date);
55 	}
56 }
57 
58 package Json readJson(string url, bool sanitize = false, bool cache_priority = false)
59 {
60 	Json ret;
61 	logDiagnostic("Getting JSON response from %s", url);
62 	Exception ex;
63 	foreach (i; 0 .. 2) {
64 		try {
65 			downloadCached(url, (scope input){
66 				scope (failure) clearCacheEntry(url);
67 				auto text = input.readAllUTF8(sanitize);
68 				ret = parseJsonString(text);
69 			}, cache_priority);
70 			return ret;
71 		} catch (Exception e) {
72 			logDiagnostic("Failed to parse downloaded JSON document (attempt #%s): %s", i+1, e.msg);
73 			ex = e;
74 		}
75 	}
76 	throw new Exception(format("Failed to read JSON from %s: %s", url, ex.msg), __FILE__, __LINE__, ex);
77 }
78 
79 private {
80 	Repository[string] s_repositories;
81 	RepositoryFactory[string] s_repositoryFactories;
82 }