Support annotated tags in push acceptance tests

Change-Id: I54b3425485e6a410783575acc05a7bedd5533ba4
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/PushOneCommit.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/PushOneCommit.java
index 32705ba..3c5d831 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/PushOneCommit.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/PushOneCommit.java
@@ -39,6 +39,7 @@
 import com.google.inject.assistedinject.AssistedInject;
 
 import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.api.TagCommand;
 import org.eclipse.jgit.api.errors.ConcurrentRefUpdateException;
 import org.eclipse.jgit.api.errors.GitAPIException;
 import org.eclipse.jgit.api.errors.InvalidTagNameException;
@@ -80,6 +81,25 @@
         @Assisted("changeId") String changeId);
   }
 
+  public static class Tag {
+    public String name;
+
+    public Tag(String name) {
+      this.name = name;
+    }
+  }
+
+  public static class AnnotatedTag extends Tag {
+    public String message;
+    public PersonIdent tagger;
+
+    public AnnotatedTag(String name, String message, PersonIdent tagger) {
+      super(name);
+      this.message = message;
+      this.tagger = tagger;
+    }
+  }
+
   private final ChangeNotes.Factory notesFactory;
   private final ApprovalsUtil approvalsUtil;
   private final ReviewDb db;
@@ -89,7 +109,7 @@
   private final String fileName;
   private final String content;
   private String changeId;
-  private String tagName;
+  private Tag tag;
 
   @AssistedInject
   PushOneCommit(ChangeNotes.Factory notesFactory,
@@ -151,14 +171,23 @@
       c = createCommit(git, i, subject);
       changeId = c.getChangeId();
     }
-    if (tagName != null) {
-      git.tag().setName(tagName).setAnnotated(false).call();
+    if (tag != null) {
+      TagCommand tagCommand = git.tag().setName(tag.name);
+      if (tag instanceof AnnotatedTag) {
+        AnnotatedTag annotatedTag = (AnnotatedTag)tag;
+        tagCommand.setAnnotated(true)
+          .setMessage(annotatedTag.message)
+          .setTagger(annotatedTag.tagger);
+      } else {
+        tagCommand.setAnnotated(false);
+      }
+      tagCommand.call();
     }
-    return new Result(ref, pushHead(git, ref, tagName != null), c, subject);
+    return new Result(ref, pushHead(git, ref, tag != null), c, subject);
   }
 
-  public void setTag(final String tagName) {
-    this.tagName = tagName;
+  public void setTag(final Tag tag) {
+    this.tag = tag;
   }
 
   public class Result {
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git/SubmitOnPushIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git/SubmitOnPushIT.java
index cdd3740..5fea12e 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git/SubmitOnPushIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git/SubmitOnPushIT.java
@@ -39,8 +39,11 @@
 import org.eclipse.jgit.errors.ConfigInvalidException;
 import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.lib.PersonIdent;
+import org.eclipse.jgit.lib.Ref;
 import org.eclipse.jgit.lib.Repository;
 import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevObject;
+import org.eclipse.jgit.revwalk.RevTag;
 import org.eclipse.jgit.revwalk.RevWalk;
 import org.eclipse.jgit.transport.RefSpec;
 import org.junit.Test;
@@ -81,7 +84,25 @@
     grant(Permission.SUBMIT, project, "refs/for/refs/heads/master");
     grant(Permission.CREATE, project, "refs/tags/*");
     grant(Permission.PUSH, project, "refs/tags/*");
-    final String tag = "v1.0";
+    PushOneCommit.Tag tag = new PushOneCommit.Tag("v1.0");
+    PushOneCommit push = pushFactory.create(db, admin.getIdent());
+    push.setTag(tag);
+    PushOneCommit.Result r = push.to(git, "refs/for/master%submit");
+    r.assertOkStatus();
+    r.assertChange(Change.Status.MERGED, null, admin);
+    assertSubmitApproval(r.getPatchSetId());
+    assertCommit(project, "refs/heads/master");
+    assertTag(project, "refs/heads/master", tag);
+  }
+
+  @Test
+  public void submitOnPushWithAnnotatedTag() throws GitAPIException,
+      OrmException, IOException, ConfigInvalidException {
+    grant(Permission.SUBMIT, project, "refs/for/refs/heads/master");
+    grant(Permission.CREATE, project, "refs/tags/*");
+    grant(Permission.PUSH, project, "refs/tags/*");
+    PushOneCommit.AnnotatedTag tag =
+        new PushOneCommit.AnnotatedTag("v1.0", "annotation", admin.getIdent());
     PushOneCommit push = pushFactory.create(db, admin.getIdent());
     push.setTag(tag);
     PushOneCommit.Result r = push.to(git, "refs/for/master%submit");
@@ -256,15 +277,34 @@
     }
   }
 
-  private void assertTag(Project.NameKey project, String branch, String tagName)
-      throws IOException {
-    Repository r = repoManager.openRepository(project);
+  private void assertTag(Project.NameKey project, String branch,
+      PushOneCommit.Tag tag) throws IOException {
+    Repository repo = repoManager.openRepository(project);
     try {
-      ObjectId headCommit = r.getRef(branch).getObjectId();
-      ObjectId taggedCommit = r.getRef(tagName).getObjectId();
+      Ref tagRef = repo.getRef(tag.name);
+      assertTrue(tagRef != null);
+      ObjectId taggedCommit = null;
+      if (tag instanceof PushOneCommit.AnnotatedTag) {
+        PushOneCommit.AnnotatedTag annotatedTag = (PushOneCommit.AnnotatedTag)tag;
+        RevWalk rw = new RevWalk(repo);
+        try {
+          RevObject object = rw.parseAny(tagRef.getObjectId());
+          assertTrue(object instanceof RevTag);
+          RevTag tagObject = (RevTag)object;
+          assertEquals(annotatedTag.message, tagObject.getFullMessage());
+          assertEquals(annotatedTag.tagger, tagObject.getTaggerIdent());
+          taggedCommit = tagObject.getObject();
+        } finally {
+          rw.dispose();
+        }
+      } else {
+        taggedCommit = tagRef.getObjectId();
+      }
+      ObjectId headCommit = repo.getRef(branch).getObjectId();
+      assertTrue(taggedCommit != null);
       assertEquals(headCommit, taggedCommit);
     } finally {
-      r.close();
+      repo.close();
     }
   }