Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

FileTreeIterator.java 14KB

Significantly speed up FileTreeIterator on Windows Getting attributes of files on Windows is an expensive operation. Windows stores file attributes in the directory, so they are basically available "for free" when a directory is listed. The implementation of Java's Files.walkFileTree() takes advantage of that (at least in the OpenJDK implementation for Windows) and provides the attributes from the directory to a FileVisitor. Using Files.walkFileTree() with a maximum depth of 1 is thus a good approach on Windows to get both the file names and the attributes in one go. In my tests, this gives a significant speed-up of FileTreeIterator over the "normal" way: using File.listFiles() and then reading the attributes of each file individually. The speed-up is hard to quantify exactly, but in my tests I've observed consistently 30-40% for staging 500 files one after another, each individually, and up to 50% for individual TreeWalks with a FileTreeIterator. On Unix, this technique is detrimental. Unix stores file attributes differently, and getting attributes of individual files is not costly. On Unix, the old way of doing a listFiles() and getting individual attributes (both native operations) is about three times faster than using walkFileTree, which is implemented in Java. Therefore, move the operation to FS/FS_Win32 and call it from FileTreeIterator, so that we can have different implementations depending on the file system. A little performance test program is included as a JUnit test (to be run manually). While this does speed up things on Windows, it doesn't solve the basic problem of bug 532300: the iterator always gets the full directory listing and the attributes of all files, and the more files there are the longer that takes. Bug: 532300 Change-Id: Ic5facb871c725256c2324b0d97b95e6efc33282a Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
pirms 6 gadiem
Significantly speed up FileTreeIterator on Windows Getting attributes of files on Windows is an expensive operation. Windows stores file attributes in the directory, so they are basically available "for free" when a directory is listed. The implementation of Java's Files.walkFileTree() takes advantage of that (at least in the OpenJDK implementation for Windows) and provides the attributes from the directory to a FileVisitor. Using Files.walkFileTree() with a maximum depth of 1 is thus a good approach on Windows to get both the file names and the attributes in one go. In my tests, this gives a significant speed-up of FileTreeIterator over the "normal" way: using File.listFiles() and then reading the attributes of each file individually. The speed-up is hard to quantify exactly, but in my tests I've observed consistently 30-40% for staging 500 files one after another, each individually, and up to 50% for individual TreeWalks with a FileTreeIterator. On Unix, this technique is detrimental. Unix stores file attributes differently, and getting attributes of individual files is not costly. On Unix, the old way of doing a listFiles() and getting individual attributes (both native operations) is about three times faster than using walkFileTree, which is implemented in Java. Therefore, move the operation to FS/FS_Win32 and call it from FileTreeIterator, so that we can have different implementations depending on the file system. A little performance test program is included as a JUnit test (to be run manually). While this does speed up things on Windows, it doesn't solve the basic problem of bug 532300: the iterator always gets the full directory listing and the attributes of all files, and the more files there are the longer that takes. Bug: 532300 Change-Id: Ic5facb871c725256c2324b0d97b95e6efc33282a Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
pirms 6 gadiem
Significantly speed up FileTreeIterator on Windows Getting attributes of files on Windows is an expensive operation. Windows stores file attributes in the directory, so they are basically available "for free" when a directory is listed. The implementation of Java's Files.walkFileTree() takes advantage of that (at least in the OpenJDK implementation for Windows) and provides the attributes from the directory to a FileVisitor. Using Files.walkFileTree() with a maximum depth of 1 is thus a good approach on Windows to get both the file names and the attributes in one go. In my tests, this gives a significant speed-up of FileTreeIterator over the "normal" way: using File.listFiles() and then reading the attributes of each file individually. The speed-up is hard to quantify exactly, but in my tests I've observed consistently 30-40% for staging 500 files one after another, each individually, and up to 50% for individual TreeWalks with a FileTreeIterator. On Unix, this technique is detrimental. Unix stores file attributes differently, and getting attributes of individual files is not costly. On Unix, the old way of doing a listFiles() and getting individual attributes (both native operations) is about three times faster than using walkFileTree, which is implemented in Java. Therefore, move the operation to FS/FS_Win32 and call it from FileTreeIterator, so that we can have different implementations depending on the file system. A little performance test program is included as a JUnit test (to be run manually). While this does speed up things on Windows, it doesn't solve the basic problem of bug 532300: the iterator always gets the full directory listing and the attributes of all files, and the more files there are the longer that takes. Bug: 532300 Change-Id: Ic5facb871c725256c2324b0d97b95e6efc33282a Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
pirms 6 gadiem
Significantly speed up FileTreeIterator on Windows Getting attributes of files on Windows is an expensive operation. Windows stores file attributes in the directory, so they are basically available "for free" when a directory is listed. The implementation of Java's Files.walkFileTree() takes advantage of that (at least in the OpenJDK implementation for Windows) and provides the attributes from the directory to a FileVisitor. Using Files.walkFileTree() with a maximum depth of 1 is thus a good approach on Windows to get both the file names and the attributes in one go. In my tests, this gives a significant speed-up of FileTreeIterator over the "normal" way: using File.listFiles() and then reading the attributes of each file individually. The speed-up is hard to quantify exactly, but in my tests I've observed consistently 30-40% for staging 500 files one after another, each individually, and up to 50% for individual TreeWalks with a FileTreeIterator. On Unix, this technique is detrimental. Unix stores file attributes differently, and getting attributes of individual files is not costly. On Unix, the old way of doing a listFiles() and getting individual attributes (both native operations) is about three times faster than using walkFileTree, which is implemented in Java. Therefore, move the operation to FS/FS_Win32 and call it from FileTreeIterator, so that we can have different implementations depending on the file system. A little performance test program is included as a JUnit test (to be run manually). While this does speed up things on Windows, it doesn't solve the basic problem of bug 532300: the iterator always gets the full directory listing and the attributes of all files, and the more files there are the longer that takes. Bug: 532300 Change-Id: Ic5facb871c725256c2324b0d97b95e6efc33282a Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
pirms 6 gadiem
Significantly speed up FileTreeIterator on Windows Getting attributes of files on Windows is an expensive operation. Windows stores file attributes in the directory, so they are basically available "for free" when a directory is listed. The implementation of Java's Files.walkFileTree() takes advantage of that (at least in the OpenJDK implementation for Windows) and provides the attributes from the directory to a FileVisitor. Using Files.walkFileTree() with a maximum depth of 1 is thus a good approach on Windows to get both the file names and the attributes in one go. In my tests, this gives a significant speed-up of FileTreeIterator over the "normal" way: using File.listFiles() and then reading the attributes of each file individually. The speed-up is hard to quantify exactly, but in my tests I've observed consistently 30-40% for staging 500 files one after another, each individually, and up to 50% for individual TreeWalks with a FileTreeIterator. On Unix, this technique is detrimental. Unix stores file attributes differently, and getting attributes of individual files is not costly. On Unix, the old way of doing a listFiles() and getting individual attributes (both native operations) is about three times faster than using walkFileTree, which is implemented in Java. Therefore, move the operation to FS/FS_Win32 and call it from FileTreeIterator, so that we can have different implementations depending on the file system. A little performance test program is included as a JUnit test (to be run manually). While this does speed up things on Windows, it doesn't solve the basic problem of bug 532300: the iterator always gets the full directory listing and the attributes of all files, and the more files there are the longer that takes. Bug: 532300 Change-Id: Ic5facb871c725256c2324b0d97b95e6efc33282a Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
pirms 6 gadiem
Significantly speed up FileTreeIterator on Windows Getting attributes of files on Windows is an expensive operation. Windows stores file attributes in the directory, so they are basically available "for free" when a directory is listed. The implementation of Java's Files.walkFileTree() takes advantage of that (at least in the OpenJDK implementation for Windows) and provides the attributes from the directory to a FileVisitor. Using Files.walkFileTree() with a maximum depth of 1 is thus a good approach on Windows to get both the file names and the attributes in one go. In my tests, this gives a significant speed-up of FileTreeIterator over the "normal" way: using File.listFiles() and then reading the attributes of each file individually. The speed-up is hard to quantify exactly, but in my tests I've observed consistently 30-40% for staging 500 files one after another, each individually, and up to 50% for individual TreeWalks with a FileTreeIterator. On Unix, this technique is detrimental. Unix stores file attributes differently, and getting attributes of individual files is not costly. On Unix, the old way of doing a listFiles() and getting individual attributes (both native operations) is about three times faster than using walkFileTree, which is implemented in Java. Therefore, move the operation to FS/FS_Win32 and call it from FileTreeIterator, so that we can have different implementations depending on the file system. A little performance test program is included as a JUnit test (to be run manually). While this does speed up things on Windows, it doesn't solve the basic problem of bug 532300: the iterator always gets the full directory listing and the attributes of all files, and the more files there are the longer that takes. Bug: 532300 Change-Id: Ic5facb871c725256c2324b0d97b95e6efc33282a Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
pirms 6 gadiem
Significantly speed up FileTreeIterator on Windows Getting attributes of files on Windows is an expensive operation. Windows stores file attributes in the directory, so they are basically available "for free" when a directory is listed. The implementation of Java's Files.walkFileTree() takes advantage of that (at least in the OpenJDK implementation for Windows) and provides the attributes from the directory to a FileVisitor. Using Files.walkFileTree() with a maximum depth of 1 is thus a good approach on Windows to get both the file names and the attributes in one go. In my tests, this gives a significant speed-up of FileTreeIterator over the "normal" way: using File.listFiles() and then reading the attributes of each file individually. The speed-up is hard to quantify exactly, but in my tests I've observed consistently 30-40% for staging 500 files one after another, each individually, and up to 50% for individual TreeWalks with a FileTreeIterator. On Unix, this technique is detrimental. Unix stores file attributes differently, and getting attributes of individual files is not costly. On Unix, the old way of doing a listFiles() and getting individual attributes (both native operations) is about three times faster than using walkFileTree, which is implemented in Java. Therefore, move the operation to FS/FS_Win32 and call it from FileTreeIterator, so that we can have different implementations depending on the file system. A little performance test program is included as a JUnit test (to be run manually). While this does speed up things on Windows, it doesn't solve the basic problem of bug 532300: the iterator always gets the full directory listing and the attributes of all files, and the more files there are the longer that takes. Bug: 532300 Change-Id: Ic5facb871c725256c2324b0d97b95e6efc33282a Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
pirms 6 gadiem
Significantly speed up FileTreeIterator on Windows Getting attributes of files on Windows is an expensive operation. Windows stores file attributes in the directory, so they are basically available "for free" when a directory is listed. The implementation of Java's Files.walkFileTree() takes advantage of that (at least in the OpenJDK implementation for Windows) and provides the attributes from the directory to a FileVisitor. Using Files.walkFileTree() with a maximum depth of 1 is thus a good approach on Windows to get both the file names and the attributes in one go. In my tests, this gives a significant speed-up of FileTreeIterator over the "normal" way: using File.listFiles() and then reading the attributes of each file individually. The speed-up is hard to quantify exactly, but in my tests I've observed consistently 30-40% for staging 500 files one after another, each individually, and up to 50% for individual TreeWalks with a FileTreeIterator. On Unix, this technique is detrimental. Unix stores file attributes differently, and getting attributes of individual files is not costly. On Unix, the old way of doing a listFiles() and getting individual attributes (both native operations) is about three times faster than using walkFileTree, which is implemented in Java. Therefore, move the operation to FS/FS_Win32 and call it from FileTreeIterator, so that we can have different implementations depending on the file system. A little performance test program is included as a JUnit test (to be run manually). While this does speed up things on Windows, it doesn't solve the basic problem of bug 532300: the iterator always gets the full directory listing and the attributes of all files, and the more files there are the longer that takes. Bug: 532300 Change-Id: Ic5facb871c725256c2324b0d97b95e6efc33282a Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
pirms 6 gadiem
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471
  1. /*
  2. * Copyright (C) 2008, Google Inc.
  3. * Copyright (C) 2007-2010, Robin Rosenberg <robin.rosenberg@dewire.com>
  4. * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
  5. * Copyright (C) 2009, Tor Arne Vestbø <torarnv@gmail.com>
  6. * and other copyright owners as documented in the project's IP log.
  7. *
  8. * This program and the accompanying materials are made available
  9. * under the terms of the Eclipse Distribution License v1.0 which
  10. * accompanies this distribution, is reproduced below, and is
  11. * available at http://www.eclipse.org/org/documents/edl-v10.php
  12. *
  13. * All rights reserved.
  14. *
  15. * Redistribution and use in source and binary forms, with or
  16. * without modification, are permitted provided that the following
  17. * conditions are met:
  18. *
  19. * - Redistributions of source code must retain the above copyright
  20. * notice, this list of conditions and the following disclaimer.
  21. *
  22. * - Redistributions in binary form must reproduce the above
  23. * copyright notice, this list of conditions and the following
  24. * disclaimer in the documentation and/or other materials provided
  25. * with the distribution.
  26. *
  27. * - Neither the name of the Eclipse Foundation, Inc. nor the
  28. * names of its contributors may be used to endorse or promote
  29. * products derived from this software without specific prior
  30. * written permission.
  31. *
  32. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
  33. * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  34. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  35. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  36. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  37. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  38. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  39. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  40. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  41. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  42. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  43. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  44. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  45. */
  46. package org.eclipse.jgit.treewalk;
  47. import static java.nio.charset.StandardCharsets.UTF_8;
  48. import java.io.ByteArrayInputStream;
  49. import java.io.File;
  50. import java.io.FileInputStream;
  51. import java.io.IOException;
  52. import java.io.InputStream;
  53. import java.time.Instant;
  54. import org.eclipse.jgit.dircache.DirCacheIterator;
  55. import org.eclipse.jgit.errors.IncorrectObjectTypeException;
  56. import org.eclipse.jgit.lib.Constants;
  57. import org.eclipse.jgit.lib.FileMode;
  58. import org.eclipse.jgit.lib.ObjectReader;
  59. import org.eclipse.jgit.lib.Repository;
  60. import org.eclipse.jgit.util.FS;
  61. /**
  62. * Working directory iterator for standard Java IO.
  63. * <p>
  64. * This iterator uses the standard <code>java.io</code> package to read the
  65. * specified working directory as part of a
  66. * {@link org.eclipse.jgit.treewalk.TreeWalk}.
  67. */
  68. public class FileTreeIterator extends WorkingTreeIterator {
  69. /**
  70. * the starting directory of this Iterator. All entries are located directly
  71. * in this directory.
  72. */
  73. protected final File directory;
  74. /**
  75. * the file system abstraction which will be necessary to perform certain
  76. * file system operations.
  77. */
  78. protected final FS fs;
  79. /**
  80. * the strategy used to compute the FileMode for a FileEntry. Can be used to
  81. * control things such as whether to recurse into a directory or create a
  82. * gitlink.
  83. *
  84. * @since 4.3
  85. */
  86. protected final FileModeStrategy fileModeStrategy;
  87. /**
  88. * Create a new iterator to traverse the work tree and its children.
  89. *
  90. * @param repo
  91. * the repository whose working tree will be scanned.
  92. */
  93. public FileTreeIterator(Repository repo) {
  94. this(repo,
  95. repo.getConfig().get(WorkingTreeOptions.KEY).isDirNoGitLinks() ?
  96. NoGitlinksStrategy.INSTANCE :
  97. DefaultFileModeStrategy.INSTANCE);
  98. }
  99. /**
  100. * Create a new iterator to traverse the work tree and its children.
  101. *
  102. * @param repo
  103. * the repository whose working tree will be scanned.
  104. * @param fileModeStrategy
  105. * the strategy to use to determine the FileMode for a FileEntry;
  106. * controls gitlinks etc.
  107. * @since 4.3
  108. */
  109. public FileTreeIterator(Repository repo, FileModeStrategy fileModeStrategy) {
  110. this(repo.getWorkTree(), repo.getFS(),
  111. repo.getConfig().get(WorkingTreeOptions.KEY),
  112. fileModeStrategy);
  113. initRootIterator(repo);
  114. }
  115. /**
  116. * Create a new iterator to traverse the given directory and its children.
  117. *
  118. * @param root
  119. * the starting directory. This directory should correspond to
  120. * the root of the repository.
  121. * @param fs
  122. * the file system abstraction which will be necessary to perform
  123. * certain file system operations.
  124. * @param options
  125. * working tree options to be used
  126. */
  127. public FileTreeIterator(File root, FS fs, WorkingTreeOptions options) {
  128. this(root, fs, options, DefaultFileModeStrategy.INSTANCE);
  129. }
  130. /**
  131. * Create a new iterator to traverse the given directory and its children.
  132. *
  133. * @param root
  134. * the starting directory. This directory should correspond to
  135. * the root of the repository.
  136. * @param fs
  137. * the file system abstraction which will be necessary to perform
  138. * certain file system operations.
  139. * @param options
  140. * working tree options to be used
  141. * @param fileModeStrategy
  142. * the strategy to use to determine the FileMode for a FileEntry;
  143. * controls gitlinks etc.
  144. * @since 4.3
  145. */
  146. public FileTreeIterator(final File root, FS fs, WorkingTreeOptions options,
  147. FileModeStrategy fileModeStrategy) {
  148. super(options);
  149. directory = root;
  150. this.fs = fs;
  151. this.fileModeStrategy = fileModeStrategy;
  152. init(entries());
  153. }
  154. /**
  155. * Create a new iterator to traverse a subdirectory.
  156. *
  157. * @param p
  158. * the parent iterator we were created from.
  159. * @param root
  160. * the subdirectory. This should be a directory contained within
  161. * the parent directory.
  162. * @param fs
  163. * the file system abstraction which will be necessary to perform
  164. * certain file system operations.
  165. * @since 4.3
  166. */
  167. protected FileTreeIterator(final FileTreeIterator p, final File root,
  168. FS fs) {
  169. this(p, root, fs, p.fileModeStrategy);
  170. }
  171. /**
  172. * Create a new iterator to traverse a subdirectory, given the specified
  173. * FileModeStrategy.
  174. *
  175. * @param p
  176. * the parent iterator we were created from.
  177. * @param root
  178. * the subdirectory. This should be a directory contained within
  179. * the parent directory
  180. * @param fs
  181. * the file system abstraction which will be necessary to perform
  182. * certain file system operations.
  183. * @param fileModeStrategy
  184. * the strategy to use to determine the FileMode for a given
  185. * FileEntry.
  186. * @since 4.3
  187. */
  188. protected FileTreeIterator(final WorkingTreeIterator p, final File root,
  189. FS fs, FileModeStrategy fileModeStrategy) {
  190. super(p);
  191. directory = root;
  192. this.fs = fs;
  193. this.fileModeStrategy = fileModeStrategy;
  194. init(entries());
  195. }
  196. /** {@inheritDoc} */
  197. @Override
  198. public AbstractTreeIterator createSubtreeIterator(ObjectReader reader)
  199. throws IncorrectObjectTypeException, IOException {
  200. if (!walksIgnoredDirectories() && isEntryIgnored()) {
  201. DirCacheIterator iterator = getDirCacheIterator();
  202. if (iterator == null) {
  203. return new EmptyTreeIterator(this);
  204. }
  205. // Only enter if we have an associated DirCacheIterator that is
  206. // at the same entry (which indicates there is some already
  207. // tracked file underneath this directory). Otherwise the
  208. // directory is indeed ignored and can be skipped entirely.
  209. }
  210. return enterSubtree();
  211. }
  212. /**
  213. * Create a new iterator for the current entry's subtree.
  214. * <p>
  215. * The parent reference of the iterator must be <code>this</code>, otherwise
  216. * the caller would not be able to exit out of the subtree iterator
  217. * correctly and return to continue walking <code>this</code>.
  218. *
  219. * @return a new iterator that walks over the current subtree.
  220. * @since 5.0
  221. */
  222. protected AbstractTreeIterator enterSubtree() {
  223. return new FileTreeIterator(this, ((FileEntry) current()).getFile(), fs,
  224. fileModeStrategy);
  225. }
  226. private Entry[] entries() {
  227. return fs.list(directory, fileModeStrategy);
  228. }
  229. /**
  230. * An interface representing the methods used to determine the FileMode for
  231. * a FileEntry.
  232. *
  233. * @since 4.3
  234. */
  235. public interface FileModeStrategy {
  236. /**
  237. * Compute the FileMode for a given File, based on its attributes.
  238. *
  239. * @param f
  240. * the file to return a FileMode for
  241. * @param attributes
  242. * the attributes of a file
  243. * @return a FileMode indicating whether the file is a regular file, a
  244. * directory, a gitlink, etc.
  245. */
  246. FileMode getMode(File f, FS.Attributes attributes);
  247. }
  248. /**
  249. * A default implementation of a FileModeStrategy; defaults to treating
  250. * nested .git directories as gitlinks, etc.
  251. *
  252. * @since 4.3
  253. */
  254. public static class DefaultFileModeStrategy implements FileModeStrategy {
  255. /**
  256. * a singleton instance of the default FileModeStrategy
  257. */
  258. public final static DefaultFileModeStrategy INSTANCE =
  259. new DefaultFileModeStrategy();
  260. @Override
  261. public FileMode getMode(File f, FS.Attributes attributes) {
  262. if (attributes.isSymbolicLink()) {
  263. return FileMode.SYMLINK;
  264. } else if (attributes.isDirectory()) {
  265. if (new File(f, Constants.DOT_GIT).exists()) {
  266. return FileMode.GITLINK;
  267. } else {
  268. return FileMode.TREE;
  269. }
  270. } else if (attributes.isExecutable()) {
  271. return FileMode.EXECUTABLE_FILE;
  272. } else {
  273. return FileMode.REGULAR_FILE;
  274. }
  275. }
  276. }
  277. /**
  278. * A FileModeStrategy that implements native git's DIR_NO_GITLINKS
  279. * behavior. This is the same as the default FileModeStrategy, except
  280. * all directories will be treated as directories regardless of whether
  281. * or not they contain a .git directory or file.
  282. *
  283. * @since 4.3
  284. */
  285. public static class NoGitlinksStrategy implements FileModeStrategy {
  286. /**
  287. * a singleton instance of the default FileModeStrategy
  288. */
  289. public final static NoGitlinksStrategy INSTANCE = new NoGitlinksStrategy();
  290. @Override
  291. public FileMode getMode(File f, FS.Attributes attributes) {
  292. if (attributes.isSymbolicLink()) {
  293. return FileMode.SYMLINK;
  294. } else if (attributes.isDirectory()) {
  295. return FileMode.TREE;
  296. } else if (attributes.isExecutable()) {
  297. return FileMode.EXECUTABLE_FILE;
  298. } else {
  299. return FileMode.REGULAR_FILE;
  300. }
  301. }
  302. }
  303. /**
  304. * Wrapper for a standard Java IO file
  305. */
  306. public static class FileEntry extends Entry {
  307. private final FileMode mode;
  308. private FS.Attributes attributes;
  309. private FS fs;
  310. /**
  311. * Create a new file entry.
  312. *
  313. * @param f
  314. * file
  315. * @param fs
  316. * file system
  317. */
  318. public FileEntry(File f, FS fs) {
  319. this(f, fs, DefaultFileModeStrategy.INSTANCE);
  320. }
  321. /**
  322. * Create a new file entry given the specified FileModeStrategy
  323. *
  324. * @param f
  325. * file
  326. * @param fs
  327. * file system
  328. * @param fileModeStrategy
  329. * the strategy to use when determining the FileMode of a
  330. * file; controls gitlinks etc.
  331. *
  332. * @since 4.3
  333. */
  334. public FileEntry(File f, FS fs, FileModeStrategy fileModeStrategy) {
  335. this.fs = fs;
  336. f = fs.normalize(f);
  337. attributes = fs.getAttributes(f);
  338. mode = fileModeStrategy.getMode(f, attributes);
  339. }
  340. /**
  341. * Create a new file entry given the specified FileModeStrategy
  342. *
  343. * @param f
  344. * file
  345. * @param fs
  346. * file system
  347. * @param attributes
  348. * of the file
  349. * @param fileModeStrategy
  350. * the strategy to use when determining the FileMode of a
  351. * file; controls gitlinks etc.
  352. *
  353. * @since 5.0
  354. */
  355. public FileEntry(File f, FS fs, FS.Attributes attributes,
  356. FileModeStrategy fileModeStrategy) {
  357. this.fs = fs;
  358. this.attributes = attributes;
  359. f = fs.normalize(f);
  360. mode = fileModeStrategy.getMode(f, attributes);
  361. }
  362. @Override
  363. public FileMode getMode() {
  364. return mode;
  365. }
  366. @Override
  367. public String getName() {
  368. return attributes.getName();
  369. }
  370. @Override
  371. public long getLength() {
  372. return attributes.getLength();
  373. }
  374. @Override
  375. @Deprecated
  376. public long getLastModified() {
  377. return attributes.getLastModifiedInstant().toEpochMilli();
  378. }
  379. @Override
  380. public Instant getLastModifiedInstant() {
  381. return attributes.getLastModifiedInstant();
  382. }
  383. @Override
  384. public InputStream openInputStream() throws IOException {
  385. if (attributes.isSymbolicLink()) {
  386. return new ByteArrayInputStream(fs.readSymLink(getFile())
  387. .getBytes(UTF_8));
  388. } else {
  389. return new FileInputStream(getFile());
  390. }
  391. }
  392. /**
  393. * Get the underlying file of this entry.
  394. *
  395. * @return the underlying file of this entry
  396. */
  397. public File getFile() {
  398. return attributes.getFile();
  399. }
  400. }
  401. /**
  402. * <p>Getter for the field <code>directory</code>.</p>
  403. *
  404. * @return The root directory of this iterator
  405. */
  406. public File getDirectory() {
  407. return directory;
  408. }
  409. /**
  410. * Get the location of the working file.
  411. *
  412. * @return The location of the working file. This is the same as {@code new
  413. * File(getDirectory(), getEntryPath())} but may be faster by
  414. * reusing an internal File instance.
  415. */
  416. public File getEntryFile() {
  417. return ((FileEntry) current()).getFile();
  418. }
  419. /** {@inheritDoc} */
  420. @Override
  421. protected byte[] idSubmodule(Entry e) {
  422. return idSubmodule(getDirectory(), e);
  423. }
  424. /** {@inheritDoc} */
  425. @Override
  426. protected String readSymlinkTarget(Entry entry) throws IOException {
  427. return fs.readSymLink(getEntryFile());
  428. }
  429. }