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