transport: Add ReceiveCommandErrorHandler
This gives a chance to handle an exception for a user. For example, when an IOException is thrown while executing `walk.parseAny(cmd.getNewId())`, it's always handled as REJECTED_MISSING_OBJECT. However, IOException can mean a Git storage IO error. By introducing an error handler class, a user can add a custom error handler for these cases. Change-Id: I3e03a536e1d8e137cb0f6e596d71642e72adde9e Signed-off-by: Masaya Suzuki <masayasuzuki@google.com>
This commit is contained in:
parent
19293add84
commit
a91489f4a8
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* Copyright (c) 2019, Google LLC and others
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Distribution License v. 1.0 which is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
package org.eclipse.jgit.transport;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jgit.errors.MissingObjectException;
|
||||
import org.eclipse.jgit.transport.ReceiveCommand.Result;
|
||||
|
||||
/**
|
||||
* Exception handler for processing {@link ReceiveCommand}.
|
||||
*
|
||||
* @since 5.7
|
||||
*/
|
||||
public interface ReceiveCommandErrorHandler {
|
||||
/**
|
||||
* Handle an exception thrown while validating the new commit ID.
|
||||
*
|
||||
* @param cmd
|
||||
* offending command
|
||||
* @param e
|
||||
* exception thrown
|
||||
*/
|
||||
default void handleNewIdValidationException(ReceiveCommand cmd,
|
||||
IOException e) {
|
||||
cmd.setResult(Result.REJECTED_MISSING_OBJECT, cmd.getNewId().name());
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an exception thrown while validating the old commit ID.
|
||||
*
|
||||
* @param cmd
|
||||
* offending command
|
||||
* @param e
|
||||
* exception thrown
|
||||
*/
|
||||
default void handleOldIdValidationException(ReceiveCommand cmd,
|
||||
IOException e) {
|
||||
cmd.setResult(Result.REJECTED_MISSING_OBJECT, cmd.getOldId().name());
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an exception thrown while checking if the update is fast-forward.
|
||||
*
|
||||
* @param cmd
|
||||
* offending command
|
||||
* @param e
|
||||
* exception thrown
|
||||
*/
|
||||
default void handleFastForwardCheckException(ReceiveCommand cmd,
|
||||
IOException e) {
|
||||
if (e instanceof MissingObjectException) {
|
||||
cmd.setResult(Result.REJECTED_MISSING_OBJECT, e.getMessage());
|
||||
} else {
|
||||
cmd.setResult(Result.REJECTED_OTHER_REASON);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an exception thrown while checking if the update is fast-forward.
|
||||
*
|
||||
* @param cmds
|
||||
* commands being processed
|
||||
* @param e
|
||||
* exception thrown
|
||||
*/
|
||||
default void handleBatchRefUpdateException(List<ReceiveCommand> cmds,
|
||||
IOException e) {
|
||||
for (ReceiveCommand cmd : cmds) {
|
||||
if (cmd.getResult() == Result.NOT_ATTEMPTED) {
|
||||
cmd.reject(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -295,6 +295,10 @@ public Set<String> getCapabilities() {
|
|||
/** Hook to validate the update commands before execution. */
|
||||
private PreReceiveHook preReceive;
|
||||
|
||||
private ReceiveCommandErrorHandler receiveCommandErrorHandler = new ReceiveCommandErrorHandler() {
|
||||
// Use the default implementation.
|
||||
};
|
||||
|
||||
/** Hook to report on the commands after execution. */
|
||||
private PostReceiveHook postReceive;
|
||||
|
||||
|
@ -1020,6 +1024,17 @@ public List<ReceiveCommand> getAllCommands() {
|
|||
return Collections.unmodifiableList(commands);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an error handler for {@link ReceiveCommand}.
|
||||
*
|
||||
* @param receiveCommandErrorHandler
|
||||
* @since 5.7
|
||||
*/
|
||||
public void setReceiveCommandErrorHandler(
|
||||
ReceiveCommandErrorHandler receiveCommandErrorHandler) {
|
||||
this.receiveCommandErrorHandler = receiveCommandErrorHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an error message to the client.
|
||||
* <p>
|
||||
|
@ -1726,16 +1741,16 @@ private void validateCommands() {
|
|||
try {
|
||||
oldObj = walk.parseAny(cmd.getOldId());
|
||||
} catch (IOException e) {
|
||||
cmd.setResult(Result.REJECTED_MISSING_OBJECT,
|
||||
cmd.getOldId().name());
|
||||
receiveCommandErrorHandler
|
||||
.handleOldIdValidationException(cmd, e);
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
newObj = walk.parseAny(cmd.getNewId());
|
||||
} catch (IOException e) {
|
||||
cmd.setResult(Result.REJECTED_MISSING_OBJECT,
|
||||
cmd.getNewId().name());
|
||||
receiveCommandErrorHandler
|
||||
.handleNewIdValidationException(cmd, e);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1743,16 +1758,14 @@ private void validateCommands() {
|
|||
&& newObj instanceof RevCommit) {
|
||||
try {
|
||||
if (walk.isMergedInto((RevCommit) oldObj,
|
||||
(RevCommit) newObj))
|
||||
(RevCommit) newObj)) {
|
||||
cmd.setTypeFastForwardUpdate();
|
||||
else
|
||||
cmd.setType(
|
||||
ReceiveCommand.Type.UPDATE_NONFASTFORWARD);
|
||||
} catch (MissingObjectException e) {
|
||||
cmd.setResult(Result.REJECTED_MISSING_OBJECT,
|
||||
e.getMessage());
|
||||
} else {
|
||||
cmd.setType(ReceiveCommand.Type.UPDATE_NONFASTFORWARD);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
cmd.setResult(Result.REJECTED_OTHER_REASON);
|
||||
receiveCommandErrorHandler
|
||||
.handleFastForwardCheckException(cmd, e);
|
||||
}
|
||||
} else {
|
||||
cmd.setType(ReceiveCommand.Type.UPDATE_NONFASTFORWARD);
|
||||
|
@ -1831,11 +1844,9 @@ private void executeCommands() {
|
|||
try {
|
||||
batch.setPushCertificate(getPushCertificate());
|
||||
batch.execute(walk, updating);
|
||||
} catch (IOException err) {
|
||||
for (ReceiveCommand cmd : toApply) {
|
||||
if (cmd.getResult() == Result.NOT_ATTEMPTED)
|
||||
cmd.reject(err);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
receiveCommandErrorHandler.handleBatchRefUpdateException(toApply,
|
||||
e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue