]> source.dussan.org Git - jgit.git/commitdiff
Expose the received pack size in ReceivePack 16/22716/2
authorSaša Živkov <sasa.zivkov@sap.com>
Fri, 28 Feb 2014 17:34:59 +0000 (18:34 +0100)
committerMatthias Sohn <matthias.sohn@sap.com>
Sun, 2 Mar 2014 00:52:06 +0000 (01:52 +0100)
PostReceiveHooks can make use of this information to, for example,
update a cached size of the Git repository.

Change-Id: I2bf1200959a50531e2155a7609c96035ba45b10d
Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/MeasurePackSizeTest.java [new file with mode: 0644]
org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectoryPackParser.java
org.eclipse.jgit/src/org/eclipse/jgit/transport/BaseReceivePack.java
org.eclipse.jgit/src/org/eclipse/jgit/transport/PackParser.java

diff --git a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/MeasurePackSizeTest.java b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/MeasurePackSizeTest.java
new file mode 100644 (file)
index 0000000..108e7bb
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2014, Matthias Sohn <matthias.sohn@sap.com>
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ *   copyright notice, this list of conditions and the following
+ *   disclaimer in the documentation and/or other materials provided
+ *   with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ *   names of its contributors may be used to endorse or promote
+ *   products derived from this software without specific prior
+ *   written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.eclipse.jgit.http.test;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.Collection;
+import java.util.Collections;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jgit.errors.RepositoryNotFoundException;
+import org.eclipse.jgit.http.server.GitServlet;
+import org.eclipse.jgit.http.server.resolver.DefaultReceivePackFactory;
+import org.eclipse.jgit.junit.TestRepository;
+import org.eclipse.jgit.junit.http.HttpTestCase;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.NullProgressMonitor;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.StoredConfig;
+import org.eclipse.jgit.revwalk.RevBlob;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.transport.PostReceiveHook;
+import org.eclipse.jgit.transport.PushResult;
+import org.eclipse.jgit.transport.ReceiveCommand;
+import org.eclipse.jgit.transport.ReceivePack;
+import org.eclipse.jgit.transport.RemoteRefUpdate;
+import org.eclipse.jgit.transport.Transport;
+import org.eclipse.jgit.transport.URIish;
+import org.eclipse.jgit.transport.resolver.RepositoryResolver;
+import org.eclipse.jgit.transport.resolver.ServiceNotAuthorizedException;
+import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException;
+import org.junit.Before;
+import org.junit.Test;
+
+public class MeasurePackSizeTest extends HttpTestCase {
+       private Repository remoteRepository;
+
+       private URIish remoteURI;
+
+       long packSize = -1;
+
+       @Before
+       public void setUp() throws Exception {
+               super.setUp();
+
+               final TestRepository<Repository> src = createTestRepository();
+               final String srcName = src.getRepository().getDirectory().getName();
+
+               ServletContextHandler app = server.addContext("/git");
+               GitServlet gs = new GitServlet();
+               gs.setRepositoryResolver(new RepositoryResolver<HttpServletRequest>() {
+                       public Repository open(HttpServletRequest req, String name)
+                                       throws RepositoryNotFoundException,
+                                       ServiceNotEnabledException {
+                               if (!name.equals(srcName))
+                                       throw new RepositoryNotFoundException(name);
+
+                               final Repository db = src.getRepository();
+                               db.incrementOpen();
+                               return db;
+                       }
+               });
+               gs.setReceivePackFactory(new DefaultReceivePackFactory() {
+                       public ReceivePack create(HttpServletRequest req, Repository db)
+                                       throws ServiceNotEnabledException,
+                                       ServiceNotAuthorizedException {
+                               ReceivePack recv = super.create(req, db);
+                               recv.setPostReceiveHook(new PostReceiveHook() {
+
+                                       public void onPostReceive(ReceivePack rp,
+                                                       Collection<ReceiveCommand> commands) {
+                                               packSize = rp.getPackSize();
+                                       }
+                               });
+                               return recv;
+                       }
+
+               });
+               app.addServlet(new ServletHolder(gs), "/*");
+
+               server.setUp();
+
+               remoteRepository = src.getRepository();
+               remoteURI = toURIish(app, srcName);
+
+               StoredConfig cfg = remoteRepository.getConfig();
+               cfg.setBoolean("http", null, "receivepack", true);
+               cfg.save();
+       }
+
+       @Test
+       public void testPush_packSize() throws Exception {
+               final TestRepository src = createTestRepository();
+               final RevBlob Q_txt = src
+                               .blob("some blob content to measure pack size");
+               final RevCommit Q = src.commit().add("Q", Q_txt).create();
+               final Repository db = src.getRepository();
+               final String dstName = Constants.R_HEADS + "new.branch";
+               Transport t;
+               PushResult result;
+
+               t = Transport.open(db, remoteURI);
+               try {
+                       final String srcExpr = Q.name();
+                       final boolean forceUpdate = false;
+                       final String localName = null;
+                       final ObjectId oldId = null;
+
+                       RemoteRefUpdate update = new RemoteRefUpdate(src.getRepository(),
+                                       srcExpr, dstName, forceUpdate, localName, oldId);
+                       result = t.push(NullProgressMonitor.INSTANCE,
+                                       Collections.singleton(update));
+               } finally {
+                       t.close();
+               }
+               assertEquals("expected 1 RemoteUpdate", 1, result.getRemoteUpdates()
+                               .size());
+               assertEquals("unexpected pack size", 1398, packSize);
+       }
+
+}
index a5a5cf6c995074210e8767f44a517d7f2fc3f14c..57c08f3691c2d5635d17e5ea3e87754c6bfb5ae5 100644 (file)
@@ -378,6 +378,7 @@ packHasUnresolvedDeltas=pack has unresolved deltas
 packingCancelledDuringObjectsWriting=Packing cancelled during objects writing
 packObjectCountMismatch=Pack object count mismatch: pack {0} index {1}: {2}
 packRefs=Pack refs
