getCapabilities() {
/** Git object size limit */
private long maxObjectSizeLimit;
+ /** 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.
*
@@ -622,6 +631,24 @@ public void setMaxObjectSizeLimit(final long limit) {
maxObjectSizeLimit = limit;
}
+
+ /**
+ * Set the maximum allowed pack size.
+ *
+ * A pack exceeding this size will be rejected.
+ *
+ * @param limit
+ * the pack size limit, in bytes
+ *
+ * @since 3.3
+ */
+ public void setMaxPackSizeLimit(final long limit) {
+ if (limit < 0)
+ throw new IllegalArgumentException(MessageFormat.format(
+ JGitText.get().receivePackInvalidLimit, Long.valueOf(limit)));
+ maxPackSizeLimit = limit;
+ }
+
/**
* Check whether the client expects a side-band stream.
*
@@ -696,6 +723,22 @@ public OutputStream getMessageOutputStream() {
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();
@@ -741,6 +784,14 @@ protected void init(final InputStream input, final OutputStream output,
rawOut = o;
}
+ if (maxPackSizeLimit >= 0)
+ rawIn = new LimitedInputStream(rawIn, maxPackSizeLimit) {
+ @Override
+ protected void limitExceeded() throws TooLargePackException {
+ throw new TooLargePackException(limit);
+ }
+ };
+
pckIn = new PacketLineIn(rawIn);
pckOut = new PacketLineOut(rawOut);
pckOut.setFlushOnEnd(false);
@@ -936,6 +987,7 @@ private void receivePack() throws IOException {
parser.setLockMessage(lockMsg);
parser.setMaxObjectSizeLimit(maxObjectSizeLimit);
packLock = parser.parse(receiving, resolving);
+ packSize = Long.valueOf(parser.getPackSize());
ins.flush();
} finally {
ins.release();
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/PackParser.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PackParser.java
index e16cce0e3..93522c1e9 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/PackParser.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PackParser.java
@@ -418,6 +418,20 @@ public List getSortedObjectList(
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.
*
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java
index a50adf91f..70f8327b1 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java
@@ -206,15 +206,6 @@ protected void initRootIterator(Repository repo) {
ignoreNode = new RootIgnoreNode(entry, repo);
}
- /**
- * @return the repository this iterator works with
- *
- * @since 3.3
- */
- public Repository getRepository() {
- return repository;
- }
-
/**
* Define the matching {@link DirCacheIterator}, to optimize ObjectIds.
*
@@ -813,7 +804,8 @@ else if (!entry.isSmudged())
@Deprecated
public boolean isModified(DirCacheEntry entry, boolean forceContentCheck) {
try {
- return isModified(entry, forceContentCheck, null);
+ return isModified(entry, forceContentCheck,
+ repository.newObjectReader());
} catch (IOException e) {
throw new JGitInternalException(e.getMessage(), e);
}
@@ -923,7 +915,8 @@ private boolean contentCheck(DirCacheEntry entry, ObjectReader reader)
} else {
if (mode == FileMode.SYMLINK.getBits())
return !new File(readContentAsNormalizedString(current()))
- .equals(new File((readContentAsNormalizedString(entry))));
+ .equals(new File((readContentAsNormalizedString(entry,
+ reader))));
// Content differs: that's a real change, perhaps
if (reader == null) // deprecated use, do no further checks
return true;
@@ -972,9 +965,9 @@ private boolean contentCheck(DirCacheEntry entry, ObjectReader reader)
}
}
- private String readContentAsNormalizedString(DirCacheEntry entry)
- throws MissingObjectException, IOException {
- ObjectLoader open = repository.open(entry.getObjectId());
+ private static String readContentAsNormalizedString(DirCacheEntry entry,
+ ObjectReader reader) throws MissingObjectException, IOException {
+ ObjectLoader open = reader.open(entry.getObjectId());
byte[] cachedBytes = open.getCachedBytes();
return FS.detect().normalize(RawParseUtils.decode(cachedBytes));
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/io/LimitedInputStream.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/io/LimitedInputStream.java
new file mode 100644
index 000000000..85c817204
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/io/LimitedInputStream.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2007 The Guava Authors
+ * Copyright (C) 2014, Sasa Zivkov , SAP AG
+ * 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.util.io;
+
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Wraps a {@link InputStream}, limiting the number of bytes which can be
+ * read.
+ *
+ * This class was copied and modifed from the Google Guava 16.0. Differently from
+ * the original Guava code, when a caller tries to read from this stream past
+ * the given limit and the wrapped stream hasn't yet reached its EOF this class
+ * will call the limitExceeded method instead of returning EOF.
+ *
+ * @since 3.3
+ */
+public abstract class LimitedInputStream extends FilterInputStream {
+
+ private long left;
+ /** Max number of bytes to be read from the wrapped stream */
+ protected final long limit;
+ private long mark = -1;
+
+ /**
+ * Create a new LimitedInputStream
+ *
+ * @param in an InputStream
+ * @param limit max number of bytes to read from the InputStream
+ */
+ protected LimitedInputStream(InputStream in, long limit) {
+ super(in);
+ left = limit;
+ this.limit = limit;
+ }
+
+ @Override
+ public int available() throws IOException {
+ return (int) Math.min(in.available(), left);
+ }
+
+ // it's okay to mark even if mark isn't supported, as reset won't work
+ @Override
+ public synchronized void mark(int readLimit) {
+ in.mark(readLimit);
+ mark = left;
+ }
+
+ @Override
+ public int read() throws IOException {
+ if (left == 0) {
+ if (in.available() == 0)
+ return -1;
+ else
+ limitExceeded();
+ }
+
+ int result = in.read();
+ if (result != -1)
+ --left;
+ return result;
+ }
+
+ @Override
+ public int read(byte[] b, int off, int len) throws IOException {
+ if (left == 0) {
+ if (in.available() == 0)
+ return -1;
+ else
+ limitExceeded();
+ }
+
+ len = (int) Math.min(len, left);
+ int result = in.read(b, off, len);
+ if (result != -1)
+ left -= result;
+ return result;
+ }
+
+ @Override
+ public synchronized void reset() throws IOException {
+ if (!in.markSupported())
+ throw new IOException("Mark not supported");
+
+ if (mark == -1)
+ throw new IOException("Mark not set");
+
+ in.reset();
+ left = mark;
+ }
+
+ @Override
+ public long skip(long n) throws IOException {
+ n = Math.min(n, left);
+ long skipped = in.skip(n);
+ left -= skipped;
+ return skipped;
+ }
+
+ /**
+ * Called when trying to read past the given {@link #limit} and the wrapped
+ * InputStream {@link #in} hasn't yet reached its EOF
+ *
+ * @throws IOException
+ * subclasses can throw an IOException when the limit is exceeded.
+ * The throws IOException will be forwarded back to the caller of
+ * the read method which read the stream past the limit.
+ */
+ protected abstract void limitExceeded() throws IOException;
+}
diff --git a/pom.xml b/pom.xml
index a27b386ba..fd65fa74f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -51,7 +51,7 @@
org.eclipse.jgit
org.eclipse.jgit-parent
pom
- 3.3.0-SNAPSHOT
+ 3.3.1-SNAPSHOT
JGit - Parent
${jgit-url}
diff --git a/tools/maven-central/deploy.rb b/tools/maven-central/deploy.rb
index f169747c7..44abccfc9 100755
--- a/tools/maven-central/deploy.rb
+++ b/tools/maven-central/deploy.rb
@@ -34,7 +34,7 @@ def get_passphrase(prompt="Enter your GPG Passphrase")
ask(prompt) {|q| q.echo = false}
end
-version = '3.1.0.201310021548-r'.freeze
+version = '3.3.0.201403021825-r'.freeze
url = 'https://oss.sonatype.org/service/local/staging/deploy/maven2/'
repositoryId = 'sonatype-nexus-staging'
puts "gpg passphrase ?"
@@ -45,6 +45,7 @@ artifacts = [group,
group + '.ant',
group + '.archive',
group + '.console',
+ group + '.http.apache',
group + '.http.server',
group + '.java7',
group + '.junit',
diff --git a/tools/maven-central/download.rb b/tools/maven-central/download.rb
index b5dd871f3..949e6242f 100755
--- a/tools/maven-central/download.rb
+++ b/tools/maven-central/download.rb
@@ -1,10 +1,11 @@
#!/usr/bin/env ruby
-version = '3.1.0.201310021548-r'.freeze
+version = '3.3.0.201403021825-r'.freeze
group = 'org.eclipse.jgit'
artifacts = [group,
group + '.ant',
group + '.archive',
group + '.console',
+ group + '.http.apache',
group + '.http.server',
group + '.java7',
group + '.junit',