summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShawn Pearce <sop@google.com>2014-11-07 22:04:33 -0500
committerGerrit Code Review @ Eclipse.org <gerrit@eclipse.org>2014-11-07 22:04:34 -0500
commitcba306096967a3cd85f76838b1efd5e9799cb0c0 (patch)
treeda6a8bae27f41414f635feb01966e81fc60d68f6
parent8456927b1bbb344cc6a768b1f491dddd50d4ce7c (diff)
parent88c1b82e7a27a5e25c9be9cba246f076825da4c6 (diff)
downloadjgit-cba306096967a3cd85f76838b1efd5e9799cb0c0.tar.gz
jgit-cba306096967a3cd85f76838b1efd5e9799cb0c0.zip
Merge "Implement atomic refs update, if possible by database"
-rw-r--r--org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties1
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java1
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/RefDatabase.java8
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/BaseReceivePack.java20
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/GitProtocolConstants.java8
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java7
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();