ListTags: Include timestamp in tag info

The tags are listed in alphanumeric order, but some clients may wish
to order the tags by the date they were created.

Add a timestamp in the tag info.

For annotated/signed tags, the timestamp is the date at which the tag
was created.

For lightweight tags, the timestamp is set to the committer timestamp,
only when the tag is on a commit.

Change-Id: I34f49f19810fa430769a50b5ae43b8107527792b
This commit is contained in:
David Pursehouse
2017-11-10 10:17:46 +09:00
parent 638a829744
commit c4e4d93410
4 changed files with 60 additions and 6 deletions

View File

@@ -3331,6 +3331,11 @@ tag points.
the signature. the signature.
|`tagger`|Only set for annotated tags, if present in the tag.|The tagger as a |`tagger`|Only set for annotated tags, if present in the tag.|The tagger as a
link:rest-api-changes.html#git-person-info[GitPersonInfo] entity. link:rest-api-changes.html#git-person-info[GitPersonInfo] entity.
|`created`|optional|The link:rest-api.html#timestamp[timestamp] of when the tag
was created. For annotated and signed tags, this is the timestamp of the tag object
and is the same as the `date` field in the `tagger`. For lightweight tags, it is
the commit timestamp of the commit to which the tag points, when the object is a
commit. It is not set when the object is any other type.
|`can_delete`|not set if `false`| |`can_delete`|not set if `false`|
Whether the calling user can delete this tag. Whether the calling user can delete this tag.
|`web_links` |optional| |`web_links` |optional|

View File

@@ -16,19 +16,47 @@ package com.google.gerrit.extensions.api.projects;
import com.google.gerrit.extensions.common.GitPerson; import com.google.gerrit.extensions.common.GitPerson;
import com.google.gerrit.extensions.common.WebLinkInfo; import com.google.gerrit.extensions.common.WebLinkInfo;
import java.sql.Timestamp;
import java.util.List; import java.util.List;
public class TagInfo extends RefInfo { public class TagInfo extends RefInfo {
public String object; public String object;
public String message; public String message;
public GitPerson tagger; public GitPerson tagger;
public Timestamp created;
public List<WebLinkInfo> webLinks; public List<WebLinkInfo> webLinks;
public TagInfo(String ref, String revision, Boolean canDelete, List<WebLinkInfo> webLinks) { public TagInfo(
String ref,
String revision,
Boolean canDelete,
List<WebLinkInfo> webLinks,
Timestamp created) {
this.ref = ref; this.ref = ref;
this.revision = revision; this.revision = revision;
this.canDelete = canDelete; this.canDelete = canDelete;
this.webLinks = webLinks; this.webLinks = webLinks;
this.created = created;
}
public TagInfo(String ref, String revision, Boolean canDelete, List<WebLinkInfo> webLinks) {
this(ref, revision, canDelete, webLinks, null);
}
public TagInfo(
String ref,
String revision,
String object,
String message,
GitPerson tagger,
Boolean canDelete,
List<WebLinkInfo> webLinks,
Timestamp created) {
this(ref, revision, canDelete, webLinks, created);
this.object = object;
this.message = message;
this.tagger = tagger;
this.webLinks = webLinks;
} }
public TagInfo( public TagInfo(
@@ -39,7 +67,7 @@ public class TagInfo extends RefInfo {
GitPerson tagger, GitPerson tagger,
Boolean canDelete, Boolean canDelete,
List<WebLinkInfo> webLinks) { List<WebLinkInfo> webLinks) {
this(ref, revision, canDelete, webLinks); this(ref, revision, object, message, tagger, canDelete, webLinks, null);
this.object = object; this.object = object;
this.message = message; this.message = message;
this.tagger = tagger; this.tagger = tagger;

View File

@@ -33,6 +33,7 @@ import com.google.gerrit.server.permissions.RefPermission;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.google.inject.Provider; import com.google.inject.Provider;
import java.io.IOException; import java.io.IOException;
import java.sql.Timestamp;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
@@ -44,6 +45,7 @@ import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.PersonIdent; import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevObject; import org.eclipse.jgit.revwalk.RevObject;
import org.eclipse.jgit.revwalk.RevTag; import org.eclipse.jgit.revwalk.RevTag;
import org.eclipse.jgit.revwalk.RevWalk; import org.eclipse.jgit.revwalk.RevWalk;
@@ -201,16 +203,24 @@ public class ListTags implements RestReadView<ProjectResource> {
tag.getName(), tag.getName(),
tag.getObject().getName(), tag.getObject().getName(),
tag.getFullMessage().trim(), tag.getFullMessage().trim(),
tagger != null ? CommonConverters.toGitPerson(tag.getTaggerIdent()) : null, tagger != null ? CommonConverters.toGitPerson(tagger) : null,
canDelete, canDelete,
webLinks.isEmpty() ? null : webLinks); webLinks.isEmpty() ? null : webLinks,
tagger != null ? new Timestamp(tagger.getWhen().getTime()) : null);
} }
Timestamp timestamp =
object instanceof RevCommit
? new Timestamp(((RevCommit) object).getCommitterIdent().getWhen().getTime())
: null;
// Lightweight tag // Lightweight tag
return new TagInfo( return new TagInfo(
ref.getName(), ref.getName(),
ref.getObjectId().getName(), ref.getObjectId().getName(),
canDelete, canDelete,
webLinks.isEmpty() ? null : webLinks); webLinks.isEmpty() ? null : webLinks,
timestamp);
} }
private Repository getRepository(Project.NameKey project) private Repository getRepository(Project.NameKey project)

