Browse Source

Merge branch 'stable-1.0'

* 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: I6340d551482e1dda01f82496296d2038b07fa68b
tags/v1.1.0.201109011030-rc2
Shawn O. Pearce 13 years ago
parent
commit
690c268c79

+ 0
- 6
.eclipse_iplog View File

@@ -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

+ 11
- 0
org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/LocalDiskRepositoryTestCase.java View File

@@ -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
*

+ 33
- 4
org.eclipse.jgit.pgm/jgit.sh View File

@@ -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

+ 17
- 0
org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/spi/RepositoryIndexTable.java View File

@@ -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;
}

+ 14
- 0
org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/spi/cache/CacheRepositoryIndexTable.java View File

@@ -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();
}
}
}

+ 12
- 0
org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/spi/memory/MemRepositoryIndexTable.java View File

@@ -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()));
}
}

+ 18
- 7
org.eclipse.jgit.storage.dht/src/org/eclipse/jgit/storage/dht/spi/util/AbstractWriteBuffer.java View File

@@ -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;
}


+ 77
- 2
org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CloneCommandTest.java View File

@@ -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()));

+ 3
- 2
org.eclipse.jgit.test/tst/org/eclipse/jgit/api/GitConstructionTest.java View File

@@ -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());

+ 2
- 0
org.eclipse.jgit.test/tst/org/eclipse/jgit/api/InitCommandTest.java View File

@@ -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) {

+ 4
- 0
org.eclipse.jgit.test/tst/org/eclipse/jgit/api/LsRemoteCommandTest.java View File

@@ -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);

+ 32
- 0
org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PackParserTest.java View File

@@ -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];

+ 18
- 2
org.eclipse.jgit/src/org/eclipse/jgit/api/CloneCommand.java View File

@@ -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;
}

}

+ 6
- 50
org.eclipse.jgit/src/org/eclipse/jgit/diff/EditList.java View File

@@ -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();
}
}

+ 36
- 0
org.eclipse.jgit/src/org/eclipse/jgit/transport/PackParser.java View File

@@ -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);

+ 1
- 0
org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java View File

@@ -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);

+ 11
- 0
org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java View File

@@ -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;

Loading…
Cancel
Save