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 }