package jetbrains.mps.tool.gentest.plugin;
/*Generated by MPS */
import java.util.Set;
import jetbrains.mps.internal.collections.runtime.SetSequence;
import java.util.HashSet;
import java.io.File;
import jetbrains.mps.internal.collections.runtime.ISelector;
import java.util.List;
import jetbrains.mps.internal.collections.runtime.ListSequence;
import java.util.ArrayList;
import jetbrains.mps.internal.collections.runtime.Sequence;
import jetbrains.mps.internal.collections.runtime.IVisitor;
import difflib.Patch;
import difflib.DiffUtils;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.FileInputStream;
import jetbrains.mps.util.FileUtil;
import java.io.IOException;
import java.util.Arrays;
public class Differ {
private static final char SLASH_CHAR = '/';
private static final String SLASH = "/";
private Set<String> ignoredFiles = SetSequence.fromSetAndArray(new HashSet<String>(), "generated", "trace.info", "dependencies", ".dependencies", ".generated", ".debug");
private String[] retainedPaths;
private Set<File> excludedFiles;
public Differ(Set<String> retainedFilePaths, Set<File> excludedFiles) {
this.retainedPaths = SetSequence.fromSet(retainedFilePaths).select(new ISelector<String, String>() {
public String select(String it) {
return straighten(it);
}
}).sort(new ISelector<String, String>() {
public String select(String p) {
return p;
}
}, true).toListSequence().toGenericArray(String.class);
this.excludedFiles = excludedFiles;
}
public List<String> diff(String origPath, String revdPath) {
List<String> diffs = ListSequence.fromList(new ArrayList<String>());
if (origPath != null && revdPath != null) {
File orig = new File(origPath);
File revd = new File(revdPath);
if (orig.exists() && revd.exists() && orig.isDirectory() && revd.isDirectory()) {
diffDirs(orig, revd, diffs);
} else if (!(orig.exists()) && !(revd.exists())) {
ListSequence.fromList(diffs).addElement("None exists: " + orig + " or " + revd);
} else if (!(orig.exists())) {
ListSequence.fromList(diffs).addElement("Created: " + revd);
} else if (!(revd.exists())) {
if (!(isRetained(orig.getAbsolutePath()))) {
ListSequence.fromList(diffs).addElement("Removed: " + orig);
}
} else {
ListSequence.fromList(diffs).addElement("Something weird here: " + orig + " or here " + revd);
}
} else if (origPath != null) {
ListSequence.fromList(diffs).addElement("Removed: " + origPath);
} else if (revdPath != null) {
ListSequence.fromList(diffs).addElement("Created: " + revdPath);
} else {
ListSequence.fromList(diffs).addElement("Invalid input");
}
return diffs;
}
private void diffDirs(final File orig, File revd, final List<String> diffs) {
Iterable<String> onames = Sequence.fromArray(orig.list());
Iterable<String> rnames = Sequence.fromArray(revd.list());
if (Sequence.fromIterable(onames).disjunction(Sequence.fromIterable(rnames)).isNotEmpty()) {
Sequence.fromIterable(onames).subtract(Sequence.fromIterable(rnames)).visitAll(new IVisitor<String>() {
public void visit(String it) {
if (!(ignoredFile(it))) {
File itfile = new File(orig, it);
if (!(itfile.isDirectory()) || !(isRetained(itfile.getAbsolutePath()))) {
ListSequence.fromList(diffs).addElement("Removed: " + itfile);
}
}
}
});
Sequence.fromIterable(rnames).subtract(Sequence.fromIterable(onames)).visitAll(new IVisitor<String>() {
public void visit(String it) {
if (!(ignoredFile(it))) {
ListSequence.fromList(diffs).addElement("Created: " + new File(orig, it));
}
}
});
}
for (String name : Sequence.fromIterable(onames).intersect(Sequence.fromIterable(rnames))) {
if (ignoredFile(name)) {
continue;
}
File onext = new File(orig, name);
if (excluded(onext)) {
continue;
}
File rnext = new File(revd, name);
if (onext.isDirectory() == rnext.isDirectory()) {
if (!(onext.isDirectory())) {
List<String> olines = fileToStrings(onext);
List<String> rlines = fileToStrings(rnext);
if (ListSequence.fromList(olines).isNotEmpty() && ListSequence.fromList(rlines).isNotEmpty()) {
Patch patch = DiffUtils.diff(olines, rlines);
if (!(patch.getDeltas().isEmpty())) {
ListSequence.fromList(diffs).addSequence(ListSequence.fromList(DiffUtils.generateUnifiedDiff(onext.getPath(), rnext.getPath(), olines, patch, 5)));
}
}
} else {
diffDirs(onext, rnext, diffs);
}
} else {
ListSequence.fromList(diffs).addElement("Something weird here: " + onext + " or here " + rnext);
}
}
}
private boolean ignoredFile(String fileName) {
return SetSequence.fromSet(ignoredFiles).contains(fileName) || (fileName != null && fileName.startsWith(".hash"));
}
private boolean excluded(File file) {
return SetSequence.fromSet(excludedFiles).contains(file);
}
private List<String> fileToStrings(File f) {
List<String> result = ListSequence.fromList(new ArrayList<String>());
BufferedReader in = null;
try {
in = new BufferedReader(new InputStreamReader(new FileInputStream(f), FileUtil.DEFAULT_CHARSET));
String line;
while ((line = in.readLine()) != null) {
ListSequence.fromList(result).addElement(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (in != null) {
try {
in.close();
} catch (IOException ignore) {
}
}
}
return result;
}
private boolean isRetained(String dir) {
String path = asDir(straighten(dir));
int idx = Arrays.binarySearch(retainedPaths, path);
idx = (idx < 0 ? -1 - idx : idx);
return idx < retainedPaths.length && startsWith(retainedPaths[idx], path);
}
private String straighten(String path) {
return path.replace(File.separatorChar, SLASH_CHAR);
}
private String asDir(String path) {
return (path.endsWith(SLASH) ? path : path + SLASH);
}
private boolean startsWith(String path, String prefix) {
return path.startsWith(prefix) && (path.length() == prefix.length() || prefix.endsWith(SLASH) || path.charAt(prefix.length()) == SLASH_CHAR);
}
}