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