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 }