1 module config;
2 
3 import std.file;
4 import std.path;
5 import std.process : environment;
6 import std..string;
7 
8 import core.runtime;
9 
10 import ae.sys.d.manager;
11 import ae.sys.paths;
12 import ae.utils.funopt;
13 import ae.utils.meta;
14 import ae.utils.sini;
15 
16 static import std.getopt;
17 
18 struct Opts
19 {
20 	Option!(string, hiddenOption) dir;
21 	Option!(string, "Path to the configuration file to use", "PATH") configFile;
22 	Switch!("Do not update D repositories from GitHub [local.offline]") offline;
23 	Option!(string, "How many jobs to run makefiles in [local.makeJobs]", "N", 'j') jobs;
24 	Option!(string[], "Additional configuration. Equivalent to digger.ini settings.", "NAME=VALUE", 'c', "config") configLines;
25 
26 	Parameter!(string, "Action to perform (see list below)") action;
27 	Parameter!(immutable(string)[]) actionArguments;
28 }
29 immutable Opts opts;
30 
31 struct ConfigFile
32 {
33 	DManager.Config.Build build;
34 	DManager.Config.Local local;
35 
36 	struct App
37 	{
38 		string[] gitOptions;
39 	}
40 	App app;
41 }
42 immutable ConfigFile config;
43 
44 shared static this()
45 {
46 	alias fun = structFun!Opts;
47 	enum funOpts = FunOptConfig([std.getopt.config.stopOnFirstNonOption]);
48 	void usageFun(string) {}
49 	auto opts = funopt!(fun, funOpts, usageFun)(Runtime.args);
50 
51 	if (opts.dir)
52 		chdir(opts.dir.value);
53 
54 	enum CONFIG_FILE = "digger.ini";
55 
56 	if (!opts.configFile)
57 	{
58 		auto searchDirs = [
59 			string.init,
60 			thisExePath.dirName,
61 			__FILE__.dirName,
62 			] ~ getConfigDirs() ~ [
63 			buildPath(environment.get("HOME", environment.get("USERPROFILE")), ".digger"), // legacy
64 		];
65 		version (Posix)
66 			searchDirs ~= "/etc/"; // legacy
67 
68 		foreach (dir; searchDirs)
69 		{
70 			auto path = dir.buildPath(CONFIG_FILE);
71 			if (path.exists)
72 			{
73 				opts.configFile = path;
74 				break;
75 			}
76 		}
77 	}
78 
79 	if (opts.configFile.value.exists)
80 	{
81 		config = cast(immutable)
82 			opts.configFile.value
83 			.readText()
84 			.splitLines()
85 			.parseIni!ConfigFile();
86 	}
87 
88 	string workDir;
89 	if (!config.local.workDir.length)
90 		if (exists("repo")) // legacy
91 			workDir = ".";
92 		else
93 			workDir = "work"; // TODO use ~/.cache/digger
94 	else
95 		workDir = config.local.workDir.expandTilde();
96 	config.local.workDir = workDir.absolutePath().buildNormalizedPath();
97 
98 	if (opts.offline)
99 		config.local.offline = opts.offline;
100 	if (opts.jobs)
101 		config.local.makeJobs = opts.jobs;
102 	opts.configLines.parseIniInto(config);
103 
104 	.opts = cast(immutable)opts;
105 
106 	if (config.app.gitOptions)
107 	{
108 		import ae.sys.git : Repository;
109 		Repository.globalOptions ~= config.app.gitOptions;
110 	}
111 }
112 
113 @property string subDir(string name)() { return buildPath(config.local.workDir, name); }