Use the user's Cygwin home directory if invoked by a Cygwin shell
[egit/zawir.git] / org.spearce.jgit / src / org / spearce / jgit / util / FS.java
blob4c92beda7007e7a2a7a85511b2db20bf790c8734
1 /*
2 * Copyright (C) 2008 Shawn Pearce <spearce@spearce.org>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License, version 2, as published by the Free Software Foundation.
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
17 package org.spearce.jgit.util;
19 import java.io.File;
20 import java.security.AccessController;
21 import java.security.PrivilegedAction;
23 /** Abstraction to support various file system operations not in Java. */
24 public abstract class FS {
25 /** The implementation selected for this operating system and JRE. */
26 public static final FS INSTANCE;
28 static {
29 if (FS_Win32.detect()) {
30 if (FS_Win32_Cygwin.detect())
31 INSTANCE = new FS_Win32_Cygwin();
32 else
33 INSTANCE = new FS_Win32();
34 } else if (FS_POSIX_Java6.detect())
35 INSTANCE = new FS_POSIX_Java6();
36 else
37 INSTANCE = new FS_POSIX_Java5();
40 /**
41 * Does this operating system and JRE support the execute flag on files?
43 * @return true if this implementation can provide reasonably accurate
44 * executable bit information; false otherwise.
46 public abstract boolean supportsExecute();
48 /**
49 * Determine if the file is executable (or not).
50 * <p>
51 * Not all platforms and JREs support executable flags on files. If the
52 * feature is unsupported this method will always return false.
54 * @param f
55 * abstract path to test.
56 * @return true if the file is believed to be executable by the user.
58 public abstract boolean canExecute(File f);
60 /**
61 * Set a file to be executable by the user.
62 * <p>
63 * Not all platforms and JREs support executable flags on files. If the
64 * feature is unsupported this method will always return false and no
65 * changes will be made to the file specified.
67 * @param f
68 * path to modify the executable status of.
69 * @param canExec
70 * true to enable execution; false to disable it.
71 * @return true if the change succeeded; false otherwise.
73 public abstract boolean setExecute(File f, boolean canExec);
75 /**
76 * Resolve this file to its actual path name that the JRE can use.
77 * <p>
78 * This method can be relatively expensive. Computing a translation may
79 * require forking an external process per path name translated. Callers
80 * should try to minimize the number of translations necessary by caching
81 * the results.
82 * <p>
83 * Not all platforms and JREs require path name translation. Currently only
84 * Cygwin on Win32 require translation for Cygwin based paths.
86 * @param dir
87 * directory relative to which the path name is.
88 * @param name
89 * path name to translate.
90 * @return the translated path. <code>new File(dir,name)</code> if this
91 * platform does not require path name translation.
93 public static File resolve(final File dir, final String name) {
94 return INSTANCE.resolveImpl(dir, name);
97 /**
98 * Resolve this file to its actual path name that the JRE can use.
99 * <p>
100 * This method can be relatively expensive. Computing a translation may
101 * require forking an external process per path name translated. Callers
102 * should try to minimize the number of translations necessary by caching
103 * the results.
104 * <p>
105 * Not all platforms and JREs require path name translation. Currently only
106 * Cygwin on Win32 require translation for Cygwin based paths.
108 * @param dir
109 * directory relative to which the path name is.
110 * @param name
111 * path name to translate.
112 * @return the translated path. <code>new File(dir,name)</code> if this
113 * platform does not require path name translation.
115 protected File resolveImpl(final File dir, final String name) {
116 final File abspn = new File(name);
117 if (abspn.isAbsolute())
118 return abspn;
119 return new File(dir, name);
123 * Determine the user's home directory (location where preferences are).
124 * <p>
125 * This method can be expensive on the first invocation if path name
126 * translation is required. Subsequent invocations return a cached result.
127 * <p>
128 * Not all platforms and JREs require path name translation. Currently only
129 * Cygwin on Win32 requires translation of the Cygwin HOME directory.
131 * @return the user's home directory; null if the user does not have one.
133 public static File userHome() {
134 return USER_HOME.home;
137 private static class USER_HOME {
138 static final File home = INSTANCE.userHomeImpl();
142 * Determine the user's home directory (location where preferences are).
144 * @return the user's home directory; null if the user does not have one.
146 protected File userHomeImpl() {
147 final String home = AccessController
148 .doPrivileged(new PrivilegedAction<String>() {
149 public String run() {
150 return System.getProperty("user.home");
153 if (home == null || home.length() == 0)
154 return null;
155 return new File(home).getAbsoluteFile();