1 /++ 2 + Copyright: Copyright © 2018, Christian Köstlin 3 + License: MIT 4 + Authors: Christian Koestlin 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 import std.process; 57 auto packageDir() 58 { 59 auto e = std.process.environment.toAA; 60 if ("DUB_PACKAGE_DIR" !in e) 61 { 62 return null; 63 } 64 return e["DUB_PACKAGE_DIR"]; 65 } 66 67 auto dubPackage() 68 { 69 auto e = std.process.environment.toAA; 70 if ("DUB_PACKAGE" !in e) 71 { 72 return null; 73 } 74 return e["DUB_PACKAGE"]; 75 } 76 77 auto getFromDubJsonFromPackageDir(string what) 78 { 79 if (string pd = packageDir) 80 { 81 return getFromDubJson(pd ~ "/dub.json", what); 82 } 83 return null; 84 } 85 86 string getFromDubSdlFromPackageDir(string what) 87 { 88 if (string pd = packageDir) 89 { 90 return getFromDubSdl(pd ~ "/dub.sdl", what); 91 } 92 return null; 93 } 94 95 string getFromGit() 96 { 97 auto gitCommand = ["git", "describe", "--dirty"].execute(null, Config.none, 98 size_t.max, packageDir); 99 if (gitCommand.status != 0) 100 { 101 "Cannot get version with git describe --dirty, make sure you have at least one annotated tag" 102 .info; 103 return null; 104 } 105 106 return gitCommand.output.strip; 107 } 108 109 string getLicense() 110 { 111 auto what = "license"; 112 if (string res = getFromDubJsonFromPackageDir(what)) 113 { 114 "Using %s from dub.json '%s'".format(what, res).warning; 115 return res; 116 } 117 if (string res = getFromDubSdlFromPackageDir(what)) 118 { 119 "Using %s from dub.sdl '%s'".format(what, res).warning; 120 return res; 121 } 122 throw new Exception("Cannot determine %s".format(what)); 123 124 } 125 126 string getVersion() 127 { 128 auto what = "version"; 129 if (string res = getFromDubJsonFromPackageDir(what)) 130 { 131 "Using %s from dub.json '%s'".format(what, res).warning; 132 return res; 133 } 134 if (string res = getFromDubSdlFromPackageDir(what)) 135 { 136 "Using %s from dub.sdl '%s'".format(what, res).warning; 137 return res; 138 } 139 if (string res = getFromGit) 140 { 141 "Using %s from git '%s'".format(what, res).warning; 142 return res; 143 } 144 throw new Exception("Cannot determine %s".format(what)); 145 } 146 147 int main(string[] args) 148 { 149 import std.getopt; 150 151 string packageName; 152 auto info = getopt(args, "packageName", &packageName); 153 if (info.helpWanted) 154 { 155 import packageversion.packageversion; 156 defaultGetoptPrinter("packageversion %s. Generate or update a simple packageversion module.".format(VERSION), 157 info.options); 158 return 0; 159 } 160 if (packageName == null) 161 { 162 defaultGetoptPrinter("Packagename required.", info.options); 163 return 1; 164 } 165 166 "packageversion for '%s' in '%s'".format(packageName, packageDir).warning; 167 168 if (packageName != dubPackage) { 169 writeln(std.process.environment.toAA); 170 "Skipping packageversion".warning; 171 return 0; 172 } 173 auto versionText = getVersion(); 174 auto license = getLicense(); 175 176 auto file = (packageDir ? packageDir ~ "/" : "./") 177 ~ "out/generated/packageversion/" 178 ~ packageName.replace(".", "/") ~ "/packageversion.d"; 179 auto moduleText = "module %s.packageversion;\n".format(packageName); 180 auto nameText = "const NAME = \"%s\";\n".format(packageName); 181 auto packageVersionText = "const VERSION = \"%s\";\n".format(versionText); 182 auto licenseText = "const LICENSE = \"%s\";\n".format(license); 183 auto registerVersionText = "static this()\n{\n import packageversion;\n packageversion.registerPackageVersion(NAME, VERSION, LICENSE);\n}\n"; 184 auto totalText = moduleText ~ nameText ~ packageVersionText ~ licenseText ~ registerVersionText; 185 186 if (exists(file)) 187 { 188 auto content = file.readText; 189 if (content != totalText) 190 { 191 "Updating packageversion module".warning; 192 file.writeContent(totalText); 193 } 194 } 195 else 196 { 197 "Writing packageversion module".warning; 198 file.writeContent(totalText); 199 } 200 return 0; 201 }