From 5b9acb0f5085fee38de8cf4c49c3a1ee5f06058c Mon Sep 17 00:00:00 2001 From: dodo920306 Date: Sun, 1 Jun 2025 14:10:26 +0800 Subject: [PATCH 01/10] Add creation time boundaries to tags for discovery Introduce upper and lower bounds for tag creation time in TagDiscoveryTrait, allowing AbstractGitSCMSource to determine whether a tag should be included based on its timestamp. Signed-off-by: dodo920306 --- .../plugins/git/AbstractGitSCMSource.java | 23 +++++++++++-- .../plugins/git/GitSCMSourceContext.java | 34 +++++++++++++++++++ .../plugins/git/traits/TagDiscoveryTrait.java | 20 +++++++++++ .../git/traits/TagDiscoveryTrait/config.jelly | 6 ++++ 4 files changed, 81 insertions(+), 2 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java b/src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java index 95979370b9..48d3ee6555 100644 --- a/src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java +++ b/src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java @@ -632,7 +632,9 @@ public Void run(GitClient client, String remoteName, FetchCommand fetch) throws discoverBranches(repository, walk, request, remoteReferences); } if (context.wantTags()) { - discoverTags(repository, walk, request, remoteReferences); + discoverTags(repository, walk, request, remoteReferences, + context.getAtLeastTagCommitTimeMillis(), + context.getAtMostTagCommitTimeMillis()); } if (context.wantOtherRefs()) { discoverOtherRefs(repository, walk, request, remoteReferences, @@ -772,7 +774,9 @@ public void record(@NonNull SCMHead head, SCMRevision revision, boolean isMatch) private void discoverTags(final Repository repository, final RevWalk walk, GitSCMSourceRequest request, - Map remoteReferences) + Map remoteReferences, + long atLeastMillis, + long atMostMillis) throws IOException, InterruptedException { listener.getLogger().println("Checking tags..."); walk.setRetainBody(false); @@ -785,6 +789,21 @@ private void discoverTags(final Repository repository, final String tagName = StringUtils.removeStart(ref.getKey(), Constants.R_TAGS); RevCommit commit = walk.parseCommit(ref.getValue()); final long lastModified = TimeUnit.SECONDS.toMillis(commit.getCommitTime()); + + if (atLeastMillis >= 0L || atMostMillis >= 0L) { + if (atMostMillis >= 0L && atLeastMillis > atMostMillis) { + /* Invalid. It's impossible for any tag to satisfy this. */ + continue; + } + long tagAge = System.currentTimeMillis() - lastModified; + if (atMostMillis >= 0L && tagAge > atMostMillis) { + continue; + } + if (atLeastMillis >= 0L && tagAge < atLeastMillis) { + continue; + } + } + if (request.process(new GitTagSCMHead(tagName, lastModified), new SCMSourceRequest.IntermediateLambda() { @Nullable diff --git a/src/main/java/jenkins/plugins/git/GitSCMSourceContext.java b/src/main/java/jenkins/plugins/git/GitSCMSourceContext.java index 494d027d2f..805876fd29 100644 --- a/src/main/java/jenkins/plugins/git/GitSCMSourceContext.java +++ b/src/main/java/jenkins/plugins/git/GitSCMSourceContext.java @@ -37,6 +37,7 @@ import java.util.Objects; import java.util.Set; import java.util.TreeSet; +import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -95,6 +96,12 @@ public class GitSCMSourceContext, R extends @NonNull private String remoteName = AbstractGitSCMSource.DEFAULT_REMOTE_NAME; + @CheckForNull + private long atLeastTagCommitTimeMillis; + + @CheckForNull + private long atMostTagCommitTimeMillis; + /** * Constructor. * @@ -192,6 +199,14 @@ public final String remoteName() { return remoteName; } + public final long getAtLeastTagCommitTimeMillis() { + return atLeastTagCommitTimeMillis; + } + + public final long getAtMostTagCommitTimeMillis() { + return atMostTagCommitTimeMillis; + } + /** * Adds a requirement for branch details to any {@link GitSCMSourceRequest} for this context. * @@ -358,6 +373,25 @@ public final List asRefSpecs() { return result; } + private long getTagCommitTimeLimitMillisFromDays(String limitDays) { + long tagCommitTimeLimit = Long.parseLong(StringUtils.defaultIfBlank(limitDays, "-1")); + return tagCommitTimeLimit < 0 ? -1L : TimeUnit.DAYS.toMillis(tagCommitTimeLimit); + } + + @SuppressWarnings("unchecked") + @NonNull + public final C withAtLeastTagCommitTimeDays(String atLeastDays) { + this.atLeastTagCommitTimeMillis = getTagCommitTimeLimitMillisFromDays(atLeastDays); + return (C) this; + } + + @SuppressWarnings("unchecked") + @NonNull + public final C withAtMostTagCommitTimeDays(String atMostDays) { + this.atMostTagCommitTimeMillis = getTagCommitTimeLimitMillisFromDays(atMostDays); + return (C) this; + } + /** * {@inheritDoc} */ diff --git a/src/main/java/jenkins/plugins/git/traits/TagDiscoveryTrait.java b/src/main/java/jenkins/plugins/git/traits/TagDiscoveryTrait.java index 9c9be145a9..8eafcac735 100644 --- a/src/main/java/jenkins/plugins/git/traits/TagDiscoveryTrait.java +++ b/src/main/java/jenkins/plugins/git/traits/TagDiscoveryTrait.java @@ -23,6 +23,7 @@ */ package jenkins.plugins.git.traits; +import edu.umd.cs.findbugs.annotations.CheckForNull; import edu.umd.cs.findbugs.annotations.NonNull; import hudson.Extension; import jenkins.plugins.git.GitSCMBuilder; @@ -51,11 +52,20 @@ * @since 3.6.0 */ public class TagDiscoveryTrait extends SCMSourceTrait { + private final String atLeastDays; + private final String atMostDays; + /** * Constructor for stapler. */ @DataBoundConstructor + public TagDiscoveryTrait(@CheckForNull String atLeastDays, @CheckForNull String atMostDays) { + this.atLeastDays = atLeastDays; + this.atMostDays = atMostDays; + } + public TagDiscoveryTrait() { + this(null, null); } /** @@ -66,6 +76,8 @@ protected void decorateContext(SCMSourceContext context) { GitSCMSourceContext ctx = (GitSCMSourceContext) context; ctx.wantTags(true); ctx.withAuthority(new TagSCMHeadAuthority()); + ctx.withAtLeastTagCommitTimeDays(atLeastDays) + .withAtMostTagCommitTimeDays(atMostDays); } /** @@ -76,6 +88,14 @@ public boolean includeCategory(@NonNull SCMHeadCategory category) { return category instanceof TagSCMHeadCategory; } + public String getAtLeastDays() { + return atLeastDays; + } + + public String getAtMostDays() { + return atMostDays; + } + /** * Our descriptor. */ diff --git a/src/main/resources/jenkins/plugins/git/traits/TagDiscoveryTrait/config.jelly b/src/main/resources/jenkins/plugins/git/traits/TagDiscoveryTrait/config.jelly index 92acdaa269..70e46bd717 100644 --- a/src/main/resources/jenkins/plugins/git/traits/TagDiscoveryTrait/config.jelly +++ b/src/main/resources/jenkins/plugins/git/traits/TagDiscoveryTrait/config.jelly @@ -1,4 +1,10 @@ + + + + + + From 8a7de390d172f74ed18c1d57ab5b7b6ee0d1a874 Mon Sep 17 00:00:00 2001 From: dodo920306 Date: Fri, 23 Jan 2026 11:58:01 +0800 Subject: [PATCH 02/10] Initialize tag time boundaries with default values Tag time boundaries are primitive long which cannot be NULL, so the `@CheckForNull` annotations on them are useless and thus removed. Instead, default values `-1L` are applied to initialize them. Signed-off-by: dodo920306 --- src/main/java/jenkins/plugins/git/GitSCMSourceContext.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/GitSCMSourceContext.java b/src/main/java/jenkins/plugins/git/GitSCMSourceContext.java index 805876fd29..87fb2623f4 100644 --- a/src/main/java/jenkins/plugins/git/GitSCMSourceContext.java +++ b/src/main/java/jenkins/plugins/git/GitSCMSourceContext.java @@ -96,11 +96,9 @@ public class GitSCMSourceContext, R extends @NonNull private String remoteName = AbstractGitSCMSource.DEFAULT_REMOTE_NAME; - @CheckForNull - private long atLeastTagCommitTimeMillis; + private long atLeastTagCommitTimeMillis = -1L; - @CheckForNull - private long atMostTagCommitTimeMillis; + private long atMostTagCommitTimeMillis = -1L; /** * Constructor. From 77c116892126b955f77745bcef973ae6177e30fd Mon Sep 17 00:00:00 2001 From: dodo920306 Date: Fri, 23 Jan 2026 12:09:19 +0800 Subject: [PATCH 03/10] Handle errors when parsing tag day limits If users input values that are not numbers to TagDiscoveryTrait day limits, an uncaught exception will be thrown for trying to parse them to long, which is dangerous and should be prevented. Signed-off-by: dodo920306 --- .../java/jenkins/plugins/git/GitSCMSourceContext.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/GitSCMSourceContext.java b/src/main/java/jenkins/plugins/git/GitSCMSourceContext.java index 87fb2623f4..0819df53c2 100644 --- a/src/main/java/jenkins/plugins/git/GitSCMSourceContext.java +++ b/src/main/java/jenkins/plugins/git/GitSCMSourceContext.java @@ -372,8 +372,12 @@ public final List asRefSpecs() { } private long getTagCommitTimeLimitMillisFromDays(String limitDays) { - long tagCommitTimeLimit = Long.parseLong(StringUtils.defaultIfBlank(limitDays, "-1")); - return tagCommitTimeLimit < 0 ? -1L : TimeUnit.DAYS.toMillis(tagCommitTimeLimit); + try { + long tagCommitTimeLimit = Long.parseLong(StringUtils.defaultIfBlank(limitDays, "-1")); + return tagCommitTimeLimit < 0 ? -1L : TimeUnit.DAYS.toMillis(tagCommitTimeLimit); + } catch (NumberFormatException e) { + return -1L; + } } @SuppressWarnings("unchecked") From d20c7eda8f2923c9148078934307f6c8c96f7b45 Mon Sep 17 00:00:00 2001 From: dodo920306 Date: Fri, 23 Jan 2026 13:48:59 +0800 Subject: [PATCH 04/10] Add lower bonds to tag time boundaries Add lower bonds "0" to tag time boundaries on UI. Moreover, for backward compatibility, the default value of `atMostDays` is removed. Signed-off-by: dodo920306 --- .../jenkins/plugins/git/traits/TagDiscoveryTrait/config.jelly | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/jenkins/plugins/git/traits/TagDiscoveryTrait/config.jelly b/src/main/resources/jenkins/plugins/git/traits/TagDiscoveryTrait/config.jelly index 70e46bd717..a39235b14e 100644 --- a/src/main/resources/jenkins/plugins/git/traits/TagDiscoveryTrait/config.jelly +++ b/src/main/resources/jenkins/plugins/git/traits/TagDiscoveryTrait/config.jelly @@ -2,9 +2,9 @@ - + - + From df42f96bc0bdda5e105874037335b222e88469a4 Mon Sep 17 00:00:00 2001 From: dodo920306 Date: Fri, 23 Jan 2026 13:54:43 +0800 Subject: [PATCH 05/10] Log messages for skipping tags Signed-off-by: dodo920306 --- .../jenkins/plugins/git/AbstractGitSCMSource.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java b/src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java index 260234f6f9..846678b377 100644 --- a/src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java +++ b/src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java @@ -796,13 +796,19 @@ private void discoverTags(final Repository repository, if (atLeastMillis >= 0L || atMostMillis >= 0L) { if (atMostMillis >= 0L && atLeastMillis > atMostMillis) { /* Invalid. It's impossible for any tag to satisfy this. */ + listener.getLogger().format(" Skipping tag %s: invalid age range (min > max)%n", tagName); continue; } - long tagAge = System.currentTimeMillis() - lastModified; - if (atMostMillis >= 0L && tagAge > atMostMillis) { + long tagAgeMillis = System.currentTimeMillis() - lastModified; + long tagAgeDays = TimeUnit.MILLISECONDS.toDays(tagAgeMillis); + if (atMostMillis >= 0L && tagAgeMillis > atMostMillis) { + listener.getLogger().format(" Skipping tag %s: too old (%d days, max %d days)%n", + tagName, tagAgeDays, TimeUnit.MILLISECONDS.toDays(atMostMillis)); continue; } - if (atLeastMillis >= 0L && tagAge < atLeastMillis) { + if (atLeastMillis >= 0L && tagAgeMillis < atLeastMillis) { + listener.getLogger().format(" Skipping tag %s: too new (%d days, min %d days)%n", + tagName, tagAgeDays, TimeUnit.MILLISECONDS.toDays(atLeastMillis)); continue; } } From 2dea2d76bd04ae4254e918b939ae10a2eb8ccfbd Mon Sep 17 00:00:00 2001 From: dodo920306 Date: Fri, 23 Jan 2026 14:58:15 +0800 Subject: [PATCH 06/10] Fix tag age filtering to work correctly with annotated tags Use tag creation time instead of commit time when filtering tags by age. For annotated tags, extract the tagger timestamp; for lightweight tags, fall back to commit time. Both values are converted to milliseconds for consistent comparison. Signed-off-by: dodo920306 --- .../jenkins/plugins/git/AbstractGitSCMSource.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java b/src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java index 846678b377..960cbe4b9e 100644 --- a/src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java +++ b/src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java @@ -109,9 +109,7 @@ import org.eclipse.jgit.lib.FileMode; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.Repository; -import org.eclipse.jgit.revwalk.RevCommit; -import org.eclipse.jgit.revwalk.RevTree; -import org.eclipse.jgit.revwalk.RevWalk; +import org.eclipse.jgit.revwalk.*; import org.eclipse.jgit.transport.RefSpec; import org.eclipse.jgit.transport.URIish; import org.eclipse.jgit.treewalk.TreeWalk; @@ -170,7 +168,7 @@ public abstract class AbstractGitSCMSource extends SCMSource { public AbstractGitSCMSource() { } - + @Deprecated public AbstractGitSCMSource(String id) { setId(id); @@ -790,9 +788,11 @@ 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()); - + RevObject tag = walk.parseAny(ref.getValue()); + long lastModified = tag instanceof RevTag ? + ((RevTag) tag).getTaggerIdent().getWhenAsInstant().toEpochMilli() : + /* For lightweight tags, there will be no RevTag object */ + TimeUnit.SECONDS.toMillis(((RevCommit) tag).getCommitTime()); if (atLeastMillis >= 0L || atMostMillis >= 0L) { if (atMostMillis >= 0L && atLeastMillis > atMostMillis) { /* Invalid. It's impossible for any tag to satisfy this. */ From ff5e2cd44a9e7907582b89f0f65103304feef329 Mon Sep 17 00:00:00 2001 From: dodo920306 Date: Fri, 23 Jan 2026 16:31:19 +0800 Subject: [PATCH 07/10] Add a unit-test for AbstractGitSCMSource Signed-off-by: dodo920306 --- .../plugins/git/AbstractGitSCMSourceTest.java | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/test/java/jenkins/plugins/git/AbstractGitSCMSourceTest.java b/src/test/java/jenkins/plugins/git/AbstractGitSCMSourceTest.java index 1524ebab11..de5c1012ba 100644 --- a/src/test/java/jenkins/plugins/git/AbstractGitSCMSourceTest.java +++ b/src/test/java/jenkins/plugins/git/AbstractGitSCMSourceTest.java @@ -36,6 +36,7 @@ import java.util.Set; import java.util.TreeMap; import java.util.UUID; +import java.util.stream.Collectors; import jenkins.plugins.git.junit.jupiter.WithGitSampleRepo; import jenkins.plugins.git.traits.BranchDiscoveryTrait; @@ -291,6 +292,31 @@ void retrieveHeadsSupportsTagDiscovery_onlyTagsWithoutBranchDiscoveryTrait() thr assertEquals("[SCMHead{'annotated'}, SCMHead{'lightweight'}]", source.fetch(listener).toString()); } + @Issue("JENKINS-64810") + @Test + void retrieveHeadsSupportsTagDiscovery_withTagAgeRestrictions() throws Exception { + assumeTrue(isTimeAvailable(), "Test class max time " + MAX_SECONDS_FOR_THESE_TESTS + " exceeded"); + sampleRepo.init(); + sampleRepo.write("file", "initial"); + sampleRepo.git("commit", "--all", "--message=initial"); + sampleRepo.git("tag", "test-tag"); + + GitSCMSource source = new GitSCMSource(sampleRepo.toString()); + TaskListener listener = StreamTaskListener.fromStderr(); + + source.setTraits(Collections.singletonList(new TagDiscoveryTrait())); + assertThat(source.fetch(listener).stream().map(SCMHead::getName).collect(Collectors.toSet()), contains("test-tag")); + + source.setTraits(Collections.singletonList(new TagDiscoveryTrait(null, "0"))); + assertThat(source.fetch(listener).stream().map(SCMHead::getName).collect(Collectors.toSet()), not(contains("test-tag"))); + + source.setTraits(Collections.singletonList(new TagDiscoveryTrait("1", null))); + assertThat(source.fetch(listener).stream().map(SCMHead::getName).collect(Collectors.toSet()), not(contains("test-tag"))); + + source.setTraits(Collections.singletonList(new TagDiscoveryTrait("1", "0"))); + assertThat(source.fetch(listener), empty()); + } + @Issue("JENKINS-45953") @Test void retrieveRevisions() throws Exception { From fa788b3126e103501e88688d23a0b3ffe4990f27 Mon Sep 17 00:00:00 2001 From: dodo920306 Date: Fri, 23 Jan 2026 16:36:43 +0800 Subject: [PATCH 08/10] Test nonnumeric values for TagDiscoveryTrait boundaries Signed-off-by: dodo920306 --- .../java/jenkins/plugins/git/AbstractGitSCMSourceTest.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/test/java/jenkins/plugins/git/AbstractGitSCMSourceTest.java b/src/test/java/jenkins/plugins/git/AbstractGitSCMSourceTest.java index de5c1012ba..9f0a164da5 100644 --- a/src/test/java/jenkins/plugins/git/AbstractGitSCMSourceTest.java +++ b/src/test/java/jenkins/plugins/git/AbstractGitSCMSourceTest.java @@ -315,6 +315,9 @@ void retrieveHeadsSupportsTagDiscovery_withTagAgeRestrictions() throws Exception source.setTraits(Collections.singletonList(new TagDiscoveryTrait("1", "0"))); assertThat(source.fetch(listener), empty()); + + source.setTraits(Collections.singletonList(new TagDiscoveryTrait("apple", "banana"))); + assertThat(source.fetch(listener).stream().map(SCMHead::getName).collect(Collectors.toSet()), contains("test-tag")); } @Issue("JENKINS-45953") From 1c59f5312fdf5d12c07fa79b3c816a58495d9303 Mon Sep 17 00:00:00 2001 From: dodo920306 Date: Mon, 26 Jan 2026 15:24:15 +0800 Subject: [PATCH 09/10] Add help messages for tag time boundaries Signed-off-by: dodo920306 --- .../TagDiscoveryTrait/help-atLeastDays.html | 15 +++++++++++++++ .../TagDiscoveryTrait/help-atMostDays.html | 16 ++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 src/main/resources/jenkins/plugins/git/traits/TagDiscoveryTrait/help-atLeastDays.html create mode 100644 src/main/resources/jenkins/plugins/git/traits/TagDiscoveryTrait/help-atMostDays.html diff --git a/src/main/resources/jenkins/plugins/git/traits/TagDiscoveryTrait/help-atLeastDays.html b/src/main/resources/jenkins/plugins/git/traits/TagDiscoveryTrait/help-atLeastDays.html new file mode 100644 index 0000000000..9bef6280f8 --- /dev/null +++ b/src/main/resources/jenkins/plugins/git/traits/TagDiscoveryTrait/help-atLeastDays.html @@ -0,0 +1,15 @@ +
+ Minimum age of tags (in days) to include when discovering tags. + Tags newer than this value are ignored. + Tag age is calculated from the tag creation / commit timestamp to the time the + scan runs. + Leave this field blank to not filter out tags based on a minimum age + (no lower age bound). + Examples: +
    +
  • 7 – ignore tags created in the last 7 days (only tags at least 7 days old are used).
  • +
  • 0 – do not ignore tags for being too new (equivalent to leaving it blank).
  • +
+ When used together with Ignore tags older than (atMostDays), + this value should be less than or equal to the older than value to define a valid age range. +
diff --git a/src/main/resources/jenkins/plugins/git/traits/TagDiscoveryTrait/help-atMostDays.html b/src/main/resources/jenkins/plugins/git/traits/TagDiscoveryTrait/help-atMostDays.html new file mode 100644 index 0000000000..638c243129 --- /dev/null +++ b/src/main/resources/jenkins/plugins/git/traits/TagDiscoveryTrait/help-atMostDays.html @@ -0,0 +1,16 @@ +
+ Maximum age of tags (in days) to include when discovering tags. + Tags older than this value are ignored. + Tag age is calculated from the tag creation / commit timestamp to the time the + scan runs. + Leave this field blank to not filter out tags based on a maximum age + (no upper age bound). + Examples: +
    +
  • 7 – ignore tags older than 7 days (only tags from the last 7 days are used).
  • +
  • 30 – ignore tags older than 30 days (only tags from the last 30 days are used).
  • +
+ When used together with Ignore tags newer than (atLeastDays), + this value should be greater than or equal to the newer than value so that the + age range is consistent. +
From 1abea7a529b38d3fa600376690a0aedf50e4c19e Mon Sep 17 00:00:00 2001 From: dodo920306 Date: Tue, 27 Jan 2026 09:47:35 +0800 Subject: [PATCH 10/10] Revert "Fix tag age filtering to work correctly with annotated tags" This reverts commit 2dea2d76bd04ae4254e918b939ae10a2eb8ccfbd. Signed-off-by: dodo920306 --- .../jenkins/plugins/git/AbstractGitSCMSource.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java b/src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java index 960cbe4b9e..068401d95e 100644 --- a/src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java +++ b/src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java @@ -109,7 +109,9 @@ import org.eclipse.jgit.lib.FileMode; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.Repository; -import org.eclipse.jgit.revwalk.*; +import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.jgit.revwalk.RevTree; +import org.eclipse.jgit.revwalk.RevWalk; import org.eclipse.jgit.transport.RefSpec; import org.eclipse.jgit.transport.URIish; import org.eclipse.jgit.treewalk.TreeWalk; @@ -788,11 +790,9 @@ private void discoverTags(final Repository repository, } count++; final String tagName = StringUtils.removeStart(ref.getKey(), Constants.R_TAGS); - RevObject tag = walk.parseAny(ref.getValue()); - long lastModified = tag instanceof RevTag ? - ((RevTag) tag).getTaggerIdent().getWhenAsInstant().toEpochMilli() : - /* For lightweight tags, there will be no RevTag object */ - TimeUnit.SECONDS.toMillis(((RevCommit) tag).getCommitTime()); + RevCommit commit = walk.parseCommit(ref.getValue()); + final long lastModified = TimeUnit.SECONDS.toMillis(commit.getCommitTime()); + if (atLeastMillis >= 0L || atMostMillis >= 0L) { if (atMostMillis >= 0L && atLeastMillis > atMostMillis) { /* Invalid. It's impossible for any tag to satisfy this. */