Add hook to allow manifest update to be triggered externally
This allow the plugin to generate snapshot manifest even when the
underlying git repositories were updated outside of Gerrit.
(Example: when a project hosted by Gerrit is a mirror of an upstream
project and it is periodically fetch by an external script. RefUpdated
event is not available from Gerrit in this case.)
Change-Id: Ie119ad393fd51d6aba4679973c0b7d9db3fbde47
diff --git a/src/main/java/com/amd/gerrit/plugins/manifestsubscription/ManifestSubscription.java b/src/main/java/com/amd/gerrit/plugins/manifestsubscription/ManifestSubscription.java
index ed72252..29699e3 100644
--- a/src/main/java/com/amd/gerrit/plugins/manifestsubscription/ManifestSubscription.java
+++ b/src/main/java/com/amd/gerrit/plugins/manifestsubscription/ManifestSubscription.java
@@ -137,7 +137,7 @@
String projectName = event.getProjectName();
String refName = event.getRefName();
String branchName = refName.startsWith("refs/heads/") ?
- refName.substring(11) : "";
+ refName.substring(11) : refName;
ProjectBranchKey pbKey = new ProjectBranchKey(projectName, branchName);
if (event.getNewObjectId().equals(ObjectId.zeroId().toString())) {
@@ -154,58 +154,59 @@
} else if (subscribedRepos.containsRow(pbKey)) {
//updates in subscribed repos
-
- // Manifest store and branch
- Map<String, Map<String, Set<
- com.amd.gerrit.plugins.manifestsubscription.manifest.Project>>>
- destinations = subscribedRepos.row(pbKey);
-
- for (String store : destinations.keySet()) {
- for (String storeBranch : destinations.get(store).keySet()) {
- Set<com.amd.gerrit.plugins.manifestsubscription.manifest.Project> ps
- = destinations.get(store).get(storeBranch);
-
- Manifest manifest = manifestStores.get(store, storeBranch);
- String manifestSrc = manifestSource.get(store, storeBranch);
- StringBuilder extraCommitMsg = new StringBuilder();
-
- Project.NameKey p = new Project.NameKey(projectName);
- try (Repository r = gitRepoManager.openRepository(p);
- RevWalk walk = new RevWalk(r)) {
-
- RevCommit c = walk.parseCommit(
- ObjectId.fromString(event.getNewObjectId()));
-
- extraCommitMsg.append(event.getNewObjectId().substring(0,7));
- extraCommitMsg.append(" ");
- extraCommitMsg.append(projectName);
- extraCommitMsg.append(" ");
- extraCommitMsg.append(c.getShortMessage());
- } catch (IOException e) {
- e.printStackTrace();
- }
-
- // these are project from the above manifest previously
- // cached in the lookup table
- for (com.amd.gerrit.plugins.manifestsubscription.manifest.Project
- updateProject : ps) {
- updateProject.setRevision(event.getNewObjectId());
- }
-
- try {
- Utilities.updateManifest(gitRepoManager, metaDataUpdateFactory,
- changeHooks, store, STORE_BRANCH_PREFIX + storeBranch,
- manifest, manifestSrc, extraCommitMsg.toString(), null);
- } catch (JAXBException | IOException e) {
- e.printStackTrace();
- }
-
- }
- }
-
+ processRepoChange(event.getNewObjectId(), projectName, pbKey);
}
+ }
+ void processRepoChange(String refUpdatedHash, String projectName,
+ ProjectBranchKey pbKey) {
+ // Manifest store and branch
+ Map<String, Map<String, Set<
+ com.amd.gerrit.plugins.manifestsubscription.manifest.Project>>>
+ destinations = subscribedRepos.row(pbKey);
+ for (String store : destinations.keySet()) {
+ for (String storeBranch : destinations.get(store).keySet()) {
+ Set<com.amd.gerrit.plugins.manifestsubscription.manifest.Project> ps
+ = destinations.get(store).get(storeBranch);
+
+ Manifest manifest = manifestStores.get(store, storeBranch);
+ String manifestSrc = manifestSource.get(store, storeBranch);
+ StringBuilder extraCommitMsg = new StringBuilder();
+
+ Project.NameKey p = new Project.NameKey(projectName);
+ try (Repository r = gitRepoManager.openRepository(p);
+ RevWalk walk = new RevWalk(r)) {
+
+ RevCommit c = walk.parseCommit(
+ ObjectId.fromString(refUpdatedHash));
+
+ extraCommitMsg.append(refUpdatedHash.substring(0,7));
+ extraCommitMsg.append(" ");
+ extraCommitMsg.append(projectName);
+ extraCommitMsg.append(" ");
+ extraCommitMsg.append(c.getShortMessage());
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ // these are project from the above manifest previously
+ // cached in the lookup table
+ for (com.amd.gerrit.plugins.manifestsubscription.manifest.Project
+ updateProject : ps) {
+ updateProject.setRevision(refUpdatedHash);
+ }
+
+ try {
+ Utilities.updateManifest(gitRepoManager, metaDataUpdateFactory,
+ changeHooks, store, STORE_BRANCH_PREFIX + storeBranch,
+ manifest, manifestSrc, extraCommitMsg.toString(), null);
+ } catch (JAXBException | IOException e) {
+ e.printStackTrace();
+ }
+
+ }
+ }
}
private void updateProjectRev(String projectName, String branch, String rev,
diff --git a/src/main/java/com/amd/gerrit/plugins/manifestsubscription/SshModule.java b/src/main/java/com/amd/gerrit/plugins/manifestsubscription/SshModule.java
index c514182..3ea815a 100644
--- a/src/main/java/com/amd/gerrit/plugins/manifestsubscription/SshModule.java
+++ b/src/main/java/com/amd/gerrit/plugins/manifestsubscription/SshModule.java
@@ -22,5 +22,6 @@
command(ShowSubscriptionCommand.class);
command(BranchManifestCommand.class);
command(TagManifestCommand.class);
+ command(TriggerManifestUpdateCommand.class);
}
}
diff --git a/src/main/java/com/amd/gerrit/plugins/manifestsubscription/TriggerManifestUpdateCommand.java b/src/main/java/com/amd/gerrit/plugins/manifestsubscription/TriggerManifestUpdateCommand.java
new file mode 100644
index 0000000..36445ca
--- /dev/null
+++ b/src/main/java/com/amd/gerrit/plugins/manifestsubscription/TriggerManifestUpdateCommand.java
@@ -0,0 +1,53 @@
+// Copyright (C) 2017 Advanced Micro Devices, Inc. All rights reserved.
+//
+// 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.amd.gerrit.plugins.manifestsubscription;
+
+import com.google.gerrit.common.data.GlobalCapability;
+import com.google.gerrit.extensions.annotations.RequiresCapability;
+import com.google.gerrit.server.git.GitRepositoryManager;
+import com.google.gerrit.sshd.CommandMetaData;
+import com.google.gerrit.sshd.SshCommand;
+import com.google.inject.Inject;
+import org.kohsuke.args4j.Option;
+
+@RequiresCapability(GlobalCapability.ADMINISTRATE_SERVER)
+@CommandMetaData(name = "project-trigger", description = "Trigger snapshot manifest update for externally updated project")
+public class TriggerManifestUpdateCommand extends SshCommand {
+
+ @Inject
+ private ManifestSubscription manifestSubscription;
+
+ @Inject
+ private GitRepositoryManager gitRepositoryManager;
+
+ @Option(name = "-b", aliases = {"--project-branch"},
+ usage = "", required = true)
+ private String projectBranch;
+
+ @Option(name = "-n", aliases = {"--project-name"},
+ usage = "", required = true)
+ private String projectName;
+
+ @Option(name = "-r", aliases = {"--project-hash"},
+ usage = "", required = true)
+ private String projectHash;
+
+ @Override
+ protected void run() {
+ Utilities.triggerManifestUpdate(gitRepositoryManager, manifestSubscription,
+ projectHash, projectName, projectBranch,
+ stdout, false);
+ }
+}
diff --git a/src/main/java/com/amd/gerrit/plugins/manifestsubscription/Utilities.java b/src/main/java/com/amd/gerrit/plugins/manifestsubscription/Utilities.java
index 850507b..92a1a82 100644
--- a/src/main/java/com/amd/gerrit/plugins/manifestsubscription/Utilities.java
+++ b/src/main/java/com/amd/gerrit/plugins/manifestsubscription/Utilities.java
@@ -16,7 +16,6 @@
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableCollection;
-import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableTable;
import com.google.common.collect.Maps;
import com.google.gerrit.common.ChangeHooks;
@@ -426,4 +425,52 @@
}
}
+
+ static void triggerManifestUpdate(GitRepositoryManager gitRepositoryManager,
+ ManifestSubscription manifestSubscription,
+ String refUpdatedHash, String projectName, String projectBranch,
+ Writer output, boolean inJSON) {
+ PrintWriter writer;
+ if (output instanceof PrintWriter) {
+ writer = (PrintWriter) output;
+ } else {
+ writer = new PrintWriter(output);
+ }
+
+ projectBranch = projectBranch.startsWith("refs/heads/") ?
+ projectBranch.substring(11) : projectBranch;
+
+ if (!refUpdatedHash.matches("[0-9a-fA-F]+")) {
+ writer.println("Invalid project-hash");
+ return;
+ }
+
+ ProjectBranchKey pbKey = new ProjectBranchKey(projectName, projectBranch);
+ if (!manifestSubscription.getSubscribedProjects().contains(pbKey)) {
+ writer.println(
+ String.format("Project '%s' with branch '%s' is not being monitored for manifest update",
+ projectName, projectBranch));
+ return;
+ }
+
+ try (Repository project =
+ gitRepositoryManager.openRepository(
+ new Project.NameKey(projectName))) {
+ ObjectId commit = project.resolve(refUpdatedHash);
+ refUpdatedHash = ObjectId.toString(commit);
+ } catch (Exception e) {
+ e.printStackTrace();
+ writer.println(e.toString());
+ writer.println(
+ String.format("Project '%s' with hash '%s' not found.",
+ projectName, refUpdatedHash));
+ return;
+ }
+
+ manifestSubscription.processRepoChange(refUpdatedHash, projectName, pbKey);
+ writer.println("Manifest update triggered by:");
+ writer.println(" - Project: " + projectName);
+ writer.println(" - Branch: " + projectBranch);
+ writer.println(" - Updated hash: " + refUpdatedHash);
+ }
}
diff --git a/src/main/resources/Documentation/cmd-project-trigger.md b/src/main/resources/Documentation/cmd-project-trigger.md
new file mode 100644
index 0000000..90c3570
--- /dev/null
+++ b/src/main/resources/Documentation/cmd-project-trigger.md
@@ -0,0 +1,39 @@
+@PLUGIN@ project-trigger
+========================
+
+NAME
+----
+@PLUGIN@ project-trigger - Trigger snapshot manifest update for externally updated project
+
+SYNOPSIS
+--------
+```
+ssh -p @SSH_PORT@ @SSH_HOST@ @PLUGIN@ project-trigger
+ {-n/--project-name <updated project name>}
+ {-b/--project-branch <updated project branch>}
+ {-r/--project-hash <git commit hash that was updated to>}
+ [--help]
+```
+
+ACCESS
+------
+Caller must be a member of the privileged 'Administrators' group
+
+OPTIONS
+-------
+
+`-n/--project-name <updated project name>`
+`-b/--project-branch <updated project branch>`
+`-r/--project-hash <git commit hash that was updated to>`
+: This specify the project on Gerrit that was updated outside of Gerrit
+(by a pull script directly on the server, for example.)
+
+EXAMPLE
+-------
+```
+ssh -p @SSH_PORT@ @SSH_HOST@ @PLUGIN@ project-trigger -n demo/project2 -b master -r 5f51acb585b6a
+```
+
+[Back to @PLUGIN@ documentation index][index]
+
+[index]: index.html
\ No newline at end of file