+packSizeNotSetYet=Pack size not yet set since it has not yet been received
 packTooLargeForIndexVersion1=Pack too large for index version 1
 packWriterStatistics=Total {0,number,#0} (delta {1,number,#0}), reused {2,number,#0} (delta {3,number,#0})
 panicCantRenameIndexFile=Panic: index file {0} must be renamed to replace {1}; until then repository is corrupt
index 8ca425a15b41dedc8f4855e5767828dbf555226a..40e74ed892763c60d232e43c564c207ce6362324 100644 (file)
@@ -440,6 +440,7 @@ public class JGitText extends TranslationBundle {
        /***/ public String packingCancelledDuringObjectsWriting;
        /***/ public String packObjectCountMismatch;
        /***/ public String packRefs;
+       /***/ public String packSizeNotSetYet;
        /***/ public String packTooLargeForIndexVersion1;
        /***/ public String packWriterStatistics;
        /***/ public String panicCantRenameIndexFile;
index 1846c47ed22e9f91c6a505219496c0a0f660e863..a186b8147088dd7379aa950c0183ea5be8f34f10 100644 (file)
@@ -168,6 +168,21 @@ public class ObjectDirectoryPackParser extends PackParser {
                return newPack;
        }
 
+       @Override
+       public long getPackSize() {
+               if (newPack == null)
+                       return super.getPackSize();
+
+               File pack = newPack.getPackFile();
+               long size = pack.length();
+               String p = pack.getAbsolutePath();
+               String i = p.substring(0, p.length() - ".pack".length()) + ".idx"; //$NON-NLS-1$ //$NON-NLS-2$
+               File idx = new File(i);
+               if (idx.exists() && idx.isFile())
+                       size += idx.length();
+               return size;
+       }
+
        @Override
        public PackLock parse(ProgressMonitor receiving, ProgressMonitor resolving)
                        throws IOException {
index 67ab9ef3a636fbd897975e41fd4601a7f6312119..68b3262a0b7964b805ebe988e0fd108d5e2e481b 100644 (file)
@@ -240,6 +240,9 @@ public abstract class BaseReceivePack {
        /** Total pack size limit */
        private long maxPackSizeLimit = -1;
 
+       /** The size of the received pack, including index size */
+       private Long packSize;
+
        /**
         * Create a new pack receive for an open repository.
         *
@@ -720,6 +723,22 @@ public abstract class BaseReceivePack {
                return msgOutWrapper;
        }
 
+       /**
+        * Get the size of the received pack file including the index size.
+        *
+        * This can only be called if the pack is already received.
+        *
+        * @return the size of the received pack including index size
+        * @throws IllegalStateException
+        *             if called before the pack has been received
+        * @since 3.3
+        */
+       public long getPackSize() {
+               if (packSize != null)
+                       return packSize.longValue();
+               throw new IllegalStateException(JGitText.get().packSizeNotSetYet);
+       }
+
        /** @return true if any commands to be executed have been read. */
        protected boolean hasCommands() {
                return !commands.isEmpty();
@@ -968,6 +987,7 @@ public abstract class BaseReceivePack {
                        parser.setLockMessage(lockMsg);
                        parser.setMaxObjectSizeLimit(maxObjectSizeLimit);
                        packLock = parser.parse(receiving, resolving);
+                       packSize = Long.valueOf(parser.getPackSize());
                        ins.flush();
                } finally {
                        ins.release();
index e16cce0e3d666e379c2eca3dc38bc9f26a370314..93522c1e923c5ea227c1fba3a8b1ae0189d151a0 100644 (file)
@@ -418,6 +418,20 @@ public abstract class PackParser {
                return list;
        }
 
+       /**
+        * Get the size of the parsed pack.
+        *
+        * This will also include the pack index size if an index was created. This
+        * method should only be called after pack parsing is finished.
+        *
+        * @return the pack size (including the index size) or -1 if the size cannot
+        *         be determined
+        * @since 3.3
+        */
+       public long getPackSize() {
+               return -1;
+       }
+
        /**
         * Parse the pack stream.
         *