package br.ic.uff.gems.oceano.ourico.experimento.VCS;
import br.ic.uff.gems.oceano.ourico.experimento.VCS.type.DistributedVCS;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Comparator;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.logging.Level;
import java.util.logging.Logger;
import sandbox.experimento.utils.FileBasedVCS;
import sandbox.experimento.utils.FileUtils;
/**
* Encapsulates Git commands
*
* @author kann
*/
public class Mercurial extends FileBasedVCS implements DistributedVCS {
/**
* Git program
*/
private String HG = "hg";
/**
* Init repository
*/
private static final String INIT = "init";
/**
* Import command
*/
private static final String PUSH = "push";
/**
* pull command
*/
private static String PULL = "pull";
/**
* Export command
*/
private static final String EXPORT = "export";
/**
* Check-out command
*/
private static final String CLONE = "clone";
/**
* Check-in command
*/
private static final String COMMIT = "commit";
/**
* Log command
*/
private static final String LOG = "log";
/**
* Show command
*/
private static final String SHOW = "show";
/**
* Add command
*/
private static final String ADD = "add";
/**
* Remove command
*/
private static final String REMOVE = "rm";
/**
* Remove command
*/
private static final String REMOTE = "remote";
/**
* origin branch
*/
private static final String ORIGIN = "origin";
/**
* master branch
*/
private static final String MASTER = "master";
/**
* && command
*/
private static final String AND = "&&";
/**
* CD command
*/
private static final String CD = "cd";
/**
* Message switch
*/
private static final String MESSAGE = "-m";
/**
* Revision switch
*/
private static final String REVISION = "--revision";
/**
* Non interactive switch
*/
private static final String NON_INTERACTIVE = "--quiet";
/**
* Verbose switch
*/
private static final String VERBOSE = "--verbose";
/**
* Force switch
*/
private static final String FORCE = "--force";
private static final String TIP = "tip";
/**
* Singleton instance
*/
private static Mercurial instance = null;
private int countPush = 10;
private int countPushOrigin = 10;
private boolean delDir = true;
/**
* Singleton constructor
*/
private Mercurial() {
}
public void setPushOriginal(String push){
if(push == null || push.trim().isEmpty()){
countPushOrigin = 1;
}else{
countPushOrigin = Integer.parseInt(push.trim());
}
countPush = countPushOrigin;
}
/**
* Provides the singleton instance
*/
public synchronized static Mercurial getInstance() {
if (instance == null) {
instance = new Mercurial();
}
return instance;
}
/**
* command: hg init <repository>
*/
public void create(String repository) throws IOException {
Process p = Runtime.getRuntime().exec(new String[]{"mkdir", repository});
try {
p.waitFor();
} catch (InterruptedException ex) {
Logger.getLogger(Mercurial.class.getName()).log(Level.SEVERE, null, ex);
}
String[] command = {HG, INIT};
long before = System.currentTimeMillis();
run(command, null, null, new File(repository));
long after = System.currentTimeMillis();
}
/**
* command: hg push <repository>
*/
public void insert(String exportedWorkspace, String studyRepository) throws IOException {
/*
Copia o diretorio exportado para o repositorio de estudo
*/
//
File wp = new File(exportedWorkspace);
String[] command = null;
//
File studyRep = new File(studyRepository);
long before = System.currentTimeMillis();
// FileUtils.copyDirectory(wp, studyRep);
command = new String[]{HG, INIT, exportedWorkspace};
run(command, null, null, null);
//command = (new String[]{HG, REMOTE, ADD, ORIGIN, studyRepository});
//run(command, null, null, wp);
command = (new String[]{HG, ADD, "."});
run(command, null, null, wp);
command = (new String[]{HG, COMMIT, MESSAGE, "Initial Commit"});
run(command, null, null, wp);
command = new String[]{HG, PUSH, studyRepository};
run(command, null, null, wp);
long after = System.currentTimeMillis();
delDir = true;
}
/**
* command: git export --revision <configuration> --non-interactive <repository> <workspace>
*/
public void export(String configuration, String repository, String workspace) throws IOException {
String[] command = {HG, EXPORT, REVISION, configuration, NON_INTERACTIVE, repository, workspace};
run(command, null, null, null);
}
/**
* command: hg clone <repository> <workspace>
*/
public void clone(String configuration, String repository, String workspace) throws IOException {
String[] command = {HG, CLONE, repository, workspace};
long before = System.currentTimeMillis();
run(command, null, null, null);
long after = System.currentTimeMillis();
}
/**
* command: "hg commit -m <message>"
*/
public void checkin(String workspace) throws IOException {
String[] command = {HG, COMMIT, MESSAGE, "message"};
File wp = new File(workspace);
long before = System.currentTimeMillis();
run(command, null, null, wp);
long after = System.currentTimeMillis();
}
public void push(File workSpace, String destinationRepositoryURL) throws IOException {
long before = System.currentTimeMillis();
run(new String[]{HG, PUSH, FORCE, destinationRepositoryURL}, null, null, workSpace);
long after = System.currentTimeMillis();
}
/**
* command: "hg log -pr tip"
*/
public void list(String repository) throws IOException {
String[] command = {HG, LOG, "-pr", TIP};
long before = System.currentTimeMillis();
run(command, null, null, new File(repository));
long after = System.currentTimeMillis();
}
/**
* command: "git add <path>"
*/
protected void add(String path) throws IOException {
String[] command = {HG, ADD, path};
run(command, null, null, null);
}
protected void add(String path, File pathWorkSpace) throws IOException {
String[] command = {HG, ADD, path};
run(command, null, null, pathWorkSpace);
}
protected void addAll(String path) throws IOException {
String[] command = {HG, ADD, "."};
run(command, null, null, new File(path));
}
/**
* command: "git rm <path> --force --non-interactive"
*/
protected void remove(String path) throws IOException {
// String[] command = {GIT, FORCE, NON_INTERACTIVE, REMOVE, path};
String[] command = {HG, REMOVE, path, "-r"};
run(command, null, null, null);
}
protected void remove(File fileRemove, File workSpace) throws IOException {
String[] command = null;
String path = fileRemove.getParent();
// if(fileRemove.isDirectory()){
// command = new String[]{HG, REMOVE, fileRemove.getPath(), "-f"};
// }else{
command = new String[]{HG, REMOVE, fileRemove.getPath(), "-f"};
// }
run(command, null, null, workSpace);
new File(path).mkdirs();
// if(!fileRemove.isDirectory()){
// String nameFile = fileRemove.getParent();
//// nameFile = nameFile.substring(0, nameFile.lastIndexOf("\\"));
// File f = new File(nameFile);
// if(!f.exists()){
// f.mkdir();
// }
// }
}
public File createWorkSpace(String workspaceStudy) {
File f = new File(workspaceStudy);
FileUtils.recursiveDelete(f);
try {
Runtime.getRuntime().exec(new String[]{HG, INIT, workspaceStudy}).waitFor();
} catch (IOException ex) {
ex.printStackTrace();
throw new RuntimeException(ex);
} catch (InterruptedException ex) {
ex.printStackTrace();
throw new RuntimeException(ex);
}
return f;
}
@Override
public void merge(File workspace, File studyWorkspace) {
if (workspace.isDirectory()) {
// "Note: this comparator imposes orderings that are inconsistent with equals."
Comparator<File> comparator = new Comparator<File>() {
public int compare(File f1, File f2) {
int result = (f1.isDirectory() ? 0 : 1) - (f2.isDirectory() ? 0 : 1);
if (result == 0) {
result = f1.getName().compareTo(f2.getName());
}
return result;
}
};
// New Workspace
SortedSet<File> newWorkspace = new TreeSet<File>(comparator);
newWorkspace.addAll(Arrays.asList(workspace.listFiles()));
// Old Workspace
SortedSet<File> oldWorkspace = new TreeSet<File>(comparator);
if(studyWorkspace.listFiles() != null){
// System.err.println("REPOSITORY WITHOUT FILES "+studyWorkspace);
oldWorkspace.addAll(Arrays.asList(studyWorkspace.listFiles()));
}else{
// oldWorkspace.add(studyWorkspace);
return;
}
File mercurialControlDirectory = new File(studyWorkspace, ".hg");
oldWorkspace.remove(mercurialControlDirectory);
// Removed Files
SortedSet<File> removedFiles = new TreeSet<File>(comparator);
removedFiles.addAll(oldWorkspace);
removedFiles.removeAll(newWorkspace);
// Added Files
SortedSet<File> addedFiles = new TreeSet<File>(comparator);
addedFiles.addAll(newWorkspace);
addedFiles.removeAll(oldWorkspace);
// Keeped Source Files
SortedSet<File> keepedSourceFiles = new TreeSet<File>(comparator);
keepedSourceFiles.addAll(newWorkspace);
keepedSourceFiles.retainAll(oldWorkspace);
// Keeped Target Files
SortedSet<File> keepedTargetFiles = new TreeSet<File>(comparator);
keepedTargetFiles.addAll(oldWorkspace);
keepedTargetFiles.retainAll(newWorkspace);
// Remove all "Removed Files"
for (File fileToRemove : removedFiles) {
try {
remove(fileToRemove, studyWorkspace);
// if(fileToRemove.exists()) {
// if (!fileToRemove.delete()) {
// System.err.println("NÃO PODE REMOVER O ARQUIVO " + fileToRemove.getPath());
// run(new String[]{GIT, REMOVE, fileToRemove.getPath(), "-q", "-f", "-r"}, null, null, studyWorkspace);
// } else {
// System.out.println("DELECÃO COM SUCESSO depois de dar um git rm");
// run(new String[]{GIT, REMOVE, fileToRemove.getPath(), "-q", "-f", "-r"}, null, null, studyWorkspace);
// }
// } else {
// System.out.println("DELECÃO COM SUCESSO "+fileToRemove.getPath());
// }
} catch (Exception e) {
// try {
// run(new String[]{"rm", "-rf", fileToRemove.getName()}, null, null, null);
//// fileToRemove.mkdirs();
// } catch (IOException ex) {
// Logger.global.info("Could not remove RM -RF" + fileToRemove + ": " + e.getMessage());
// }
Logger.global.info("Could not remove file " + fileToRemove + ": " + e.getMessage());
}
}
// // Add all "Added Files"
for (File fileToAdd : addedFiles) {
File newFile = new File(studyWorkspace, fileToAdd.getName());
try {
if(fileToAdd.renameTo(newFile)){
// while (!fileToAdd.renameTo(newFile)) {
// String nameFile = newFile.getAbsolutePath();
// nameFile = nameFile.substring(0, nameFile.lastIndexOf("\\"));
// new File(nameFile).mkdir();
// }
// add(newFile.getPath(), studyWorkspace);
System.out.println("add " + newFile.getPath());
}
} catch (Exception e) {
e.printStackTrace();
Logger.global.info("Could not add file " + newFile + ": " + e.getMessage());
}
}
// Run recursivelly for "Keeped Files"
for (File sourceFile : keepedSourceFiles) {
File targetFile = keepedTargetFiles.tailSet(sourceFile).first();
merge(sourceFile, targetFile);
}
} else {
studyWorkspace.delete();
workspace.renameTo(studyWorkspace);
}
}
public void plan(String studyRepositoryURL, File workspace, int countResivion, String workspaceStudy) throws Exception {
// List the repository
list(studyRepositoryURL);
File studyWorkspace = null;
if (delDir) {
delDir = false;
// Create study workspace
studyWorkspace = createWorkSpace(workspaceStudy);
}else{
studyWorkspace = new File(workspaceStudy);
}
// Clone the configuration
File clonedWorkspace = new File(workspace.getPath()+"HgClone");
FileUtils.recursiveDelete(clonedWorkspace);
clone("HEAD", studyRepositoryURL, clonedWorkspace.getAbsolutePath());
// Merge the configurations
merge(workspace, studyWorkspace);
addAll(studyWorkspace.getAbsolutePath());
// System.out.println("CHECKINNNNNNN \n");
checkin(studyWorkspace.getPath());
if (--countPush == 0 || countResivion == 0) {
push(studyWorkspace, studyRepositoryURL);
countPush = countPushOrigin;
FileUtils.recursiveDelete(clonedWorkspace);
}
}
public void setConfigureMainCommands(String path) {
HG = path+HG;
}
}