mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
Merged WOLF-6 (WOLF.0.0) to 5.1.1 (5.1.1)
122680 mward: UTF-383: moved diff tool from update-tool to full-installer code base. Had erroneously added the code to the wrong project. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/services/full-installer/branches/5.1.1@123991 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -53,6 +53,37 @@
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>de.schlichtherle.truezip</groupId>
|
||||
<artifactId>truezip-driver-zip</artifactId>
|
||||
<version>7.7.9</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>de.schlichtherle.truezip</groupId>
|
||||
<artifactId>truezip-file</artifactId>
|
||||
<version>7.7.9</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>2.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-api</artifactId>
|
||||
<version>2.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-core</artifactId>
|
||||
<version>2.3</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<version>4.2.4.RELEASE</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2016 Alfresco Software, Ltd. All rights reserved.
|
||||
*
|
||||
* License rights for this program may be obtained from Alfresco Software, Ltd.
|
||||
* pursuant to a written agreement and any use of this program without such an
|
||||
* agreement is prohibited.
|
||||
*/
|
||||
package org.alfresco.update.tool.dircomp;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.Comparator;
|
||||
|
||||
/**
|
||||
* Provides a platform agnostic and consistent sorting mechanism
|
||||
* for {@link java.nio.file.Path} objects.
|
||||
*
|
||||
* @author Matt Ward
|
||||
*/
|
||||
public class CaseSensitivePathComparator implements Comparator<Path>
|
||||
{
|
||||
@Override
|
||||
public int compare(Path p1, Path p2)
|
||||
{
|
||||
String pathStr1 = p1.toString();
|
||||
String pathStr2 = p2.toString();
|
||||
return pathStr1.compareTo(pathStr2);
|
||||
}
|
||||
}
|
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright 2016 Alfresco Software, Ltd. All rights reserved.
|
||||
*
|
||||
* License rights for this program may be obtained from Alfresco Software, Ltd.
|
||||
* pursuant to a written agreement and any use of this program without such an
|
||||
* agreement is prohibited.
|
||||
*/
|
||||
package org.alfresco.update.tool.dircomp;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* File tree comparison tool interface.
|
||||
*
|
||||
* @author Matt Ward
|
||||
*/
|
||||
public interface FileTreeCompare
|
||||
{
|
||||
ResultSet compare(Path p1, Path p2);
|
||||
}
|
@@ -0,0 +1,241 @@
|
||||
/*
|
||||
* Copyright 2016 Alfresco Software, Ltd. All rights reserved.
|
||||
*
|
||||
* License rights for this program may be obtained from Alfresco Software, Ltd.
|
||||
* pursuant to a written agreement and any use of this program without such an
|
||||
* agreement is prohibited.
|
||||
*/
|
||||
package org.alfresco.update.tool.dircomp;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.update.tool.dircomp.exception.FileTreeCompareException;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
|
||||
import de.schlichtherle.truezip.file.TArchiveDetector;
|
||||
import de.schlichtherle.truezip.file.TConfig;
|
||||
import de.schlichtherle.truezip.file.TFile;
|
||||
import de.schlichtherle.truezip.file.TVFS;
|
||||
import de.schlichtherle.truezip.fs.archive.zip.ZipDriver;
|
||||
import de.schlichtherle.truezip.socket.sl.IOPoolLocator;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
|
||||
/**
|
||||
* Class capable of comparing two trees of files to determine which directories or
|
||||
* files appear in one tree and not the other, or whether a file that appears in
|
||||
* both has differences in its content.
|
||||
*
|
||||
* @author Matt Ward
|
||||
*/
|
||||
public class FileTreeCompareImpl implements FileTreeCompare
|
||||
{
|
||||
private static final Logger log = LogManager.getLogger(FileTreeCompareImpl.class);
|
||||
private final Set<String> ignorePaths = new HashSet<>();
|
||||
private final AntPathMatcher pathMatcher = new AntPathMatcher(File.separator);
|
||||
|
||||
public FileTreeCompareImpl()
|
||||
{
|
||||
this(new HashSet<String>());
|
||||
}
|
||||
|
||||
public FileTreeCompareImpl(Set<String> ignorePaths)
|
||||
{
|
||||
// This config MUST be present before any TFile objects etc. are created.
|
||||
TConfig config = TConfig.get();
|
||||
config.setArchiveDetector(new TArchiveDetector("war|jar", new ZipDriver(IOPoolLocator.SINGLETON)));
|
||||
this.ignorePaths.addAll(ignorePaths);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResultSet compare(Path p1, Path p2)
|
||||
{
|
||||
ResultSet resultSet = new ResultSet();
|
||||
try
|
||||
{
|
||||
compare(resultSet.stats, resultSet.results, p1, p2);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new FileTreeCompareException("Unable to compare file trees.", e);
|
||||
}
|
||||
return resultSet;
|
||||
}
|
||||
|
||||
private void compare(ResultSet.Stats stats, List<Result> results, Path tree1, Path tree2) throws IOException
|
||||
{
|
||||
SortedPathSet set1 = sortedPaths(tree1);
|
||||
SortedPathSet set2 = sortedPaths(tree2);
|
||||
|
||||
SortedPathSet all = new SortedPathSet();
|
||||
all.addAll(set1);
|
||||
all.addAll(set2);
|
||||
|
||||
for (Path pathToFind : all)
|
||||
{
|
||||
if (pathMatchesIgnorePattern(pathToFind))
|
||||
{
|
||||
// Skip paths that we don't want to examine, e.g. tomcat/temp
|
||||
log.debug("Skipping path: "+pathToFind);
|
||||
stats.ignoredFileCount++;
|
||||
continue;
|
||||
}
|
||||
|
||||
Result result = new Result();
|
||||
results.add(result);
|
||||
stats.resultCount++;
|
||||
|
||||
if (set1.contains(pathToFind) && set2.contains(pathToFind))
|
||||
{
|
||||
log.debug("In both: "+pathToFind);
|
||||
// Set the results, translating paths back to absolute as required.
|
||||
result.p1 = tree1.resolve(pathToFind);
|
||||
result.p2 = tree2.resolve(pathToFind);
|
||||
boolean contentMatches = false;
|
||||
if (Files.isRegularFile(result.p1) && Files.isRegularFile(result.p2))
|
||||
{
|
||||
contentMatches = FileUtils.contentEquals(result.p1.toFile(), result.p2.toFile());
|
||||
if (!contentMatches && isSpecialArchive(pathToFind))
|
||||
{
|
||||
Path archive1 = extract(result.p1);
|
||||
Path archive2 = extract(result.p2);
|
||||
result.subTree1 = archive1;
|
||||
result.subTree2 = archive2;
|
||||
final int diffBefore = stats.differenceCount;
|
||||
compare(stats, result.subResults, archive1, archive2);
|
||||
final int diffAfter = stats.differenceCount;
|
||||
if (diffAfter == diffBefore)
|
||||
{
|
||||
// No significant differences were found in the (recursive) subtree comparison.
|
||||
// We can therefore mark the special archive files matching in both trees.
|
||||
contentMatches = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (Files.isDirectory(result.p1) && Files.isDirectory(result.p2))
|
||||
{
|
||||
// Two directories are counted as the same.
|
||||
contentMatches = true;
|
||||
}
|
||||
result.equal = contentMatches;
|
||||
}
|
||||
else if (set1.contains(pathToFind))
|
||||
{
|
||||
log.debug("In tree1 only: "+pathToFind);
|
||||
result.p1 = tree1.resolve(pathToFind);
|
||||
result.p2 = null;
|
||||
}
|
||||
else if (set2.contains(pathToFind))
|
||||
{
|
||||
log.debug("In tree2 only: "+pathToFind);
|
||||
result.p1 = null;
|
||||
result.p2 = tree2.resolve(pathToFind);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalStateException(
|
||||
"Something went wrong. The path is not found in either tree: "+pathToFind);
|
||||
}
|
||||
|
||||
if (!result.equal)
|
||||
{
|
||||
stats.differenceCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isSpecialArchive(Path pathToFind)
|
||||
{
|
||||
return pathToFind.getFileName().toString().toLowerCase().endsWith(".war") ||
|
||||
pathToFind.getFileName().toString().toLowerCase().endsWith(".jar");
|
||||
}
|
||||
|
||||
/**
|
||||
* If the set of paths to ignore ({@link #ignorePaths}) contains
|
||||
* a pattern matching the specified path, then true is returned.
|
||||
* <p>
|
||||
* Patterns are ant-style patterns.
|
||||
*
|
||||
* @param path The path to check
|
||||
* @return True if there is a path in the ignorePaths set that is a prefix of the path.
|
||||
*/
|
||||
private boolean pathMatchesIgnorePattern(String path)
|
||||
{
|
||||
for (String pattern : ignorePaths)
|
||||
{
|
||||
if (pathMatcher.match(pattern, path))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #pathMatchesIgnorePattern(String)
|
||||
*/
|
||||
private boolean pathMatchesIgnorePattern(Path path)
|
||||
{
|
||||
return pathMatchesIgnorePattern(path.toString());
|
||||
}
|
||||
|
||||
private Path extract(Path archivePath) throws IOException
|
||||
{
|
||||
String destDirName = archivePath.getFileName().toString();
|
||||
Path dest = Files.createTempDirectory(destDirName);
|
||||
extract(archivePath, dest);
|
||||
return dest;
|
||||
}
|
||||
|
||||
private void extract(Path archivePath, Path destPath) throws IOException
|
||||
{
|
||||
TFile archive = new TFile(archivePath.toFile());
|
||||
TFile dest = new TFile(destPath.toFile(), TArchiveDetector.NULL);
|
||||
try
|
||||
{
|
||||
// Unzip the archive.
|
||||
archive.cp_rp(dest);
|
||||
}
|
||||
finally
|
||||
{
|
||||
TVFS.umount(archive);
|
||||
TVFS.umount(dest);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Traverse path and create a {@link SortedPathSet} containing the set
|
||||
* of paths encountered. The {@link Path} instances are relative to
|
||||
* the base path provided as a parameter to this method.
|
||||
*
|
||||
* @param path The path to traverse.
|
||||
* @return SortedPathSet
|
||||
* @throws IOException
|
||||
*/
|
||||
protected SortedPathSet sortedPaths(Path path) throws IOException
|
||||
{
|
||||
SortedPathSet sortedPaths = new SortedPathSet();
|
||||
collectPaths(sortedPaths, path, path.toFile());
|
||||
return sortedPaths;
|
||||
}
|
||||
|
||||
private void collectPaths(SortedPathSet sortedSet, Path root, File path) throws IOException
|
||||
{
|
||||
for (File f : path.listFiles())
|
||||
{
|
||||
Path relativePath = root.relativize(f.toPath());
|
||||
sortedSet.add(relativePath);
|
||||
if (f.isDirectory())
|
||||
{
|
||||
collectPaths(sortedSet, root, f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright 2016 Alfresco Software, Ltd. All rights reserved.
|
||||
*
|
||||
* License rights for this program may be obtained from Alfresco Software, Ltd.
|
||||
* pursuant to a written agreement and any use of this program without such an
|
||||
* agreement is prohibited.
|
||||
*/
|
||||
package org.alfresco.update.tool.dircomp;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Format results as HTML.
|
||||
*
|
||||
* @author Matt Ward
|
||||
*/
|
||||
public class HtmlResultFormatter implements ResultFormatter
|
||||
{
|
||||
private int maxPathDisplayLength = 80;
|
||||
private boolean differencesOnly;
|
||||
|
||||
|
||||
@Override
|
||||
public void format(ResultSet resultSet, OutputStream out)
|
||||
{
|
||||
try(PrintWriter pw = new PrintWriter(out))
|
||||
{
|
||||
pw.println("<!DOCTYPE HTML>");
|
||||
pw.println("<html>");
|
||||
pw.println("<head>");
|
||||
pw.println("<title>File tree comparison results</title>");
|
||||
pw.println("<link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css\" integrity=\"sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7\" crossorigin=\"anonymous\">");
|
||||
pw.println("</head>");
|
||||
pw.println("<body>");
|
||||
pw.println("<p>Files examined: <strong>"+resultSet.stats.resultCount+"</strong></p>");
|
||||
pw.println("<p>Files with differences: <strong>"+resultSet.stats.differenceCount+"</strong></p>");
|
||||
pw.println("<p>Ignored files: <strong>"+resultSet.stats.ignoredFileCount+"</strong></p>");
|
||||
String passOrFail;
|
||||
if (resultSet.stats.differenceCount > 0)
|
||||
{
|
||||
passOrFail = "<span style=\"color: red\"><strong>FAILED</strong></span>";
|
||||
}
|
||||
else
|
||||
{
|
||||
passOrFail = "<span style=\"color: green\"><strong>PASSED</strong></span>";
|
||||
}
|
||||
pw.println("<p>Status: "+passOrFail+"</p>");
|
||||
|
||||
outputResultsTable(resultSet.results, pw, 0);
|
||||
|
||||
pw.println("</body>");
|
||||
pw.println("</html>");
|
||||
}
|
||||
}
|
||||
|
||||
private void outputResultsTable(List<Result> results, PrintWriter pw, int row)
|
||||
{
|
||||
pw.println("<table class=\"table table-striped table-hover\">");
|
||||
pw.println("<thead>");
|
||||
pw.println("<tr>");
|
||||
pw.println("<th>#</th>");
|
||||
pw.println("<th>Updated install</th>");
|
||||
pw.println("<th>Fresh install</th>");
|
||||
pw.println("</tr>");
|
||||
pw.println("</thead>");
|
||||
pw.println("<tbody>");
|
||||
|
||||
for (Result r : results)
|
||||
{
|
||||
++row;
|
||||
|
||||
outputResult(pw, row, r);
|
||||
|
||||
if (!r.subResults.isEmpty())
|
||||
{
|
||||
// Only show the subresults if there are
|
||||
if (!differencesOnly || !r.equal)
|
||||
{
|
||||
pw.println("<tr><td> </td><td colspan=\"2\">");
|
||||
outputResultsTable(r.subResults, pw, row);
|
||||
pw.println("</td></tr>");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pw.println("</tbody>");
|
||||
pw.println("</table>");
|
||||
}
|
||||
|
||||
private void outputResult(PrintWriter pw, int row, Result r)
|
||||
{
|
||||
if (differencesOnly && r.equal)
|
||||
{
|
||||
return;
|
||||
}
|
||||
pw.println("<tr>");
|
||||
|
||||
pw.println("<td>"+row+"</td>");
|
||||
|
||||
String p1 = (r.p1 == null) ? "" : r.p1.toString();
|
||||
String p1Abbr = abbreviate(p1, maxPathDisplayLength);
|
||||
String p2 = (r.p2 == null) ? "" : r.p2.toString();
|
||||
String p2Abbr = abbreviate(p2, maxPathDisplayLength);
|
||||
|
||||
// TODO: URL/HTML-encode as appropriate
|
||||
String diffClass;
|
||||
if (r.equal)
|
||||
{
|
||||
if (r.subResults.isEmpty())
|
||||
{
|
||||
// Result refers to a normal file or directory.
|
||||
diffClass = "info";
|
||||
}
|
||||
else
|
||||
{
|
||||
// File is a special archive, but no differences in the sub-results are considered important.
|
||||
diffClass = "warning";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// The file/directory appears different in each tree. If it is a special archive, then there
|
||||
// are differences that we care about.
|
||||
diffClass = "danger";
|
||||
}
|
||||
|
||||
pw.println(
|
||||
String.format("<td class=\"%s\"><a href=\"file://%s\">%s</a></td><td class=\"%s\"><a href=\"file://%s\">%s</a></td>",
|
||||
diffClass,
|
||||
p1,
|
||||
p1Abbr,
|
||||
diffClass,
|
||||
p2,
|
||||
p2Abbr));
|
||||
|
||||
pw.println("</tr>");
|
||||
}
|
||||
|
||||
private String abbreviate(String str, int maxLength)
|
||||
{
|
||||
return (str.length() > maxLength) ? "..."+str.substring(str.length()-maxLength) : str;
|
||||
}
|
||||
|
||||
public void setMaxPathDisplayLength(int maxPathDisplayLength)
|
||||
{
|
||||
this.maxPathDisplayLength = maxPathDisplayLength;
|
||||
}
|
||||
|
||||
public void setDifferencesOnly(boolean differencesOnly)
|
||||
{
|
||||
this.differencesOnly = differencesOnly;
|
||||
}
|
||||
}
|
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright 2016 Alfresco Software, Ltd. All rights reserved.
|
||||
*
|
||||
* License rights for this program may be obtained from Alfresco Software, Ltd.
|
||||
* pursuant to a written agreement and any use of this program without such an
|
||||
* agreement is prohibited.
|
||||
*/
|
||||
package org.alfresco.update.tool.dircomp;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Simple struct-style result data class.
|
||||
*
|
||||
* @author Matt Ward
|
||||
*/
|
||||
public final class Result
|
||||
{
|
||||
/**
|
||||
* The path within tree1 being compared (intended to be the updated Alfresco installation).
|
||||
* <p>
|
||||
* This field will be <code>null</code> if the file in question appears only in the tree2.
|
||||
*/
|
||||
Path p1;
|
||||
/**
|
||||
* The path within tree2 being compared (intended to be the freshly installed equivalent of {@link #p1}).
|
||||
* <p>
|
||||
* This field will be <code>null</code> if the file in question appears only in the tree1.
|
||||
*/
|
||||
Path p2;
|
||||
/**
|
||||
* Are the paths in {@link #p1} and {@link #p2} of identical content? If they refer to a directory, then
|
||||
* equal in this sense is to have the same directory name. If they refer to a plain file, then equal means
|
||||
* that they contain the exact same contents.
|
||||
*/
|
||||
boolean equal;
|
||||
/**
|
||||
* The root path of sub-tree1 to which {@link #subResults} refers.
|
||||
* @see #subResults
|
||||
*/
|
||||
Path subTree1;
|
||||
/**
|
||||
* The root path of sub-tree2 to which {@link #subResults} refers.
|
||||
* @see #subResults
|
||||
*/
|
||||
Path subTree2;
|
||||
/**
|
||||
* If p1 and p2 refer to a special archive with differences, e.g. they refer to alfresco.war,
|
||||
* then a deep comparison of the archives will be performed and the results stored here.
|
||||
* <p>
|
||||
* The paths to the expanded archives will be stored in {@link #subTree1} and {@link #subTree2}
|
||||
* and all the paths in {@link #subResults} will be within those new roots.
|
||||
*/
|
||||
List<Result> subResults = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + (this.equal ? 1231 : 1237);
|
||||
result = prime * result + ((this.p1 == null) ? 0 : this.p1.hashCode());
|
||||
result = prime * result + ((this.p2 == null) ? 0 : this.p2.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (this == obj) return true;
|
||||
if (obj == null) return false;
|
||||
if (getClass() != obj.getClass()) return false;
|
||||
Result other = (Result) obj;
|
||||
if (this.equal != other.equal) return false;
|
||||
if (this.p1 == null)
|
||||
{
|
||||
if (other.p1 != null) return false;
|
||||
}
|
||||
else if (!this.p1.equals(other.p1)) return false;
|
||||
if (this.p2 == null)
|
||||
{
|
||||
if (other.p2 != null) return false;
|
||||
}
|
||||
else if (!this.p2.equals(other.p2)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return String.format("Result[p1=%s, p2=%s, equal=%b]", p1, p2, equal);
|
||||
}
|
||||
}
|
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2016 Alfresco Software, Ltd. All rights reserved.
|
||||
*
|
||||
* License rights for this program may be obtained from Alfresco Software, Ltd.
|
||||
* pursuant to a written agreement and any use of this program without such an
|
||||
* agreement is prohibited.
|
||||
*/
|
||||
package org.alfresco.update.tool.dircomp;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Format a set of {@link Result} objects.
|
||||
*
|
||||
* @author Matt Ward
|
||||
*/
|
||||
public interface ResultFormatter
|
||||
{
|
||||
/**
|
||||
* Format the result set to the supplied {@link OutputStream}. The caller
|
||||
* must take care of creating and destroying the OutputStream correctly.
|
||||
*
|
||||
* @param results The results to format.
|
||||
* @param out The stream to format the results to.
|
||||
*/
|
||||
void format(ResultSet results, OutputStream out);
|
||||
}
|
@@ -0,0 +1,40 @@
|
||||
package org.alfresco.update.tool.dircomp;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/*
|
||||
* Copyright 2015-2016 Alfresco Software, Ltd. All rights reserved.
|
||||
*
|
||||
* License rights for this program may be obtained from Alfresco Software, Ltd.
|
||||
* pursuant to a written agreement and any use of this program without such an
|
||||
* agreement is prohibited.
|
||||
*/
|
||||
public class ResultSet
|
||||
{
|
||||
final List<Result> results = new ArrayList<>();
|
||||
final Stats stats = new Stats();
|
||||
|
||||
/**
|
||||
* Class for aggregating basic statistics relating to the directory tree comparisons.
|
||||
* <p>
|
||||
* For all counts, unless specified otherwise, if a file appears in both trees, it is
|
||||
* counted only once, as it is relative files we are tracking regardless of which
|
||||
* tree(s) they exist in.
|
||||
*/
|
||||
public static class Stats
|
||||
{
|
||||
/**
|
||||
* The number of files (including directories) examined.
|
||||
*/
|
||||
int resultCount;
|
||||
/**
|
||||
* The number of files discovered to have differences.
|
||||
*/
|
||||
int differenceCount;
|
||||
/**
|
||||
* The number of files that were completely ignored due to being in the ignore list.
|
||||
*/
|
||||
int ignoredFileCount;
|
||||
}
|
||||
}
|
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2016 Alfresco Software, Ltd. All rights reserved.
|
||||
*
|
||||
* License rights for this program may be obtained from Alfresco Software, Ltd.
|
||||
* pursuant to a written agreement and any use of this program without such an
|
||||
* agreement is prohibited.
|
||||
*/
|
||||
package org.alfresco.update.tool.dircomp;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.TreeSet;
|
||||
|
||||
/**
|
||||
* Sorted set of {@link Path} objects that provides consistent
|
||||
* cross-platform sort order.
|
||||
*
|
||||
* @see java.util.TreeSet
|
||||
* @author Matt Ward
|
||||
*/
|
||||
public class SortedPathSet extends TreeSet<Path>
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public SortedPathSet()
|
||||
{
|
||||
super(new CaseSensitivePathComparator());
|
||||
}
|
||||
}
|
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2016 Alfresco Software, Ltd. All rights reserved.
|
||||
*
|
||||
* License rights for this program may be obtained from Alfresco Software, Ltd.
|
||||
* pursuant to a written agreement and any use of this program without such an
|
||||
* agreement is prohibited.
|
||||
*/
|
||||
package org.alfresco.update.tool.dircomp.exception;
|
||||
|
||||
import org.alfresco.update.tool.dircomp.FileTreeCompare;
|
||||
|
||||
/**
|
||||
* Exception class representing failures during file tree comparison.
|
||||
*
|
||||
* @see FileTreeCompare
|
||||
* @author Matt Ward
|
||||
*/
|
||||
public class FileTreeCompareException extends RuntimeException
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public FileTreeCompareException(String message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
|
||||
public FileTreeCompareException(String message, Throwable cause)
|
||||
{
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
@@ -0,0 +1,298 @@
|
||||
/*
|
||||
* Copyright 2016 Alfresco Software, Ltd. All rights reserved.
|
||||
*
|
||||
* License rights for this program may be obtained from Alfresco Software, Ltd.
|
||||
* pursuant to a written agreement and any use of this program without such an
|
||||
* agreement is prohibited.
|
||||
*/
|
||||
package org.alfresco.update.tool.dircomp;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
|
||||
/**
|
||||
* Tests for the {@link FileTreeCompareImpl} class.
|
||||
*
|
||||
* @author Matt Ward
|
||||
*/
|
||||
public class FileTreeCompareImplTest
|
||||
{
|
||||
FileTreeCompareImpl comparator;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception
|
||||
{
|
||||
comparator = new FileTreeCompareImpl();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canGetSortedPathSet() throws IOException
|
||||
{
|
||||
Path tree = pathFromClasspath("dir_compare/simple_file_folders/tree1");
|
||||
SortedPathSet paths = comparator.sortedPaths(tree);
|
||||
Iterator<Path> it = paths.iterator();
|
||||
|
||||
System.out.println("Paths:");
|
||||
for (Path p : paths)
|
||||
{
|
||||
System.out.println("\t"+p);
|
||||
}
|
||||
|
||||
assertEquals(11, paths.size());
|
||||
|
||||
assertEquals("a", unixPathStr(tree, it.next()));
|
||||
assertEquals("b", unixPathStr(tree, it.next()));
|
||||
assertEquals("b/blah.txt", unixPathStr(tree, it.next()));
|
||||
assertEquals("c", unixPathStr(tree, it.next()));
|
||||
assertEquals("c/c1", unixPathStr(tree, it.next()));
|
||||
assertEquals("c/c1/commands.bat", unixPathStr(tree, it.next()));
|
||||
assertEquals("c/c1/commands.sh", unixPathStr(tree, it.next()));
|
||||
assertEquals("c/c2", unixPathStr(tree, it.next()));
|
||||
assertEquals("c/c2/Aardvark.java", unixPathStr(tree, it.next()));
|
||||
assertEquals("c/c2/Banana.java", unixPathStr(tree, it.next()));
|
||||
assertEquals("d", unixPathStr(tree, it.next()));
|
||||
}
|
||||
|
||||
private String unixPathStr(Path root, Path path)
|
||||
{
|
||||
// Allow test to run on Windows also
|
||||
String pathStr = path.toString();
|
||||
pathStr = pathStr.replace(File.separatorChar, '/');
|
||||
return pathStr;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canDiffSimpleTreesOfFilesAndFolders()
|
||||
{
|
||||
Path tree1 = pathFromClasspath("dir_compare/simple_file_folders/tree1");
|
||||
Path tree2 = pathFromClasspath("dir_compare/simple_file_folders/tree2");
|
||||
|
||||
ResultSet resultSet = comparator.compare(tree1, tree2);
|
||||
|
||||
System.out.println("Comparison results:");
|
||||
for (Result r : resultSet.results)
|
||||
{
|
||||
System.out.println("\t"+r);
|
||||
}
|
||||
|
||||
// One result for each relative file/folder
|
||||
assertEquals(13, resultSet.results.size());
|
||||
assertEquals(13, resultSet.stats.resultCount);
|
||||
|
||||
Iterator<Result> rit = resultSet.results.iterator();
|
||||
// TODO: currently all of the files are in one, other or both but where they
|
||||
// are in both, the file *contents* are identical.
|
||||
// TODO: evolve test data and functionality to cope with different file contents.
|
||||
assertResultEquals(tree1.resolve("a"), tree2.resolve("a"), true, rit.next());
|
||||
assertResultEquals(null, tree2.resolve("a/story.txt"), false, rit.next());
|
||||
assertResultEquals(tree1.resolve("b"), tree2.resolve("b"), true, rit.next());
|
||||
assertResultEquals(tree1.resolve("b/blah.txt"), tree2.resolve("b/blah.txt"), true, rit.next());
|
||||
assertResultEquals(tree1.resolve("c"), tree2.resolve("c"), true, rit.next());
|
||||
assertResultEquals(tree1.resolve("c/c1"), tree2.resolve("c/c1"), true, rit.next());
|
||||
assertResultEquals(tree1.resolve("c/c1/commands.bat"), tree2.resolve("c/c1/commands.bat"), true, rit.next());
|
||||
assertResultEquals(tree1.resolve("c/c1/commands.sh"), tree2.resolve("c/c1/commands.sh"), true, rit.next());
|
||||
assertResultEquals(tree1.resolve("c/c2"), tree2.resolve("c/c2"), true, rit.next());
|
||||
// Aardvark.java appears in both trees but is not the same!
|
||||
assertResultEquals(tree1.resolve("c/c2/Aardvark.java"), tree2.resolve("c/c2/Aardvark.java"), false, rit.next());
|
||||
assertResultEquals(tree1.resolve("c/c2/Banana.java"), null, false, rit.next());
|
||||
assertResultEquals(tree1.resolve("d"), null, false, rit.next());
|
||||
assertResultEquals(null, tree2.resolve("e"), false, rit.next());
|
||||
}
|
||||
|
||||
/**
|
||||
* A "learning test" allowing me to check my assumptions and document the expected behaviour.
|
||||
*/
|
||||
@Test
|
||||
public void testAntPathMatcher()
|
||||
{
|
||||
AntPathMatcher matcher = new AntPathMatcher();
|
||||
assertTrue(matcher.match("**/common/lib/**/*.pc", "prefix/common/lib/pkgconfig/ImageMagick++-6.Q16.pc"));
|
||||
assertFalse(matcher.match("**/common/lib/**/*.pc", "/absolute/prefix/common/lib/pkgconfig/ImageMagick++-6.Q16.pc"));
|
||||
assertTrue(matcher.match("/**/common/lib/**/*.pc", "/absolute/prefix/common/lib/pkgconfig/ImageMagick++-6.Q16.pc"));
|
||||
assertTrue(matcher.match("common/lib/**/*.pc", "common/lib/pkgconfig/Wand.pc"));
|
||||
assertTrue(matcher.match("**/*.pc", "common/lib/pkgconfig/Wand.pc"));
|
||||
assertFalse(matcher.match("*.pc", "common/lib/pkgconfig/Wand.pc"));
|
||||
|
||||
assertTrue(matcher.match("libreoffice.app/Contents/Resources/bootstraprc", "libreoffice.app/Contents/Resources/bootstraprc"));
|
||||
assertTrue(matcher.match("*.sh", "alfresco.sh"));
|
||||
assertFalse(matcher.match("*.sh", "a/different/alfresco.sh"));
|
||||
|
||||
// What about path separators?
|
||||
assertTrue(matcher.match("**\\common\\lib\\**\\*.pc", "prefix\\common\\lib\\pkgconfig\\ImageMagick++-6.Q16.pc"));
|
||||
assertTrue(matcher.match("\\**\\common\\lib\\**\\*.pc", "\\absolute\\prefix\\common\\lib\\pkgconfig\\ImageMagick++-6.Q16.pc"));
|
||||
|
||||
// Path separator must be set before this will work
|
||||
assertFalse(matcher.match("**/common/lib/**/*.pc", "prefix\\common\\lib\\pkgconfig\\ImageMagick++-6.Q16.pc"));
|
||||
matcher.setPathSeparator("\\");
|
||||
assertTrue(matcher.match("**/common/lib/**/*.pc", "prefix\\common\\lib\\pkgconfig\\ImageMagick++-6.Q16.pc"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canIgnoreSpecifiedPaths()
|
||||
{
|
||||
Path tree1 = pathFromClasspath("dir_compare/simple_file_folders/tree1");
|
||||
Path tree2 = pathFromClasspath("dir_compare/simple_file_folders/tree2");
|
||||
|
||||
Set<String> ignorePaths = new HashSet<>();
|
||||
ignorePaths.add("b/blah.txt");
|
||||
ignorePaths.add("c/c2/**");
|
||||
ignorePaths.add("d/**");
|
||||
ignorePaths.add("e/**");
|
||||
comparator = new FileTreeCompareImpl(ignorePaths);
|
||||
|
||||
// Perform the comparison
|
||||
ResultSet resultSet = comparator.compare(tree1, tree2);
|
||||
|
||||
System.out.println("Comparison results:");
|
||||
for (Result r : resultSet.results)
|
||||
{
|
||||
System.out.println("\t"+r);
|
||||
}
|
||||
|
||||
Iterator<Result> rit = resultSet.results.iterator();
|
||||
assertResultEquals(tree1.resolve("a"), tree2.resolve("a"), true, rit.next());
|
||||
assertResultEquals(null, tree2.resolve("a/story.txt"), false, rit.next());
|
||||
assertResultEquals(tree1.resolve("b"), tree2.resolve("b"), true, rit.next());
|
||||
// No b/blah.txt here.
|
||||
assertResultEquals(tree1.resolve("c"), tree2.resolve("c"), true, rit.next());
|
||||
assertResultEquals(tree1.resolve("c/c1"), tree2.resolve("c/c1"), true, rit.next());
|
||||
assertResultEquals(tree1.resolve("c/c1/commands.bat"), tree2.resolve("c/c1/commands.bat"), true, rit.next());
|
||||
assertResultEquals(tree1.resolve("c/c1/commands.sh"), tree2.resolve("c/c1/commands.sh"), true, rit.next());
|
||||
// No c/c2, c/c2/Aardvark.java, c/c2/Banana.java, d or e here.
|
||||
|
||||
List<Result> results = resultSet.results;
|
||||
assertResultNotPresent(tree1.resolve("b/blah.txt"), tree2.resolve("b/blah.txt"), true, results);
|
||||
assertResultNotPresent(tree1.resolve("c/c2"), tree2.resolve("c/c2"), true, results);
|
||||
assertResultNotPresent(tree1.resolve("c/c2/Aardvark.java"), tree2.resolve("c/c2/Aardvark.java"), false, results);
|
||||
assertResultNotPresent(tree1.resolve("c/c2/Banana.java"), null, false, results);
|
||||
assertResultNotPresent(tree1.resolve("d"), null, false, results);
|
||||
assertResultNotPresent(null, tree2.resolve("e"), false, results);
|
||||
assertEquals(7, results.size());
|
||||
|
||||
// TODO: What about paths within war/jar/zip files?
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canDiffTreesContainingWarFiles()
|
||||
{
|
||||
Path tree1 = pathFromClasspath("dir_compare/file_folders_plus_war/tree1");
|
||||
Path tree2 = pathFromClasspath("dir_compare/file_folders_plus_war/tree2");
|
||||
|
||||
ResultSet resultSet = comparator.compare(tree1, tree2);
|
||||
|
||||
System.out.println("Comparison results:");
|
||||
for (Result r : resultSet.results)
|
||||
{
|
||||
System.out.println("\t"+r);
|
||||
}
|
||||
|
||||
// The 14 top-level results + 17 sub-results.
|
||||
assertEquals(31, resultSet.stats.resultCount);
|
||||
|
||||
// One result for each relative file/folder
|
||||
assertEquals(14, resultSet.results.size());
|
||||
|
||||
|
||||
Iterator<Result> rit = resultSet.results.iterator();
|
||||
// TODO: currently all of the files are in one, other or both but where they
|
||||
// are in both, the file *contents* are identical.
|
||||
// TODO: evolve test data and functionality to cope with different file contents.
|
||||
assertResultEquals(tree1.resolve("a"), tree2.resolve("a"), true, rit.next());
|
||||
assertResultEquals(null, tree2.resolve("a/story.txt"), false, rit.next());
|
||||
assertResultEquals(tree1.resolve("b"), tree2.resolve("b"), true, rit.next());
|
||||
|
||||
// Examine the results of the war file comparison
|
||||
Result result = rit.next();
|
||||
// The WAR files are different.
|
||||
assertResultEquals(
|
||||
tree1.resolve("b/alfresco-testdata-webapp.war"),
|
||||
tree2.resolve("b/alfresco-testdata-webapp.war"),
|
||||
false,
|
||||
result);
|
||||
List<Result> subResults = result.subResults;
|
||||
System.out.println("subResults:");
|
||||
for (Result r : subResults)
|
||||
{
|
||||
System.out.println("\t"+r);
|
||||
}
|
||||
Iterator<Result> subIt = subResults.iterator();
|
||||
Path subTree1 = result.subTree1;
|
||||
Path subTree2 = result.subTree2;
|
||||
assertEquals(17, subResults.size());
|
||||
assertResultEquals(subTree1.resolve("META-INF"), subTree2.resolve("META-INF"), true, subIt.next());
|
||||
assertResultEquals(subTree1.resolve("META-INF/MANIFEST.MF"), subTree2.resolve("META-INF/MANIFEST.MF"), false, subIt.next());
|
||||
assertResultEquals(subTree1.resolve("META-INF/maven"), subTree2.resolve("META-INF/maven"), true, subIt.next());
|
||||
assertResultEquals(subTree1.resolve("META-INF/maven/org.alfresco.dummy"), subTree2.resolve("META-INF/maven/org.alfresco.dummy"), true, subIt.next());
|
||||
assertResultEquals(subTree1.resolve("META-INF/maven/org.alfresco.dummy/alfresco-testdata-webapp"), subTree2.resolve("META-INF/maven/org.alfresco.dummy/alfresco-testdata-webapp"), true, subIt.next());
|
||||
assertResultEquals(subTree1.resolve("META-INF/maven/org.alfresco.dummy/alfresco-testdata-webapp/pom.properties"), subTree2.resolve("META-INF/maven/org.alfresco.dummy/alfresco-testdata-webapp/pom.properties"), false, subIt.next());
|
||||
assertResultEquals(subTree1.resolve("META-INF/maven/org.alfresco.dummy/alfresco-testdata-webapp/pom.xml"), subTree2.resolve("META-INF/maven/org.alfresco.dummy/alfresco-testdata-webapp/pom.xml"), true, subIt.next());
|
||||
assertResultEquals(subTree1.resolve("WEB-INF"), subTree2.resolve("WEB-INF"), true, subIt.next());
|
||||
assertResultEquals(subTree1.resolve("WEB-INF/classes"), subTree2.resolve("WEB-INF/classes"), true, subIt.next());
|
||||
assertResultEquals(subTree1.resolve("WEB-INF/classes/org"), subTree2.resolve("WEB-INF/classes/org"), true, subIt.next());
|
||||
assertResultEquals(subTree1.resolve("WEB-INF/classes/org/alfresco"), subTree2.resolve("WEB-INF/classes/org/alfresco"), true, subIt.next());
|
||||
assertResultEquals(subTree1.resolve("WEB-INF/classes/org/alfresco/testdata"), subTree2.resolve("WEB-INF/classes/org/alfresco/testdata"), true, subIt.next());
|
||||
assertResultEquals(subTree1.resolve("WEB-INF/classes/org/alfresco/testdata/webapp"), subTree2.resolve("WEB-INF/classes/org/alfresco/testdata/webapp"), true, subIt.next());
|
||||
assertResultEquals(null, subTree2.resolve("WEB-INF/classes/org/alfresco/testdata/webapp/Another.class"), false, subIt.next());
|
||||
assertResultEquals(subTree1.resolve("WEB-INF/classes/org/alfresco/testdata/webapp/ExampleJavaClass.class"), subTree2.resolve("WEB-INF/classes/org/alfresco/testdata/webapp/ExampleJavaClass.class"), true, subIt.next());
|
||||
assertResultEquals(subTree1.resolve("WEB-INF/web.xml"), subTree2.resolve("WEB-INF/web.xml"), true, subIt.next());
|
||||
assertResultEquals(subTree1.resolve("index.jsp"), subTree2.resolve("index.jsp"), false, subIt.next());
|
||||
|
||||
// Back up to the top-level comparisons
|
||||
assertResultEquals(tree1.resolve("b/blah.txt"), tree2.resolve("b/blah.txt"), true, rit.next());
|
||||
assertResultEquals(tree1.resolve("c"), tree2.resolve("c"), true, rit.next());
|
||||
assertResultEquals(tree1.resolve("c/c1"), tree2.resolve("c/c1"), true, rit.next());
|
||||
assertResultEquals(tree1.resolve("c/c1/commands.bat"), tree2.resolve("c/c1/commands.bat"), true, rit.next());
|
||||
assertResultEquals(tree1.resolve("c/c1/commands.sh"), tree2.resolve("c/c1/commands.sh"), true, rit.next());
|
||||
assertResultEquals(tree1.resolve("c/c2"), tree2.resolve("c/c2"), true, rit.next());
|
||||
// Aardvark.java appears in both trees but is not the same!
|
||||
assertResultEquals(tree1.resolve("c/c2/Aardvark.java"), tree2.resolve("c/c2/Aardvark.java"), false, rit.next());
|
||||
assertResultEquals(tree1.resolve("c/c2/Banana.java"), null, false, rit.next());
|
||||
assertResultEquals(tree1.resolve("d"), null, false, rit.next());
|
||||
assertResultEquals(null, tree2.resolve("e"), false, rit.next());
|
||||
}
|
||||
|
||||
private void assertResultNotPresent(Path p1, Path p2, boolean contentEqual, List<Result> results)
|
||||
{
|
||||
Result r = new Result();
|
||||
r.p1 = p1;
|
||||
r.p2 = p2;
|
||||
r.equal = contentEqual;
|
||||
assertFalse("Result should not be present: "+r, results.contains(r));
|
||||
}
|
||||
|
||||
private void assertResultEquals(Path p1, Path p2, boolean contentEqual, Result result)
|
||||
{
|
||||
Result expected = new Result();
|
||||
expected.p1 = p1;
|
||||
expected.p2 = p2;
|
||||
expected.equal = contentEqual;
|
||||
assertEquals(expected, result);
|
||||
}
|
||||
|
||||
private Path pathFromClasspath(String path)
|
||||
{
|
||||
try
|
||||
{
|
||||
return Paths.get(getClass().getClassLoader().getResource(path).toURI());
|
||||
}
|
||||
catch (URISyntaxException error)
|
||||
{
|
||||
throw new RuntimeException("");
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright 2016 Alfresco Software, Ltd. All rights reserved.
|
||||
*
|
||||
* License rights for this program may be obtained from Alfresco Software, Ltd.
|
||||
* pursuant to a written agreement and any use of this program without such an
|
||||
* agreement is prohibited.
|
||||
*/
|
||||
package org.alfresco.update.tool.dircomp;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* Tests for the {@link HtmlResultFormatter} class.
|
||||
* <p>
|
||||
* TODO: currently these aren't tests so much as useful utilities to help with manual testing.
|
||||
*
|
||||
* @author Matt Ward
|
||||
*/
|
||||
public class HtmlResultFormatterTest
|
||||
{
|
||||
@Before
|
||||
public void setUp() throws Exception
|
||||
{
|
||||
}
|
||||
|
||||
@Test
|
||||
public void canFormatToHTML() throws IOException
|
||||
{
|
||||
ResultSet resultSet = new ResultSet();
|
||||
List<Result> results = resultSet.results;
|
||||
addResult(results, "/t1/a", "/t2/a", true);
|
||||
addResult(results, "/t1/a/b", "/t2/a/b", true);
|
||||
addResult(results, "/t1/a/c", "/t2/a/c", true);
|
||||
addResult(results, "/t1/a/b/c/something.txt", "/t2/a/b/c/something.txt", true);
|
||||
addResult(results, "/t1/a/b/c/another.txt", "/t2/a/b/c/another.txt", false);
|
||||
addResult(results, null, "/t2/a/b/c/blah.txt", false);
|
||||
addResult(results, "/t1/dir-only-in-p1", null, false);
|
||||
addResult(results, null, "/t2/dir-only-in-p2", false);
|
||||
|
||||
try(ByteArrayOutputStream os = new ByteArrayOutputStream())
|
||||
{
|
||||
HtmlResultFormatter formatter = new HtmlResultFormatter();
|
||||
formatter.format(resultSet, os);
|
||||
System.out.println(os.toString());
|
||||
|
||||
// Uncomment to write to file
|
||||
// Path file = Files.createTempFile(getClass().getSimpleName(), ".html");
|
||||
// FileUtils.write(file.toFile(), os.toString());
|
||||
// System.out.println("File: "+file);
|
||||
}
|
||||
}
|
||||
|
||||
@Ignore
|
||||
@Test
|
||||
public void bigDiff() throws IOException
|
||||
{
|
||||
Path path1 = Paths.get("/Users/MWard/dev2/alf-installs/alf-5.1-b667");
|
||||
Path path2 = Paths.get("/Users/MWard/dev2/alf-installs/alf-5.1-b669");
|
||||
|
||||
Set<String> ignores = new HashSet<>();
|
||||
ignores.add("alf_data/postgresql/**");
|
||||
ignores.add("META-INF/MANIFEST.MF");
|
||||
ignores.add("META-INF/maven/**");
|
||||
ignores.add("README.txt");
|
||||
|
||||
// Temporary ignores, until we sort out custom diffing or pre-processing before diffs.
|
||||
ignores.add("**/*.sh");
|
||||
ignores.add("**/*.bat");
|
||||
ignores.add("uninstall.app/**");
|
||||
ignores.add("common/bin/**");
|
||||
ignores.add("common/include/**");
|
||||
ignores.add("common/lib/**/*.pc");
|
||||
ignores.add("common/lib/**/*.la");
|
||||
ignores.add("libreoffice.app/Contents/Resources/bootstraprc");
|
||||
ignores.add("postgresql/bin/**");
|
||||
|
||||
FileTreeCompare comparator = new FileTreeCompareImpl(ignores);
|
||||
ResultSet resultSet = comparator.compare(path1, path2);
|
||||
|
||||
Path file = Files.createTempFile(getClass().getSimpleName(), ".html");
|
||||
HtmlResultFormatter formatter = new HtmlResultFormatter();
|
||||
formatter.setDifferencesOnly(true);
|
||||
try(FileOutputStream fos = new FileOutputStream(file.toFile());
|
||||
BufferedOutputStream bos = new BufferedOutputStream(fos))
|
||||
{
|
||||
formatter.format(resultSet, bos);
|
||||
}
|
||||
System.out.println("File: "+file);
|
||||
}
|
||||
|
||||
private void addResult(List<Result> results, String p1, String p2, boolean contentMatch)
|
||||
{
|
||||
Result r = new Result();
|
||||
r.p1 = p1 != null ? Paths.get(p1) : null;
|
||||
r.p2 = p2 != null ? Paths.get(p2) : null;
|
||||
r.equal = contentMatch;
|
||||
results.add(r);
|
||||
}
|
||||
}
|
Binary file not shown.
@@ -0,0 +1,2 @@
|
||||
Sample content
|
||||
More sample content
|
@@ -0,0 +1,2 @@
|
||||
echo Hello
|
||||
echo World
|
@@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo hello
|
||||
echo world
|
@@ -0,0 +1,7 @@
|
||||
public class Aardvark
|
||||
{
|
||||
public static void main(String[] args)
|
||||
{
|
||||
System.out.println("Aardvark!");
|
||||
}
|
||||
}
|
@@ -0,0 +1,7 @@
|
||||
public class Aardvark
|
||||
{
|
||||
public static void main(String[] args)
|
||||
{
|
||||
System.out.println("Banana!");
|
||||
}
|
||||
}
|
@@ -0,0 +1,5 @@
|
||||
Once upon
|
||||
A time
|
||||
Lived
|
||||
A
|
||||
Troll
|
Binary file not shown.
@@ -0,0 +1,2 @@
|
||||
Sample content
|
||||
More sample content
|
@@ -0,0 +1,2 @@
|
||||
echo Hello
|
||||
echo World
|
@@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo hello
|
||||
echo world
|
@@ -0,0 +1,7 @@
|
||||
public class Aardvark
|
||||
{
|
||||
public static void main(String[] args)
|
||||
{
|
||||
System.out.println("Hello Aardvark!");
|
||||
}
|
||||
}
|
@@ -0,0 +1,2 @@
|
||||
Sample content
|
||||
More sample content
|
@@ -0,0 +1,2 @@
|
||||
echo Hello
|
||||
echo World
|
@@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo hello
|
||||
echo world
|
@@ -0,0 +1,7 @@
|
||||
public class Aardvark
|
||||
{
|
||||
public static void main(String[] args)
|
||||
{
|
||||
System.out.println("Aardvark!");
|
||||
}
|
||||
}
|
@@ -0,0 +1,7 @@
|
||||
public class Aardvark
|
||||
{
|
||||
public static void main(String[] args)
|
||||
{
|
||||
System.out.println("Banana!");
|
||||
}
|
||||
}
|
@@ -0,0 +1,5 @@
|
||||
Once upon
|
||||
A time
|
||||
Lived
|
||||
A
|
||||
Troll
|
@@ -0,0 +1,2 @@
|
||||
Sample content
|
||||
More sample content
|
@@ -0,0 +1,2 @@
|
||||
echo Hello
|
||||
echo World
|
@@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo hello
|
||||
echo world
|
@@ -0,0 +1,7 @@
|
||||
public class Aardvark
|
||||
{
|
||||
public static void main(String[] args)
|
||||
{
|
||||
System.out.println("Hello Aardvark!");
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user