Skip to content

Commit

Permalink
add only fork default branch
Browse files Browse the repository at this point in the history
  • Loading branch information
Alaurant committed Dec 13, 2024
1 parent 58dcca1 commit aceb784
Show file tree
Hide file tree
Showing 58 changed files with 5,424 additions and 36 deletions.
51 changes: 16 additions & 35 deletions src/main/java/org/kohsuke/github/GHRepository.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.InterruptedIOException;
import java.io.Reader;
import java.net.URL;
import java.util.Arrays;
Expand Down Expand Up @@ -1458,23 +1457,11 @@ public PagedIterable<GHRepository> listForks(final ForkSort sort) {
* @return Newly forked repository that belong to you.
* @throws IOException
* the io exception
* @deprecated Use {@link #createFork()}
*/
@Deprecated
public GHRepository fork() throws IOException {
root().createRequest().method("POST").withUrlPath(getApiTailUrl("forks")).send();

// this API is asynchronous. we need to wait for a bit
for (int i = 0; i < 10; i++) {
GHRepository r = root().getMyself().getRepository(name);
if (r != null) {
return r;
}
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
throw (IOException) new InterruptedIOException().initCause(e);
}
}
throw new IOException(this + " was forked but can't find the new repository");
return this.createFork().create();
}

/**
Expand Down Expand Up @@ -1503,27 +1490,11 @@ public GHBranchSync sync(String branch) throws IOException {
* @return Newly forked repository that belong to you.
* @throws IOException
* the io exception
* @deprecated Use {@link #createFork()}
*/
@Deprecated
public GHRepository forkTo(GHOrganization org) throws IOException {
root().createRequest()
.method("POST")
.with("organization", org.getLogin())
.withUrlPath(getApiTailUrl("forks"))
.send();

// this API is asynchronous. we need to wait for a bit
for (int i = 0; i < 10; i++) {
GHRepository r = org.getRepository(name);
if (r != null) {
return r;
}
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
throw (IOException) new InterruptedIOException().initCause(e);
}
}
throw new IOException(this + " was forked into " + org.getLogin() + " but can't find the new repository");
return this.createFork().organization(org).create();
}

/**
Expand Down Expand Up @@ -3435,4 +3406,14 @@ public void deleteAutolink(int autolinkId) throws IOException {
.send();
}

/**
* Create fork gh repository fork builder.
* (https://docs.github.com/en/rest/repos/forks?apiVersion=2022-11-28#create-a-fork)
*
* @return the gh repository fork builder
*/
public GHRepositoryForkBuilder createFork() {
return new GHRepositoryForkBuilder(this);
}

}
129 changes: 129 additions & 0 deletions src/main/java/org/kohsuke/github/GHRepositoryForkBuilder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
package org.kohsuke.github;

import java.io.IOException;
import java.io.InterruptedIOException;

/**
* A builder pattern object for creating a fork of a repository.
*
* @see GHRepository#createFork() GHRepository#createFork()GHRepository#createFork()
* @see <a href="https://docs.github.com/en/rest/repos/forks#create-a-fork">Repository fork API</a>
*/
public class GHRepositoryForkBuilder {
private final GHRepository repo;
private final Requester req;
private String organization;
private String name;
private Boolean defaultBranchOnly;

/**
* Instantiates a new Gh repository fork builder.
*
* @param repo
* the repository
*/
GHRepositoryForkBuilder(GHRepository repo) {
this.repo = repo;
this.req = repo.root().createRequest();
}

/**
* Sets whether to fork only the default branch.
*
* @param defaultBranchOnly
* the default branch only
* @return the gh repository fork builder
*/
public GHRepositoryForkBuilder defaultBranchOnly(boolean defaultBranchOnly) {
this.defaultBranchOnly = defaultBranchOnly;
return this;
}

/**
* Specifies the target organization for the fork.
*
* @param organization
* the organization
* @return the gh repository fork builder
*/
public GHRepositoryForkBuilder organization(GHOrganization organization) {
this.organization = organization.getLogin();
return this;
}

/**
* Sets a custom name for the forked repository.
*
* @param name
* the desired repository name
* @return the builder
*/
public GHRepositoryForkBuilder name(String name) {
this.name = name;
return this;
}

/**
* Creates the fork with the specified parameters.
*
* @return the gh repository
* @throws IOException
* the io exception
*/
public GHRepository create() throws IOException {
if (defaultBranchOnly != null) {
req.with("default_branch_only", defaultBranchOnly);
}
if (organization != null) {
req.with("organization", organization);
}
if (name != null) {
req.with("name", name);
}

req.method("POST").withUrlPath(repo.getApiTailUrl("forks")).send();

// this API is asynchronous. we need to wait for a bit
for (int i = 0; i < 10; i++) {
GHRepository r = lookupForkedRepository();
if (r != null) {
return r;
}
sleep(3000);
}
throw new IOException(createTimeoutMessage());
}

private GHRepository lookupForkedRepository() throws IOException {
String repoName = name != null ? name : repo.getName();

if (organization != null) {
return repo.root().getOrganization(organization).getRepository(repoName);
}
return repo.root().getMyself().getRepository(repoName);
}

private void sleep(int millis) throws IOException {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
throw (IOException) new InterruptedIOException().initCause(e);
}
}

