Fire git ref update events for all imported refs

Trigger git reference updated events for all imported refs
to notify other parts of the system that the new project with
refs is imported. Triggering those events fixes the issue
with replication plugin not replicating branches to the other
destinations after import.

Bug: Issue 12740
Change-Id: Ic87424b91dfb0c3c0e2a5754ea8b73b1eef90f4d
diff --git a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/GitCloneStep.java b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/GitCloneStep.java
index 02dfe87..8923b52 100644
--- a/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/GitCloneStep.java
+++ b/github-plugin/src/main/java/com/googlesource/gerrit/plugins/github/git/GitCloneStep.java
@@ -20,11 +20,15 @@
 import com.google.gerrit.extensions.registration.DynamicSet;
 import com.google.gerrit.extensions.restapi.ResourceConflictException;
 import com.google.gerrit.extensions.restapi.RestApiException;
+import com.google.gerrit.server.IdentifiedUser;
+import com.google.gerrit.server.account.AccountState;
+import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
 import com.google.gerrit.server.git.GitRepositoryManager;
 import com.google.gerrit.server.project.ProjectCache;
 import com.google.gerrit.server.util.ManualRequestContext;
 import com.google.gerrit.server.util.OneOffRequestContext;
 import com.google.inject.Inject;
+import com.google.inject.Provider;
 import com.google.inject.assistedinject.Assisted;
 import com.googlesource.gerrit.plugins.github.GitHubConfig;
 import java.io.File;
@@ -33,7 +37,9 @@
 import org.eclipse.jgit.api.FetchCommand;
 import org.eclipse.jgit.api.Git;
 import org.eclipse.jgit.api.errors.GitAPIException;
+import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.lib.ProgressMonitor;
+import org.eclipse.jgit.lib.Ref;
 import org.eclipse.jgit.lib.Repository;
 import org.eclipse.jgit.lib.RepositoryCache;
 import org.slf4j.Logger;
@@ -52,6 +58,8 @@
   private final DynamicSet<ProjectDeletedListener> deletedListeners;
   private final ProjectCache projectCache;
   private final GitRepositoryManager repoManager;
+  private final GitReferenceUpdated referenceUpdated;
+  private final Provider<IdentifiedUser> identifiedUser;
 
   public interface Factory {
     GitCloneStep create(
@@ -67,6 +75,8 @@
       DynamicSet<ProjectDeletedListener> deletedListeners,
       ProjectCache projectCache,
       GitRepositoryManager repoManager,
+      GitReferenceUpdated referenceUpdated,
+      Provider<IdentifiedUser> identifiedUser,
       @Assisted("organisation") String organisation,
       @Assisted("name") String repository)
       throws GitException {
@@ -83,6 +93,8 @@
     this.deletedListeners = deletedListeners;
     this.projectCache = projectCache;
     this.repoManager = repoManager;
+    this.referenceUpdated = referenceUpdated;
+    this.identifiedUser = identifiedUser;
   }
 
   private static File prepareTargetGitDirectory(File gitDir, String organisation, String repository)
@@ -95,10 +107,11 @@
     return repositoryDir;
   }
 
-  private void createNewProject() throws GitException {
+  private String createNewProject() throws GitException {
     String projectName = organisation + "/" + repository;
     try (ManualRequestContext requestContext = context.openAs(config.importAccountId)) {
       gerritApi.projects().create(projectName).get();
+      return projectName;
     } catch (ResourceConflictException e) {
       throw new GitDestinationAlreadyExistsException(projectName);
     } catch (RestApiException e) {
@@ -108,7 +121,7 @@
 
   @Override
   public void doImport(ProgressMonitor progress) throws GitException {
-    createNewProject();
+    Project.NameKey projectName = Project.nameKey(createNewProject());
     String sourceUri = getSourceUri();
     try (Git git = Git.open(destinationDirectory)) {
       FetchCommand fetch = git.fetch().setRefSpecs("refs/*:refs/*").setRemote(sourceUri);
@@ -118,6 +131,11 @@
       }
       LOG.info(sourceUri + "| Clone into " + destinationDirectory);
       fetch.call();
+      AccountState accountState = identifiedUser.get().state();
+      for (Ref ref : git.getRepository().getRefDatabase().getRefs()) {
+        referenceUpdated.fire(
+            projectName, ref.getName(), ObjectId.zeroId(), ref.getObjectId(), accountState);
+      }
     } catch (IOException | GitAPIException e) {
       LOG.error("Unable to fetch from {} into {}", sourceUri, destinationDirectory, e);
       throw new GitCloneFailedException(sourceUri, e);