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         trace(e);
39         return null;
40     }
41 }
42 
43 auto getFromDubJson(string path, string what)
44 {
45     try
46     {
47         import std.json;
48 
49         auto json = parseJSON(readText(path));
50         return json[what].str;
51     }
52     catch (FileException e)
53     {
54         trace(e);
55         return null;
56     }
57 }
58 
59 auto packageDir()
60 {
61     import std.process;
62 
63     auto e = std.process.environment.toAA;
64     if ("DUB_PACKAGE_DIR" !in e)
65     {
66         return null;
67     }
68     return e["DUB_PACKAGE_DIR"];
69 }
70 
71 auto getFromDubJsonFromPackageDir()
72 {
73     if (string pd = packageDir)
74     {
75         return getFromDubJson(pd ~ "/dub.json", "version");
76     }
77     return null;
78 }
79 
80 string getFromDubSdlFromPackageDir()
81 {
82     if (string pd = packageDir)
83     {
84         return getFromDubSdl(pd ~ "/dub.sdl", "version");
85     }
86     return null;
87 }
88 
89 string getFromGit()
90 {
91     auto gitCommand = ["git", "describe", "--dirty"].execute(null, Config.none,
92             size_t.max, packageDir);
93     if (gitCommand.status != 0)
94     {
95         "Cannot get version with git describe --dirty, make sure you have at least one annotated tag"
96             .info;
97         return null;
98     }
99 
100     return gitCommand.output.strip;
101 }
102 
103 string getVersion()
104 {
105     if (string res = getFromDubJsonFromPackageDir)
106     {
107         "Using version from dub.json '%s'".format(res).warning;
108         return res;
109     }
110     if (string res = getFromDubSdlFromPackageDir)
111     {
112         "Using version from dub.sdl '%s'".format(res).warning;
113         return res;
114     }
115     if (string res = getFromGit)
116     {
117         "Using version from git '%s'".format(res).warning;
118         return res;
119     }
120     throw new Exception("Cannot determine version");
121 }
122 
123 int main(string[] args)
124 {
125     import std.getopt;
126 
127     string packageName;
128     auto info = getopt(args, "packageName", &packageName);
129     if (info.helpWanted)
130     {
131         defaultGetoptPrinter("packageversion %s. Generate or update a simple packageversion module.".format("v0.0.11"),
132                 info.options);
133         return 0;
134     }
135     if (packageName == null)
136     {
137         defaultGetoptPrinter("Packagename required.", info.options);
138         return 1;
139     }
140 
141     auto versionText = getVersion();
142 
143     auto file = "out/generated/packageversion/" ~ packageName.replace(".",
144             "/") ~ "/packageversion.d";
145     auto moduleText = "module %s.packageversion;\n".format(packageName);
146     auto packageVersionText = "const PACKAGE_VERSION = \"%s\";\n".format(versionText);
147     auto registerVersionText = "static this()\n{\n    import packageversion;\n    packageversion.registerPackageVersion(\"%s\", \"%s\");\n}\n"
148         .format(packageName, versionText);
149     auto totalText = moduleText ~ packageVersionText ~ registerVersionText;
150 
151     if (exists(file))
152     {
153         auto content = file.readText;
154         if (content != totalText)
155         {
156             "Updating packageversion module".warning;
157             file.writeContent(totalText);
158         }
159     }
160     else
161     {
162         "Writing packageversion module".warning;
163         file.writeContent(totalText);
164     }
165     return 0;
166 }