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. */
|
/** Hook to validate the update commands before execution. */
|
||||||
private PreReceiveHook preReceive;
|
private PreReceiveHook preReceive;
|
||||||
|
|
||||||
|
private ReceiveCommandErrorHandler receiveCommandErrorHandler = new ReceiveCommandErrorHandler() {
|
||||||
|
// Use the default implementation.
|
||||||
|
};
|
||||||
|
|
||||||
/** Hook to report on the commands after execution. */
|
/** Hook to report on the commands after execution. */
|
||||||
private PostReceiveHook postReceive;
|
private PostReceiveHook postReceive;
|
||||||
|
|
||||||
|
@ -1020,6 +1024,17 @@ public List<ReceiveCommand> getAllCommands() {
|
||||||
return Collections.unmodifiableList(commands);
|
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.
|
* Send an error message to the client.
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -1726,16 +1741,16 @@ private void validateCommands() {
|
||||||
try {
|
try {
|
||||||
oldObj = walk.parseAny(cmd.getOldId());
|
oldObj = walk.parseAny(cmd.getOldId());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
cmd.setResult(Result.REJECTED_MISSING_OBJECT,
|
receiveCommandErrorHandler
|
||||||
cmd.getOldId().name());
|
.handleOldIdValidationException(cmd, e);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
newObj = walk.parseAny(cmd.getNewId());
|
newObj = walk.parseAny(cmd.getNewId());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
cmd.setResult(Result.REJECTED_MISSING_OBJECT,
|
receiveCommandErrorHandler
|
||||||
cmd.getNewId().name());
|
.handleNewIdValidationException(cmd, e);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1743,16 +1758,14 @@ private void validateCommands() {
|
||||||
&& newObj instanceof RevCommit) {
|
&& newObj instanceof RevCommit) {
|
||||||
try {
|
try {
|
||||||
if (walk.isMergedInto((RevCommit) oldObj,
|
if (walk.isMergedInto((RevCommit) oldObj,
|
||||||
(RevCommit) newObj))
|
(RevCommit) newObj)) {
|
||||||
cmd.setTypeFastForwardUpdate();
|
cmd.setTypeFastForwardUpdate();
|
||||||
else
|
} else {
|
||||||
cmd.setType(
|
cmd.setType(ReceiveCommand.Type.UPDATE_NONFASTFORWARD);
|
||||||
ReceiveCommand.Type.UPDATE_NONFASTFORWARD);
|
}
|
||||||
} catch (MissingObjectException e) {
|
|
||||||
cmd.setResult(Result.REJECTED_MISSING_OBJECT,
|
|
||||||
e.getMessage());
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
cmd.setResult(Result.REJECTED_OTHER_REASON);
|
receiveCommandErrorHandler
|
||||||
|
.handleFastForwardCheckException(cmd, e);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
cmd.setType(ReceiveCommand.Type.UPDATE_NONFASTFORWARD);
|
cmd.setType(ReceiveCommand.Type.UPDATE_NONFASTFORWARD);
|
||||||
|
@ -1831,11 +1844,9 @@ private void executeCommands() {
|
||||||
try {
|
try {
|
||||||
batch.setPushCertificate(getPushCertificate());
|
batch.setPushCertificate(getPushCertificate());
|
||||||
batch.execute(walk, updating);
|
batch.execute(walk, updating);
|
||||||
} catch (IOException err) {
|
} catch (IOException e) {
|
||||||
for (ReceiveCommand cmd : toApply) {
|
receiveCommandErrorHandler.handleBatchRefUpdateException(toApply,
|
||||||
if (cmd.getResult() == Result.NOT_ATTEMPTED)
|
e);
|
||||||
cmd.reject(err);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue