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, DbRepoStats;
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 	/// Get basic repository information, throws FileNotFoundException when the repo no longer exists.
47 	RepositoryInfo getInfo();
48 	void readFile(string commit_sha, Path path, scope void delegate(scope InputStream) reader);
49 	string getDownloadUrl(string tag_or_branch);
50 	void download(string tag_or_branch, scope void delegate(scope InputStream) del);
51 }
52 
53 struct RepositoryInfo {
54 	bool isFork;
55 	DbRepoStats stats;
56 }
57 
58 struct RefInfo {
59 	string name;
60 	string sha;
61 	BsonDate date;
62 
63 	this(string name, string sha, SysTime date)
64 	{
65 		this.name = name;
66 		this.sha = sha;
67 		this.date = BsonDate(date);
68 	}
69 }
70 
71 package Json readJson(string url, bool sanitize = false, bool cache_priority = false)
72 {
73 	import dubregistry.internal.utils : black;
74 
75 	Json ret;
76 	logDiagnostic("Getting JSON response from %s", url.black);
77 	Exception ex;
78 	foreach (i; 0 .. 2) {
79 		try {
80 			downloadCached(url, (scope input){
81 				scope (failure) clearCacheEntry(url);
82 				auto text = input.readAllUTF8(sanitize);
83 				ret = parseJsonString(text);
84 			}, cache_priority);
85 			return ret;
86 		} catch (FileNotFoundException e) {
87 			throw e;
88 		} catch (Exception e) {
89 			logDiagnostic("Failed to parse downloaded JSON document (attempt #%s): %s", i+1, e.msg);
90 			ex = e;
91 		}
92 	}
93 	throw new Exception(format("Failed to read JSON from %s: %s", url.black, ex.msg), __FILE__, __LINE__, ex);
94 }
95 
96 private {
97 	Repository[DbRepository] s_repositories;
98 	RepositoryFactory[string] s_repositoryFactories;
99 }