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 }