1 /** 2 * This file is part of DCD, a development tool for the D programming language. 3 * Copyright (C) 2014 Brian Schott 4 * 5 * This program is free software: you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation, either version 3 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 */ 18 19 module server.server; 20 21 import std.algorithm; 22 import std.array; 23 import std.experimental.logger; 24 import std.file; 25 import std.path; 26 import std.process: environment; 27 import std.stdio: File; 28 import std.stdio: KeepTerminator; 29 30 import dsymbol.modulecache; 31 32 /// Name of the server configuration file 33 enum CONFIG_FILE_NAME = "dcd.conf"; 34 35 version(linux) version = useXDG; 36 version(BSD) version = useXDG; 37 version(FreeBSD) version = useXDG; 38 version(OSX) version = useXDG; 39 40 /** 41 * Locates the configuration file 42 */ 43 string getConfigurationLocation() 44 { 45 version (useXDG) 46 { 47 string configDir = environment.get("XDG_CONFIG_HOME", null); 48 if (configDir is null) 49 { 50 configDir = environment.get("HOME", null); 51 if (configDir !is null) 52 configDir = buildPath(configDir, ".config", "dcd", CONFIG_FILE_NAME); 53 if (!exists(configDir)) 54 configDir = buildPath("/etc/", CONFIG_FILE_NAME); 55 } 56 else 57 { 58 configDir = buildPath(configDir, "dcd", CONFIG_FILE_NAME); 59 } 60 return configDir; 61 } 62 else version(Windows) 63 { 64 return CONFIG_FILE_NAME; 65 } 66 } 67 68 /** 69 * Prints a warning message to the user when an old config file is detected. 70 */ 71 void warnAboutOldConfigLocation() 72 { 73 version (linux) if ("~/.config/dcd".expandTilde().exists() 74 && "~/.config/dcd".expandTilde().isFile()) 75 { 76 warning("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); 77 warning("!! Upgrade warning:"); 78 warning("!! '~/.config/dcd' should be moved to '$XDG_CONFIG_HOME/dcd/dcd.conf'"); 79 warning("!! or '$HOME/.config/dcd/dcd.conf'"); 80 warning("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); 81 } 82 } 83 84 import std.regex : ctRegex; 85 alias envVarRegex = ctRegex!(`\$\{([_a-zA-Z][_a-zA-Z 0-9]*)\}`); 86 87 private unittest 88 { 89 import std.regex : replaceAll; 90 91 enum input = `${HOME}/aaa/${_bb_b}/ccc`; 92 93 assert(replaceAll!(m => m[1])(input, envVarRegex) == `HOME/aaa/_bb_b/ccc`); 94 } 95 96 /** 97 * Loads import directories from the configuration file 98 */ 99 string[] loadConfiguredImportDirs() 100 { 101 string expandEnvVars(string l) 102 { 103 import std.regex : replaceAll; 104 return replaceAll!(m => environment.get(m[1], ""))(l, envVarRegex); 105 } 106 107 warnAboutOldConfigLocation(); 108 immutable string configLocation = getConfigurationLocation(); 109 if (!configLocation.exists()) 110 return []; 111 info("Loading configuration from ", configLocation); 112 File f = File(configLocation, "rt"); 113 return f.byLine(KeepTerminator.no) 114 .filter!(a => a.length > 0 && a[0] != '#') 115 .map!(a => a.idup) 116 .map!(expandEnvVars) 117 .filter!(a => existanceCheck(a)) 118 .array(); 119 }