1 /++ 2 + License: MIT 3 + Copyright: Copyright (c) 2018, Christian Koestlin 4 + Authors: Christian Koestlin 5 +/ 6 7 module ponies.dlang.dub.registry; 8 9 import asdf; 10 import ponies.dlang.dub; 11 import ponies.shields; 12 import requests; 13 import std.experimental.logger; 14 import std; 15 import std.datetime.stopwatch; 16 17 struct Package { 18 string name; 19 } 20 class DubRegistryCache 21 { 22 private static bool packagesRead; 23 24 private static Package[] packages; 25 26 bool includes(string name) 27 { 28 if (!packagesRead) 29 { 30 packages = getPackages(); 31 packagesRead = true; 32 } 33 return packages.any!(v => v.name == name); 34 } 35 36 37 private auto getPackages() 38 { 39 const path = "%s/.ponies".format(environment.get("HOME")); 40 const cachePath = "%s/dub-registry.cache".format(path); 41 if (!cachePath.exists) 42 { 43 "Populating cache %s".format(cachePath).info; 44 const url = "https://code.dlang.org/api/packages/dump"; 45 auto sw = std.datetime.stopwatch.StopWatch(AutoStart.yes); 46 auto content = url.getContent; 47 "Downloading took %s".format(sw.peek).info; 48 sw.reset; 49 auto packages = content.to!string.deserialize!(Package[]); 50 "Parsing took %s".format(sw.peek).info; 51 if (!path.exists) 52 { 53 path.mkdir; 54 } 55 std.file.write(cachePath, packages.map!(v => v.name).join("\n")); 56 return packages; 57 } 58 auto sw = std.datetime.stopwatch.StopWatch(AutoStart.yes); 59 auto result = cachePath.readText.splitter("\n").map!(v => Package(v)).array; 60 "Loading cache took %s".format(sw.peek).info; 61 return result; 62 } 63 } 64 65 class DubRegistryShieldPony : ShieldPony 66 { 67 DubRegistryCache cache; 68 string dubPackageName; 69 string what; 70 71 this(DubRegistryCache cache, string what) 72 { 73 this.cache = cache; 74 this.dubPackageName = getFromDubSdl("name"); 75 this.what = what; 76 } 77 78 override bool applicable() 79 { 80 if (dubPackageName == null) 81 { 82 return false; 83 } 84 return dubSdlAvailable && cache.includes(dubPackageName) && super.applicable; 85 } 86 87 override string[] doctor() 88 { 89 string[] hints; 90 if (!exists("readme.org")) 91 { 92 hints ~= "Please add readme.org"; 93 } 94 if (!dubSdlAvailable) 95 { 96 hints ~= "Please add dub.sdl"; 97 } 98 if (!cache.includes(dubPackageName)) { 99 hints ~= "Please upload you package to the https://code.dlang.org"; 100 } 101 return hints; 102 } 103 104 override string shield() 105 { 106 return "[[http://code.dlang.org/packages/%1$s][https://img.shields.io/dub/%2$s/%1$s.svg?style=flat-square]]" 107 .format(dubPackageName, what); 108 } 109 110 } 111 112 class DubLicenseShieldPony : DubRegistryShieldPony 113 { 114 this(DubRegistryCache cache) 115 { 116 super(cache, "l"); 117 } 118 119 override string name() 120 { 121 return "Setup dub registry license shield in readme.org"; 122 } 123 } 124 125 class DubVersionShieldPony : DubRegistryShieldPony 126 { 127 this(DubRegistryCache cache) 128 { 129 super(cache, "v"); 130 } 131 132 override string name() 133 { 134 return "Setup dub registry version shield in readme.org"; 135 } 136 } 137 138 class DubWeeklyDownloadsShieldPony : DubRegistryShieldPony 139 { 140 this(DubRegistryCache cache) 141 { 142 super(cache, "dw"); 143 } 144 145 override string name() 146 { 147 return "Setup dub registry weekly downloads shield in readme.org"; 148 } 149 }