/*******************************************************************************
* Copyright (c) Sep 6, 2011 Zend Technologies Ltd.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*******************************************************************************/
package org.zend.sdkcli.internal.commands;
import java.io.File;
import java.io.PrintWriter;
import java.net.URISyntaxException;
import java.text.MessageFormat;
import org.eclipse.jgit.api.CloneCommand;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.api.errors.InvalidRemoteException;
import org.eclipse.jgit.api.errors.JGitInternalException;
import org.eclipse.jgit.api.errors.TransportException;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.TextProgressMonitor;
import org.eclipse.jgit.transport.CredentialsProvider;
import org.eclipse.jgit.transport.URIish;
import org.zend.sdkcli.internal.mapping.CliMappingLoader;
import org.zend.sdkcli.internal.options.Option;
import org.zend.sdklib.application.ZendProject;
/**
* Clones repository based on provided remote repository URL.
*
* @author Wojciech Galanciak, 2011
*
*/
public class GitCloneProjectCommand extends AbstractGitCommand {
private static final String GITHUB_HOST = "github.com";
private static final String REPO = "r";
private static final String DIR = "d";
private static final String BRANCH = "b";
@Option(opt = REPO, required = true, description = "Repository to clone from", argName = "repository")
public String getRepo() {
final String value = getValue(REPO);
return value;
}
@Option(opt = DIR, required = false, description = "The optional directory associated with the clone operation. If the directory isn't set, a name associated with the source uri will be used", argName = "directory")
public String getDir() {
final String value = getValue(DIR);
return value;
}
@Option(opt = BRANCH, required = false, description = " the initial branch to check out when cloning the repository", argName = "branch")
public String getBranch() {
final String value = getValue(BRANCH);
return value;
}
@Override
protected boolean doExecute() {
CloneCommand clone = new CloneCommand();
String repo = getRepo();
clone.setURI(repo);
clone.setRemote(Constants.DEFAULT_REMOTE_NAME);
File dir = null;
try {
dir = getDirectory(repo);
if (dir.exists()) {
File[] children = dir.listFiles();
if (children != null && children.length > 0) {
getLogger()
.error(MessageFormat
.format("Destination folder {0} already exists and is not an empty directory",
dir.getName()));
return false;
}
}
clone.setDirectory(dir);
} catch (URISyntaxException e) {
getLogger().error(e);
return false;
}
clone.setProgressMonitor(new TextProgressMonitor(new PrintWriter(
System.out)));
if (!askUsername()) {
getLogger().info(
MessageFormat.format("Cloning into {0}...", dir.getName()));
}
String branch = getBranch();
if (branch != null) {
clone.setBranch(Constants.R_HEADS + branch);
}
try {
URIish uri = new URIish(repo);
if (GITHUB_HOST.equals(uri.getHost())
&& "git".equals(uri.getUser())) {
if (!prepareSSHFactory()) {
return false;
}
} else {
CredentialsProvider credentials = getCredentials(repo);
if (credentials != null) {
clone.setCredentialsProvider(credentials);
}
}
clone.call();
} catch (JGitInternalException e) {
delete(dir);
getLogger().error(e);
return false;
} catch (URISyntaxException e) {
delete(dir);
getLogger().error(e);
return false;
} catch (InvalidRemoteException e) {
delete(dir);
getLogger().error(e);
return false;
} catch (TransportException e) {
delete(dir);
String repoUrl = getRepo();
if (repoUrl != null && repoUrl.startsWith("https")) {
if (e.getMessage().endsWith("not authorized")) {
setAskUsername(true);
return doExecute();
}
}
getLogger().error(e);
return false;
} catch (GitAPIException e) {
delete(dir);
getLogger().error(e);
return false;
}
updateProject(dir);
getLogger().info(
"The remote name used to keep track of the cloned repository is: "
+ Constants.DEFAULT_REMOTE_NAME);
return true;
}
private void updateProject(File directory) {
ZendProject project = new ZendProject(directory, new CliMappingLoader());
try {
final boolean update = project.update(null);
if (update) {
getLogger()
.debug("Project is updated with deployment descriptor and properties");
}
} catch (IllegalArgumentException e) {
getLogger().error(e);
}
}
protected File getDirectory(String repo) throws URISyntaxException {
String dir = getDir();
if (dir != null) {
File dirFile = new File(dir);
if (dirFile.isAbsolute()) {
return dirFile;
}
return new File(getCurrentDirectory(), dir);
}
URIish uri = new URIish(repo);
return new File(getCurrentDirectory(), uri.getHumanishName());
}
private boolean delete(File file) {
if (file != null && file.exists() && file.isDirectory()) {
String[] children = file.list();
for (int i = 0; i < children.length; i++) {
boolean result = delete(new File(file, children[i]));
if (!result) {
return false;
}
}
}
return file.delete();
}
}