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 10139f9b8..e041b27f8 100644 --- a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties +++ b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties @@ -136,6 +136,7 @@ compressingObjects=Compressing objects configSubsectionContainsNewline=config subsection name contains newline configSubsectionContainsNullByte=config subsection name contains byte 0x00 configValueContainsNullByte=config value contains byte 0x00 +configHandleIsStale=config file handle is stale, {0}. retry connectionFailed=connection failed connectionTimeOut=Connection time out: {0} contextMustBeNonNegative=context must be >= 0 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 753a7f9a8..8cac95d19 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java @@ -197,6 +197,7 @@ public class JGitText extends TranslationBundle { /***/ public String configSubsectionContainsNewline; /***/ public String configSubsectionContainsNullByte; /***/ public String configValueContainsNullByte; + /***/ public String configHandleIsStale; /***/ public String connectionFailed; /***/ public String connectionTimeOut; /***/ public String contextMustBeNonNegative; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/FileBasedConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/FileBasedConfig.java index 9927daf3d..3f064e334 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/FileBasedConfig.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/storage/file/FileBasedConfig.java @@ -66,13 +66,19 @@ import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.StoredConfig; import org.eclipse.jgit.util.FS; +import org.eclipse.jgit.util.FileUtils; import org.eclipse.jgit.util.IO; import org.eclipse.jgit.util.RawParseUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * The configuration file that is stored in the file of the file system. */ public class FileBasedConfig extends StoredConfig { + private final static Logger LOG = LoggerFactory + .getLogger(FileBasedConfig.class); + private final File configFile; private final FS fs; @@ -141,40 +147,58 @@ public class FileBasedConfig extends StoredConfig { */ @Override public void load() throws IOException, ConfigInvalidException { - final FileSnapshot oldSnapshot = snapshot; - final FileSnapshot newSnapshot = FileSnapshot.save(getFile()); - try { - final byte[] in = IO.readFully(getFile()); - final ObjectId newHash = hash(in); - if (hash.equals(newHash)) { - if (oldSnapshot.equals(newSnapshot)) - oldSnapshot.setClean(newSnapshot); - else - snapshot = newSnapshot; - } else { - final String decoded; - if (isUtf8(in)) { - decoded = RawParseUtils.decode(RawParseUtils.UTF8_CHARSET, - in, 3, in.length); - utf8Bom = true; + final int maxStaleRetries = 5; + int retries = 0; + while (true) { + final FileSnapshot oldSnapshot = snapshot; + final FileSnapshot newSnapshot = FileSnapshot.save(getFile()); + try { + final byte[] in = IO.readFully(getFile()); + final ObjectId newHash = hash(in); + if (hash.equals(newHash)) { + if (oldSnapshot.equals(newSnapshot)) { + oldSnapshot.setClean(newSnapshot); + } else { + snapshot = newSnapshot; + } } else { - decoded = RawParseUtils.decode(in); + final String decoded; + if (isUtf8(in)) { + decoded = RawParseUtils.decode( + RawParseUtils.UTF8_CHARSET, in, 3, in.length); + utf8Bom = true; + } else { + decoded = RawParseUtils.decode(in); + } + fromText(decoded); + snapshot = newSnapshot; + hash = newHash; } - fromText(decoded); + return; + } catch (FileNotFoundException noFile) { + if (configFile.exists()) { + throw noFile; + } + clear(); snapshot = newSnapshot; - hash = newHash; - } - } catch (FileNotFoundException noFile) { - if (configFile.exists()) { - throw noFile; + return; + } catch (IOException e) { + if (FileUtils.isStaleFileHandle(e) + && retries < maxStaleRetries) { + if (LOG.isDebugEnabled()) { + LOG.debug(MessageFormat.format( + JGitText.get().configHandleIsStale, + Integer.valueOf(retries)), e); + } + retries++; + continue; + } + throw new IOException(MessageFormat + .format(JGitText.get().cannotReadFile, getFile()), e); + } catch (ConfigInvalidException e) { + throw new ConfigInvalidException(MessageFormat + .format(JGitText.get().cannotReadFile, getFile()), e); } - clear(); - snapshot = newSnapshot; - } catch (IOException e) { - throw new IOException(MessageFormat - .format(JGitText.get().cannotReadFile, getFile()), e); - } catch (ConfigInvalidException e) { - throw new ConfigInvalidException(MessageFormat.format(JGitText.get().cannotReadFile, getFile()), e); } }