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 package org.eclipse.jgit.util;
44
45 import java.io.BufferedReader;
46 import java.io.File;
47 import java.io.IOException;
48 import java.io.InputStreamReader;
49 import java.io.PrintStream;
50 import java.nio.charset.Charset;
51 import java.nio.file.Files;
52 import java.nio.file.Path;
53 import java.nio.file.attribute.PosixFilePermission;
54 import java.util.ArrayList;
55 import java.util.Arrays;
56 import java.util.List;
57 import java.util.Set;
58
59 import org.eclipse.jgit.api.errors.JGitInternalException;
60 import org.eclipse.jgit.lib.Constants;
61 import org.eclipse.jgit.lib.Repository;
62
63
64
65
66
67
68 public class FS_POSIX extends FS {
69 private static final int DEFAULT_UMASK = 0022;
70 private volatile int umask = -1;
71
72
73 protected FS_POSIX() {
74 }
75
76
77
78
79
80
81
82 protected FS_POSIX(FS src) {
83 super(src);
84 if (src instanceof FS_POSIX) {
85 umask = ((FS_POSIX) src).umask;
86 }
87 }
88
89 @Override
90 public FS newInstance() {
91 return new FS_POSIX(this);
92 }
93
94
95
96
97
98
99
100
101 public void setUmask(int umask) {
102 this.umask = umask;
103 }
104
105 private int umask() {
106 int u = umask;
107 if (u == -1) {
108 u = readUmask();
109 umask = u;
110 }
111 return u;
112 }
113
114
115 private static int readUmask() {
116 try {
117 Process p = Runtime.getRuntime().exec(
118 new String[] { "sh", "-c", "umask" },
119 null, null);
120 try (BufferedReader lineRead = new BufferedReader(
121 new InputStreamReader(p.getInputStream(), Charset
122 .defaultCharset().name()))) {
123 if (p.waitFor() == 0) {
124 String s = lineRead.readLine();
125 if (s.matches("0?\\d{3}")) {
126 return Integer.parseInt(s, 8);
127 }
128 }
129 return DEFAULT_UMASK;
130 }
131 } catch (Exception e) {
132 return DEFAULT_UMASK;
133 }
134 }
135
136 @Override
137 protected File discoverGitExe() {
138 String path = SystemReader.getInstance().getenv("PATH");
139 File gitExe = searchPath(path, "git");
140
141 if (gitExe == null) {
142 if (SystemReader.getInstance().isMacOS()) {
143 if (searchPath(path, "bash") != null) {
144
145
146
147 String w = readPipe(userHome(),
148 new String[]{"bash", "--login", "-c", "which git"},
149 Charset.defaultCharset().name());
150 if (!StringUtils.isEmptyOrNull(w))
151 gitExe = new File(w);
152 }
153 }
154 }
155
156 return gitExe;
157 }
158
159 @Override
160 public boolean isCaseSensitive() {
161 return !SystemReader.getInstance().isMacOS();
162 }
163
164 @Override
165 public boolean supportsExecute() {
166 return true;
167 }
168
169 @Override
170 public boolean canExecute(File f) {
171 return FileUtils.canExecute(f);
172 }
173
174 @Override
175 public boolean setExecute(File f, boolean canExecute) {
176 if (!isFile(f))
177 return false;
178 if (!canExecute)
179 return f.setExecutable(false);
180
181 try {
182 Path path = f.toPath();
183 Set<PosixFilePermission> pset = Files.getPosixFilePermissions(path);
184
185
186 pset.add(PosixFilePermission.OWNER_EXECUTE);
187
188 int mask = umask();
189 apply(pset, mask, PosixFilePermission.GROUP_EXECUTE, 1 << 3);
190 apply(pset, mask, PosixFilePermission.OTHERS_EXECUTE, 1);
191 Files.setPosixFilePermissions(path, pset);
192 return true;
193 } catch (IOException e) {
194
195 final boolean debug = Boolean.parseBoolean(SystemReader
196 .getInstance().getProperty("jgit.fs.debug"));
197 if (debug)
198 System.err.println(e);
199 return false;
200 }
201 }
202
203 private static void apply(Set<PosixFilePermission> set,
204 int umask, PosixFilePermission perm, int test) {
205 if ((umask & test) == 0) {
206
207 set.add(perm);
208 } else {
209
210 set.remove(perm);
211 }
212 }
213
214 @Override
215 public ProcessBuilder runInShell(String cmd, String[] args) {
216 List<String> argv = new ArrayList<String>(4 + args.length);
217 argv.add("sh");
218 argv.add("-c");
219 argv.add(cmd + " \"$@\"");
220 argv.add(cmd);
221 argv.addAll(Arrays.asList(args));
222 ProcessBuilder proc = new ProcessBuilder();
223 proc.command(argv);
224 return proc;
225 }
226
227
228
229
230 @Override
231 public ProcessResult runHookIfPresent(Repository repository, String hookName,
232 String[] args, PrintStream outRedirect, PrintStream errRedirect,
233 String stdinArgs) throws JGitInternalException {
234 return internalRunHookIfPresent(repository, hookName, args, outRedirect,
235 errRedirect, stdinArgs);
236 }
237
238 @Override
239 public boolean retryFailedLockFileCommit() {
240 return false;
241 }
242
243 @Override
244 public boolean supportsSymlinks() {
245 return true;
246 }
247
248 @Override
249 public void setHidden(File path, boolean hidden) throws IOException {
250
251 }
252
253
254
255
256 @Override
257 public Attributes getAttributes(File path) {
258 return FileUtils.getFileAttributesPosix(this, path);
259 }
260
261
262
263
264 @Override
265 public File normalize(File file) {
266 return FileUtils.normalize(file);
267 }
268
269
270
271
272 @Override
273 public String normalize(String name) {
274 return FileUtils.normalize(name);
275 }
276
277
278
279
280 @Override
281 public File findHook(Repository repository, String hookName) {
282 final File gitdir = repository.getDirectory();
283 if (gitdir == null) {
284 return null;
285 }
286 final Path hookPath = gitdir.toPath().resolve(Constants.HOOKS)
287 .resolve(hookName);
288 if (Files.isExecutable(hookPath))
289 return hookPath.toFile();
290 return null;
291 }
292 }