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 d8a0fc7f3..8ca3d9ae8 100644 --- a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties +++ b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties @@ -440,6 +440,7 @@ outputHasAlreadyBeenStarted=Output has already been started. packChecksumMismatch=Pack checksum mismatch detected for pack file {0} packCorruptedWhileWritingToFilesystem=Pack corrupted while writing to filesystem packDoesNotMatchIndex=Pack {0} does not match index +packedRefsHandleIsStale=packed-refs handle is stale, {0}. retry packetSizeMustBeAtLeast=packet size {0} must be >= {1} packetSizeMustBeAtMost=packet size {0} must be <= {1} packfileCorruptionDetected=Packfile corruption detected: {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 31be94c71..c227884d5 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java @@ -499,6 +499,7 @@ public static JGitText get() { /***/ public String packChecksumMismatch; /***/ public String packCorruptedWhileWritingToFilesystem; /***/ public String packDoesNotMatchIndex; + /***/ public String packedRefsHandleIsStale; /***/ public String packetSizeMustBeAtLeast; /***/ public String packetSizeMustBeAtMost; /***/ public String packfileCorruptionDetected; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectory.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectory.java index c7b60882a..6a04a538e 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectory.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/RefDirectory.java @@ -98,6 +98,8 @@ import org.eclipse.jgit.util.RawParseUtils; import org.eclipse.jgit.util.RefList; import org.eclipse.jgit.util.RefMap; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Traditional file system based {@link RefDatabase}. @@ -115,6 +117,9 @@ * overall size of a Git repository on disk. */ public class RefDirectory extends RefDatabase { + private final static Logger LOG = LoggerFactory + .getLogger(RefDirectory.class); + /** Magic string denoting the start of a symbolic reference file. */ public static final String SYMREF = "ref: "; //$NON-NLS-1$ @@ -746,22 +751,37 @@ private PackedRefList getPackedRefs() throws IOException { } private PackedRefList readPackedRefs() throws IOException { - final FileSnapshot snapshot = FileSnapshot.save(packedRefsFile); - final BufferedReader br; - final MessageDigest digest = Constants.newMessageDigest(); - try { - br = new BufferedReader(new InputStreamReader( - new DigestInputStream(new FileInputStream(packedRefsFile), - digest), CHARSET)); - } catch (FileNotFoundException noPackedRefs) { - // Ignore it and leave the new list empty. - return PackedRefList.NO_PACKED_REFS; - } - try { - return new PackedRefList(parsePackedRefs(br), snapshot, - ObjectId.fromRaw(digest.digest())); - } finally { - br.close(); + int maxStaleRetries = 5; + int retries = 0; + while (true) { + final FileSnapshot snapshot = FileSnapshot.save(packedRefsFile); + final BufferedReader br; + final MessageDigest digest = Constants.newMessageDigest(); + try { + br = new BufferedReader(new InputStreamReader( + new DigestInputStream(new FileInputStream(packedRefsFile), + digest), CHARSET)); + } catch (FileNotFoundException noPackedRefs) { + // Ignore it and leave the new list empty. + return PackedRefList.NO_PACKED_REFS; + } + try { + return new PackedRefList(parsePackedRefs(br), snapshot, + ObjectId.fromRaw(digest.digest())); + } catch (IOException e) { + if (FileUtils.isStaleFileHandle(e) && retries < maxStaleRetries) { + if (LOG.isDebugEnabled()) { + LOG.debug(MessageFormat.format( + JGitText.get().packedRefsHandleIsStale, + Integer.valueOf(retries)), e); + } + retries++; + continue; + } + throw e; + } finally { + br.close(); + } } }