private String createTimeoutMessage() {
StringBuilder message = new StringBuilder(repo.getFullName());
message.append(" was forked");

if (organization != null) {
message.append(" into ").append(organization);
}

if (name != null) {
message.append(" with name ").append(name);
}

message.append(" but can't find the new repository");
return message.toString();
}
}
135 changes: 135 additions & 0 deletions src/test/java/org/kohsuke/github/GHRepositoryForkBuilderTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
package org.kohsuke.github;

import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.util.Map;

import static org.hamcrest.Matchers.*;

// TODO: Auto-generated Javadoc

/**
* The Class GHRepositoryForkBuilderTest.
*/
public class GHRepositoryForkBuilderTest extends AbstractGitHubWireMockTest {
private GHRepository repo;
private static final String TARGET_ORG = "nts-api-test-org";

/**
* Instantiates a new Gh repository fork builder test.
*/
public GHRepositoryForkBuilderTest() {
}

/**
* Sets up.
*
* @throws Exception
* the exception
*/
@Before
public void setUp() throws Exception {
repo = gitHub.getRepository("TestDitto/test-repo");
if (repo == null) {
throw new IllegalStateException("Failed to initialize repository");
}
}

private void verifyBasicForkProperties(GHRepository original,
GHRepository forked,
String expectedOwner,
String expectedName) throws IOException {
assertThat(forked, notNullValue());
assertThat(forked.getName(), equalTo(expectedName));
assertThat(forked.getOwner().getLogin(), equalTo(expectedOwner));
assertThat(forked.isFork(), is(true));
assertThat(forked.getParent().getFullName(), equalTo(original.getFullName()));
}

private void verifyBranches(GHRepository original, GHRepository forked, boolean defaultBranchOnly)
throws IOException {
Map<String, GHBranch> branches = forked.getBranches();
if (defaultBranchOnly) {
assertThat(branches.size(), equalTo(1));
} else {
assertThat(branches.size(), greaterThan(1));
}
assertThat(branches.containsKey(forked.getDefaultBranch()), is(true));
}

/**
* Test fork.
*
* @throws Exception
* the exception
*/
@Test
public void testFork() throws Exception {
// GHRepository forkedRepo = repo.createFork().create();
GHRepository forkedRepo = repo.fork();

Thread.sleep(30000);
verifyBasicForkProperties(repo, forkedRepo, gitHub.getMyself().getLogin(), repo.getName());
verifyBranches(repo, forkedRepo, false);

forkedRepo.delete();
}

/**
* Test fork to org.
*
* @throws Exception
* the exception
*/
@Test
public void testForkToOrg() throws Exception {
GHOrganization targetOrg = gitHub.getOrganization(TARGET_ORG);
// GHRepository forkedRepo = repo.createFork().organization(targetOrg).create();
GHRepository forkedRepo = repo.forkTo(targetOrg);

Thread.sleep(30000);
verifyBasicForkProperties(repo, forkedRepo, targetOrg.getLogin(), repo.getName());
verifyBranches(repo, forkedRepo, false);

forkedRepo.delete();
}

/**
* Test fork default branch only.
*
* @throws Exception
* the exception
*/
@Test
public void testForkDefaultBranchOnly() throws Exception {
GHRepository forkedRepo = repo.createFork().defaultBranchOnly(true).create();

Thread.sleep(30000);
verifyBasicForkProperties(repo, forkedRepo, gitHub.getMyself().getLogin(), repo.getName());
verifyBranches(repo, forkedRepo, true);

forkedRepo.delete();
}

/**
* Test fork changed name.
*
* @throws Exception
* the exception
*/
@Test
public void testForkChangedName() throws Exception {
String newRepoName = "new-fork";
GHRepository forkedRepo = repo.createFork().name(newRepoName).create();

Thread.sleep(30000);
assertThat(forkedRepo.getName(), equalTo(newRepoName));
verifyBasicForkProperties(repo, forkedRepo, gitHub.getMyself().getLogin(), newRepoName);
verifyBranches(repo, forkedRepo, false);

forkedRepo.delete();
}

}
3 changes: 2 additions & 1 deletion src/test/resources/no-reflect-and-serialization-list
Original file line number Diff line number Diff line change
Expand Up @@ -83,4 +83,5 @@ org.kohsuke.github.internal.EnumUtils
org.kohsuke.github.internal.Previews
org.kohsuke.github.EnterpriseManagedSupport
org.kohsuke.github.GHAutolink
org.kohsuke.github.GHAutolinkBuilder
org.kohsuke.github.GHAutolinkBuilder
org.kohsuke.github.GHRepositoryForkBuilder
Loading

0 comments on commit aceb784

Please sign in to comment.