diff --git a/scm-core/src/main/java/sonia/scm/repository/Tag.java b/scm-core/src/main/java/sonia/scm/repository/Tag.java
index bdeec544a4..1c037e4764 100644
--- a/scm-core/src/main/java/sonia/scm/repository/Tag.java
+++ b/scm-core/src/main/java/sonia/scm/repository/Tag.java
@@ -67,4 +67,15 @@ public final class Tag {
this.revision = revision;
this.date = date;
}
+
+ /**
+ * The date is retrieved in a best-effort fashion.
+ * In certain situations it might not be available.
+ * In these cases, this method returns null.
+ *
+ * @since 2.5.0
+ */
+ public Long getDate() {
+ return date;
+ }
}
diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java
index 96e4266a5d..97fc29163a 100644
--- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java
+++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java
@@ -392,27 +392,39 @@ public final class GitUtil
/**
* Method description
*
+ * @param repository
+ * @param ref
+ * @return
+ * @throws IOException
+ * @since 2.5.0
+ */
+ public static Long getTagTime(org.eclipse.jgit.lib.Repository repository, Ref ref) throws IOException {
+ try (RevWalk walk = new RevWalk(repository)) {
+ return GitUtil.getTagTime(repository, walk, ref);
+ }
+ }
+
+ /**
+ * Method description
*
* @param repository
* @param revWalk
* @param ref
- *
* @return
- *
* @throws IOException
- *
* @since 2.5.0
*/
public static Long getTagTime(org.eclipse.jgit.lib.Repository repository,
- RevWalk revWalk, Ref ref)
- throws IOException
- {
+ RevWalk revWalk, Ref ref)
+ throws IOException {
+ if (ref == null) {
+ return null;
+ }
+
ObjectId id = ref.getObjectId();
- if (id != null)
- {
- if (revWalk == null)
- {
+ if (id != null) {
+ if (revWalk == null) {
revWalk = new RevWalk(repository);
}
diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/api/GitHookTagProvider.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/api/GitHookTagProvider.java
index 5bc5069112..c1a333400b 100644
--- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/api/GitHookTagProvider.java
+++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/api/GitHookTagProvider.java
@@ -68,8 +68,8 @@ public class GitHookTagProvider implements HookTagProvider {
LOG.debug("received ref name {} is not a tag", refName);
} else {
Long tagTime = null;
- try (RevWalk walk = new RevWalk(repository)) {
- tagTime = GitUtil.getTagTime(repository, walk, rc.getRef());
+ try {
+ tagTime = GitUtil.getTagTime(repository, rc.getRef());
} catch (IOException e) {
LOG.error("Could not read tag time", e);
}
diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/api/GitHookTagProviderTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/api/GitHookTagProviderTest.java
index d27f881a13..f40d71378c 100644
--- a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/api/GitHookTagProviderTest.java
+++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/api/GitHookTagProviderTest.java
@@ -26,6 +26,11 @@ package sonia.scm.repository.api;
import com.google.common.collect.Lists;
import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.ObjectLoader;
+import org.eclipse.jgit.lib.ObjectReader;
+import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevTag;
import org.eclipse.jgit.transport.ReceiveCommand;
import org.junit.Before;
import org.junit.Rule;
@@ -33,13 +38,19 @@ import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.mockito.Mock;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
+import sonia.scm.repository.GitUtil;
import sonia.scm.repository.Tag;
import java.util.List;
import static org.hamcrest.Matchers.empty;
import static org.junit.Assert.*;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
/**
@@ -48,16 +59,22 @@ import static org.mockito.Mockito.when;
* @author Sebastian Sdorra
*/
@RunWith(MockitoJUnitRunner.class)
-public class GitHookTagProviderTest {
+public class GitHookTagProviderTest{
private static final String ZERO = ObjectId.zeroId().getName();
- @Rule
- public TemporaryFolder temporaryFolder = new TemporaryFolder();
-
@Mock
private ReceiveCommand command;
-
+
+ @Mock
+ private Repository repository;
+
+ @Mock
+ private Ref gitRef;
+
+ @Mock
+ private ObjectId objectId;
+
private List commands;
/**
@@ -73,11 +90,21 @@ public class GitHookTagProviderTest {
*/
@Test
public void testGetCreatedTags() {
- String revision = "b2002b64013e54b78eac251df0672bd5d6a83aa7";
- GitHookTagProvider provider = createProvider(ReceiveCommand.Type.CREATE, "refs/tags/1.0.0", revision, ZERO);
-
- assertTag("1.0.0", revision, provider.getCreatedTags());
- assertThat(provider.getDeletedTags(), empty());
+ try (MockedStatic dummy = Mockito.mockStatic(GitUtil.class)) {
+ String revision = "86a6645eceefe8b9a247db5eb16e3d89a7e6e6d1";
+ Long timestamp = 1339416344000L;
+ String tagName = "test-tag";
+ String ref = "refs/tags/" + tagName;
+
+ dummy.when(() -> GitUtil.getTagTime(repository, gitRef)).thenReturn(timestamp);
+ dummy.when(() -> GitUtil.getTagName(ref)).thenReturn(tagName);
+ dummy.when(() -> GitUtil.getId(ObjectId.fromString(revision))).thenReturn(revision);
+
+ GitHookTagProvider provider = createProvider(ReceiveCommand.Type.CREATE, ref, revision, ZERO);
+
+ assertTag(tagName, revision, timestamp, provider.getCreatedTags());
+ assertThat(provider.getDeletedTags(), empty());
+ }
}
/**
@@ -89,14 +116,14 @@ public class GitHookTagProviderTest {
GitHookTagProvider provider = createProvider(ReceiveCommand.Type.DELETE, "refs/tags/1.0.0", ZERO, revision);
assertThat(provider.getCreatedTags(), empty());
- assertTag("1.0.0", revision, provider.getDeletedTags());
+ assertTag("1.0.0", revision, null, provider.getDeletedTags());
}
/**
* Tests {@link GitHookTagProvider} with a branch ref instead of a tag.
*/
@Test
- public void testWithBranch(){
+ public void testWithBranch() {
String revision = "b2002b64013e54b78eac251df0672bd5d6a83aa7";
GitHookTagProvider provider = createProvider(ReceiveCommand.Type.CREATE, "refs/heads/1.0.0", revision, revision);
@@ -113,25 +140,28 @@ public class GitHookTagProviderTest {
String oldId = "e0f2be968b147ff7043684a7715d2fe852553db4";
GitHookTagProvider provider = createProvider(ReceiveCommand.Type.UPDATE, "refs/tags/1.0.0", newId, oldId);
- assertTag("1.0.0", newId, provider.getCreatedTags());
- assertTag("1.0.0", oldId, provider.getDeletedTags());
+ assertTag("1.0.0", newId, null, provider.getCreatedTags());
+ assertTag("1.0.0", oldId, null, provider.getDeletedTags());
}
- private void assertTag(String name, String revision, List tags){
+ private void assertTag(String name, String revision, Long date, List tags){
assertNotNull(tags);
assertFalse(tags.isEmpty());
assertEquals(1, tags.size());
Tag tag = tags.get(0);
assertEquals(name, tag.getName());
assertEquals(revision, tag.getRevision());
+ assertEquals(date, tag.getDate());
}
- private GitHookTagProvider createProvider(ReceiveCommand.Type type, String ref, String newId, String oldId){
+ private GitHookTagProvider createProvider(ReceiveCommand.Type type, String ref, String newId, String oldId) {
when(command.getNewId()).thenReturn(ObjectId.fromString(newId));
when(command.getOldId()).thenReturn(ObjectId.fromString(oldId));
when(command.getType()).thenReturn(type);
when(command.getRefName()).thenReturn(ref);
- return new GitHookTagProvider(commands);
+ when(command.getRef()).thenReturn(gitRef);
+ when(gitRef.getObjectId()).thenReturn(objectId);
+ return new GitHookTagProvider(commands, repository);
}
}
diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/api/HgHookTagProvider.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/api/HgHookTagProvider.java
index ed140ee4b6..7b8ecef67d 100644
--- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/api/HgHookTagProvider.java
+++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/api/HgHookTagProvider.java
@@ -92,7 +92,7 @@ public class HgHookTagProvider implements HookTagProvider {
if (tagNames != null){
for ( String tagName : tagNames ){
logger.trace("found tag {} at changeset {}", tagName, c.getId());
- tags.add(new Tag(tagName, c.getId()));
+ tags.add(new Tag(tagName, c.getId(), c.getDate()));
}
}
}
diff --git a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/api/HgHookTagProviderTest.java b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/api/HgHookTagProviderTest.java
index a2486732a0..f557fec51e 100644
--- a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/api/HgHookTagProviderTest.java
+++ b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/api/HgHookTagProviderTest.java
@@ -26,6 +26,8 @@ package sonia.scm.repository.api;
import com.google.common.collect.Lists;
import java.util.List;
+
+import org.assertj.core.api.Assertions;
import org.junit.Test;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
@@ -71,7 +73,7 @@ public class HgHookTagProviderTest {
public void testGetCreatedTags(){
Changeset c1 = new Changeset("1", Long.MIN_VALUE, null);
c1.getTags().add("1.0.0");
- Changeset c2 = new Changeset("2", Long.MIN_VALUE, null);
+ Changeset c2 = new Changeset("2", Long.MAX_VALUE, null);
c2.getTags().add("2.0.0");
Changeset c3 = new Changeset("3", Long.MIN_VALUE, null);
prepareChangesets(c1, c2, c3);
@@ -83,10 +85,12 @@ public class HgHookTagProviderTest {
Tag t1 = tags.get(0);
assertEquals("1", t1.getRevision());
assertEquals("1.0.0", t1.getName());
-
+ Assertions.assertThat(t1.getDate()).isEqualTo(Long.MIN_VALUE);
+
Tag t2 = tags.get(1);
assertEquals("2", t2.getRevision());
assertEquals("2.0.0", t2.getName());
+ Assertions.assertThat(t2.getDate()).isEqualTo(Long.MAX_VALUE);
}
private void prepareChangesets(Changeset... changesets){
diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/TagDto.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/TagDto.java
index b7c6b3bacf..7d4fd6dada 100644
--- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/TagDto.java
+++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/TagDto.java
@@ -24,6 +24,7 @@
package sonia.scm.api.v2.resources;
+import com.fasterxml.jackson.annotation.JsonInclude;
import de.otto.edison.hal.Embedded;
import de.otto.edison.hal.HalRepresentation;
import de.otto.edison.hal.Links;
@@ -42,6 +43,7 @@ public class TagDto extends HalRepresentation {
private String revision;
+ @JsonInclude(JsonInclude.Include.NON_NULL)
private Instant date;
TagDto(Links links, Embedded embedded) {