1 /++ 2 + Copyright: Copyright © 2018, Christian Köstlin 3 + License: MIT 4 + Authors: Christian Koestlin, Christian Köstlin 5 +/ 6 module app; 7 8 import std.stdio; 9 import std..string; 10 import std.process; 11 import std.file; 12 import std.path; 13 import std.file; 14 import std.regex; 15 import std.experimental.logger; 16 17 void writeContent(string file, string content) 18 { 19 file.dirName.mkdirRecurse; 20 std.file.write(file, content); 21 } 22 23 auto getFromDubSdl(string path, string what) 24 { 25 try 26 { 27 auto pattern = "^%1$s \"(?P<%1$s>.*)\"$".format(what); 28 auto text = readText(path); 29 auto match = matchFirst(text, regex(pattern, "m")); 30 if (match.empty) 31 { 32 return null; 33 } 34 return match[what]; 35 } 36 catch (FileException e) 37 { 38 return null; 39 } 40 } 41 42 auto getFromDubJson(string path, string what) 43 { 44 try 45 { 46 import std.json; 47 48 return parseJSON(readText(path))[what].str; 49 } 50 catch (FileException e) 51 { 52 return null; 53 } 54 } 55 56 auto packageDir() 57 { 58 auto e = std.process.environment.toAA; 59 if ("DUB_PACKAGE_DIR" !in e) 60 { 61 return null; 62 } 63 return e["DUB_PACKAGE_DIR"]; 64 } 65 66 auto dubPackage() 67 { 68 auto e = std.process.environment.toAA; 69 if ("DUB_PACKAGE" !in e) 70 { 71 return null; 72 } 73 return e["DUB_PACKAGE"]; 74 } 75 76 auto getFromDubJsonFromPackageDir(string what) 77 { 78 if (string pd = packageDir) 79 { 80 return getFromDubJson(pd ~ "/dub.json", what); 81 } 82 return null; 83 } 84 85 string getFromDubSdlFromPackageDir(string what) 86 { 87 if (string pd = packageDir) 88 { 89 return getFromDubSdl(pd ~ "/dub.sdl", what); 90 } 91 return null; 92 } 93 94 string getFromGit() 95 { 96 auto gitCommand = ["git", "describe", "--dirty"].execute(null, Config.none, 97 size_t.max, packageDir); 98 if (gitCommand.status != 0) 99 { 100 "Cannot get version with git describe --dirty, make sure you have at least one annotated tag" 101 .info; 102 return null; 103 } 104 105 return gitCommand.output.strip; 106 } 107 108 string getLicense() 109 { 110 auto what = "license"; 111 if (string res = getFromDubJsonFromPackageDir(what)) 112 { 113 "Using %s from dub.json '%s'".format(what, res).warning; 114 return res; 115 } 116 if (string res = getFromDubSdlFromPackageDir(what)) 117 { 118 "Using %s from dub.sdl '%s'".format(what, res).warning; 119 return res; 120 } 121 throw new Exception("Cannot determine %s".format(what)); 122 123 } 124 125 string getVersionFromEnv() 126 { 127 return std.process.environment["DUB_PACKAGE_VERSION"]; 128 } 129 130 string getVersion() 131 { 132 auto what = "version"; 133 if (string res = getVersionFromEnv()) 134 { 135 "Using %s from env".format(res).warning; 136 return res; 137 } 138 if (string res = getFromDubJsonFromPackageDir(what)) 139 { 140 "Using %s from dub.json '%s'".format(what, res).warning; 141 return res; 142 } 143 if (string res = getFromDubSdlFromPackageDir(what)) 144 { 145 "Using %s from dub.sdl '%s'".format(what, res).warning; 146 return res; 147 } 148 if (string res = getFromGit) 149 { 150 "Using %s from git '%s'".format(what, res).warning; 151 return res; 152 } 153 throw new Exception("Cannot determine %s".format(what)); 154 } 155 156 int main(string[] args) 157 { 158 import std.getopt; 159 160 class CustomLogger : Logger 161 { 162 this(LogLevel lv) @safe 163 { 164 super(lv); 165 } 166 167 override void writeLogMsg(ref LogEntry payload) 168 { 169 import std.stdio; 170 171 writeln(payload.msg); 172 } 173 } 174 175 sharedLog = new CustomLogger(LogLevel.trace); 176 writeln(args); 177 string packageName = std.process.environment.get("DUB_PACKAGE"); 178 auto info = getopt(args, "packageName", &packageName); 179 if (info.helpWanted) 180 { 181 import packageversion.packageversion; 182 183 defaultGetoptPrinter("packageversion %s. Generate or update a simple packageversion module.".format(VERSION), 184 info.options); 185 return 0; 186 } 187 if (packageName == null) 188 { 189 defaultGetoptPrinter("Packagename required.", info.options); 190 return 1; 191 } 192 "packageversion for '%s' in '%s'".format(packageName, packageDir).warning; 193 194 if (packageName != dubPackage) 195 { 196 "Skipping packageversion".warning; 197 return 0; 198 } 199 auto versionText = getVersion(); 200 auto license = getLicense(); 201 202 auto file = (packageDir ? packageDir ~ "/" : "./") ~ "out/generated/packageversion/" 203 ~ packageName.replace(".", "/") ~ "/packageversion.d"; 204 auto moduleText = "module %s.packageversion;\n".format(packageName); 205 auto nameText = "const NAME = \"%s\";\n".format(packageName); 206 auto packageVersionText = "const VERSION = \"%s\";\n".format(versionText); 207 auto licenseText = "const LICENSE = \"%s\";\n".format(license); 208 auto registerVersionText = "static this()\n{\n import packageversion;\n packageversion.registerPackageVersion(NAME, VERSION, LICENSE);\n}\n"; 209 auto totalText = moduleText ~ nameText ~ packageVersionText ~ licenseText ~ registerVersionText; 210 211 if (exists(file)) 212 { 213 auto content = file.readText; 214 if (content != totalText) 215 { 216 "Updating packageversion module".warning; 217 file.writeContent(totalText); 218 } 219 else 220 { 221 "Packageversion already up-to-date".warning; 222 } 223 } 224 else 225 { 226 "Writing packageversion module".warning; 227 file.writeContent(totalText); 228 } 229 return 0; 230 }