in Sharpmake.Application/Program.cs [734:819]
private static void LogFileChanges(List<BuildContext.RegressionTest.OutputInfo> fileChanges, bool showRegressionDiff)
{
if (fileChanges.Count == 0)
return;
var diffs = new Dictionary<string, List<string>>(StringComparer.OrdinalIgnoreCase);
object dictionaryAccess = new object();
string diffExecutable = LocateDiffExecutable();
if (!showRegressionDiff || diffExecutable == null)
{
DebugWriteLine($" {fileChanges.Count} files have changed from the reference:");
fileChanges.ForEach(x =>
{
DebugWriteLine($" Exp: {x.ReferencePath}");
DebugWriteLine($" Was: {x.OutputPath}");
});
}
else
{
DebugWriteLine($" {fileChanges.Count} files have changed from the reference. Aggregating diff using '{diffExecutable}'");
Parallel.ForEach(fileChanges, x =>
{
bool refFileExists = File.Exists(x.ReferencePath);
bool outFileExists = File.Exists(x.OutputPath);
if (refFileExists && outFileExists)
{
Process process = new Process();
process.StartInfo.FileName = diffExecutable;
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.RedirectStandardOutput = true;
// -i, --ignore-case ignore case differences in file contents
// -u, -U NUM, --unified[=NUM] output NUM (default 3) lines of unified context
// -w, --ignore-all-space ignore all white space
process.StartInfo.Arguments = $"-i -u -w {x.ReferencePath} {x.OutputPath}";
process.Start();
var output = process.StandardOutput.ReadToEnd();
process.WaitForExit();
var lines = output.Split('\n').Where(l => (l.Length > 1 && (l[0] == '+' || l[0] == '-') && !l.StartsWith("--- ") && !l.StartsWith("+++ ")));
var diff = string.Concat(lines);
lock (dictionaryAccess)
{
List<string> currentList = null;
if (!diffs.TryGetValue(diff, out currentList))
diffs[diff] = new List<string> { x.OutputPath };
else
currentList.Add(x.OutputPath);
}
}
else if (!refFileExists)
DebugWriteLine($" ExtraFileGenerated: {x.OutputPath}");
else if (!outFileExists)
DebugWriteLine($" MissingFileInOutput: {x.ReferencePath}");
});
int i = 0;
foreach (var diff in diffs.OrderByDescending(d => d.Value.Count))
{
DebugWriteLine(
$" Diff block {++i}/{diffs.Count}"
+ (diff.Value.Count > 1 ? $" shared by {diff.Value.Count} files:" : " only in '" + diff.Value.First() + "':")
);
int j = 0;
foreach (var file in diff.Value.OrderBy(f => f))
DebugWriteLine($" {++j}/{diff.Value.Count} {file}");
var diffLines = diff.Key.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
if (diffLines.Length == 0)
{
DebugWriteLine(" // only whitespace or casing changes");
}
else
{
foreach (var diffLine in diffLines)
DebugWriteLine($" {diffLine}");
}
}
}
}