Merge "Implement atomic refs update, if possible by database"

This commit is contained in:
Shawn Pearce 2014-11-07 22:04:33 -05:00 committed by Gerrit Code Review @ Eclipse.org
commit cba3060969
6 changed files with 45 additions and 0 deletions

View File

@ -500,6 +500,7 @@ tagOnRepoWithoutHEADCurrentlyNotSupported=Tag on repository without HEAD current
theFactoryMustNotBeNull=The factory must not be null
timerAlreadyTerminated=Timer already terminated
topologicalSortRequired=Topological sort required.
transactionAborted=transaction aborted
transportExceptionBadRef=Empty ref: {0}: {1}
transportExceptionEmptyRef=Empty ref: {0}
transportExceptionInvalid=Invalid {0} {1}:{2}

View File

@ -556,6 +556,7 @@ public static JGitText get() {
/***/ public String tagAlreadyExists;
/***/ public String tagNameInvalid;
/***/ public String tagOnRepoWithoutHEADCurrentlyNotSupported;
/***/ public String transactionAborted;
/***/ public String theFactoryMustNotBeNull;
/***/ public String timerAlreadyTerminated;
/***/ public String topologicalSortRequired;

View File

@ -196,6 +196,14 @@ public BatchRefUpdate newBatchUpdate() {
return new BatchRefUpdate(this);
}
/**
* @return if the database performs {@code newBatchUpdate()} as an atomic
* transaction.
*/
public boolean performsAtomicTransactions() {
return false;
}
/**
* Read a single reference.
* <p>

View File

@ -43,6 +43,7 @@
package org.eclipse.jgit.transport;
import static org.eclipse.jgit.transport.GitProtocolConstants.CAPABILITY_ATOMIC;
import static org.eclipse.jgit.transport.GitProtocolConstants.CAPABILITY_DELETE_REFS;
import static org.eclipse.jgit.transport.GitProtocolConstants.CAPABILITY_OFS_DELTA;
import static org.eclipse.jgit.transport.GitProtocolConstants.CAPABILITY_REPORT_STATUS;
@ -908,6 +909,8 @@ public void sendAdvertisedRefs(final RefAdvertiser adv)
adv.advertiseCapability(CAPABILITY_SIDE_BAND_64K);
adv.advertiseCapability(CAPABILITY_DELETE_REFS);
adv.advertiseCapability(CAPABILITY_REPORT_STATUS);
if (db.getRefDatabase().performsAtomicTransactions())
adv.advertiseCapability(CAPABILITY_ATOMIC);
if (allowOfsDelta)
adv.advertiseCapability(CAPABILITY_OFS_DELTA);
adv.send(getAdvertisedOrDefaultRefs());
@ -1251,6 +1254,23 @@ protected void validateCommands() {
}
}
/** @return if any commands have been rejected so far. */
protected boolean anyRejects() {
for (ReceiveCommand cmd : commands) {
if (cmd.getResult() != Result.NOT_ATTEMPTED && cmd.getResult() != Result.OK)
return true;
}
return false;
}
/** Set the result to fail for any command that was not processed yet. */
protected void failPendingCommands() {
for (ReceiveCommand cmd : commands) {
if (cmd.getResult() == Result.NOT_ATTEMPTED)
cmd.setResult(Result.REJECTED_OTHER_REASON, JGitText.get().transactionAborted);
}
}
/**
* Filter the list of commands according to result.
*

View File

@ -129,6 +129,14 @@ public class GitProtocolConstants {
*/
public static final String OPTION_ALLOW_TIP_SHA1_IN_WANT = "allow-tip-sha1-in-want"; //$NON-NLS-1$
/**
* The client supports atomic pushes. If this option is used, the server
* will update all refs within one atomic transaction.
*
* @since 3.6
*/
public static final String CAPABILITY_ATOMIC = "atomic-push"; //$NON-NLS-1$
/**
* The client expects a status report after the server processes the pack.
*

View File

@ -43,6 +43,7 @@
package org.eclipse.jgit.transport;
import static org.eclipse.jgit.transport.GitProtocolConstants.CAPABILITY_ATOMIC;
import static org.eclipse.jgit.transport.GitProtocolConstants.CAPABILITY_REPORT_STATUS;
import java.io.IOException;
@ -199,8 +200,14 @@ private void service() throws IOException {
}
if (unpackError == null) {
boolean atomic = isCapabilityEnabled(CAPABILITY_ATOMIC);
validateCommands();
if (atomic && anyRejects())
failPendingCommands();
preReceive.onPreReceive(this, filterCommands(Result.NOT_ATTEMPTED));
if (atomic && anyRejects())
failPendingCommands();
executeCommands();
}
unlockPack();