Add an event for the update of a project's HEAD
When the HEAD of a project is updated Gerrit now informs about this by sending an event. Plugins can implement a listener to be notified about this event. Having this new event enables the replication plugin to replicate HEAD updates. Change-Id: I4dd7969020880190668190e8345197a23dbc92f1 Signed-off-by: Edwin Kempin <edwin.kempin@sap.com>
This commit is contained in:
		| @@ -364,6 +364,10 @@ Project creation | |||||||
| + | + | ||||||
| Project deletion | Project deletion | ||||||
|  |  | ||||||
|  | * `com.google.gerrit.extensions.events.HeadUpdatedListener`: | ||||||
|  | + | ||||||
|  | Update of HEAD on a project | ||||||
|  |  | ||||||
| [[stream-events]] | [[stream-events]] | ||||||
| Sending Events to the Events Stream | Sending Events to the Events Stream | ||||||
| ----------------------------------- | ----------------------------------- | ||||||
|   | |||||||
| @@ -0,0 +1,29 @@ | |||||||
|  | // Copyright (C) 2013 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.google.gerrit.extensions.events; | ||||||
|  |  | ||||||
|  | import com.google.gerrit.extensions.annotations.ExtensionPoint; | ||||||
|  |  | ||||||
|  | /** Notified whenever the HEAD of a project is updated. */ | ||||||
|  | @ExtensionPoint | ||||||
|  | public interface HeadUpdatedListener { | ||||||
|  |   public interface Event { | ||||||
|  |     String getProjectName(); | ||||||
|  |     String getOldHeadName(); | ||||||
|  |     String getNewHeadName(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   void onHeadUpdated(Event event); | ||||||
|  | } | ||||||
| @@ -23,6 +23,7 @@ import com.google.gerrit.extensions.config.CapabilityDefinition; | |||||||
| import com.google.gerrit.extensions.config.DownloadCommand; | import com.google.gerrit.extensions.config.DownloadCommand; | ||||||
| import com.google.gerrit.extensions.config.DownloadScheme; | import com.google.gerrit.extensions.config.DownloadScheme; | ||||||
| import com.google.gerrit.extensions.events.GitReferenceUpdatedListener; | import com.google.gerrit.extensions.events.GitReferenceUpdatedListener; | ||||||
|  | import com.google.gerrit.extensions.events.HeadUpdatedListener; | ||||||
| import com.google.gerrit.extensions.events.LifecycleListener; | import com.google.gerrit.extensions.events.LifecycleListener; | ||||||
| import com.google.gerrit.extensions.events.NewProjectCreatedListener; | import com.google.gerrit.extensions.events.NewProjectCreatedListener; | ||||||
| import com.google.gerrit.extensions.events.ProjectDeletedListener; | import com.google.gerrit.extensions.events.ProjectDeletedListener; | ||||||
| @@ -241,6 +242,7 @@ public class GerritGlobalModule extends FactoryModule { | |||||||
|     DynamicSet.setOf(binder(), GitReferenceUpdatedListener.class); |     DynamicSet.setOf(binder(), GitReferenceUpdatedListener.class); | ||||||
|     DynamicSet.setOf(binder(), NewProjectCreatedListener.class); |     DynamicSet.setOf(binder(), NewProjectCreatedListener.class); | ||||||
|     DynamicSet.setOf(binder(), ProjectDeletedListener.class); |     DynamicSet.setOf(binder(), ProjectDeletedListener.class); | ||||||
|  |     DynamicSet.setOf(binder(), HeadUpdatedListener.class); | ||||||
|     DynamicSet.bind(binder(), GitReferenceUpdatedListener.class).to(ChangeCache.class); |     DynamicSet.bind(binder(), GitReferenceUpdatedListener.class).to(ChangeCache.class); | ||||||
|     DynamicSet.setOf(binder(), ChangeListener.class); |     DynamicSet.setOf(binder(), ChangeListener.class); | ||||||
|     DynamicSet.setOf(binder(), CommitValidationListener.class); |     DynamicSet.setOf(binder(), CommitValidationListener.class); | ||||||
|   | |||||||
| @@ -15,6 +15,8 @@ | |||||||
| package com.google.gerrit.server.project; | package com.google.gerrit.server.project; | ||||||
|  |  | ||||||
| import com.google.common.base.Strings; | import com.google.common.base.Strings; | ||||||
|  | import com.google.gerrit.extensions.events.HeadUpdatedListener; | ||||||
|  | import com.google.gerrit.extensions.registration.DynamicSet; | ||||||
| import com.google.gerrit.extensions.restapi.BadRequestException; | import com.google.gerrit.extensions.restapi.BadRequestException; | ||||||
| import com.google.gerrit.extensions.restapi.DefaultInput; | import com.google.gerrit.extensions.restapi.DefaultInput; | ||||||
| import com.google.gerrit.extensions.restapi.ResourceNotFoundException; | import com.google.gerrit.extensions.restapi.ResourceNotFoundException; | ||||||
| @@ -31,10 +33,14 @@ import org.eclipse.jgit.errors.RepositoryNotFoundException; | |||||||
| import org.eclipse.jgit.lib.Constants; | import org.eclipse.jgit.lib.Constants; | ||||||
| import org.eclipse.jgit.lib.RefUpdate; | import org.eclipse.jgit.lib.RefUpdate; | ||||||
| import org.eclipse.jgit.lib.Repository; | import org.eclipse.jgit.lib.Repository; | ||||||
|  | import org.slf4j.Logger; | ||||||
|  | import org.slf4j.LoggerFactory; | ||||||
|  |  | ||||||
| import java.io.IOException; | import java.io.IOException; | ||||||
|  |  | ||||||
| public class SetHead implements RestModifyView<ProjectResource, Input> { | public class SetHead implements RestModifyView<ProjectResource, Input> { | ||||||
|  |   private static final Logger log = LoggerFactory.getLogger(SetHead.class); | ||||||
|  |  | ||||||
|   static class Input { |   static class Input { | ||||||
|     @DefaultInput |     @DefaultInput | ||||||
|     String ref; |     String ref; | ||||||
| @@ -42,15 +48,19 @@ public class SetHead implements RestModifyView<ProjectResource, Input> { | |||||||
|  |  | ||||||
|   private final GitRepositoryManager repoManager; |   private final GitRepositoryManager repoManager; | ||||||
|   private final Provider<IdentifiedUser> identifiedUser; |   private final Provider<IdentifiedUser> identifiedUser; | ||||||
|  |   private final DynamicSet<HeadUpdatedListener> headUpdatedListener; | ||||||
|  |  | ||||||
|   @Inject |   @Inject | ||||||
|   SetHead(GitRepositoryManager repoManager, Provider<IdentifiedUser> identifiedUser) { |   SetHead(GitRepositoryManager repoManager, | ||||||
|  |       Provider<IdentifiedUser> identifiedUser, | ||||||
|  |       DynamicSet<HeadUpdatedListener> headUpdatedListener) { | ||||||
|     this.repoManager = repoManager; |     this.repoManager = repoManager; | ||||||
|     this.identifiedUser = identifiedUser; |     this.identifiedUser = identifiedUser; | ||||||
|  |     this.headUpdatedListener = headUpdatedListener; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   @Override |   @Override | ||||||
|   public String apply(ProjectResource rsrc, Input input) throws AuthException, |   public String apply(final ProjectResource rsrc, Input input) throws AuthException, | ||||||
|       ResourceNotFoundException, BadRequestException, |       ResourceNotFoundException, BadRequestException, | ||||||
|       UnprocessableEntityException, IOException { |       UnprocessableEntityException, IOException { | ||||||
|     if (!rsrc.getControl().isOwner()) { |     if (!rsrc.getControl().isOwner()) { | ||||||
| @@ -72,10 +82,12 @@ public class SetHead implements RestModifyView<ProjectResource, Input> { | |||||||
|             "Ref Not Found: %s", ref)); |             "Ref Not Found: %s", ref)); | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       if (!repo.getRef(Constants.HEAD).getTarget().getName().equals(ref)) { |       final String oldHead = repo.getRef(Constants.HEAD).getTarget().getName(); | ||||||
|  |       final String newHead = ref; | ||||||
|  |       if (!oldHead.equals(newHead)) { | ||||||
|         final RefUpdate u = repo.updateRef(Constants.HEAD, true); |         final RefUpdate u = repo.updateRef(Constants.HEAD, true); | ||||||
|         u.setRefLogIdent(identifiedUser.get().newRefLogIdent()); |         u.setRefLogIdent(identifiedUser.get().newRefLogIdent()); | ||||||
|         RefUpdate.Result res = u.link(ref); |         RefUpdate.Result res = u.link(newHead); | ||||||
|         switch(res) { |         switch(res) { | ||||||
|           case NO_CHANGE: |           case NO_CHANGE: | ||||||
|           case RENAMED: |           case RENAMED: | ||||||
| @@ -85,6 +97,30 @@ public class SetHead implements RestModifyView<ProjectResource, Input> { | |||||||
|           default: |           default: | ||||||
|             throw new IOException("Setting HEAD failed with " + res); |             throw new IOException("Setting HEAD failed with " + res); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         HeadUpdatedListener.Event event = new HeadUpdatedListener.Event() { | ||||||
|  |           @Override | ||||||
|  |           public String getProjectName() { | ||||||
|  |             return rsrc.getNameKey().get(); | ||||||
|  |           } | ||||||
|  |  | ||||||
|  |           @Override | ||||||
|  |           public String getOldHeadName() { | ||||||
|  |             return oldHead; | ||||||
|  |           } | ||||||
|  |  | ||||||
|  |           @Override | ||||||
|  |           public String getNewHeadName() { | ||||||
|  |             return newHead; | ||||||
|  |           } | ||||||
|  |         }; | ||||||
|  |         for (HeadUpdatedListener l : headUpdatedListener) { | ||||||
|  |           try { | ||||||
|  |             l.onHeadUpdated(event); | ||||||
|  |           } catch (RuntimeException e) { | ||||||
|  |             log.warn("Failure in HeadUpdatedListener", e); | ||||||
|  |           } | ||||||
|  |         } | ||||||
|       } |       } | ||||||
|       return ref; |       return ref; | ||||||
|     } catch (RepositoryNotFoundException e) { |     } catch (RepositoryNotFoundException e) { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Edwin Kempin
					Edwin Kempin