]> source.dussan.org Git - jgit.git/commitdiff
transport: Add ReceiveCommandErrorHandler 57/152357/2
authorMasaya Suzuki <masayasuzuki@google.com>
Fri, 8 Nov 2019 02:22:17 +0000 (18:22 -0800)
committerMasaya Suzuki <masayasuzuki@google.com>
Mon, 2 Dec 2019 20:49:15 +0000 (12:49 -0800)
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>
org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceiveCommandErrorHandler.java [new file with mode: 0644]
org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java

diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceiveCommandErrorHandler.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceiveCommandErrorHandler.java
new file mode 100644 (file)
index 0000000..d9a1486
--- /dev/null
@@ -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);
+                       }
+               }
+       }
+}
index 8cafe775a399ed737162d6806a83dd763eb090e7..523dbecd21881d66fd831527f16ca45ad6dcb4c4 100644 (file)
@@ -295,6 +295,10 @@ public class ReceivePack {
        /** 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 class ReceivePack {
                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 @@ public class ReceivePack {
                                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 @@ public class ReceivePack {
                                                && 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 @@ public class ReceivePack {
                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);
                }
        }