Mercurial > jhg
comparison src/org/tmatesoft/hg/internal/Internals.java @ 379:fa2be7a05af6
Implement discovery of mercurial installation, use it to read/write configuration files
author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
---|---|
date | Thu, 09 Feb 2012 16:47:17 +0100 |
parents | 9fb990c8a724 |
children | 82336b7c54f4 |
comparison
equal
deleted
inserted
replaced
378:9fb990c8a724 | 379:fa2be7a05af6 |
---|---|
20 | 20 |
21 import java.io.File; | 21 import java.io.File; |
22 import java.io.FileOutputStream; | 22 import java.io.FileOutputStream; |
23 import java.io.IOException; | 23 import java.io.IOException; |
24 import java.util.ArrayList; | 24 import java.util.ArrayList; |
25 import java.util.Arrays; | |
26 import java.util.Collections; | |
27 import java.util.LinkedHashSet; | |
25 import java.util.List; | 28 import java.util.List; |
29 import java.util.StringTokenizer; | |
26 | 30 |
27 import org.tmatesoft.hg.repo.HgInternals; | 31 import org.tmatesoft.hg.repo.HgInternals; |
28 import org.tmatesoft.hg.repo.HgRepoConfig.ExtensionsSection; | 32 import org.tmatesoft.hg.repo.HgRepoConfig.ExtensionsSection; |
29 import org.tmatesoft.hg.repo.HgRepository; | 33 import org.tmatesoft.hg.repo.HgRepository; |
30 import org.tmatesoft.hg.util.PathRewrite; | 34 import org.tmatesoft.hg.util.PathRewrite; |
34 * | 38 * |
35 * @author Artem Tikhomirov | 39 * @author Artem Tikhomirov |
36 * @author TMate Software Ltd. | 40 * @author TMate Software Ltd. |
37 */ | 41 */ |
38 public class Internals { | 42 public class Internals { |
43 | |
44 public static final String CFG_PROPERTY_HG_INSTALL_ROOT = "hg4j.hg.install_root"; | |
39 | 45 |
40 private int requiresFlags = 0; | 46 private int requiresFlags = 0; |
41 private List<Filter.Factory> filterFactories; | 47 private List<Filter.Factory> filterFactories; |
42 | 48 |
43 | 49 |
112 } | 118 } |
113 | 119 |
114 public static boolean runningOnWindows() { | 120 public static boolean runningOnWindows() { |
115 return System.getProperty("os.name").indexOf("Windows") != -1; | 121 return System.getProperty("os.name").indexOf("Windows") != -1; |
116 } | 122 } |
117 | 123 |
124 /** | |
125 * For Unix, returns installation root, which is the parent directory of the hg executable (or symlink) being run. | |
126 * For Windows, it's Mercurial installation directory itself | |
127 */ | |
128 private static File findHgInstallRoot() { | |
129 // let clients to override Hg install location | |
130 String p = System.getProperty(CFG_PROPERTY_HG_INSTALL_ROOT); | |
131 if (p != null) { | |
132 return new File(p); | |
133 } | |
134 StringTokenizer st = new StringTokenizer(System.getenv("PATH"), System.getProperty("path.separator"), false); | |
135 final boolean runsOnWin = runningOnWindows(); | |
136 while (st.hasMoreTokens()) { | |
137 String pe = st.nextToken(); | |
138 File execCandidate = new File(pe, runsOnWin ? "hg.exe" : "hg"); | |
139 if (execCandidate.exists() && execCandidate.isFile()) { | |
140 File execDir = execCandidate.getParentFile(); | |
141 // e.g. on Unix runs "/shared/tools/bin/hg", directory of interest is "/shared/tools/" | |
142 return runsOnWin ? execDir : execDir.getParentFile(); | |
143 } | |
144 } | |
145 return null; | |
146 } | |
147 | |
148 /** | |
149 * @see http://www.selenic.com/mercurial/hgrc.5.html | |
150 */ | |
118 public ConfigFile readConfiguration(HgRepository hgRepo, File repoRoot) throws IOException { | 151 public ConfigFile readConfiguration(HgRepository hgRepo, File repoRoot) throws IOException { |
119 ConfigFile configFile = new ConfigFile(); | 152 ConfigFile configFile = new ConfigFile(); |
153 File hgInstallRoot = findHgInstallRoot(); // may be null | |
154 // | |
120 if (runningOnWindows()) { | 155 if (runningOnWindows()) { |
121 // FIXME read install-dir | 156 if (hgInstallRoot != null) { |
122 // | 157 for (File f : getWindowsConfigFilesPerInstall(hgInstallRoot)) { |
123 // XXX perhaps, makes sense to compare getenv(USERPROFILE) and getenv(HOME) and use | 158 configFile.addLocation(f); |
124 // them if set (and use both if their values do not match). Only if both not set, rely to user.home? | 159 } |
125 // Also respect #getUserConfigurationFileToWrite() below | 160 } |
126 configFile.addLocation(new File(System.getProperty("user.home"), "Mercurial.ini")); | 161 LinkedHashSet<String> locations = new LinkedHashSet<String>(); |
162 locations.add(System.getenv("USERPROFILE")); | |
163 locations.add(System.getenv("HOME")); | |
164 locations.remove(null); | |
165 for (String loc : locations) { | |
166 File location = new File(loc); | |
167 configFile.addLocation(new File(location, "Mercurial.ini")); | |
168 configFile.addLocation(new File(location, ".hgrc")); | |
169 } | |
127 } else { | 170 } else { |
128 // FIXME read from install-root | 171 if (hgInstallRoot != null) { |
129 // | 172 File d = new File(hgInstallRoot, "etc/mercurial/hgrc.d/"); |
130 File d = new File("/etc/mercurial/hgrc.d/"); | 173 if (d.isDirectory() && d.canRead()) { |
131 if (d.isDirectory()) { | 174 for (File f : listConfigFiles(d)) { |
132 for (File f : d.listFiles()) { | |
133 // XXX in fact, need to sort in alphabetical order | |
134 if (f.getName().endsWith(".rc")) { | |
135 configFile.addLocation(f); | 175 configFile.addLocation(f); |
136 } | 176 } |
137 } | 177 } |
178 configFile.addLocation(new File(hgInstallRoot, "etc/mercurial/hgrc")); | |
179 } | |
180 // same, but with absolute paths | |
181 File d = new File("/etc/mercurial/hgrc.d/"); | |
182 if (d.isDirectory() && d.canRead()) { | |
183 for (File f : listConfigFiles(d)) { | |
184 configFile.addLocation(f); | |
185 } | |
138 } | 186 } |
139 configFile.addLocation(new File("/etc/mercurial/hgrc")); | 187 configFile.addLocation(new File("/etc/mercurial/hgrc")); |
140 } | 188 configFile.addLocation(new File(System.getenv("HOME"), ".hgrc")); |
141 configFile.addLocation(new File(System.getProperty("user.home"), ".hgrc")); | 189 } |
142 // last one, overrides anything else | 190 // last one, overrides anything else |
143 // <repo>/.hg/hgrc | 191 // <repo>/.hg/hgrc |
144 configFile.addLocation(new File(repoRoot, "hgrc")); | 192 configFile.addLocation(new File(repoRoot, "hgrc")); |
145 return configFile; | 193 return configFile; |
146 } | 194 } |
147 | 195 |
148 /** | 196 private static List<File> getWindowsConfigFilesPerInstall(File hgInstallDir) { |
149 * @return | 197 File f = new File(hgInstallDir, "Mercurial.ini"); |
150 */ | 198 if (f.exists()) { |
199 return Collections.singletonList(f); | |
200 } | |
201 f = new File(hgInstallDir, "hgrc.d/"); | |
202 if (f.canRead() && f.isDirectory()) { | |
203 return listConfigFiles(f); | |
204 } | |
205 // FIXME query registry, e.g. with | |
206 // Runtime.exec("reg query HKLM\Software\Mercurial") | |
207 // | |
208 f = new File("C:\\Mercurial\\Mercurial.ini"); | |
209 if (f.exists()) { | |
210 return Collections.singletonList(f); | |
211 } | |
212 return Collections.emptyList(); | |
213 } | |
214 | |
215 private static List<File> listConfigFiles(File dir) { | |
216 assert dir.canRead(); | |
217 assert dir.isDirectory(); | |
218 final File[] allFiles = dir.listFiles(); | |
219 // File is Comparable, lexicographically by default | |
220 Arrays.sort(allFiles); | |
221 ArrayList<File> rv = new ArrayList<File>(allFiles.length); | |
222 for (File f : allFiles) { | |
223 if (f.getName().endsWith(".rc")) { | |
224 rv.add(f); | |
225 } | |
226 } | |
227 return rv; | |
228 } | |
229 | |
151 public static File getInstallationConfigurationFileToWrite() { | 230 public static File getInstallationConfigurationFileToWrite() { |
152 // TODO Auto-generated method stub | 231 File hgInstallRoot = findHgInstallRoot(); // may be null |
153 // FIXME find out install-root | 232 // choice of which hgrc to pick here is according to my own pure discretion |
154 throw new UnsupportedOperationException(); | 233 if (hgInstallRoot != null) { |
155 } | 234 // use this location only if it's writable |
156 | 235 File cfg = new File(hgInstallRoot, runningOnWindows() ? "Mercurial.ini" : "etc/mercurial/hgrc"); |
157 /** | 236 if (cfg.canWrite() || cfg.getParentFile().canWrite()) { |
158 * @return | 237 return cfg; |
159 */ | 238 } |
239 } | |
240 // fallback | |
241 if (runningOnWindows()) { | |
242 if (hgInstallRoot == null) { | |
243 return new File("C:\\Mercurial\\Mercurial.ini"); | |
244 } else { | |
245 // yes, we tried this file already (above) and found it non-writable | |
246 // let caller fail with can't write | |
247 return new File(hgInstallRoot, "Mercurial.ini"); | |
248 } | |
249 } else { | |
250 return new File("/etc/mercurial/hgrc"); | |
251 } | |
252 } | |
253 | |
160 public static File getUserConfigurationFileToWrite() { | 254 public static File getUserConfigurationFileToWrite() { |
161 final File rv = new File(System.getProperty("user.home"), ".hgrc"); | 255 LinkedHashSet<String> locations = new LinkedHashSet<String>(); |
162 if (rv.exists() && rv.canWrite()) { | 256 final boolean runsOnWindows = runningOnWindows(); |
163 return rv; | 257 if (runsOnWindows) { |
164 } | 258 locations.add(System.getenv("USERPROFILE")); |
165 if (runningOnWindows()) { | 259 } |
166 // try another well-known location | 260 locations.add(System.getenv("HOME")); |
167 // TODO comment above regarding USERPROFILE and HOME variables applies here as well | 261 locations.remove(null); |
168 File f = new File(System.getProperty("user.home"), "Mercurial.ini"); | 262 for (String loc : locations) { |
169 if (f.exists() && f.canWrite()) { | 263 File location = new File(loc); |
170 return f; | 264 File rv = new File(location, ".hgrc"); |
171 } | 265 if (rv.exists() && rv.canWrite()) { |
172 } | 266 return rv; |
173 // fallback to default value | 267 } |
174 return rv; | 268 if (runsOnWindows) { |
269 rv = new File(location, "Mercurial.ini"); | |
270 if (rv.exists() && rv.canWrite()) { | |
271 return rv; | |
272 } | |
273 } | |
274 } | |
275 // fallback to default, let calling code fail with Exception if can't write | |
276 return new File(System.getProperty("user.home"), ".hgrc"); | |
175 } | 277 } |
176 } | 278 } |