1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47 package org.eclipse.jgit.util;
48
49 import java.io.File;
50 import java.io.IOException;
51 import java.net.InetAddress;
52 import java.net.UnknownHostException;
53 import java.nio.file.Files;
54 import java.nio.file.InvalidPathException;
55 import java.nio.file.Path;
56 import java.nio.file.Paths;
57 import java.security.AccessController;
58 import java.security.PrivilegedAction;
59 import java.text.DateFormat;
60 import java.text.SimpleDateFormat;
61 import java.util.Locale;
62 import java.util.TimeZone;
63 import java.util.concurrent.atomic.AtomicReference;
64
65 import org.eclipse.jgit.errors.ConfigInvalidException;
66 import org.eclipse.jgit.errors.CorruptObjectException;
67 import org.eclipse.jgit.internal.JGitText;
68 import org.eclipse.jgit.lib.Config;
69 import org.eclipse.jgit.lib.Constants;
70 import org.eclipse.jgit.lib.ObjectChecker;
71 import org.eclipse.jgit.lib.StoredConfig;
72 import org.eclipse.jgit.storage.file.FileBasedConfig;
73 import org.eclipse.jgit.util.time.MonotonicClock;
74 import org.eclipse.jgit.util.time.MonotonicSystemClock;
75 import org.slf4j.Logger;
76 import org.slf4j.LoggerFactory;
77
78
79
80
81
82
83
84
85
86 public abstract class SystemReader {
87
88 private final static Logger LOG = LoggerFactory
89 .getLogger(SystemReader.class);
90
91 private static final SystemReader DEFAULT;
92
93 private static Boolean isMacOS;
94
95 private static Boolean isWindows;
96
97 static {
98 SystemReader r = new Default();
99 r.init();
100 DEFAULT = r;
101 }
102
103 private static class Default extends SystemReader {
104 private volatile String hostname;
105
106 @Override
107 public String getenv(String variable) {
108 return System.getenv(variable);
109 }
110
111 @Override
112 public String getProperty(String key) {
113 return System.getProperty(key);
114 }
115
116 @Override
117 public FileBasedConfig openSystemConfig(Config parent, FS fs) {
118 if (StringUtils
119 .isEmptyOrNull(getenv(Constants.GIT_CONFIG_NOSYSTEM_KEY))) {
120 File configFile = fs.getGitSystemConfig();
121 if (configFile != null) {
122 return new FileBasedConfig(parent, configFile, fs);
123 }
124 }
125 return new FileBasedConfig(parent, null, fs) {
126 @Override
127 public void load() {
128
129 }
130
131 @Override
132 public boolean isOutdated() {
133
134 return false;
135 }
136 };
137 }
138
139 @Override
140 public FileBasedConfig openUserConfig(Config parent, FS fs) {
141 return new FileBasedConfig(parent, new File(fs.userHome(), ".gitconfig"),
142 fs);
143 }
144
145 private Path getXDGConfigHome(FS fs) {
146 String configHomePath = getenv(Constants.XDG_CONFIG_HOME);
147 if (StringUtils.isEmptyOrNull(configHomePath)) {
148 configHomePath = new File(fs.userHome(), ".config")
149 .getAbsolutePath();
150 }
151 try {
152 Path xdgHomePath = Paths.get(configHomePath);
153 Files.createDirectories(xdgHomePath);
154 return xdgHomePath;
155 } catch (IOException | InvalidPathException e) {
156 LOG.error(JGitText.get().createXDGConfigHomeFailed,
157 configHomePath, e);
158 }
159 return null;
160 }
161
162 @Override
163 public FileBasedConfig openJGitConfig(Config parent, FS fs) {
164 Path xdgPath = getXDGConfigHome(fs);
165 if (xdgPath != null) {
166 Path configPath = null;
167 try {
168 configPath = xdgPath.resolve("jgit");
169 Files.createDirectories(configPath);
170 configPath = configPath.resolve(Constants.CONFIG);
171 return new FileBasedConfig(parent, configPath.toFile(), fs);
172 } catch (IOException e) {
173 LOG.error(JGitText.get().createJGitConfigFailed, configPath,
174 e);
175 }
176 }
177 return new FileBasedConfig(parent,
178 new File(fs.userHome(), ".jgitconfig"), fs);
179 }
180
181 @Override
182 public String getHostname() {
183 if (hostname == null) {
184 try {
185 InetAddress localMachine = InetAddress.getLocalHost();
186 hostname = localMachine.getCanonicalHostName();
187 } catch (UnknownHostException e) {
188
189 hostname = "localhost";
190 }
191 assert hostname != null;
192 }
193 return hostname;
194 }
195
196 @Override
197 public long getCurrentTime() {
198 return System.currentTimeMillis();
199 }
200
201 @Override
202 public int getTimezone(long when) {
203 return getTimeZone().getOffset(when) / (60 * 1000);
204 }
205 }
206
207 private static volatile SystemReader INSTANCE = DEFAULT;
208
209
210
211
212
213
214 public static SystemReader getInstance() {
215 return INSTANCE;
216 }
217
218
219
220
221
222
223
224
225 public static void setInstance(SystemReader newReader) {
226 isMacOS = null;
227 isWindows = null;
228 if (newReader == null)
229 INSTANCE = DEFAULT;
230 else {
231 newReader.init();
232 INSTANCE = newReader;
233 }
234 }
235
236 private ObjectChecker platformChecker;
237
238 private AtomicReference<FileBasedConfig> systemConfig = new AtomicReference<>();
239
240 private AtomicReference<FileBasedConfig> userConfig = new AtomicReference<>();
241
242 private AtomicReference<FileBasedConfig> jgitConfig = new AtomicReference<>();
243
244 private void init() {
245
246
247 if (platformChecker == null)
248 setPlatformChecker();
249 }
250
251
252
253
254
255
256 protected final void setPlatformChecker() {
257 platformChecker = new ObjectChecker()
258 .setSafeForWindows(isWindows())
259 .setSafeForMacOS(isMacOS());
260 }
261
262
263
264
265
266
267
268 public abstract String getHostname();
269
270
271
272
273
274
275
276
277 public abstract String getenv(String variable);
278
279
280
281
282
283
284
285
286 public abstract String getProperty(String key);
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301 public abstract FileBasedConfig openUserConfig(Config parent, FS fs);
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318 public abstract FileBasedConfig openSystemConfig(Config parent, FS fs);
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334 public abstract FileBasedConfig openJGitConfig(Config parent, FS fs);
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349 public StoredConfig getUserConfig()
350 throws ConfigInvalidException, IOException {
351 FileBasedConfig c = userConfig.get();
352 if (c == null) {
353 userConfig.compareAndSet(null,
354 openUserConfig(getSystemConfig(), FS.DETECTED));
355 c = userConfig.get();
356 }
357
358
359 updateAll(c);
360 return c;
361 }
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376 public StoredConfig getJGitConfig()
377 throws ConfigInvalidException, IOException {
378 FileBasedConfig c = jgitConfig.get();
379 if (c == null) {
380 jgitConfig.compareAndSet(null,
381 openJGitConfig(null, FS.DETECTED));
382 c = jgitConfig.get();
383 }
384 updateAll(c);
385 return c;
386 }
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401 public StoredConfig getSystemConfig()
402 throws ConfigInvalidException, IOException {
403 FileBasedConfig c = systemConfig.get();
404 if (c == null) {
405 systemConfig.compareAndSet(null,
406 openSystemConfig(getJGitConfig(), FS.DETECTED));
407 c = systemConfig.get();
408 }
409 updateAll(c);
410 return c;
411 }
412
413
414
415
416
417
418
419
420
421
422
423 private void updateAll(Config config)
424 throws ConfigInvalidException, IOException {
425 if (config == null) {
426 return;
427 }
428 updateAll(config.getBaseConfig());
429 if (config instanceof FileBasedConfig) {
430 FileBasedConfig cfg = (FileBasedConfig) config;
431 if (cfg.isOutdated()) {
432 LOG.debug("loading config {}", cfg);
433 cfg.load();
434 }
435 }
436 }
437
438
439
440
441
442
443 public abstract long getCurrentTime();
444
445
446
447
448
449
450
451 public MonotonicClock getClock() {
452 return new MonotonicSystemClock();
453 }
454
455
456
457
458
459
460
461
462 public abstract int getTimezone(long when);
463
464
465
466
467
468
469
470 public TimeZone getTimeZone() {
471 return TimeZone.getDefault();
472 }
473
474
475
476
477
478
479
480 public Locale getLocale() {
481 return Locale.getDefault();
482 }
483
484
485
486
487
488
489
490
491
492
493 public SimpleDateFormat getSimpleDateFormat(String pattern) {
494 return new SimpleDateFormat(pattern);
495 }
496
497
498
499
500
501
502
503
504
505
506
507
508 public SimpleDateFormat getSimpleDateFormat(String pattern, Locale locale) {
509 return new SimpleDateFormat(pattern, locale);
510 }
511
512
513
514
515
516
517
518
519
520
521
522
523
524 public DateFormat getDateTimeInstance(int dateStyle, int timeStyle) {
525 return DateFormat.getDateTimeInstance(dateStyle, timeStyle);
526 }
527
528
529
530
531
532
533 public boolean isWindows() {
534 if (isWindows == null) {
535 String osDotName = getOsName();
536 isWindows = Boolean.valueOf(osDotName.startsWith("Windows"));
537 }
538 return isWindows.booleanValue();
539 }
540
541
542
543
544
545
546 public boolean isMacOS() {
547 if (isMacOS == null) {
548 String osDotName = getOsName();
549 isMacOS = Boolean.valueOf(
550 "Mac OS X".equals(osDotName) || "Darwin".equals(osDotName));
551 }
552 return isMacOS.booleanValue();
553 }
554
555 private String getOsName() {
556 return AccessController.doPrivileged(
557 (PrivilegedAction<String>) () -> getProperty("os.name")
558 );
559 }
560
561
562
563
564
565
566
567
568
569
570 public void checkPath(String path) throws CorruptObjectException {
571 platformChecker.checkPath(path);
572 }
573
574
575
576
577
578
579
580
581
582
583
584
585 public void checkPath(byte[] path) throws CorruptObjectException {
586 platformChecker.checkPath(path, 0, path.length);
587 }
588 }