-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
initial bc-github integration sample application
- Loading branch information
Showing
27 changed files
with
1,793 additions
and
0 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
/target | ||
/local | ||
target/ | ||
# Eclipse, Netbeans and IntelliJ files | ||
/.* | ||
/**/.* | ||
!.gitignore | ||
/nbproject | ||
*.ipr | ||
*.iws | ||
*.iml | ||
|
||
# Repository wide ignore mac DS_Store files | ||
.DS_Store | ||
|
||
# Created by Zanata | ||
/org.uberfire | ||
/org.dashbuilder | ||
|
||
# Live editing asciidoc leaves .html files behind in the source dir | ||
uberfire-docs/src/main/asciidoc/*.html | ||
**/dependency-reduced-pom.xml |
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,45 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
|
||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
|
||
<parent> | ||
<groupId>me.porcelli.bc-github-integration</groupId> | ||
<artifactId>bc-github-integration-parent</artifactId> | ||
<version>1.0-SNAPSHOT</version> | ||
<relativePath>../pom.xml</relativePath> | ||
</parent> | ||
|
||
<artifactId>bc-github-githook</artifactId> | ||
<packaging>jar</packaging> | ||
|
||
<name>bc-github-githook</name> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>org.eclipse.jgit</groupId> | ||
<artifactId>org.eclipse.jgit</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.kohsuke</groupId> | ||
<artifactId>github-api</artifactId> | ||
</dependency> | ||
</dependencies> | ||
|
||
<build> | ||
<plugins> | ||
<plugin> | ||
<artifactId>maven-jar-plugin</artifactId> | ||
<version>3.1.0</version> | ||
<configuration> | ||
<archive> | ||
<manifest> | ||
<mainClass>porcelli.me.git.integration.githook.GitHook</mainClass> | ||
</manifest> | ||
</archive> | ||
</configuration> | ||
</plugin> | ||
</plugins> | ||
</build> | ||
</project> |
119 changes: 119 additions & 0 deletions
119
bc-github-githook/src/main/java/porcelli/me/git/integration/githook/GitHook.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,119 @@ | ||
package porcelli.me.git.integration.githook; | ||
|
||
import java.io.File; | ||
import java.io.IOException; | ||
import java.nio.file.Path; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.Set; | ||
|
||
import org.eclipse.jgit.api.Git; | ||
import org.eclipse.jgit.api.ListBranchCommand; | ||
import org.eclipse.jgit.api.errors.GitAPIException; | ||
import org.eclipse.jgit.lib.ObjectId; | ||
import org.eclipse.jgit.lib.Ref; | ||
import org.eclipse.jgit.lib.Repository; | ||
import org.eclipse.jgit.lib.StoredConfig; | ||
import org.eclipse.jgit.revwalk.RevCommit; | ||
import org.eclipse.jgit.revwalk.RevWalk; | ||
import org.eclipse.jgit.storage.file.FileRepositoryBuilder; | ||
import org.eclipse.jgit.transport.RefSpec; | ||
import porcelli.me.git.integration.githook.command.GetPreviousCommitCommand; | ||
import porcelli.me.git.integration.githook.command.GetRepoName; | ||
import porcelli.me.git.integration.githook.command.SetupRemote; | ||
import porcelli.me.git.integration.githook.command.SquashCommand; | ||
import porcelli.me.git.integration.githook.command.TrackingStatus; | ||
import porcelli.me.git.integration.githook.command.TrackingStatusCommand; | ||
import porcelli.me.git.integration.githook.github.GitHubCredentials; | ||
import porcelli.me.git.integration.githook.github.GitHubIntegration; | ||
|
||
import static java.util.Comparator.comparing; | ||
|
||
public class GitHook { | ||
|
||
public static void main(String[] args) throws IOException, GitAPIException { | ||
final Path currentPath = new File("").toPath().toAbsolutePath(); | ||
final String parentFolderName = currentPath.getParent().getName(currentPath.getParent().getNameCount() - 1).toString(); | ||
if (parentFolderName.equalsIgnoreCase("system")) { | ||
return; | ||
} | ||
final Repository repo = new FileRepositoryBuilder() | ||
.setGitDir(currentPath.toFile()) | ||
.build(); | ||
|
||
final Git git = new Git(repo); | ||
final StoredConfig storedConfig = repo.getConfig(); | ||
final Set<String> remotes = storedConfig.getSubsections("remote"); | ||
|
||
final GitHubCredentials ghCredentials = new GitHubCredentials(); | ||
final GitHubIntegration integration = new GitHubIntegration(ghCredentials); | ||
|
||
if (remotes.isEmpty()) { | ||
new SetupRemote(ghCredentials, integration).execute(git, currentPath); | ||
return; | ||
} | ||
|
||
final List<Ref> branches = git.branchList().setListMode(ListBranchCommand.ListMode.ALL).call(); | ||
final RevWalk revWalk = new RevWalk(git.getRepository()); | ||
|
||
branches.stream() | ||
.map(branch -> { | ||
try { | ||
return revWalk.parseCommit(branch.getObjectId()); | ||
} catch (Exception e) { | ||
throw new RuntimeException(e); | ||
} | ||
}) | ||
.max(comparing((RevCommit commit) -> commit.getAuthorIdent().getWhen())) | ||
.ifPresent(newestCommit -> { | ||
RevCommit commit = newestCommit; | ||
try { | ||
boolean hasSyncOnCommitMessage = commit.getFullMessage().trim().startsWith("sync:"); | ||
|
||
if (hasSyncOnCommitMessage) { | ||
final Map<ObjectId, String> branchesAffected = git | ||
.nameRev() | ||
.addPrefix("refs/heads") | ||
.add(commit) | ||
.call(); | ||
|
||
for (String remoteName : remotes) { | ||
final String remoteURL = storedConfig.getString("remote", remoteName, "url"); | ||
for (String ref : branchesAffected.values()) { | ||
final String remote = storedConfig.getString("branch", ref, "remote"); | ||
|
||
if (remote == null) { | ||
git.push() | ||
.setRefSpecs(new RefSpec(ref + ":" + ref)) | ||
.setRemote(remoteURL) | ||
.setCredentialsProvider(ghCredentials.getCredentials()) | ||
.call(); | ||
storedConfig.setString("branch", ref, "remote", "origin"); | ||
storedConfig.setString("branch", ref, "merge", "refs/heads/" + ref); | ||
storedConfig.save(); | ||
if (ref.contains("-pr")) { | ||
integration.createPR(new GetRepoName().execute(currentPath), ref); | ||
} | ||
} else { | ||
git.fetch().call(); | ||
final TrackingStatusCommand trackingStatusCommand = new TrackingStatusCommand(git.getRepository()); | ||
final TrackingStatus counts = trackingStatusCommand.getCounts(ref); | ||
if (counts.getCommitsAhead() > 0) { | ||
final RevCommit id = new GetPreviousCommitCommand(repo).execute(commit, counts.getCommitsAhead() - 1); | ||
new SquashCommand(git, ref, id.name(), commit.getFullMessage()).execute(commit); | ||
} | ||
git.push() | ||
.setRefSpecs(new RefSpec(ref + ":" + ref)) | ||
.setRemote(remoteURL) | ||
.setCredentialsProvider(ghCredentials.getCredentials()) | ||
.call(); | ||
} | ||
} | ||
} | ||
} | ||
} catch (Exception e) { | ||
throw new RuntimeException(e); | ||
} | ||
}); | ||
} | ||
} |
5 changes: 5 additions & 0 deletions
5
bc-github-githook/src/main/java/porcelli/me/git/integration/githook/command/Command.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,5 @@ | ||
package porcelli.me.git.integration.githook.command; | ||
|
||
public interface Command { | ||
|
||
} |
24 changes: 24 additions & 0 deletions
24
...k/src/main/java/porcelli/me/git/integration/githook/command/GetPreviousCommitCommand.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,24 @@ | ||
package porcelli.me.git.integration.githook.command; | ||
|
||
import java.io.IOException; | ||
|
||
import org.eclipse.jgit.lib.Repository; | ||
import org.eclipse.jgit.revwalk.RevCommit; | ||
|
||
public class GetPreviousCommitCommand implements Command { | ||
|
||
private final Repository repo; | ||
|
||
public GetPreviousCommitCommand(Repository repo) { | ||
this.repo = repo; | ||
} | ||
|
||
public RevCommit execute(final RevCommit commit, | ||
final int commitsAhead) throws IOException { | ||
RevCommit result = commit; | ||
for (int i = 0; i < commitsAhead; i++) { | ||
result = repo.parseCommit(repo.resolve(result.getParent(0).name())); | ||
} | ||
return result; | ||
} | ||
} |
13 changes: 13 additions & 0 deletions
13
bc-github-githook/src/main/java/porcelli/me/git/integration/githook/command/GetRepoName.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,13 @@ | ||
package porcelli.me.git.integration.githook.command; | ||
|
||
import java.nio.file.Path; | ||
|
||
public class GetRepoName implements Command { | ||
|
||
public String execute(final Path currentPath) { | ||
return currentPath | ||
.getName(currentPath.getNameCount() - 1) | ||
.toString() | ||
.replaceAll(".git", ""); | ||
} | ||
} |
82 changes: 82 additions & 0 deletions
82
...b-githook/src/main/java/porcelli/me/git/integration/githook/command/RefUpdateCommand.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,82 @@ | ||
/* | ||
* Copyright 2016 Red Hat, Inc. and/or its affiliates. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package porcelli.me.git.integration.githook.command; | ||
|
||
import java.io.IOException; | ||
import java.text.MessageFormat; | ||
|
||
import org.eclipse.jgit.api.Git; | ||
import org.eclipse.jgit.api.errors.ConcurrentRefUpdateException; | ||
import org.eclipse.jgit.api.errors.JGitInternalException; | ||
import org.eclipse.jgit.internal.JGitText; | ||
import org.eclipse.jgit.lib.Constants; | ||
import org.eclipse.jgit.lib.ObjectId; | ||
import org.eclipse.jgit.lib.RefUpdate; | ||
import org.eclipse.jgit.revwalk.RevCommit; | ||
|
||
import static java.util.Objects.requireNonNull; | ||
|
||
public class RefUpdateCommand implements Command { | ||
|
||
private final Git git; | ||
private final String refName; | ||
private final RevCommit commit; | ||
|
||
public RefUpdateCommand(final Git git, | ||
final String refName, | ||
final RevCommit commit) { | ||
this.git = requireNonNull(git); | ||
this.refName = requireNonNull(refName); | ||
this.commit = commit; | ||
} | ||
|
||
public void execute(final RevCommit lastCommit) | ||
throws IOException, ConcurrentRefUpdateException { | ||
requireNonNull(lastCommit, "lastCommit"); | ||
final RefUpdate ru = git.getRepository().updateRef("refs/heads/" + refName); | ||
if (commit == null) { | ||
ru.setExpectedOldObjectId(ObjectId.zeroId()); | ||
} else { | ||
ru.setExpectedOldObjectId(commit); | ||
} | ||
ru.setNewObjectId(lastCommit.getId()); | ||
ru.setRefLogMessage(commit.getFullMessage(), false); | ||
forceUpdate(ru, commit.getId()); | ||
} | ||
|
||
private void forceUpdate(final RefUpdate ru, | ||
final ObjectId id) throws IOException, ConcurrentRefUpdateException { | ||
final RefUpdate.Result rc = ru.forceUpdate(); | ||
switch (rc) { | ||
case NEW: | ||
case FORCED: | ||
case FAST_FORWARD: | ||
case NO_CHANGE: | ||
break; | ||
case REJECTED: | ||
case LOCK_FAILURE: | ||
throw new ConcurrentRefUpdateException(JGitText.get().couldNotLockHEAD, | ||
ru.getRef(), | ||
rc); | ||
default: | ||
throw new JGitInternalException(MessageFormat.format(JGitText.get().updatingRefFailed, | ||
Constants.HEAD, | ||
id.toString(), | ||
rc)); | ||
} | ||
} | ||
} |
47 changes: 47 additions & 0 deletions
47
bc-github-githook/src/main/java/porcelli/me/git/integration/githook/command/SetupRemote.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,47 @@ | ||
package porcelli.me.git.integration.githook.command; | ||
|
||
import java.io.IOException; | ||
import java.nio.file.Path; | ||
import java.util.List; | ||
|
||
import porcelli.me.git.integration.githook.github.GitHubCredentials; | ||
import porcelli.me.git.integration.githook.github.GitHubIntegration; | ||
import org.eclipse.jgit.api.Git; | ||
import org.eclipse.jgit.api.ListBranchCommand; | ||
import org.eclipse.jgit.api.errors.GitAPIException; | ||
import org.eclipse.jgit.lib.Ref; | ||
import org.eclipse.jgit.lib.StoredConfig; | ||
import org.eclipse.jgit.transport.CredentialsProvider; | ||
|
||
public class SetupRemote implements Command { | ||
|
||
private final GitHubCredentials credentials; | ||
private final GitHubIntegration integration; | ||
|
||
public SetupRemote(GitHubCredentials credentials, | ||
GitHubIntegration integration) { | ||
this.credentials = credentials; | ||
this.integration = integration; | ||
} | ||
|
||
public String execute(final Git git, | ||
final Path currentPath) throws IOException, GitAPIException { | ||
final StoredConfig storedConfig = git.getRepository().getConfig(); | ||
|
||
final String repoName = new GetRepoName().execute(currentPath); | ||
final String remoteURL = integration.createRepository(repoName); | ||
storedConfig.setString("remote", "origin", "url", remoteURL); | ||
storedConfig.setString("remote", "origin", "fetch", "+refs/heads/*:refs/remotes/origin/*"); | ||
|
||
final List<Ref> branches = git.branchList().setListMode(ListBranchCommand.ListMode.ALL).call(); | ||
for (Ref value : branches) { | ||
final String shortName = value.getName().replaceAll("refs/heads/", ""); | ||
storedConfig.setString("branch", shortName, "remote", "origin"); | ||
storedConfig.setString("branch", shortName, "merge", "refs/heads/" + shortName); | ||
} | ||
storedConfig.save(); | ||
|
||
git.push().setCredentialsProvider(credentials.getCredentials()).call(); | ||
return repoName; | ||
} | ||
} |
Oops, something went wrong.