package org.jenkinsci.plugins.openshift;
import static org.apache.commons.io.FileUtils.copyDirectoryToDirectory;
import static org.apache.commons.io.FileUtils.copyFile;
import static org.apache.commons.io.FileUtils.copyFileToDirectory;
import static org.apache.commons.io.FileUtils.forceDelete;
import static org.apache.commons.io.FilenameUtils.getName;
import static org.apache.commons.lang3.StringUtils.isEmpty;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.List;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.PushCommand;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.api.errors.InvalidRemoteException;
import org.eclipse.jgit.api.errors.TransportException;
import org.eclipse.jgit.lib.TextProgressMonitor;
import org.eclipse.jgit.transport.JschConfigSessionFactory;
import org.eclipse.jgit.transport.OpenSshConfig.Host;
import org.eclipse.jgit.transport.PushResult;
import org.eclipse.jgit.transport.SshSessionFactory;
import org.eclipse.jgit.util.FS;
import org.jenkinsci.plugins.openshift.util.Logger;
import com.jcraft.jsch.Session;
import com.openshift.client.IApplication;
import org.jenkinsci.plugins.openshift.util.Utils;
/**
* @author Siamak Sadeghianfar <ssadeghi@redhat.com>
*/
public class GitClient {
private Logger log = Logger.NOOP;
private IApplication app;
public GitClient(IApplication app) {
super();
this.app = app;
}
public void setLogger(Logger log) {
this.log = log;
}
public void deploy(List<String> deployments, File workingCopyDir, String relativeDeployDir)
throws IOException, GitAPIException {
deploy(deployments, workingCopyDir, relativeDeployDir, "", "");
}
/**
* Deploy the deployment units through Git.
*
* @param deployments list of packages to be deployed
* @param workingCopyDir where git repo will be cloned
* @param relativeDeployDir the relative path in the working copy where the deployment packages should be copied
* @param commitMsg git commit message
* @param openshiftDirectory The configured value that contains an openshift directory structure.
* This value should be the Absolute Path to the directory. The Parameter can
* also be null or empty
*
* @throws IOException
* @throws GitAPIException
* @throws TransportException
* @throws InvalidRemoteException
*/
public void deploy(List<String> deployments, File workingCopyDir, String relativeDeployDir, String commitMsg, String openshiftDirectory) throws IOException, GitAPIException {
// Sanity Check
if(openshiftDirectory != null && !StringUtils.isEmpty(openshiftDirectory))
{
if(!openshiftDirectory.startsWith(File.separator))
throw new IllegalArgumentException("openshiftDirectory is not null or empty and is not an absolute path.");
}
// clone repo
log.info("Cloning '" + app.getName() + "' [" + app.getGitUrl() + "] to " + workingCopyDir);
SshSessionFactory.setInstance(new JschConfigSessionFactory() {
@Override
protected void configure(Host hc, Session session) {
session.setConfig("StrictHostKeyChecking", "no");
}
// Use private key defined in Jenkins System Configuration
@Override
protected JSch createDefaultJSch( FS fs ) throws JSchException {
JSch defaultJSch = super.createDefaultJSch( fs );
defaultJSch.addIdentity(Utils.getSSHPrivateKey() );
return defaultJSch;
}
});
Git git = Git.cloneRepository().setURI(app.getGitUrl()).setDirectory(workingCopyDir).call();
// clean git repo
File[] removeList = workingCopyDir.listFiles();
for (File fileToRemove : removeList) {
if (!fileToRemove.getName().equals(".git") && !fileToRemove.getName().equals(".openshift")) {
log.info("Deleting '" + fileToRemove.getName() + "'");
forceDelete(fileToRemove);
}
}
// copy deployment
File dest = new File(workingCopyDir.getAbsoluteFile() + relativeDeployDir);
copyDeploymentPackages(deployments, dest);
// Handle OpenShift Directory
File dotOpenshiftSource = null;
if(!isEmpty(openshiftDirectory)) {
if (!openshiftDirectory.endsWith("openshift")) {
// Examine the current directory if it contains an openshift or .openshift directory
File directory = new File(openshiftDirectory);
File[] dirContents = directory.listFiles(new FilenameFilter() {
public boolean accept(File dir, String name) {
if (name.equals(".") || name.equals(".."))
return false;
else
return true;
}
});
for (File file : dirContents) {
if(file.getName().endsWith("openshift")) {
dotOpenshiftSource = file;
break;
}
}
} else {
dotOpenshiftSource = new File(openshiftDirectory); // Absolute Path
}
if (dotOpenshiftSource != null && dotOpenshiftSource.exists()) {
for (File source : dotOpenshiftSource.listFiles()) {
copyDirectoryToDirectory(source, new File(workingCopyDir + File.separator + ".openshift"));
}
}
}
// add directories
git.add().addFilepattern(".").call();
// commit changes
log.info("Committing repo");
git.commit().setAll(true).setMessage(commitMsg).call();
log.info("Pushing to upstream");
PushCommand pushCommand = git.push();
pushCommand.setProgressMonitor(new TextProgressMonitor(new OutputStreamWriter(System.out)));
Iterable<PushResult> pushResults = pushCommand.call();
for(PushResult result : pushResults)
System.out.println(result.toString());
}
private void copyDeploymentPackages(List<String> deployments, File dest) throws IOException {
if (deployments.size() == 1) {
String deployment = deployments.get(0);
File destFile = new File(dest, "ROOT." + FilenameUtils.getExtension(deployment));
copyFile(new File(deployment), destFile);
log.info("Deployment '" + FilenameUtils.getName(deployment) + "' copied to '" + destFile.getName() + "'");
} else {
for (String deployment : deployments) {
copyFileToDirectory(new File(deployment), dest);
log.info("Deployment '" + getName(deployment) + "' copied to '" + dest.getName() + "'");
}
}
}
}