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 package org.eclipse.jgit.util;
46
47 import java.io.File;
48 import java.io.IOException;
49 import java.nio.charset.Charset;
50 import java.nio.file.FileVisitOption;
51 import java.nio.file.FileVisitResult;
52 import java.nio.file.Files;
53 import java.nio.file.Path;
54 import java.nio.file.SimpleFileVisitor;
55 import java.nio.file.attribute.BasicFileAttributes;
56 import java.util.ArrayList;
57 import java.util.Arrays;
58 import java.util.EnumSet;
59 import java.util.List;
60
61 import org.eclipse.jgit.errors.CommandFailedException;
62 import org.eclipse.jgit.treewalk.FileTreeIterator.FileEntry;
63 import org.eclipse.jgit.treewalk.FileTreeIterator.FileModeStrategy;
64 import org.eclipse.jgit.treewalk.WorkingTreeIterator.Entry;
65 import org.slf4j.Logger;
66 import org.slf4j.LoggerFactory;
67
68
69
70
71
72
73
74 public class FS_Win32 extends FS {
75 private final static Logger LOG = LoggerFactory.getLogger(FS_Win32.class);
76
77 private volatile Boolean supportSymlinks;
78
79
80
81
82 public FS_Win32() {
83 super();
84 }
85
86
87
88
89
90
91
92 protected FS_Win32(FS src) {
93 super(src);
94 }
95
96
97 @Override
98 public FS newInstance() {
99 return new FS_Win32(this);
100 }
101
102
103 @Override
104 public boolean supportsExecute() {
105 return false;
106 }
107
108
109 @Override
110 public boolean canExecute(File f) {
111 return false;
112 }
113
114
115 @Override
116 public boolean setExecute(File f, boolean canExec) {
117 return false;
118 }
119
120
121 @Override
122 public boolean isCaseSensitive() {
123 return false;
124 }
125
126
127 @Override
128 public boolean retryFailedLockFileCommit() {
129 return true;
130 }
131
132
133 @Override
134 public Entry[] list(File directory, FileModeStrategy fileModeStrategy) {
135 List<Entry> result = new ArrayList<>();
136 FS fs = this;
137 boolean checkExecutable = fs.supportsExecute();
138 try {
139 Files.walkFileTree(directory.toPath(),
140 EnumSet.noneOf(FileVisitOption.class), 1,
141 new SimpleFileVisitor<Path>() {
142 @Override
143 public FileVisitResult visitFile(Path file,
144 BasicFileAttributes attrs) throws IOException {
145 File f = file.toFile();
146 FS.Attributes attributes = new FS.Attributes(fs, f,
147 true, attrs.isDirectory(),
148 checkExecutable && f.canExecute(),
149 attrs.isSymbolicLink(),
150 attrs.isRegularFile(),
151 attrs.creationTime().toMillis(),
152 attrs.lastModifiedTime().toInstant(),
153 attrs.size());
154 result.add(new FileEntry(f, fs, attributes,
155 fileModeStrategy));
156 return FileVisitResult.CONTINUE;
157 }
158
159 @Override
160 public FileVisitResult visitFileFailed(Path file,
161 IOException exc) throws IOException {
162
163 return FileVisitResult.CONTINUE;
164 }
165 });
166 } catch (IOException e) {
167
168 }
169 if (result.isEmpty()) {
170 return NO_ENTRIES;
171 }
172 return result.toArray(new Entry[0]);
173 }
174
175
176 @Override
177 protected File discoverGitExe() {
178 String path = SystemReader.getInstance().getenv("PATH");
179 File gitExe = searchPath(path, "git.exe", "git.cmd");
180
181 if (gitExe == null) {
182 if (searchPath(path, "bash.exe") != null) {
183
184
185 String w;
186 try {
187 w = readPipe(userHome(),
188 new String[]{"bash", "--login", "-c", "which git"},
189 Charset.defaultCharset().name());
190 } catch (CommandFailedException e) {
191 LOG.warn(e.getMessage());
192 return null;
193 }
194 if (!StringUtils.isEmptyOrNull(w)) {
195
196 gitExe = resolve(null, w);
197 }
198 }
199 }
200
201 return gitExe;
202 }
203
204
205 @Override
206 protected File userHomeImpl() {
207 String home = SystemReader.getInstance().getenv("HOME");
208 if (home != null)
209 return resolve(null, home);
210 String homeDrive = SystemReader.getInstance().getenv("HOMEDRIVE");
211 if (homeDrive != null) {
212 String homePath = SystemReader.getInstance().getenv("HOMEPATH");
213 if (homePath != null)
214 return new File(homeDrive, homePath);
215 }
216
217 String homeShare = SystemReader.getInstance().getenv("HOMESHARE");
218 if (homeShare != null)
219 return new File(homeShare);
220
221 return super.userHomeImpl();
222 }
223
224
225 @Override
226 public ProcessBuilder runInShell(String cmd, String[] args) {
227 List<String> argv = new ArrayList<>(3 + args.length);
228 argv.add("cmd.exe");
229 argv.add("/c");
230 argv.add(cmd);
231 argv.addAll(Arrays.asList(args));
232 ProcessBuilder proc = new ProcessBuilder();
233 proc.command(argv);
234 return proc;
235 }
236
237
238 @Override
239 public boolean supportsSymlinks() {
240 if (supportSymlinks == null)
241 detectSymlinkSupport();
242 return Boolean.TRUE.equals(supportSymlinks);
243 }
244
245 private void detectSymlinkSupport() {
246 File tempFile = null;
247 try {
248 tempFile = File.createTempFile("tempsymlinktarget", "");
249 File linkName = new File(tempFile.getParentFile(), "tempsymlink");
250 createSymLink(linkName, tempFile.getPath());
251 supportSymlinks = Boolean.TRUE;
252 linkName.delete();
253 } catch (IOException | UnsupportedOperationException
254 | InternalError e) {
255 supportSymlinks = Boolean.FALSE;
256 } finally {
257 if (tempFile != null)
258 try {
259 FileUtils.delete(tempFile);
260 } catch (IOException e) {
261 throw new RuntimeException(e);
262 }
263 }
264 }
265
266
267 @Override
268 public Attributes getAttributes(File path) {
269 return FileUtils.getFileAttributesBasic(this, path);
270 }
271 }