Merge branch 'stable-5.2' into stable-5.3 * stable-5.2: Fix error log message in ObjectDirectory.handlePackError() Properly format pack checksums in PackFile.idx() Cancel gc if thread was interrupted PackFile: report correct message for checksum mismatch ObjectDirectory: Clean up logging Bazel: Stop using native.git_repository ObjectDirectory: extra logging on packfile exceptions Change-Id: I81cf1cdc9d8dcd54536a79e522274fd244fa1d00
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcConcurrentTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcConcurrentTest.java index 9ea62b3..05f7c65 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcConcurrentTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/GcConcurrentTest.java
@@ -47,27 +47,35 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import java.io.IOException; import java.util.Collection; import java.util.Collections; import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.Callable; +import java.util.concurrent.CountDownLatch; import java.util.concurrent.CyclicBarrier; +import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; +import org.eclipse.jgit.errors.CancelledException; import org.eclipse.jgit.internal.JGitText; import org.eclipse.jgit.internal.storage.pack.PackWriter; import org.eclipse.jgit.junit.TestRepository; +import org.eclipse.jgit.lib.ConfigConstants; import org.eclipse.jgit.lib.EmptyProgressMonitor; import org.eclipse.jgit.lib.NullProgressMonitor; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.Sets; import org.eclipse.jgit.revwalk.RevBlob; import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.jgit.storage.file.FileBasedConfig; +import org.eclipse.jgit.test.resources.SampleDataRepositoryTestCase; import org.junit.Test; public class GcConcurrentTest extends GcTestCase { @@ -221,4 +229,48 @@ public void repackAndCheckBitmapUsage() throws Exception { assertEquals(getSinglePack(repository).getPackName(), newPackName); assertNotNull(getSinglePack(repository).getBitmapIndex()); } + + @Test + public void testInterruptGc() throws Exception { + FileBasedConfig c = repo.getConfig(); + c.setInt(ConfigConstants.CONFIG_GC_SECTION, null, + ConfigConstants.CONFIG_KEY_AUTOPACKLIMIT, 1); + c.save(); + SampleDataRepositoryTestCase.copyCGitTestPacks(repo); + ExecutorService executor = Executors.newSingleThreadExecutor(); + final CountDownLatch latch = new CountDownLatch(1); + Future<Collection<PackFile>> result = executor + .submit(new Callable<Collection<PackFile>>() { + + @Override + public Collection<PackFile> call() throws Exception { + long start = System.currentTimeMillis(); + System.out.println("starting gc"); + latch.countDown(); + Collection<PackFile> r = gc.gc(); + System.out.println("gc took " + + (System.currentTimeMillis() - start) + " ms"); + return r; + } + }); + try { + latch.await(); + Thread.sleep(5); + executor.shutdownNow(); + result.get(); + fail("thread wasn't interrupted"); + } catch (ExecutionException e) { + Throwable cause = e.getCause(); + if (cause instanceof CancelledException) { + assertEquals(JGitText.get().operationCanceled, + cause.getMessage()); + } else if (cause instanceof IOException) { + Throwable cause2 = cause.getCause(); + assertTrue(cause2 instanceof InterruptedException + || cause2 instanceof ExecutionException); + } else { + fail("unexpected exception " + e); + } + } + } }
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 6ee144f..38901f9 100644 --- a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties +++ b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
@@ -290,7 +290,7 @@ exceptionHookExecutionInterrupted=Execution of "{0}" hook interrupted. exceptionOccurredDuringAddingOfOptionToALogCommand=Exception occurred during adding of {0} as option to a Log command exceptionOccurredDuringReadingOfGIT_DIR=Exception occurred during reading of $GIT_DIR/{0}. {1} -exceptionWhileReadingPack=ERROR: Exception caught while accessing pack file {0}, the pack file might be corrupt, {1}. Caught {2} consecutive errors while trying to read this pack. +exceptionWhileReadingPack=Exception caught while accessing pack file {0}, the pack file might be corrupt. Caught {1} consecutive errors while trying to read this pack. expectedACKNAKFoundEOF=Expected ACK/NAK, found EOF expectedACKNAKGot=Expected ACK/NAK, got: {0} expectedBooleanStringValue=Expected boolean string value @@ -520,7 +520,7 @@ operationCanceled=Operation {0} was canceled outputHasAlreadyBeenStarted=Output has already been started. overflowedReftableBlock=Overflowed reftable block -packChecksumMismatch=Pack checksum mismatch detected for pack file {0} +packChecksumMismatch=Pack checksum mismatch detected for pack file {0}: .pack has {1} whilst .idx has {2} packCorruptedWhileWritingToFilesystem=Pack corrupted while writing to filesystem packDoesNotMatchIndex=Pack {0} does not match index packedRefsHandleIsStale=packed-refs handle is stale, {0}. retry @@ -722,6 +722,7 @@ tSizeMustBeGreaterOrEqual1=tSize must be >= 1 unableToCheckConnectivity=Unable to check connectivity. unableToCreateNewObject=Unable to create new object: {0} +unableToReadPackfile=Unable to read packfile {0} unableToRemovePath=Unable to remove path ''{0}'' unableToStore=Unable to store {0}. unableToWrite=Unable to write {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 bd91fe0..ac9a637 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
@@ -782,6 +782,7 @@ public static JGitText get() { /***/ public String tSizeMustBeGreaterOrEqual1; /***/ public String unableToCheckConnectivity; /***/ public String unableToCreateNewObject; + /***/ public String unableToReadPackfile; /***/ public String unableToRemovePath; /***/ public String unableToStore; /***/ public String unableToWrite;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java index 037338e..8040548 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java
@@ -1269,7 +1269,7 @@ private File nameFor(String name, String ext) { } private void checkCancelled() throws CancelledException { - if (pm.isCancelled()) { + if (pm.isCancelled() || Thread.currentThread().isInterrupted()) { throw new CancelledException(JGitText.get().operationCanceled); } }
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectory.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectory.java index ad5afbf..d4a8adc 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectory.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectory.java
@@ -359,7 +359,9 @@ boolean hasPackedObject(AnyObjectId objectId) { // The hasObject call should have only touched the index, // so any failure here indicates the index is unreadable // by this process, and the pack is likewise not readable. - LOG.warn("Unable to read packfile " + p.getPackFile(), e); + LOG.warn(MessageFormat.format( + JGitText.get().unableToReadPackfile, + p.getPackFile().getAbsolutePath()), e); removePack(p); } } @@ -652,7 +654,8 @@ private void handlePackError(IOException e, PackFile p) { if ((e instanceof CorruptObjectException) || (e instanceof PackInvalidException)) { warnTmpl = JGitText.get().corruptPack; - LOG.warn("Packfile " + p.getPackFile() + " is corrupted", e); + LOG.warn(MessageFormat.format(warnTmpl, + p.getPackFile().getAbsolutePath()), e); // Assume the pack is corrupted, and remove it from the list. removePack(p); } else if (e instanceof FileNotFoundException) { @@ -682,8 +685,8 @@ private void handlePackError(IOException e, PackFile p) { // Don't remove the pack from the list, as the error may be // transient. LOG.error(MessageFormat.format(errTmpl, - p.getPackFile().getAbsolutePath()), - Integer.valueOf(transientErrorCount), e); + p.getPackFile().getAbsolutePath(), + Integer.valueOf(transientErrorCount)), e); } } }
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackFile.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackFile.java index 71f64ae..ed238a4 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackFile.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackFile.java
@@ -187,7 +187,9 @@ private synchronized PackIndex idx() throws IOException { } else if (!Arrays.equals(packChecksum, idx.packChecksum)) { throw new PackMismatchException(MessageFormat.format( JGitText.get().packChecksumMismatch, - packFile.getPath())); + packFile.getPath(), + ObjectId.fromRaw(packChecksum).name(), + ObjectId.fromRaw(idx.packChecksum).name())); } loadedIdx = idx; } catch (InterruptedIOException e) { @@ -753,10 +755,10 @@ private void onOpenPack() throws IOException { fd.readFully(buf, 0, 20); if (!Arrays.equals(buf, packChecksum)) { throw new PackMismatchException(MessageFormat.format( - JGitText.get().packObjectCountMismatch - , ObjectId.fromRaw(buf).name() - , ObjectId.fromRaw(idx.packChecksum).name() - , getPackFile())); + JGitText.get().packChecksumMismatch, + getPackFile(), + ObjectId.fromRaw(buf).name(), + ObjectId.fromRaw(idx.packChecksum).name())); } }