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