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 }
211 String homeDrive = SystemReader.getInstance().getenv("HOMEDRIVE");
212 if (homeDrive != null) {
213 String homePath = SystemReader.getInstance().getenv("HOMEPATH");
214 if (homePath != null) {
215 return new File(homeDrive, homePath);
216 }
217 }
218
219 String homeShare = SystemReader.getInstance().getenv("HOMESHARE");
220 if (homeShare != null) {
221 return new File(homeShare);
222 }
223
224 return super.userHomeImpl();
225 }
226
227
228 @Override
229 public ProcessBuilder runInShell(String cmd, String[] args) {
230 List<String> argv = new ArrayList<>(3 + args.length);
231 argv.add("cmd.exe");
232 argv.add("/c");
233 argv.add(cmd);
234 argv.addAll(Arrays.asList(args));
235 ProcessBuilder proc = new ProcessBuilder();
236 proc.command(argv);
237 return proc;
238 }
239
240
241 @Override
242 public boolean supportsSymlinks() {
243 if (supportSymlinks == null) {
244 detectSymlinkSupport();
245 }
246 return Boolean.TRUE.equals(supportSymlinks);
247 }
248
249 private void detectSymlinkSupport() {
250 File tempFile = null;
251 try {
252 tempFile = File.createTempFile("tempsymlinktarget", "");
253 File linkName = new File(tempFile.getParentFile(), "tempsymlink");
254 createSymLink(linkName, tempFile.getPath());
255 supportSymlinks = Boolean.TRUE;
256 linkName.delete();
257 } catch (IOException | UnsupportedOperationException
258 | InternalError e) {
259 supportSymlinks = Boolean.FALSE;
260 } finally {
261 if (tempFile != null) {
262 try {
263 FileUtils.delete(tempFile);
264 } catch (IOException e) {
265 throw new RuntimeException(e);
266 }
267 }
268 }
269 }
270
271
272 @Override
273 public Attributes getAttributes(File path) {
274 return FileUtils.getFileAttributesBasic(this, path);
275 }
276 }