-
Notifications
You must be signed in to change notification settings - Fork 736
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
58 changed files
with
5,424 additions
and
36 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
129 changes: 129 additions & 0 deletions
129
src/main/java/org/kohsuke/github/GHRepositoryForkBuilder.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
135
src/test/java/org/kohsuke/github/GHRepositoryForkBuilderTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.