View File

@@ -33,6 +33,7 @@ import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.MethodNotAllowedException; import com.google.gerrit.extensions.restapi.MethodNotAllowedException;
import com.google.gerrit.extensions.restapi.ResourceConflictException; import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException; import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import java.sql.Timestamp;
import java.util.List; import java.util.List;
import org.junit.Test; import org.junit.Test;
@@ -177,12 +178,14 @@ public class TagsIT extends AbstractDaemonTest {
assertThat(result.ref).isEqualTo(R_TAGS + input.ref); assertThat(result.ref).isEqualTo(R_TAGS + input.ref);
assertThat(result.revision).isEqualTo(input.revision); assertThat(result.revision).isEqualTo(input.revision);
assertThat(result.canDelete).isTrue(); assertThat(result.canDelete).isTrue();
assertThat(result.created).isEqualTo(timestamp(r));
input.ref = "refs/tags/v2.0"; input.ref = "refs/tags/v2.0";
result = tag(input.ref).create(input).get(); result = tag(input.ref).create(input).get();
assertThat(result.ref).isEqualTo(input.ref); assertThat(result.ref).isEqualTo(input.ref);
assertThat(result.revision).isEqualTo(input.revision); assertThat(result.revision).isEqualTo(input.revision);
assertThat(result.canDelete).isTrue(); assertThat(result.canDelete).isTrue();
assertThat(result.created).isEqualTo(timestamp(r));
setApiUser(user); setApiUser(user);
result = tag(input.ref).get(); result = tag(input.ref).get();
@@ -210,6 +213,7 @@ public class TagsIT extends AbstractDaemonTest {
assertThat(result.message).isEqualTo(input.message); assertThat(result.message).isEqualTo(input.message);
assertThat(result.tagger.name).isEqualTo(admin.fullName); assertThat(result.tagger.name).isEqualTo(admin.fullName);
assertThat(result.tagger.email).isEqualTo(admin.email); assertThat(result.tagger.email).isEqualTo(admin.email);
assertThat(result.created).isEqualTo(result.tagger.date);
eventRecorder.assertRefUpdatedEvents(project.get(), result.ref, null, result.revision); eventRecorder.assertRefUpdatedEvents(project.get(), result.ref, null, result.revision);
@@ -224,6 +228,7 @@ public class TagsIT extends AbstractDaemonTest {
assertThat(result2.message).isEqualTo(input2.message); assertThat(result2.message).isEqualTo(input2.message);
assertThat(result2.tagger.name).isEqualTo(admin.fullName); assertThat(result2.tagger.name).isEqualTo(admin.fullName);
assertThat(result2.tagger.email).isEqualTo(admin.email); assertThat(result2.tagger.email).isEqualTo(admin.email);
assertThat(result2.created).isEqualTo(result2.tagger.date);
eventRecorder.assertRefUpdatedEvents(project.get(), result2.ref, null, result2.revision); eventRecorder.assertRefUpdatedEvents(project.get(), result2.ref, null, result2.revision);
} }
@@ -325,7 +330,9 @@ public class TagsIT extends AbstractDaemonTest {
throws Exception { throws Exception {
assertThat(actual).hasSize(expected.size()); assertThat(actual).hasSize(expected.size());
for (int i = 0; i < expected.size(); i++) { for (int i = 0; i < expected.size(); i++) {
assertThat(actual.get(i).ref).isEqualTo(R_TAGS + expected.get(i)); TagInfo info = actual.get(i);
assertThat(info.created).isNotNull();
assertThat(info.ref).isEqualTo(R_TAGS + expected.get(i));
} }
} }
@@ -351,6 +358,10 @@ public class TagsIT extends AbstractDaemonTest {
return gApi.projects().name(project.get()).tag(tagname); return gApi.projects().name(project.get()).tag(tagname);
} }
private Timestamp timestamp(PushOneCommit.Result r) {
return new Timestamp(r.getCommit().getCommitterIdent().getWhen().getTime());
}
private void assertBadRequest(ListRefsRequest<TagInfo> req) throws Exception { private void assertBadRequest(ListRefsRequest<TagInfo> req) throws Exception {
try { try {
req.get(); req.get();