* stable-1.0: DHT: Support removing a repository name DHT: Fix thread-safety issue in AbstractWriteBuffer jgit.sh: Implement pager support Change EditList to extend ArrayList Ensure the HTTP request is fully consumed Make sure test repositories are closed Fix CloneCommand not to fetch into remote tracking branches when bare Update Eclipse IP log for 1.0 Change-Id: I6340d551482e1dda01f82496296d2038b07fa68btags/v1.1.0.201109011030-rc2
@@ -120,9 +120,3 @@ | |||
license = Apache License, 2.0 | |||
use = unmodified source & binary | |||
state = approved | |||
[CQ "5135"] | |||
description = Protocol Buffers Version: 2.4.0a (ATO CQ4876) | |||
license = New BSD license | |||
use = unmodified source & binary | |||
state = approved |
@@ -302,6 +302,17 @@ public abstract class LocalDiskRepositoryTestCase { | |||
return db; | |||
} | |||
/** | |||
* Adds a repository to the list of repositories which is closed at the end | |||
* of the tests | |||
* | |||
* @param r | |||
* the repository to be closed | |||
*/ | |||
public void addRepoToClose(Repository r) { | |||
toClose.add(r); | |||
} | |||
/** | |||
* Creates a new unique directory for a test repository | |||
* |
@@ -41,6 +41,20 @@ | |||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | |||
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
cmd= | |||
for a in "$@" | |||
do | |||
case "$a" in | |||
-*) continue ;; | |||
*) cmd=$a; break; ;; | |||
esac | |||
done | |||
use_pager= | |||
case "$cmd" in | |||
diff) use_pager=1 ;; | |||
log) use_pager=1 ;; | |||
esac | |||
this_script=`which "$0" 2>/dev/null` | |||
[ $? -gt 0 -a -f "$0" ] && this_script="$0" | |||
@@ -58,7 +72,7 @@ CYGWIN*) | |||
cp=`cygpath --windows --mixed --path "$cp"` | |||
;; | |||
Darwin) | |||
if test -e /System/Library/Frameworks/JavaVM.framework | |||
if [ -e /System/Library/Frameworks/JavaVM.framework ] | |||
then | |||
java_args=' | |||
-Dcom.apple.mrj.application.apple.menu.about.name=JGit | |||
@@ -74,10 +88,25 @@ CLASSPATH="$cp" | |||
export CLASSPATH | |||
java=java | |||
if test -n "$JAVA_HOME" | |||
if [ -n "$JAVA_HOME" ] | |||
then | |||
java="$JAVA_HOME/bin/java" | |||
fi | |||
exec "$java" $java_args org.eclipse.jgit.pgm.Main "$@" | |||
exit 1 | |||
if [ -n "$use_pager" ] | |||
then | |||
use_pager=${GIT_PAGER:-${PAGER:-less}} | |||
[ cat = "$use_pager" ] && use_pager= | |||
fi | |||
if [ -n "$use_pager" ] | |||
then | |||
LESS=${LESS:-FSRX} | |||
export LESS | |||
"$java" $java_args org.eclipse.jgit.pgm.Main "$@" | $use_pager | |||
exit | |||
else | |||
exec "$java" $java_args org.eclipse.jgit.pgm.Main "$@" | |||
exit 1 | |||
fi |
@@ -87,4 +87,21 @@ public interface RepositoryIndexTable { | |||
*/ | |||
public void putUnique(RepositoryName name, RepositoryKey key) | |||
throws DhtException, TimeoutException; | |||
/** | |||
* Remove the association of a name to an identifier. | |||
* <p> | |||
* This method must use some sort of transaction system to ensure the name | |||
* is removed only if it currently references {@code key}. This may require | |||
* running some sort of lock management service in parallel to the database. | |||
* | |||
* @param name | |||
* name of the repository. | |||
* @param key | |||
* internal key defining the repository. | |||
* @throws DhtException | |||
* @throws TimeoutException | |||
*/ | |||
public void remove(RepositoryName name, RepositoryKey key) | |||
throws DhtException, TimeoutException; | |||
} |
@@ -128,4 +128,18 @@ public class CacheRepositoryIndexTable implements RepositoryIndexTable { | |||
throw new TimeoutException(); | |||
} | |||
} | |||
public void remove(RepositoryName name, RepositoryKey key) | |||
throws DhtException, TimeoutException { | |||
db.remove(name, key); | |||
Sync<Void> sync = Sync.create(); | |||
CacheKey memKey = ns.key(name); | |||
client.modify(singleton(Change.remove(memKey)), sync); | |||
try { | |||
sync.get(options.getTimeout()); | |||
} catch (InterruptedException e) { | |||
throw new TimeoutException(); | |||
} | |||
} | |||
} |
@@ -78,4 +78,16 @@ final class MemRepositoryIndexTable implements RepositoryIndexTable { | |||
throw new DhtException(MessageFormat.format( | |||
DhtText.get().repositoryAlreadyExists, name.asString())); | |||
} | |||
public void remove(RepositoryName name, RepositoryKey key) | |||
throws DhtException, TimeoutException { | |||
boolean ok = table.compareAndSet( | |||
name.asBytes(), | |||
colId.name(), | |||
key.asBytes(), | |||
null); | |||
if (!ok) | |||
throw new DhtException(MessageFormat.format( | |||
DhtText.get().repositoryAlreadyExists, name.asString())); | |||
} | |||
} |
@@ -82,6 +82,8 @@ public abstract class AbstractWriteBuffer implements WriteBuffer { | |||
private final List<Future<?>> running; | |||
private final Object runningLock; | |||
private final Semaphore spaceAvailable; | |||
private int queuedCount; | |||
@@ -102,6 +104,7 @@ public abstract class AbstractWriteBuffer implements WriteBuffer { | |||
this.executor = executor; | |||
this.bufferSize = bufferSize; | |||
this.running = new LinkedList<Future<?>>(); | |||
this.runningLock = new Object(); | |||
this.spaceAvailable = new Semaphore(bufferSize); | |||
} | |||
@@ -189,14 +192,18 @@ public abstract class AbstractWriteBuffer implements WriteBuffer { | |||
} | |||
} | |||
checkRunningTasks(true); | |||
synchronized (runningLock) { | |||
checkRunningTasks(true); | |||
} | |||
} finally { | |||
flushing = false; | |||
} | |||
} | |||
public void abort() throws DhtException { | |||
checkRunningTasks(true); | |||
synchronized (runningLock) { | |||
checkRunningTasks(true); | |||
} | |||
} | |||
private void acquireSpace(int sz) throws DhtException { | |||
@@ -259,9 +266,11 @@ public abstract class AbstractWriteBuffer implements WriteBuffer { | |||
return; | |||
} | |||
if (!flushing) | |||
checkRunningTasks(false); | |||
running.add(executor.submit(op)); | |||
synchronized (runningLock) { | |||
if (!flushing) | |||
checkRunningTasks(false); | |||
running.add(executor.submit(op)); | |||
} | |||
} | |||
/** | |||
@@ -284,8 +293,10 @@ public abstract class AbstractWriteBuffer implements WriteBuffer { | |||
int size) throws DhtException { | |||
int permits = permitsForSize(size); | |||
WrappedCallback<T> op = new WrappedCallback<T>(callback, permits); | |||
checkRunningTasks(false); | |||
running.add(op); | |||
synchronized (runningLock) { | |||
checkRunningTasks(false); | |||
running.add(op); | |||
} | |||
return op; | |||
} | |||
@@ -49,12 +49,14 @@ import static org.junit.Assert.fail; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import java.util.Collections; | |||
import java.util.List; | |||
import org.eclipse.jgit.api.ListBranchCommand.ListMode; | |||
import org.eclipse.jgit.junit.TestRepository; | |||
import org.eclipse.jgit.lib.ConfigConstants; | |||
import org.eclipse.jgit.lib.Constants; | |||
import org.eclipse.jgit.lib.ObjectId; | |||
import org.eclipse.jgit.lib.Ref; | |||
import org.eclipse.jgit.lib.RefUpdate; | |||
import org.eclipse.jgit.lib.Repository; | |||
import org.eclipse.jgit.lib.RepositoryTestCase; | |||
@@ -99,6 +101,7 @@ public class CloneCommandTest extends RepositoryTestCase { | |||
command.setURI("file://" | |||
+ git.getRepository().getWorkTree().getPath()); | |||
Git git2 = command.call(); | |||
addRepoToClose(git2.getRepository()); | |||
assertNotNull(git2); | |||
ObjectId id = git2.getRepository().resolve("tag-for-blob"); | |||
assertNotNull(id); | |||
@@ -133,9 +136,51 @@ public class CloneCommandTest extends RepositoryTestCase { | |||
command.setURI("file://" | |||
+ git.getRepository().getWorkTree().getPath()); | |||
Git git2 = command.call(); | |||
addRepoToClose(git2.getRepository()); | |||
assertNotNull(git2); | |||
assertEquals(git2.getRepository().getFullBranch(), | |||
"refs/heads/master"); | |||
assertEquals( | |||
"refs/heads/master, refs/remotes/origin/master, refs/remotes/origin/test", | |||
allRefNames(git2.branchList().setListMode(ListMode.ALL) | |||
.call())); | |||
// Same thing, but now without checkout | |||
directory = createTempDirectory("testCloneRepositoryWithBranch_bare"); | |||
command = Git.cloneRepository(); | |||
command.setBranch("refs/heads/master"); | |||
command.setDirectory(directory); | |||
command.setURI("file://" | |||
+ git.getRepository().getWorkTree().getPath()); | |||
command.setNoCheckout(true); | |||
git2 = command.call(); | |||
addRepoToClose(git2.getRepository()); | |||
assertNotNull(git2); | |||
assertEquals(git2.getRepository().getFullBranch(), | |||
"refs/heads/master"); | |||
assertEquals( | |||
"refs/remotes/origin/master, refs/remotes/origin/test", | |||
allRefNames(git2.branchList().setListMode(ListMode.ALL) | |||
.call())); | |||
// Same thing, but now test with bare repo | |||
directory = createTempDirectory("testCloneRepositoryWithBranch_bare"); | |||
command = Git.cloneRepository(); | |||
command.setBranch("refs/heads/master"); | |||
command.setDirectory(directory); | |||
command.setURI("file://" | |||
+ git.getRepository().getWorkTree().getPath()); | |||
command.setBare(true); | |||
git2 = command.call(); | |||
addRepoToClose(git2.getRepository()); | |||
assertNotNull(git2); | |||
assertEquals(git2.getRepository().getFullBranch(), | |||
"refs/heads/master"); | |||
assertEquals("refs/heads/master, refs/heads/test", allRefNames(git2 | |||
.branchList().setListMode(ListMode.ALL).call())); | |||
} catch (Exception e) { | |||
fail(e.getMessage()); | |||
} | |||
@@ -153,16 +198,46 @@ public class CloneCommandTest extends RepositoryTestCase { | |||
command.setURI("file://" | |||
+ git.getRepository().getWorkTree().getPath()); | |||
Git git2 = command.call(); | |||
addRepoToClose(git2.getRepository()); | |||
assertNotNull(git2); | |||
assertEquals(git2.getRepository().getFullBranch(), | |||
"refs/heads/master"); | |||
assertEquals(1, git2.branchList().setListMode(ListMode.REMOTE) | |||
.call().size()); | |||
assertEquals("refs/remotes/origin/master", | |||
allRefNames(git2.branchList() | |||
.setListMode(ListMode.REMOTE).call())); | |||
// Same thing, but now test with bare repo | |||
directory = createTempDirectory("testCloneRepositoryWithBranch_bare"); | |||
command = Git.cloneRepository(); | |||
command.setBranch("refs/heads/master"); | |||
command.setBranchesToClone(Collections | |||
.singletonList("refs/heads/master")); | |||
command.setDirectory(directory); | |||
command.setURI("file://" | |||
+ git.getRepository().getWorkTree().getPath()); | |||
command.setBare(true); | |||
git2 = command.call(); | |||
addRepoToClose(git2.getRepository()); | |||
assertNotNull(git2); | |||
assertEquals(git2.getRepository().getFullBranch(), | |||
"refs/heads/master"); | |||
assertEquals("refs/heads/master", allRefNames(git2 | |||
.branchList().setListMode(ListMode.ALL).call())); | |||
} catch (Exception e) { | |||
fail(e.getMessage()); | |||
} | |||
} | |||
public static String allRefNames(List<Ref> refs) { | |||
StringBuilder sb = new StringBuilder(); | |||
for (Ref f : refs) { | |||
if (sb.length() > 0) | |||
sb.append(", "); | |||
sb.append(f.getName()); | |||
} | |||
return sb.toString(); | |||
} | |||
public static File createTempDirectory(String name) throws IOException { | |||
final File temp; | |||
temp = File.createTempFile(name, Long.toString(System.nanoTime())); |
@@ -72,6 +72,7 @@ public class GitConstructionTest extends RepositoryTestCase { | |||
.setURI(db.getDirectory().toURI().toString()) | |||
.setDirectory(createUniqueTestGitDir(true)).call() | |||
.getRepository(); | |||
addRepoToClose(bareRepo); | |||
} | |||
@Override | |||
@@ -88,7 +89,7 @@ public class GitConstructionTest extends RepositoryTestCase { | |||
assertEquals(1, git.branchList().call().size()); | |||
git = Git.wrap(bareRepo); | |||
assertEquals(2, git.branchList().setListMode(ListMode.ALL).call() | |||
assertEquals(1, git.branchList().setListMode(ListMode.ALL).call() | |||
.size()); | |||
try { | |||
@@ -105,7 +106,7 @@ public class GitConstructionTest extends RepositoryTestCase { | |||
assertEquals(1, git.branchList().call().size()); | |||
git = Git.open(bareRepo.getDirectory()); | |||
assertEquals(2, git.branchList().setListMode(ListMode.ALL).call() | |||
assertEquals(1, git.branchList().setListMode(ListMode.ALL).call() | |||
.size()); | |||
git = Git.open(db.getWorkTree()); |
@@ -70,6 +70,7 @@ public class InitCommandTest extends RepositoryTestCase { | |||
InitCommand command = new InitCommand(); | |||
command.setDirectory(directory); | |||
Repository repository = command.call().getRepository(); | |||
addRepoToClose(repository); | |||
assertNotNull(repository); | |||
} catch (Exception e) { | |||
fail(e.getMessage()); | |||
@@ -84,6 +85,7 @@ public class InitCommandTest extends RepositoryTestCase { | |||
command.setDirectory(directory); | |||
command.setBare(true); | |||
Repository repository = command.call().getRepository(); | |||
addRepoToClose(repository); | |||
assertNotNull(repository); | |||
assertTrue(repository.isBare()); | |||
} catch (Exception e) { |
@@ -89,6 +89,8 @@ public class LsRemoteCommandTest extends RepositoryTestCase { | |||
+ git.getRepository().getWorkTree().getPath()); | |||
command.setCloneAllBranches(true); | |||
Git git2 = command.call(); | |||
addRepoToClose(git2.getRepository()); | |||
LsRemoteCommand lsRemoteCommand = git2.lsRemote(); | |||
Collection<Ref> refs = lsRemoteCommand.call(); | |||
@@ -109,6 +111,7 @@ public class LsRemoteCommandTest extends RepositoryTestCase { | |||
+ git.getRepository().getWorkTree().getPath()); | |||
command.setCloneAllBranches(true); | |||
Git git2 = command.call(); | |||
addRepoToClose(git2.getRepository()); | |||
LsRemoteCommand lsRemoteCommand = git2.lsRemote(); | |||
lsRemoteCommand.setTags(true); | |||
@@ -130,6 +133,7 @@ public class LsRemoteCommandTest extends RepositoryTestCase { | |||
+ git.getRepository().getWorkTree().getPath()); | |||
command.setCloneAllBranches(true); | |||
Git git2 = command.call(); | |||
addRepoToClose(git2.getRepository()); | |||
LsRemoteCommand lsRemoteCommand = git2.lsRemote(); | |||
lsRemoteCommand.setHeads(true); |
@@ -46,7 +46,9 @@ | |||
package org.eclipse.jgit.transport; | |||
import static org.junit.Assert.assertEquals; | |||
import static org.junit.Assert.assertTrue; | |||
import static org.junit.Assert.fail; | |||
import java.io.ByteArrayInputStream; | |||
import java.io.File; | |||
@@ -54,8 +56,10 @@ import java.io.FileInputStream; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.security.MessageDigest; | |||
import java.text.MessageFormat; | |||
import java.util.zip.Deflater; | |||
import org.eclipse.jgit.JGitText; | |||
import org.eclipse.jgit.junit.JGitTestUtil; | |||
import org.eclipse.jgit.junit.TestRepository; | |||
import org.eclipse.jgit.lib.Constants; | |||
@@ -69,6 +73,7 @@ import org.eclipse.jgit.storage.file.ObjectDirectoryPackParser; | |||
import org.eclipse.jgit.storage.file.PackFile; | |||
import org.eclipse.jgit.util.NB; | |||
import org.eclipse.jgit.util.TemporaryBuffer; | |||
import org.eclipse.jgit.util.io.UnionInputStream; | |||
import org.junit.After; | |||
import org.junit.Test; | |||
@@ -177,6 +182,33 @@ public class PackParserTest extends RepositoryTestCase { | |||
p.parse(NullProgressMonitor.INSTANCE); | |||
} | |||
@Test | |||
public void testPackWithTrailingGarbage() throws Exception { | |||
TestRepository d = new TestRepository(db); | |||
RevBlob a = d.blob("a"); | |||
TemporaryBuffer.Heap pack = new TemporaryBuffer.Heap(1024); | |||
packHeader(pack, 1); | |||
pack.write((Constants.OBJ_REF_DELTA) << 4 | 4); | |||
a.copyRawTo(pack); | |||
deflate(pack, new byte[] { 0x1, 0x1, 0x1, 'b' }); | |||
digest(pack); | |||
PackParser p = index(new UnionInputStream( | |||
new ByteArrayInputStream(pack.toByteArray()), | |||
new ByteArrayInputStream(new byte[] { 0x7e }))); | |||
p.setAllowThin(true); | |||
p.setCheckEofAfterPackFooter(true); | |||
try { | |||
p.parse(NullProgressMonitor.INSTANCE); | |||
fail("Pack with trailing garbage was accepted"); | |||
} catch (IOException err) { | |||
assertEquals( | |||
MessageFormat.format(JGitText.get().expectedEOFReceived, "\\x73"), | |||
err.getMessage()); | |||
} | |||
} | |||
private void packHeader(TemporaryBuffer.Heap tinyPack, int cnt) | |||
throws IOException { | |||
final byte[] hdr = new byte[8]; |
@@ -98,6 +98,8 @@ public class CloneCommand implements Callable<Git> { | |||
private boolean cloneAllBranches; | |||
private boolean noCheckout; | |||
private Collection<String> branchesToClone; | |||
/** | |||
@@ -112,7 +114,8 @@ public class CloneCommand implements Callable<Git> { | |||
URIish u = new URIish(uri); | |||
Repository repository = init(u); | |||
FetchResult result = fetch(repository, u); | |||
checkout(repository, result); | |||
if (!noCheckout) | |||
checkout(repository, result); | |||
return new Git(repository); | |||
} catch (IOException ioe) { | |||
throw new JGitInternalException(ioe.getMessage(), ioe); | |||
@@ -140,7 +143,8 @@ public class CloneCommand implements Callable<Git> { | |||
RemoteConfig config = new RemoteConfig(repo.getConfig(), remote); | |||
config.addURI(u); | |||
final String dst = Constants.R_REMOTES + config.getName(); | |||
final String dst = bare ? Constants.R_HEADS : Constants.R_REMOTES | |||
+ config.getName(); | |||
RefSpec refSpec = new RefSpec(); | |||
refSpec = refSpec.setForceUpdate(true); | |||
refSpec = refSpec.setSourceDestination(Constants.R_HEADS + "*", dst + "/*"); //$NON-NLS-1$ //$NON-NLS-2$ | |||
@@ -368,4 +372,16 @@ public class CloneCommand implements Callable<Git> { | |||
return this; | |||
} | |||
/** | |||
* @param noCheckout | |||
* if set to <code>true</code> no branch will be checked out | |||
* after the clone. This enhances performance of the clone | |||
* command when there is no need for a checked out branch. | |||
* @return {@code this} | |||
*/ | |||
public CloneCommand setNoCheckout(boolean noCheckout) { | |||
this.noCheckout = noCheckout; | |||
return this; | |||
} | |||
} |
@@ -43,12 +43,12 @@ | |||
package org.eclipse.jgit.diff; | |||
import java.util.AbstractList; | |||
import java.util.ArrayList; | |||
import java.util.Collection; | |||
/** Specialized list of {@link Edit}s in a document. */ | |||
public class EditList extends AbstractList<Edit> { | |||
public class EditList extends ArrayList<Edit> { | |||
private static final long serialVersionUID = 1L; | |||
/** | |||
* Construct an edit list containing a single edit. | |||
* | |||
@@ -62,11 +62,9 @@ public class EditList extends AbstractList<Edit> { | |||
return res; | |||
} | |||
private final ArrayList<Edit> container; | |||
/** Create a new, empty edit list. */ | |||
public EditList() { | |||
container = new ArrayList<Edit>(); | |||
super(16); | |||
} | |||
/** | |||
@@ -77,53 +75,11 @@ public class EditList extends AbstractList<Edit> { | |||
* added to the list, it will be grown to support them. | |||
*/ | |||
public EditList(int capacity) { | |||
container = new ArrayList<Edit>(capacity); | |||
} | |||
@Override | |||
public int size() { | |||
return container.size(); | |||
} | |||
@Override | |||
public Edit get(final int index) { | |||
return container.get(index); | |||
} | |||
@Override | |||
public Edit set(final int index, final Edit element) { | |||
return container.set(index, element); | |||
} | |||
@Override | |||
public void add(final int index, final Edit element) { | |||
container.add(index, element); | |||
} | |||
@Override | |||
public boolean addAll(Collection<? extends Edit> c) { | |||
return container.addAll(c); | |||
} | |||
@Override | |||
public Edit remove(final int index) { | |||
return container.remove(index); | |||
} | |||
@Override | |||
public int hashCode() { | |||
return container.hashCode(); | |||
} | |||
@Override | |||
public boolean equals(final Object o) { | |||
if (o instanceof EditList) | |||
return container.equals(((EditList) o).container); | |||
return false; | |||
super(capacity); | |||
} | |||
@Override | |||
public String toString() { | |||
return "EditList" + container.toString(); | |||
return "EditList" + super.toString(); | |||
} | |||
} |
@@ -136,6 +136,8 @@ public abstract class PackParser { | |||
private boolean needBaseObjectIds; | |||
private boolean checkEofAfterPackFooter; | |||
private long objectCount; | |||
private PackedObjectInfo[] entries; | |||
@@ -282,6 +284,21 @@ public abstract class PackParser { | |||
this.needBaseObjectIds = b; | |||
} | |||
/** @return true if the EOF should be read from the input after the footer. */ | |||
public boolean isCheckEofAfterPackFooter() { | |||
return checkEofAfterPackFooter; | |||
} | |||
/** | |||
* Ensure EOF is read from the input stream after the footer. | |||
* | |||
* @param b | |||
* true if the EOF should be read; false if it is not checked. | |||
*/ | |||
public void setCheckEofAfterPackFooter(boolean b) { | |||
checkEofAfterPackFooter = b; | |||
} | |||
/** @return the new objects that were sent by the user */ | |||
public ObjectIdSubclassMap<ObjectId> getNewObjectIds() { | |||
if (newObjectIds != null) | |||
@@ -782,6 +799,25 @@ public abstract class PackParser { | |||
System.arraycopy(buf, c, srcHash, 0, 20); | |||
use(20); | |||
// The input stream should be at EOF at this point. We do not support | |||
// yielding back any remaining buffered data after the pack footer, so | |||
// protocols that embed a pack stream are required to either end their | |||
// stream with the pack, or embed the pack with a framing system like | |||
// the SideBandInputStream does. | |||
if (bAvail != 0) | |||
throw new CorruptObjectException(MessageFormat.format( | |||
JGitText.get().expectedEOFReceived, | |||
"\\x" + Integer.toHexString(buf[bOffset] & 0xff))); | |||
if (isCheckEofAfterPackFooter()) { | |||
int eof = in.read(); | |||
if (0 <= eof) | |||
throw new CorruptObjectException(MessageFormat.format( | |||
JGitText.get().expectedEOFReceived, | |||
"\\x" + Integer.toHexString(eof))); | |||
} | |||
if (!Arrays.equals(actHash, srcHash)) | |||
throw new CorruptObjectException( | |||
JGitText.get().corruptObjectPackfileChecksumIncorrect); |
@@ -825,6 +825,7 @@ public class ReceivePack { | |||
parser.setAllowThin(true); | |||
parser.setNeedNewObjectIds(checkReferencedIsReachable); | |||
parser.setNeedBaseObjectIds(checkReferencedIsReachable); | |||
parser.setCheckEofAfterPackFooter(!biDirectionalPipe); | |||
parser.setObjectChecking(isCheckReceivedObjects()); | |||
parser.setLockMessage(lockMsg); | |||
packLock = parser.parse(receiving, resolving); |
@@ -55,6 +55,7 @@ import java.util.Map; | |||
import java.util.Set; | |||
import org.eclipse.jgit.JGitText; | |||
import org.eclipse.jgit.errors.CorruptObjectException; | |||
import org.eclipse.jgit.errors.MissingObjectException; | |||
import org.eclipse.jgit.errors.PackProtocolException; | |||
import org.eclipse.jgit.lib.Constants; | |||
@@ -757,6 +758,16 @@ public class UploadPack { | |||
final boolean sideband = options.contains(OPTION_SIDE_BAND) | |||
|| options.contains(OPTION_SIDE_BAND_64K); | |||
if (!biDirectionalPipe) { | |||
// Ensure the request was fully consumed. Any remaining input must | |||
// be a protocol error. If we aren't at EOF the implementation is broken. | |||
int eof = rawIn.read(); | |||
if (0 <= eof) | |||
throw new CorruptObjectException(MessageFormat.format( | |||
JGitText.get().expectedEOFReceived, | |||
"\\x" + Integer.toHexString(eof))); | |||
} | |||
ProgressMonitor pm = NullProgressMonitor.INSTANCE; | |||
OutputStream packOut = rawOut; | |||
SideBandOutputStream msgOut = null; |