You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

FileTreeIterator.java 12KB

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>
6 years ago
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>
6 years ago
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>
6 years ago
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>
6 years ago
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>
6 years ago
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>
6 years ago
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>
6 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439
  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> and others
  6. *
  7. * This program and the accompanying materials are made available under the
  8. * terms of the Eclipse Distribution License v. 1.0 which is available at
  9. * https://www.eclipse.org/org/documents/edl-v10.php.
  10. *
  11. * SPDX-License-Identifier: BSD-3-Clause
  12. */
  13. package org.eclipse.jgit.treewalk;
  14. import static java.nio.charset.StandardCharsets.UTF_8;
  15. import java.io.ByteArrayInputStream;
  16. import java.io.File;
  17. import java.io.FileInputStream;
  18. import java.io.IOException;
  19. import java.io.InputStream;
  20. import java.time.Instant;
  21. import org.eclipse.jgit.dircache.DirCacheIterator;
  22. import org.eclipse.jgit.errors.IncorrectObjectTypeException;
  23. import org.eclipse.jgit.lib.Constants;
  24. import org.eclipse.jgit.lib.FileMode;
  25. import org.eclipse.jgit.lib.ObjectReader;
  26. import org.eclipse.jgit.lib.Repository;
  27. import org.eclipse.jgit.util.FS;
  28. /**
  29. * Working directory iterator for standard Java IO.
  30. * <p>
  31. * This iterator uses the standard <code>java.io</code> package to read the
  32. * specified working directory as part of a
  33. * {@link org.eclipse.jgit.treewalk.TreeWalk}.
  34. */
  35. public class FileTreeIterator extends WorkingTreeIterator {
  36. /**
  37. * the starting directory of this Iterator. All entries are located directly
  38. * in this directory.
  39. */
  40. protected final File directory;
  41. /**
  42. * the file system abstraction which will be necessary to perform certain
  43. * file system operations.
  44. */
  45. protected final FS fs;
  46. /**
  47. * the strategy used to compute the FileMode for a FileEntry. Can be used to
  48. * control things such as whether to recurse into a directory or create a
  49. * gitlink.
  50. *
  51. * @since 4.3
  52. */
  53. protected final FileModeStrategy fileModeStrategy;
  54. /**
  55. * Create a new iterator to traverse the work tree and its children.
  56. *
  57. * @param repo
  58. * the repository whose working tree will be scanned.
  59. */
  60. public FileTreeIterator(Repository repo) {
  61. this(repo,
  62. repo.getConfig().get(WorkingTreeOptions.KEY).isDirNoGitLinks() ?
  63. NoGitlinksStrategy.INSTANCE :
  64. DefaultFileModeStrategy.INSTANCE);
  65. }
  66. /**
  67. * Create a new iterator to traverse the work tree and its children.
  68. *
  69. * @param repo
  70. * the repository whose working tree will be scanned.
  71. * @param fileModeStrategy
  72. * the strategy to use to determine the FileMode for a FileEntry;
  73. * controls gitlinks etc.
  74. * @since 4.3
  75. */
  76. public FileTreeIterator(Repository repo, FileModeStrategy fileModeStrategy) {
  77. this(repo.getWorkTree(), repo.getFS(),
  78. repo.getConfig().get(WorkingTreeOptions.KEY),
  79. fileModeStrategy);
  80. initRootIterator(repo);
  81. }
  82. /**
  83. * Create a new iterator to traverse the given directory and its children.
  84. *
  85. * @param root
  86. * the starting directory. This directory should correspond to
  87. * the root of the repository.
  88. * @param fs
  89. * the file system abstraction which will be necessary to perform
  90. * certain file system operations.
  91. * @param options
  92. * working tree options to be used
  93. */
  94. public FileTreeIterator(File root, FS fs, WorkingTreeOptions options) {
  95. this(root, fs, options, DefaultFileModeStrategy.INSTANCE);
  96. }
  97. /**
  98. * Create a new iterator to traverse the given directory and its children.
  99. *
  100. * @param root
  101. * the starting directory. This directory should correspond to
  102. * the root of the repository.
  103. * @param fs
  104. * the file system abstraction which will be necessary to perform
  105. * certain file system operations.
  106. * @param options
  107. * working tree options to be used
  108. * @param fileModeStrategy
  109. * the strategy to use to determine the FileMode for a FileEntry;
  110. * controls gitlinks etc.
  111. * @since 4.3
  112. */
  113. public FileTreeIterator(final File root, FS fs, WorkingTreeOptions options,
  114. FileModeStrategy fileModeStrategy) {
  115. super(options);
  116. directory = root;
  117. this.fs = fs;
  118. this.fileModeStrategy = fileModeStrategy;
  119. init(entries());
  120. }
  121. /**
  122. * Create a new iterator to traverse a subdirectory.
  123. *
  124. * @param p
  125. * the parent iterator we were created from.
  126. * @param root
  127. * the subdirectory. This should be a directory contained within
  128. * the parent directory.
  129. * @param fs
  130. * the file system abstraction which will be necessary to perform
  131. * certain file system operations.
  132. * @since 4.3
  133. */
  134. protected FileTreeIterator(final FileTreeIterator p, final File root,
  135. FS fs) {
  136. this(p, root, fs, p.fileModeStrategy);
  137. }
  138. /**
  139. * Create a new iterator to traverse a subdirectory, given the specified
  140. * FileModeStrategy.
  141. *
  142. * @param p
  143. * the parent iterator we were created from.
  144. * @param root
  145. * the subdirectory. This should be a directory contained within
  146. * the parent directory
  147. * @param fs
  148. * the file system abstraction which will be necessary to perform
  149. * certain file system operations.
  150. * @param fileModeStrategy
  151. * the strategy to use to determine the FileMode for a given
  152. * FileEntry.
  153. * @since 4.3
  154. */
  155. protected FileTreeIterator(final WorkingTreeIterator p, final File root,
  156. FS fs, FileModeStrategy fileModeStrategy) {
  157. super(p);
  158. directory = root;
  159. this.fs = fs;
  160. this.fileModeStrategy = fileModeStrategy;
  161. init(entries());
  162. }
  163. /** {@inheritDoc} */
  164. @Override
  165. public AbstractTreeIterator createSubtreeIterator(ObjectReader reader)
  166. throws IncorrectObjectTypeException, IOException {
  167. if (!walksIgnoredDirectories() && isEntryIgnored()) {
  168. DirCacheIterator iterator = getDirCacheIterator();
  169. if (iterator == null) {
  170. return new EmptyTreeIterator(this);
  171. }
  172. // Only enter if we have an associated DirCacheIterator that is
  173. // at the same entry (which indicates there is some already
  174. // tracked file underneath this directory). Otherwise the
  175. // directory is indeed ignored and can be skipped entirely.
  176. }
  177. return enterSubtree();
  178. }
  179. /**
  180. * Create a new iterator for the current entry's subtree.
  181. * <p>
  182. * The parent reference of the iterator must be <code>this</code>, otherwise
  183. * the caller would not be able to exit out of the subtree iterator
  184. * correctly and return to continue walking <code>this</code>.
  185. *
  186. * @return a new iterator that walks over the current subtree.
  187. * @since 5.0
  188. */
  189. protected AbstractTreeIterator enterSubtree() {
  190. return new FileTreeIterator(this, ((FileEntry) current()).getFile(), fs,
  191. fileModeStrategy);
  192. }
  193. private Entry[] entries() {
  194. return fs.list(directory, fileModeStrategy);
  195. }
  196. /**
  197. * An interface representing the methods used to determine the FileMode for
  198. * a FileEntry.
  199. *
  200. * @since 4.3
  201. */
  202. public interface FileModeStrategy {
  203. /**
  204. * Compute the FileMode for a given File, based on its attributes.
  205. *
  206. * @param f
  207. * the file to return a FileMode for
  208. * @param attributes
  209. * the attributes of a file
  210. * @return a FileMode indicating whether the file is a regular file, a
  211. * directory, a gitlink, etc.
  212. */
  213. FileMode getMode(File f, FS.Attributes attributes);
  214. }
  215. /**
  216. * A default implementation of a FileModeStrategy; defaults to treating
  217. * nested .git directories as gitlinks, etc.
  218. *
  219. * @since 4.3
  220. */
  221. public static class DefaultFileModeStrategy implements FileModeStrategy {
  222. /**
  223. * a singleton instance of the default FileModeStrategy
  224. */
  225. public static final DefaultFileModeStrategy INSTANCE =
  226. new DefaultFileModeStrategy();
  227. @Override
  228. public FileMode getMode(File f, FS.Attributes attributes) {
  229. if (attributes.isSymbolicLink()) {
  230. return FileMode.SYMLINK;
  231. } else if (attributes.isDirectory()) {
  232. if (new File(f, Constants.DOT_GIT).exists()) {
  233. return FileMode.GITLINK;
  234. }
  235. return FileMode.TREE;
  236. } else if (attributes.isExecutable()) {
  237. return FileMode.EXECUTABLE_FILE;
  238. } else {
  239. return FileMode.REGULAR_FILE;
  240. }
  241. }
  242. }
  243. /**
  244. * A FileModeStrategy that implements native git's DIR_NO_GITLINKS
  245. * behavior. This is the same as the default FileModeStrategy, except
  246. * all directories will be treated as directories regardless of whether
  247. * or not they contain a .git directory or file.
  248. *
  249. * @since 4.3
  250. */
  251. public static class NoGitlinksStrategy implements FileModeStrategy {
  252. /**
  253. * a singleton instance of the default FileModeStrategy
  254. */
  255. public static final NoGitlinksStrategy INSTANCE = new NoGitlinksStrategy();
  256. @Override
  257. public FileMode getMode(File f, FS.Attributes attributes) {
  258. if (attributes.isSymbolicLink()) {
  259. return FileMode.SYMLINK;
  260. } else if (attributes.isDirectory()) {
  261. return FileMode.TREE;
  262. } else if (attributes.isExecutable()) {
  263. return FileMode.EXECUTABLE_FILE;
  264. } else {
  265. return FileMode.REGULAR_FILE;
  266. }
  267. }
  268. }
  269. /**
  270. * Wrapper for a standard Java IO file
  271. */
  272. public static class FileEntry extends Entry {
  273. private final FileMode mode;
  274. private FS.Attributes attributes;
  275. private FS fs;
  276. /**
  277. * Create a new file entry.
  278. *
  279. * @param f
  280. * file
  281. * @param fs
  282. * file system
  283. */
  284. public FileEntry(File f, FS fs) {
  285. this(f, fs, DefaultFileModeStrategy.INSTANCE);
  286. }
  287. /**
  288. * Create a new file entry given the specified FileModeStrategy
  289. *
  290. * @param f
  291. * file
  292. * @param fs
  293. * file system
  294. * @param fileModeStrategy
  295. * the strategy to use when determining the FileMode of a
  296. * file; controls gitlinks etc.
  297. *
  298. * @since 4.3
  299. */
  300. public FileEntry(File f, FS fs, FileModeStrategy fileModeStrategy) {
  301. this.fs = fs;
  302. f = fs.normalize(f);
  303. attributes = fs.getAttributes(f);
  304. mode = fileModeStrategy.getMode(f, attributes);
  305. }
  306. /**
  307. * Create a new file entry given the specified FileModeStrategy
  308. *
  309. * @param f
  310. * file
  311. * @param fs
  312. * file system
  313. * @param attributes
  314. * of the file
  315. * @param fileModeStrategy
  316. * the strategy to use when determining the FileMode of a
  317. * file; controls gitlinks etc.
  318. *
  319. * @since 5.0
  320. */
  321. public FileEntry(File f, FS fs, FS.Attributes attributes,
  322. FileModeStrategy fileModeStrategy) {
  323. this.fs = fs;
  324. this.attributes = attributes;
  325. f = fs.normalize(f);
  326. mode = fileModeStrategy.getMode(f, attributes);
  327. }
  328. @Override
  329. public FileMode getMode() {
  330. return mode;
  331. }
  332. @Override
  333. public String getName() {
  334. return attributes.getName();
  335. }
  336. @Override
  337. public long getLength() {
  338. return attributes.getLength();
  339. }
  340. @Override
  341. @Deprecated
  342. public long getLastModified() {
  343. return attributes.getLastModifiedInstant().toEpochMilli();
  344. }
  345. /**
  346. * @since 5.1.9
  347. */
  348. @Override
  349. public Instant getLastModifiedInstant() {
  350. return attributes.getLastModifiedInstant();
  351. }
  352. @Override
  353. public InputStream openInputStream() throws IOException {
  354. if (attributes.isSymbolicLink()) {
  355. return new ByteArrayInputStream(fs.readSymLink(getFile())
  356. .getBytes(UTF_8));
  357. }
  358. return new FileInputStream(getFile());
  359. }
  360. /**
  361. * Get the underlying file of this entry.
  362. *
  363. * @return the underlying file of this entry
  364. */
  365. public File getFile() {
  366. return attributes.getFile();
  367. }
  368. }
  369. /**
  370. * <p>Getter for the field <code>directory</code>.</p>
  371. *
  372. * @return The root directory of this iterator
  373. */
  374. public File getDirectory() {
  375. return directory;
  376. }
  377. /**
  378. * Get the location of the working file.
  379. *
  380. * @return The location of the working file. This is the same as {@code new
  381. * File(getDirectory(), getEntryPath())} but may be faster by
  382. * reusing an internal File instance.
  383. */
  384. public File getEntryFile() {
  385. return ((FileEntry) current()).getFile();
  386. }
  387. /** {@inheritDoc} */
  388. @Override
  389. protected byte[] idSubmodule(Entry e) {
  390. return idSubmodule(getDirectory(), e);
  391. }
  392. /** {@inheritDoc} */
  393. @Override
  394. protected String readSymlinkTarget(Entry entry) throws IOException {
  395. return fs.readSymLink(getEntryFile());
  396. }
  397. }