From d8d649a43eb6b72f97979112066378748d0cabaf Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Tue, 22 May 2012 16:22:41 -0700 Subject: [PATCH] Expose ReceiveCommand.updateType to check for UPDATE_NONFASTFORWARD When a command's type is UPDATE, JGit might not yet be sure if it is a fast-forward or not. Expose a utility method to compute the exact type by performing the merge base test, allowing the type to be switched to UPDATE_NONFASTFORWARD if old ObjectId is not contained in new ObjectId. BaseReceivePack already does this test when validating the incoming command list, so provide a package level backdoor to set the type and avoid needing to redo the merge test later. Change-Id: If5a6fcc50dc4d6f96e9bb0bb7bba15ebe8b86377 --- .../jgit/transport/BaseReceivePack.java | 10 ++--- .../jgit/transport/ReceiveCommand.java | 41 +++++++++++++++++++ 2 files changed, 46 insertions(+), 5 deletions(-) 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 a0b1c58c6..9d72ef868 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BaseReceivePack.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BaseReceivePack.java @@ -1086,11 +1086,11 @@ public abstract class BaseReceivePack { if (oldObj instanceof RevCommit && newObj instanceof RevCommit) { try { - if (!walk.isMergedInto((RevCommit) oldObj, - (RevCommit) newObj)) { - cmd - .setType(ReceiveCommand.Type.UPDATE_NONFASTFORWARD); - } + if (walk.isMergedInto((RevCommit) oldObj, + (RevCommit) newObj)) + cmd.setTypeFastForwardUpdate(); + else + cmd.setType(ReceiveCommand.Type.UPDATE_NONFASTFORWARD); } catch (MissingObjectException e) { cmd.setResult(Result.REJECTED_MISSING_OBJECT, e .getMessage()); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceiveCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceiveCommand.java index 96814c85a..26bbcdcbc 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceiveCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceiveCommand.java @@ -49,9 +49,13 @@ import java.util.ArrayList; import java.util.List; import org.eclipse.jgit.internal.JGitText; +import org.eclipse.jgit.lib.AnyObjectId; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.RefUpdate; +import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.jgit.revwalk.RevObject; +import org.eclipse.jgit.revwalk.RevWalk; /** * A command being processed by {@link BaseReceivePack}. @@ -157,6 +161,8 @@ public class ReceiveCommand { private String message; + private boolean typeIsCorrect; + /** * Create a new command for {@link BaseReceivePack}. * @@ -264,6 +270,36 @@ public class ReceiveCommand { message = m; } + /** + * Update the type of this command by checking for fast-forward. + *

+ * If the command's current type is UPDATE, a merge test will be performed + * using the supplied RevWalk to determine if {@link #getOldId()} is fully + * merged into {@link #getNewId()}. If some commits are not merged the + * update type is changed to {@link Type#UPDATE_NONFASTFORWARD}. + * + * @param walk + * an instance to perform the merge test with. The caller must + * allocate and release this object. + * @throws IOException + * either oldId or newId is not accessible in the repository + * used by the RevWalk. This usually indicates data corruption, + * and the command cannot be processed. + */ + public void updateType(RevWalk walk) throws IOException { + if (typeIsCorrect) + return; + if (type == Type.UPDATE && !AnyObjectId.equals(oldId, newId)) { + RevObject o = walk.parseAny(oldId); + RevObject n = walk.parseAny(newId); + if (!(o instanceof RevCommit) + || !(n instanceof RevCommit) + || !walk.isMergedInto((RevCommit) o, (RevCommit) n)) + setType(Type.UPDATE_NONFASTFORWARD); + } + typeIsCorrect = true; + } + /** * Execute this command during a receive-pack session. *

@@ -314,6 +350,11 @@ public class ReceiveCommand { type = t; } + void setTypeFastForwardUpdate() { + type = Type.UPDATE; + typeIsCorrect = true; + } + private void setResult(final RefUpdate.Result r) { switch (r) { case NOT_ATTEMPTED: