private Task Diff(string filePath) { // TODO: throw? warn? if (string.IsNullOrEmpty(diffTool.Cmd)) { return(Task.CompletedTask); } var changes = repository.Diff.Compare <TreeChanges>().Modified.First(x => x.Path == filePath); var old = repository.Lookup <Blob>(changes.OldOid); // We can't show diff in this case if (changes.Mode != Mode.NonExecutableFile || !changes.Exists || old == null || old.IsBinary) { return(Task.CompletedTask); } // Write the old content to a temp file for comparison. var baseFile = Path.Combine(Path.GetTempPath(), Path.ChangeExtension(Path.GetFileName(filePath), ".BASE" + Path.GetExtension(filePath))); File.WriteAllText(baseFile, old.GetContentText()); #pragma warning disable CS8602 // Dereference of a possibly null reference. var indexOfDolar = diffTool.Cmd.IndexOf("$"); if (indexOfDolar == -1) { // TODO: There were no replacements, so we can't diff anything. Report warning/error? return(Task.CompletedTask); } var indexOfArgs = diffTool.Cmd.Substring(0, indexOfDolar).LastIndexOf(' '); var toolFilePath = diffTool.Cmd.Substring(0, indexOfArgs).Trim(); var fullFilePath = repository.GetFullPath(filePath); // Replace arguments as documented in https://git-scm.com/docs/git-difftool#_options var arguments = diffTool.Cmd.Substring(indexOfArgs) // "$LOCAL is set to the name of the temporary file containing the contents of the diff pre-image" .Replace("$LOCAL", baseFile) // "$REMOTE is set to the name of the temporary file containing the contents of the diff post-image" // We want the current file to be the one including the "changes post-image". .Replace("$REMOTE", fullFilePath) // Yes, it's confusing even in the docs that $BASE == $MERGED. // "$MERGED is the name of the file which is being compared. .Replace("$MERGED", fullFilePath) // "$BASE is provided for compatibility with custom merge tool commands and has the same value as $MERGED." .Replace("$BASE", fullFilePath); #pragma warning restore CS8602 // Dereference of a possibly null reference. RunTool(toolFilePath, arguments); return(Task.CompletedTask); }