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
This commit is contained in:
Shawn O. Pearce 2012-05-22 16:22:41 -07:00
parent 04fa307a70
commit d8d649a43e
2 changed files with 46 additions and 5 deletions

View File

@ -1086,11 +1086,11 @@ protected void validateCommands() {
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());

View File

@ -49,9 +49,13 @@
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 static List<ReceiveCommand> filter(List<ReceiveCommand> commands,
private String message;
private boolean typeIsCorrect;
/**
* Create a new command for {@link BaseReceivePack}.
*
@ -264,6 +270,36 @@ public void setResult(final Result s, final String m) {
message = m;
}
/**
* Update the type of this command by checking for fast-forward.
* <p>
* 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.
* <p>
@ -314,6 +350,11 @@ void setType(final Type t) {
type = t;
}
void setTypeFastForwardUpdate() {
type = Type.UPDATE;
typeIsCorrect = true;
}
private void setResult(final RefUpdate.Result r) {
switch (r) {
case NOT_ATTEMPTED: