Log when a webhook is created or updated

This allows admins to monitor various webhooks being added/updated on
a server.

Change-Id: Ie0d1831b715aecf081ef18fe84d6c28a7eabc15b
diff --git a/src/main/java/com/googlesource/gerrit/plugins/webhooks/PluginModule.java b/src/main/java/com/googlesource/gerrit/plugins/webhooks/PluginModule.java
index a4d446f..6a19bcc 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/webhooks/PluginModule.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/webhooks/PluginModule.java
@@ -19,6 +19,7 @@
 
 import com.google.gerrit.extensions.annotations.PluginName;
 import com.google.gerrit.extensions.config.FactoryModule;
+import com.google.gerrit.extensions.events.GitReferenceUpdatedListener;
 import com.google.gerrit.extensions.registration.DynamicSet;
 import com.google.gerrit.server.events.EventListener;
 import com.google.inject.Inject;
@@ -49,6 +50,7 @@
     factory(HttpSession.Factory.class);
 
     DynamicSet.bind(binder(), EventListener.class).to(EventHandler.class);
+    DynamicSet.bind(binder(), GitReferenceUpdatedListener.class).to(WebHookUpdateListener.class);
 
     bind(CloseableHttpClient.class)
         .annotatedWith(Names.named(DEFAULT))
diff --git a/src/main/java/com/googlesource/gerrit/plugins/webhooks/WebHookUpdateListener.java b/src/main/java/com/googlesource/gerrit/plugins/webhooks/WebHookUpdateListener.java
new file mode 100644
index 0000000..0b02e11
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/webhooks/WebHookUpdateListener.java
@@ -0,0 +1,61 @@
+// Copyright (C) 2025 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.googlesource.gerrit.plugins.webhooks;
+
+import com.google.common.flogger.FluentLogger;
+import com.google.gerrit.entities.Project;
+import com.google.gerrit.entities.RefNames;
+import com.google.gerrit.extensions.events.GitReferenceUpdatedListener;
+import com.google.gerrit.server.patch.DiffNotAvailableException;
+import com.google.gerrit.server.patch.DiffOperations;
+import com.google.gerrit.server.patch.DiffOptions;
+import com.google.gerrit.server.patch.filediff.FileDiffOutput;
+import com.google.inject.Inject;
+import java.util.Map;
+import org.eclipse.jgit.lib.ObjectId;
+
+public class WebHookUpdateListener implements GitReferenceUpdatedListener {
+  private static final FluentLogger log = FluentLogger.forEnclosingClass();
+  private final String cfgFileName;
+  private final DiffOperations diffOperations;
+
+  @Inject
+  WebHookUpdateListener(@WebhooksConfigFileName String cfgFileName, DiffOperations diffOperations) {
+    this.cfgFileName = cfgFileName;
+    this.diffOperations = diffOperations;
+  }
+
+  @Override
+  public void onGitReferenceUpdated(Event event) {
+    if (event.getRefName().equals(RefNames.REFS_CONFIG)) {
+      Project.NameKey project = Project.NameKey.parse(event.getProjectName());
+      try {
+        Map<String, FileDiffOutput> diffByFile =
+            diffOperations.listModifiedFilesAgainstParent(
+                project,
+                ObjectId.fromString(event.getNewObjectId()),
+                /* parentNum= */ 0,
+                DiffOptions.DEFAULTS);
+        FileDiffOutput diff = diffByFile.get(cfgFileName);
+        if (diff != null) {
+          log.atInfo().log("Webhook config %s for project %s", diff.changeType(), project.get());
+        }
+      } catch (DiffNotAvailableException e) {
+        log.atSevere().withCause(e).log(
+            "Unable to get diff for %s in %s", event.getNewObjectId(), event.getProjectName());
+      }
+    }
+  }
+}