diff --git a/pom.xml b/pom.xml
index cd115e5525..85c35698b2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -53,7 +53,7 @@
io.jenkins.tools.bom
bom-${jenkins.baseline}.x
- 5857.vb_f3dd0731f44
+ 5933.vcf06f7b_5d1a_2
pom
import
@@ -227,5 +227,4 @@
https://repo.jenkins-ci.org/public/
-
diff --git a/src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java b/src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java
index 1504297965..268ec30e2c 100644
--- a/src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java
+++ b/src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java
@@ -110,6 +110,7 @@
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevTag;
import org.eclipse.jgit.revwalk.RevTree;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.transport.RefSpec;
@@ -425,6 +426,34 @@ private , R extends GitSCMSourceRequest>
}
}
+ private long getTagTimestamp(RevWalk walk, ObjectId objectId) throws IOException {
+ try {
+ // Annotated tag object
+ RevTag tag = walk.parseTag(objectId);
+
+ if (tag.getTaggerIdent() != null
+ && tag.getTaggerIdent().getWhen() != null) {
+ return tag.getTaggerIdent().getWhen().getTime();
+ }
+
+ // No tagger ident (or weird tag) — walk the tag chain to a commit, if any
+ Object target = tag.getObject();
+ for (int i = 0; i < 32 && target instanceof RevTag; i++) {
+ target = ((RevTag) target).getObject();
+ }
+
+ if (target instanceof RevCommit) {
+ return TimeUnit.SECONDS.toMillis(((RevCommit) target).getCommitTime());
+ }
+
+ throw new IOException("Tag does not ultimately reference a commit: " + objectId.name());
+ } catch (org.eclipse.jgit.errors.IncorrectObjectTypeException e) {
+ // Lightweight tag (or direct commit id)
+ RevCommit commit = walk.parseCommit(objectId);
+ return TimeUnit.SECONDS.toMillis(commit.getCommitTime());
+ }
+ }
+
/**
* {@inheritDoc}
*/
@@ -786,8 +815,7 @@ private void discoverTags(final Repository repository,
}
count++;
final String tagName = StringUtils.removeStart(ref.getKey(), Constants.R_TAGS);
- RevCommit commit = walk.parseCommit(ref.getValue());
- final long lastModified = TimeUnit.SECONDS.toMillis(commit.getCommitTime());
+ final long lastModified = getTagTimestamp(walk, ref.getValue());
if (request.process(new GitTagSCMHead(tagName, lastModified),
new SCMSourceRequest.IntermediateLambda() {
@Nullable
@@ -804,7 +832,7 @@ public SCMSourceCriteria.Probe create(@NonNull GitTagSCMHead head,
@Nullable ObjectId revisionInfo)
throws IOException, InterruptedException {
RevCommit commit = walk.parseCommit(revisionInfo);
- final long lastModified = TimeUnit.SECONDS.toMillis(commit.getCommitTime());
+ final long lastModified = getTagTimestamp(walk, revisionInfo);
final RevTree tree = commit.getTree();
return new TreeWalkingSCMProbe(tagName, lastModified, repository, tree);
}
@@ -1012,8 +1040,7 @@ public SCMRevision run(GitClient client, String remoteName) throws GitException,
final Repository repository = client.getRepository();
RevWalk walk = new RevWalk(repository)) {
ObjectId ref = client.revParse(tagRef);
- RevCommit commit = walk.parseCommit(ref);
- long lastModified = TimeUnit.SECONDS.toMillis(commit.getCommitTime());
+ long lastModified = getTagTimestamp(walk, ref);
listener.getLogger().printf("Resolved tag %s revision %s%n", revision,
ref.getName());
return new GitTagSCMRevision(new GitTagSCMHead(revision, lastModified),
diff --git a/src/test/java/jenkins/plugins/git/AbstractGitSCMSourceWantTagsTest.java b/src/test/java/jenkins/plugins/git/AbstractGitSCMSourceWantTagsTest.java
index 2a7b87ca76..18140f1f90 100644
--- a/src/test/java/jenkins/plugins/git/AbstractGitSCMSourceWantTagsTest.java
+++ b/src/test/java/jenkins/plugins/git/AbstractGitSCMSourceWantTagsTest.java
@@ -3,6 +3,7 @@
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.empty;
+import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.is;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -169,6 +170,25 @@ void indexingHasBranchAndTagDiscoveryTraitIgnoreTagDiscoveryTrait() throws Excep
assertTrue(tagsFetched);
}
+ @Test
+ public void tagTimestampsAreValid() throws Exception {
+ source.setTraits(Collections.singletonList(new TagDiscoveryTrait()));
+ Set heads = source.fetch(LISTENER);
+
+ Set tags = heads.stream()
+ .filter(h -> h instanceof GitTagSCMHead)
+ .map(h -> (GitTagSCMHead) h)
+ .collect(Collectors.toSet());
+
+ assertThat("Should discover both tags", tags.size(), is(2));
+
+ long year2000 = 946684800000L; // Jan 1, 2000
+ for (GitTagSCMHead tag : tags) {
+ assertThat("Tag " + tag.getName() + " should have valid timestamp",
+ tag.getTimestamp(), greaterThan(year2000));
+ }
+ }
+
static boolean tagsFetched;
public static class MockGitClientForTags extends TestJGitAPIImpl {