{"thread":{"id":"17659","subject":"[JGIT PATCH v2] Don't keep an empty pack uploaded through receive-pack","startedAt":"2009-02-08T20:46:13Z","lastAt":"2009-02-08T20:46:13Z","messageCount":1,"participants":["Shawn O. Pearce"],"isPatch":true,"patchVersion":2,"patchTotal":null},"messages":[{"id":"103781","messageId":"1234125973-15077-1-git-send-email-spearce@spearce.org","threadId":"17659","inReplyTo":null,"subject":"[JGIT PATCH v2] Don't keep an empty pack uploaded through receive-pack","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2009-02-08T20:46:13Z","receivedAt":"2009-02-08T20:46:13Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"The receive-pack protocol sometimes gets an empty pack file if\nthere are commands to process but no data was needed to be sent.\nIn such cases we shouldn't create an empty 32 byte pack on disk,\nbut instead should discard it.\n\nSince ReceivePack doesn't read the pack header, we only know\nthe empty state inside of IndexPack.  So we fix it here, to\navoid duplicating the header parsing code into ReceivePack.\n\nSigned-off-by: Shawn O. Pearce <spearce@spearce.org>\n---\n\n I missed the test case that assumes we kept an empty pack on disk.\n This version of the patch fixes that test case.\n\n .../tst/org/spearce/jgit/lib/PackWriterTest.java   |    1 +\n .../src/org/spearce/jgit/transport/IndexPack.java  |   34 ++++++++++++++++---\n 2 files changed, 29 insertions(+), 6 deletions(-)\n\ndiff --git a/org.spearce.jgit.test/tst/org/spearce/jgit/lib/PackWriterTest.java b/org.spearce.jgit.test/tst/org/spearce/jgit/lib/PackWriterTest.java\nindex 98e0d3a..e828ccc 100644\n--- a/org.spearce.jgit.test/tst/org/spearce/jgit/lib/PackWriterTest.java\n+++ b/org.spearce.jgit.test/tst/org/spearce/jgit/lib/PackWriterTest.java\n@@ -468,6 +468,7 @@ private void verifyOpenPack(final boolean thin) throws IOException {\n \t\t}\n \t\tfinal InputStream is = new ByteArrayInputStream(os.toByteArray());\n \t\tfinal IndexPack indexer = new IndexPack(db, is, packBase);\n+\t\tindexer.setKeepEmpty(true);\n \t\tindexer.setFixThin(thin);\n \t\tindexer.index(new TextProgressMonitor());\n \t\tpack = new PackFile(db, indexFile, packFile);\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/transport/IndexPack.java b/org.spearce.jgit/src/org/spearce/jgit/transport/IndexPack.java\nindex 82cd615..bd7bfd0 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/transport/IndexPack.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/transport/IndexPack.java\n@@ -143,6 +143,8 @@ public static IndexPack create(final Repository db, final InputStream is)\n \n \tprivate boolean fixThin;\n \n+\tprivate boolean keepEmpty;\n+\n \tprivate int outputVersion;\n \n \tprivate final File dstPack;\n@@ -239,6 +241,19 @@ public void setFixThin(final boolean fix) {\n \t}\n \n \t/**\n+\t * Configure this index pack instance to keep an empty pack.\n+\t * <p>\n+\t * By default an empty pack (a pack with no objects) is not kept, as doing\n+\t * so is completely pointless. With no objects in the pack there is no data\n+\t * stored by it, so the pack is unnecessary.\n+\t * \n+\t * @param empty true to enable keeping an empty pack.\n+\t */\n+\tpublic void setKeepEmpty(final boolean empty) {\n+\t\tkeepEmpty = empty;\n+\t}\n+\n+\t/**\n \t * Configure the checker used to validate received objects.\n \t * <p>\n \t * Usually object checking isn't necessary, as Git implementations only\n@@ -313,14 +328,14 @@ public void index(final ProgressMonitor progress) throws IOException {\n \t\t\t\t\t\tfixThinPack(progress);\n \t\t\t\t\t}\n \t\t\t\t}\n-\t\t\t\tif (packOut != null)\n+\t\t\t\tif (packOut != null && (keepEmpty || entryCount > 0))\n \t\t\t\t\tpackOut.getChannel().force(true);\n \n \t\t\t\tpackDigest = null;\n \t\t\t\tbaseById = null;\n \t\t\t\tbaseByPos = null;\n \n-\t\t\t\tif (dstIdx != null)\n+\t\t\t\tif (dstIdx != null && (keepEmpty || entryCount > 0))\n \t\t\t\t\twriteIdx();\n \n \t\t\t} finally {\n@@ -336,10 +351,12 @@ public void index(final ProgressMonitor progress) throws IOException {\n \t\t\t\t\tpackOut.close();\n \t\t\t}\n \n-\t\t\tif (dstPack != null)\n-\t\t\t\tdstPack.setReadOnly();\n-\t\t\tif (dstIdx != null)\n-\t\t\t\tdstIdx.setReadOnly();\n+\t\t\tif (keepEmpty || entryCount > 0) {\n+\t\t\t\tif (dstPack != null)\n+\t\t\t\t\tdstPack.setReadOnly();\n+\t\t\t\tif (dstIdx != null)\n+\t\t\t\t\tdstIdx.setReadOnly();\n+\t\t\t}\n \t\t} catch (IOException err) {\n \t\t\tif (dstPack != null)\n \t\t\t\tdstPack.delete();\n@@ -946,6 +963,11 @@ UnresolvedDelta(final long headerOffset, final int crc32) {\n \t *             removed prior to throwing the exception to the caller.\n \t */\n \tpublic void renameAndOpenPack() throws IOException {\n+\t\tif (!keepEmpty && entryCount == 0) {\n+\t\t\tcleanupTemporaryFiles();\n+\t\t\treturn;\n+\t\t}\n+\n \t\tfinal MessageDigest d = Constants.newMessageDigest();\n \t\tfinal byte[] oeBytes = new byte[Constants.OBJECT_ID_LENGTH];\n \t\tfor (int i = 0; i < entryCount; i++) {\n-- \n1.6.2.rc0.173.g5e148\n"}]}