diff options
author | Stefan Beller <sbeller@google.com> | 2014-11-07 18:51:18 -0800 |
---|---|---|
committer | Stefan Beller <sbeller@google.com> | 2014-11-07 18:51:18 -0800 |
commit | 88c1b82e7a27a5e25c9be9cba246f076825da4c6 (patch) | |
tree | a6d0ffad3c3ea0c5b19cfe77fb0e20fd117c4d44 /org.eclipse.jgit | |
parent | 2532c28cb93ccb8e674ef374f08fb3bf246c353b (diff) | |
download | jgit-88c1b82e7a27a5e25c9be9cba246f076825da4c6.tar.gz jgit-88c1b82e7a27a5e25c9be9cba246f076825da4c6.zip |
Implement atomic refs update, if possible by database
Inspired by the series[1], this implements the possibility to
have atomic ref transactions.
If the database supports atomic ref update capabilities, we'll
advertise these. If the client wishes to use this feature, either
all refs will be updated or none at all.
[1] http://thread.gmane.org/gmane.comp.version-control.git/259019/focus=259024
Change-Id: I7b5d19c21f3b5557e41b9bcb5d359a65ff1a493d
Signed-off-by: Stefan Beller <sbeller@google.com>
Diffstat (limited to 'org.eclipse.jgit')
6 files changed, 45 insertions, 0 deletions
diff --git a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties index 45021e847c..524aa3e6ac 100644 --- a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties +++ b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties @@ -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} diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java index f2a1b948cc..dd1be0d5f7 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java @@ -556,6 +556,7 @@ public class JGitText extends TranslationBundle { /***/ public String tagAlreadyExists; /***/ public String tagNameInvalid; /***/ public String tagOnRepoWithoutHEADCurrentlyNotSupported; + /***/ public String transactionAborted; /***/ public String theFactoryMustNotBeNull; /***/ public String timerAlreadyTerminated; /***/ public String topologicalSortRequired; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDatabase.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDatabase.java index 682cac162c..0458ac4911 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDatabase.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDatabase.java @@ -197,6 +197,14 @@ public abstract class RefDatabase { } /** + * @return if the database performs {@code newBatchUpdate()} as an atomic + * transaction. + */ + public boolean performsAtomicTransactions() { + return false; + } + + /** * Read a single reference. * <p> * Aside from taking advantage of {@link #SEARCH_PATH}, this method may be diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BaseReceivePack.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BaseReceivePack.java index 72c1697593..475ba35283 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BaseReceivePack.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BaseReceivePack.java @@ -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 abstract class BaseReceivePack { 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 @@ public abstract class BaseReceivePack { } } + /** @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. * diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/GitProtocolConstants.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/GitProtocolConstants.java index c0a70d0437..43fd07944c 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/GitProtocolConstants.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/GitProtocolConstants.java @@ -130,6 +130,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. * * @since 3.2 diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java index 4d931dd5df..e5eb822418 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java @@ -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 @@ public class ReceivePack extends BaseReceivePack { } 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(); |