/*
* Copyright 2008-2010 Xebia and the original author or authors.
*
* 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 fr.xebia.workshop.git;
import com.github.api.v2.schema.Repository;
import com.github.api.v2.services.GitHubServiceFactory;
import com.github.api.v2.services.RepositoryService;
import org.apache.commons.io.FileUtils;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.ResetCommand;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.revwalk.RevCommit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
/**
* Creates github repositories. You can specify a source github repository and a GitRepositoryHandler to modify the
* repository before to push it.
* <p/>
*
* If you use HTTP way, you have to use a login/password access.<p/>
* If you use SSH way, you can use oauth token for github access and you have to configure a private key which has
* access to the target account.<p/>
* To configure ssh key :<br/>
* http://help.github.com/linux-set-up-git/<br/>
* http://help.github.com/ssh-issues/<br/>
* http://help.github.com/multiple-ssh-keys/<br/>
*
*/
public class GithubRepositoriesCreator {
private static final Logger logger = LoggerFactory.getLogger(GithubRepositoriesCreator.class);
public static final String GIT_TMP_REPO_PREFIX = "git-tmp-repo-";
public static final String JAVA_IO_TMPDIR = "java.io.tmpdir";
public static final String DEFAULT_TMPDIR = "temp";
private final GitHubServiceFactory gitHubServiceFactory;
private String sourceGitHubRepositoryUrl;
private List<GithubCreateRepositoryRequest> createRequests = new ArrayList<GithubCreateRepositoryRequest>();
private GithubCreateRepositoryRequest defaultGithubCreateRepositoryRequest = new GithubCreateRepositoryRequest();
public GithubRepositoriesCreator() {
gitHubServiceFactory = GitHubServiceFactory.newInstance();
}
public GithubRepositoriesCreator(GitHubServiceFactory factory) {
gitHubServiceFactory = factory;
}
/**
* Use cases just for demo
*
* @param args
*/
public static void main(String[] args) {
String[] teams = {"team1", "team2"};
if (GithubCreateRepositoryRequest.AccessType.HTTP.name().equals(args[0])) {
String passwd = args[1];
final GithubRepositoriesCreator creator = new GithubRepositoriesCreator()
.fromGithubRepository("git://github.com/xebia-france-training/xebia-petclinic-lite.git")
.onAccountName("xebia-guest")
.withAccessType(GithubCreateRepositoryRequest.AccessType.HTTP)
.withGithubLoginPassword("xebia-guest", passwd);
for (String team : teams) {
creator.addGithubCreateRepositoryRequest(new GithubCreateRepositoryRequest()
.toRepositoryName("xebia-petclinic-lite-" + team)
.withGitRepositoryHandler(new UpdatePomFileAndCommit(team)));
}
creator.createRepositories();
}
if (GithubCreateRepositoryRequest.AccessType.SSH.name().equals(args[0])) {
String token = args[1];
final GithubRepositoriesCreator jobCreator = new GithubRepositoriesCreator()
.fromGithubRepository("git@github.com:xebia-france-training/xebia-petclinic-lite.git")
.onAccountName("xebia-guest")
.atHost("github-xebia-guest")
.withGithubOAuthToken(token);
for (String team : teams) {
jobCreator.addGithubCreateRepositoryRequest(new GithubCreateRepositoryRequest()
.toRepositoryName("xebia-petclinic-lite-" + team)
.withGitRepositoryHandler(new UpdatePomFileAndCommit(team)));
}
jobCreator.createRepositories();
}
}
public GithubRepositoriesCreator fromGithubRepository(String sourceGitHubRepositoryUrl) {
this.sourceGitHubRepositoryUrl = sourceGitHubRepositoryUrl;
return this;
}
public GithubRepositoriesCreator addGithubCreateRepositoryRequest(GithubCreateRepositoryRequest githubCreateRepositoryRequest) {
this.createRequests.add(githubCreateRepositoryRequest);
return this;
}
public GithubRepositoriesCreator withDescription(String defaultDescription) {
this.defaultGithubCreateRepositoryRequest.withDescription(defaultDescription);
return this;
}
public GithubRepositoriesCreator withHomepage(String defaultHomepage) {
this.defaultGithubCreateRepositoryRequest.withHomepage(defaultHomepage);
return this;
}
public GithubRepositoriesCreator onAccountName(String defaultTargetAccountName) {
this.defaultGithubCreateRepositoryRequest.onAccountName(defaultTargetAccountName);
return this;
}
public GithubRepositoriesCreator withAccessType(GithubCreateRepositoryRequest.AccessType defaultAccessType) {
this.defaultGithubCreateRepositoryRequest.withAccessType(defaultAccessType);
return this;
}
public GithubRepositoriesCreator atHost(String defaultHost) {
this.defaultGithubCreateRepositoryRequest.atHost(defaultHost);
return this;
}
public GithubRepositoriesCreator withGithubLoginPassword(String defaultLogin, String defaultPassword) {
this.defaultGithubCreateRepositoryRequest.withGithubLoginPassword(defaultLogin, defaultPassword);
return this;
}
public GithubRepositoriesCreator withGithubOAuthToken(String defaulGithubOAuthToken) {
this.defaultGithubCreateRepositoryRequest.withGithubOAuthToken(defaulGithubOAuthToken);
return this;
}
public List<Repository> createRepositories() {
List<Repository> repositories = new ArrayList<Repository>();
File tmpRepoDir = getTmpLocalRepositoryDir();
Git git = initGitLocalRepository(tmpRepoDir);
for (GithubCreateRepositoryRequest createRequest : createRequests) {
try {
createRequest.initWithDefaultGithubCreateRepositoryRequest(defaultGithubCreateRepositoryRequest);
Repository repository = createGithubRepository(createRequest);
if (createRequest.getGitRepositoryHandler() != null) {
processGitRepositoryHandler(git, createRequest);
}
repositories.add(repository);
} catch (Exception e) {
logger.error("Could not create repository: " + createRequest, e);
}
}
// clean
try {
FileUtils.deleteDirectory(tmpRepoDir);
} catch (IOException e) {
logger.warn("cannot delete local temporary git repository", e);
}
createRequests.clear();
return repositories;
}
private void processGitRepositoryHandler(Git git, GithubCreateRepositoryRequest createRequest) {
try {
RevCommit revCommit = git.log().call().iterator().next();
//call delegate
createRequest.getGitRepositoryHandler().updateGitRepository(git, createRequest);
logger.info("Local repository is pushing on remote {}", createRequest.getGithubRepositoryUrl());
git.push()
.setCredentialsProvider(createRequest.getCredentialsProvider())
.setRemote(createRequest.getGithubRepositoryUrl())
.call();
git.reset()
.setRef(revCommit.getName())
.setMode(ResetCommand.ResetType.HARD)
.call();
} catch (IOException e) {
throw new RuntimeException("cannot perform git operation", e);
} catch (GitAPIException e) {
throw new RuntimeException("cannot perform git operation", e);
}
}
private Git initGitLocalRepository(File tmpRepoDir) {
Git git;
if (sourceGitHubRepositoryUrl != null) {
logger.info("Repository {} is cloning into {}", new Object[] {sourceGitHubRepositoryUrl, tmpRepoDir.getAbsolutePath()});
git = Git.cloneRepository()
.setURI(sourceGitHubRepositoryUrl)
.setDirectory(tmpRepoDir)
.call();
} else {
logger.info("Repository is initiating into {}", tmpRepoDir);
git = Git.init()
.setDirectory(tmpRepoDir)
.call();
}
return git;
}
private Repository createGithubRepository(GithubCreateRepositoryRequest createRepositoryRequest) {
RepositoryService repositoryService = gitHubServiceFactory.createRepositoryService();
repositoryService.setAuthentication(createRepositoryRequest.getAuthentication());
logger.info("Repository {} is creating on github account {}", createRepositoryRequest.getRepositoryName(), createRepositoryRequest.getAccountName());
return repositoryService.createRepository(createRepositoryRequest.getRepositoryName(), createRepositoryRequest.getDescription(), createRepositoryRequest.getHomepage(), Repository.Visibility.PUBLIC);
}
private File getTmpLocalRepositoryDir() {
String systemTmpDirStr = System.getProperty(JAVA_IO_TMPDIR, DEFAULT_TMPDIR);
File systemTmpDir = new File(systemTmpDirStr);
File tmpLocalRepositoryDir = new File(systemTmpDir, GIT_TMP_REPO_PREFIX + UUID.randomUUID());
if (!tmpLocalRepositoryDir.mkdir()) {
throw new IllegalStateException("Cannot create temporary directory." + systemTmpDir.getAbsolutePath());
}
return tmpLocalRepositoryDir;
}
}