Skip to content

Commit eeb403d

Browse files
committed
[JENKINS-76426] add lazy iteration APIs
1 parent e5631e0 commit eeb403d

File tree

10 files changed

+611
-8
lines changed

10 files changed

+611
-8
lines changed

src/main/java/com/cloudbees/jenkins/plugins/bitbucket/BitbucketSCMSource.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,7 @@ class Skip extends IOException {
407407
final Set<String> livePRs = new HashSet<>();
408408
int count = 0;
409409
Map<Boolean, Set<ChangeRequestCheckoutStrategy>> strategies = request.getPRStrategies();
410-
for (final BitbucketPullRequest pull : request.getPullRequests()) {
410+
for (final BitbucketPullRequest pull : request.getPullRequestsLazy()) {
411411
String originalBranchName = pull.getSource().getBranch().getName();
412412
request.listener().getLogger().printf(
413413
"Checking PR-%s from %s and %s %s%n",
@@ -511,7 +511,7 @@ private void retrieveBranches(final BitbucketSCMSourceRequest request) throws IO
511511
request.listener().getLogger().println("Looking up " + fullName + " for branches");
512512

513513
int count = 0;
514-
for (final BitbucketBranch branch : request.getBranches()) {
514+
for (final BitbucketBranch branch : request.getBranchesLazy()) {
515515
request.listener().getLogger().println("Checking branch " + branch.getName() + " from " + fullName);
516516
count++;
517517
BranchSCMHead head = new BranchSCMHead(branch.getName());
@@ -529,7 +529,7 @@ private void retrieveTags(final BitbucketSCMSourceRequest request) throws IOExce
529529
request.listener().getLogger().println("Looking up " + fullName + " for tags");
530530

531531
int count = 0;
532-
for (final BitbucketBranch tag : request.getTags()) {
532+
for (final BitbucketBranch tag : request.getTagsLazy()) {
533533
request.listener().getLogger().println("Checking tag " + tag.getName() + " from " + fullName);
534534
count++;
535535
BitbucketTagSCMHead head = new BitbucketTagSCMHead(tag.getName(), tag.getDateMillis());

src/main/java/com/cloudbees/jenkins/plugins/bitbucket/BitbucketSCMSourceRequest.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,11 @@ public final Iterable<BitbucketPullRequest> getPullRequests() throws IOException
511511
return Util.fixNull(pullRequests);
512512
}
513513

514+
@NonNull
515+
public final Iterable<BitbucketPullRequest> getPullRequestsLazy() {
516+
return (Iterable<BitbucketPullRequest>) getBitbucketApiClient().getPullRequestsLazy();
517+
}
518+
514519
/**
515520
* Retrieves the full details of a pull request.
516521
* @param id The id of the pull request to retrieve the details about.
@@ -559,6 +564,11 @@ public final Iterable<BitbucketBranch> getBranches() throws IOException, Interru
559564
return Util.fixNull(branches);
560565
}
561566

567+
@NonNull
568+
public final Iterable<BitbucketBranch> getBranchesLazy() {
569+
return (Iterable<BitbucketBranch>) getBitbucketApiClient().getBranchesLazy();
570+
}
571+
562572
/**
563573
* Provides the requests with the tag details.
564574
*
@@ -585,6 +595,12 @@ public final Iterable<BitbucketBranch> getTags() throws IOException, Interrupted
585595
return Util.fixNull(tags);
586596
}
587597

598+
@NonNull
599+
public final Iterable<BitbucketBranch> getTagsLazy() {
600+
return (Iterable<BitbucketBranch>) getBitbucketApiClient().getTagsLazy();
601+
}
602+
603+
588604
/**
589605
* {@inheritDoc}
590606
*/

src/main/java/com/cloudbees/jenkins/plugins/bitbucket/api/BitbucketApi.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,14 @@ public interface BitbucketApi extends AutoCloseable {
8181
@NonNull
8282
BitbucketPullRequest getPullRequestById(@NonNull Integer id) throws IOException;
8383

84+
/**
85+
* Returns the pull requests in the repository lazily
86+
*
87+
* @return the list of pull requests in the repository.
88+
*/
89+
@NonNull
90+
Iterable<? extends BitbucketPullRequest> getPullRequestsLazy();
91+
8492
/**
8593
* Returns the repository details.
8694
*
@@ -139,6 +147,14 @@ boolean checkPathExists(@NonNull String branchOrHash, @NonNull String path)
139147
@NonNull
140148
List<? extends BitbucketBranch> getBranches() throws IOException, InterruptedException;
141149

150+
/**
151+
* Returns the branches in the repository lazily.
152+
*
153+
* @return an interable of branches in the repository.
154+
*/
155+
@NonNull
156+
Iterable<? extends BitbucketBranch> getBranchesLazy();
157+
142158
/**
143159
* Returns a tag in the repository.
144160
*
@@ -158,6 +174,16 @@ boolean checkPathExists(@NonNull String branchOrHash, @NonNull String path)
158174
@NonNull
159175
List<? extends BitbucketBranch> getTags() throws IOException, InterruptedException;
160176

177+
/**
178+
* Returns the tags in the repository lazily
179+
*
180+
* @return an iterable of tags in the repository.
181+
* @throws IOException if there was a network communications error.
182+
* @throws InterruptedException if interrupted while waiting on remote communications.
183+
*/
184+
@NonNull
185+
Iterable<? extends BitbucketBranch> getTagsLazy();
186+
161187
/**
162188
* Resolve the commit object given its hash.
163189
*
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* The MIT License
3+
*
4+
* Copyright (c) 2026, CloudBees, Inc.
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in
14+
* all copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22+
* THE SOFTWARE.
23+
*/
24+
package com.cloudbees.jenkins.plugins.bitbucket.api.paginated;
25+
26+
public interface PageFetcher<T> {
27+
PaginatedList<T> fetchNextPage();
28+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* The MIT License
3+
*
4+
* Copyright (c) 2026, CloudBees, Inc.
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in
14+
* all copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22+
* THE SOFTWARE.
23+
*/
24+
package com.cloudbees.jenkins.plugins.bitbucket.api.paginated;
25+
26+
import java.util.Iterator;
27+
import java.util.function.Supplier;
28+
29+
public class PaginatedIterable<T> implements Iterable<T> {
30+
31+
private final Supplier<PageFetcher<T>> fetcherSupplier;
32+
33+
public PaginatedIterable(Supplier<PageFetcher<T>> fetcherSupplier) {
34+
this.fetcherSupplier = fetcherSupplier;
35+
}
36+
37+
@Override
38+
public Iterator<T> iterator() {
39+
return new PaginatedIterator<>(fetcherSupplier.get());
40+
}
41+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*
2+
* The MIT License
3+
*
4+
* Copyright (c) 2026, CloudBees, Inc.
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in
14+
* all copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22+
* THE SOFTWARE.
23+
*/
24+
package com.cloudbees.jenkins.plugins.bitbucket.api.paginated;
25+
26+
import java.util.Iterator;
27+
import java.util.NoSuchElementException;
28+
29+
public class PaginatedIterator<T> implements Iterator<T> {
30+
31+
private final PageFetcher<T> fetcher;
32+
private Iterator<T> currentIterator;
33+
private boolean lastPageReached = false;
34+
35+
public PaginatedIterator(PageFetcher<T> fetcher) {
36+
this.fetcher = fetcher;
37+
loadNextPage();
38+
}
39+
40+
private void loadNextPage() {
41+
if (this.lastPageReached) return;
42+
43+
PaginatedList<T> page = fetcher.fetchNextPage();
44+
45+
this.lastPageReached = page.isLastPage();
46+
47+
if (page.hasItems()) {
48+
currentIterator = page.iterator();
49+
} else {
50+
currentIterator = null;
51+
}
52+
}
53+
54+
@Override
55+
public boolean hasNext() {
56+
if (currentIterator != null && currentIterator.hasNext()) {
57+
return true;
58+
} else if (!this.lastPageReached) {
59+
loadNextPage();
60+
return hasNext();
61+
}
62+
63+
return false;
64+
}
65+
66+
@Override
67+
public T next() {
68+
if (!hasNext()) {
69+
throw new NoSuchElementException();
70+
}
71+
return currentIterator.next();
72+
}
73+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* The MIT License
3+
*
4+
* Copyright (c) 2026, CloudBees, Inc.
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in
14+
* all copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22+
* THE SOFTWARE.
23+
*/
24+
package com.cloudbees.jenkins.plugins.bitbucket.api.paginated;
25+
26+
import java.util.Iterator;
27+
import java.util.List;
28+
29+
public class PaginatedList<T> implements Iterable<T> {
30+
31+
private List<T> items;
32+
private boolean isLastPage;
33+
34+
public PaginatedList(List<T> items, boolean isLastPage) {
35+
this.items = items;
36+
this.isLastPage = isLastPage;
37+
}
38+
39+
public boolean hasItems() {
40+
return items != null && !items.isEmpty();
41+
}
42+
43+
public boolean isLastPage() {
44+
return isLastPage;
45+
}
46+
47+
@Override
48+
public Iterator<T> iterator() {
49+
return items.iterator();
50+
}
51+
}

0 commit comments

Comments
 (0)