diff --git a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties index b7805b19e..0a2f7029e 100644 --- a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties +++ b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties @@ -680,6 +680,7 @@ theFactoryMustNotBeNull=The factory must not be null threadInterruptedWhileRunning="Current thread interrupted while running {0}" timeIsUncertain=Time is uncertain timerAlreadyTerminated=Timer already terminated +timeoutMeasureFsTimestampResolution=measuring filesystem timestamp resolution for ''{0}'' timed out, fall back to resolution of 2 seconds tooManyCommands=Too many commands tooManyFilters=Too many "filter" lines in request tooManyIncludeRecursions=Too many recursions; circular includes in config file(s)? diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java index da0ba4a77..bcd6d5ce2 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java @@ -737,6 +737,7 @@ public static JGitText get() { /***/ public String tagAlreadyExists; /***/ public String tagNameInvalid; /***/ public String tagOnRepoWithoutHEADCurrentlyNotSupported; + /***/ public String timeoutMeasureFsTimestampResolution; /***/ public String transactionAborted; /***/ public String theFactoryMustNotBeNull; /***/ public String threadInterruptedWhileRunning; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java index e559d2167..e7db6cee7 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java @@ -208,7 +208,7 @@ static Duration getFsTimestampResolution(Path file) { FileStore s = Files.getFileStore(dir); FileStoreAttributeCache c = attributeCache.get(s); if (c == null) { - c = new FileStoreAttributeCache(dir); + c = new FileStoreAttributeCache(s, dir); attributeCache.put(s, c); if (LOG.isDebugEnabled()) { LOG.debug(c.toString()); @@ -228,16 +228,24 @@ Duration getFsTimestampResolution() { return fsTimestampResolution; } - private FileStoreAttributeCache(Path dir) + private FileStoreAttributeCache(FileStore s, Path dir) throws IOException, InterruptedException { Path probe = dir.resolve(".probe-" + UUID.randomUUID()); //$NON-NLS-1$ Files.createFile(probe); try { + long start = System.nanoTime(); FileTime startTime = Files.getLastModifiedTime(probe); FileTime actTime = startTime; long sleepTime = 512; while (actTime.compareTo(startTime) <= 0) { TimeUnit.NANOSECONDS.sleep(sleepTime); + if (timeout(start)) { + LOG.warn(MessageFormat.format(JGitText + .get().timeoutMeasureFsTimestampResolution, + s.toString())); + fsTimestampResolution = FALLBACK_TIMESTAMP_RESOLUTION; + return; + } FileUtils.touch(probe); actTime = Files.getLastModifiedTime(probe); // limit sleep time to max. 100ms @@ -254,6 +262,11 @@ private FileStoreAttributeCache(Path dir) } } + private static boolean timeout(long start) { + return System.nanoTime() - start >= FALLBACK_TIMESTAMP_RESOLUTION + .toNanos(); + } + @SuppressWarnings("nls") @Override public String toString() {