diff --git a/lib/std/private/gitutils.nim b/lib/std/private/gitutils.nim index db0c607255..16eaf3580f 100644 --- a/lib/std/private/gitutils.nim +++ b/lib/std/private/gitutils.nim @@ -39,14 +39,27 @@ proc isGitRepo*(dir: string): bool = # remove trailing whitespaces from the result. result = status == 0 and output.strip() == "" -proc diffStrings*(a, b: string): string = +proc diffFiles*(path1, path2: string): tuple[output: string, same: bool] = + # could be customized, e.g. non-git diff with `diff -uNdr`, or with git diff options (e.g. --color-moved, --word-diff). + # in general, git diff has more options. + var status = 0 + (result.output, status) = execCmdEx("git diff --no-index $1 $2" % [path1.quoteShell, path2.quoteShell]) + doAssert (status == 0) or (status == 1) + result.same = status == 0 + +proc diffStrings*(a, b: string): tuple[output: string, same: bool] = runnableExamples: - let a = "ok1\nok2\nok3" - let b = "ok1\nok2 alt\nok3" - let c = diffStrings(a, b) - echo c - let c2 = diffStrings(a, a) - echo c2 + let a = "ok1\nok2\nok3\n" + let b = "ok1\nok2 alt\nok3\nok4\n" + let (c, same) = diffStrings(a, b) + doAssert not same + let (c2, same2) = diffStrings(a, a) + doAssert same2 + + runnableExamples("-r:off"): + let a = "ok1\nok2\nok3\n" + let b = "ok1\nok2 alt\nok3\nok4\n" + echo diffStrings(a, b).output template tmpFileImpl(prefix, str): auto = # pending https://github.com/nim-lang/Nim/pull/17889 @@ -59,7 +72,4 @@ proc diffStrings*(a, b: string): string = defer: removeFile(patha) removeFile(pathb) - # could be customized, e.g. non-git diff with `diff -uNdr`, or with git diff options. - var status = 0 - (result, status) = execCmdEx("git diff --no-index $1 $2" % [patha.quoteShell, pathb.quoteShell]) - echo status + result = diffFiles(patha, pathb) diff --git a/nimdoc/rsttester.nim b/nimdoc/rsttester.nim index 6d41ffb86b..daca3dfc76 100644 --- a/nimdoc/rsttester.nim +++ b/nimdoc/rsttester.nim @@ -1,4 +1,5 @@ import os, strutils +from std/private/gitutils import diffFiles const baseDir = "nimdoc/rst2html" @@ -19,7 +20,7 @@ proc testRst2Html(fixup = false) = exec("$1 rst2html $2" % [nimExe, sourceFile]) let producedHtml = expectedHtml.replace('\\', '/').replace("/expected/", "/source/htmldocs/") if readFile(expectedHtml) != readFile(producedHtml): - discard execShellCmd("diff -uNdr " & expectedHtml & " " & producedHtml) + echo diffFiles(expectedHtml, producedHtml).output inc failures if fixup: copyFile(producedHtml, expectedHtml) diff --git a/nimdoc/tester.nim b/nimdoc/tester.nim index 5262952224..9daa0bb51e 100644 --- a/nimdoc/tester.nim +++ b/nimdoc/tester.nim @@ -3,6 +3,7 @@ # to change expected results (after carefully verifying everything), use -d:fixup import strutils, os +from std/private/gitutils import diffFiles var failures = 0 @@ -40,7 +41,7 @@ proc testNimDoc(prjDir, docsDir: string; switches: NimSwitches; fixup = false) = inc failures elif readFile(expected) != readFile(produced): echo "FAILURE: files differ: ", produced - discard execShellCmd("diff -uNdr " & expected & " " & produced) + echo diffFiles(expected, produced).output inc failures if fixup: copyFile(produced, expected) diff --git a/nimpretty/tester.nim b/nimpretty/tester.nim index 0a60ce6935..b1f15aee61 100644 --- a/nimpretty/tester.nim +++ b/nimpretty/tester.nim @@ -1,6 +1,7 @@ # Small program that runs the test cases import strutils, os, sequtils +from std/private/gitutils import diffFiles const dir = "nimpretty/tests" @@ -26,7 +27,7 @@ proc test(infile, ext: string) = let produced = dir / nimFile.changeFileExt(ext) if readFile(expected) != readFile(produced): echo "FAILURE: files differ: ", nimFile - discard execShellCmd("diff -uNdr " & expected & " " & produced) + echo diffFiles(expected, produced).output failures += 1 else: echo "SUCCESS: files identical: ", nimFile @@ -43,7 +44,7 @@ proc testTogether(infiles: seq[string]) = let produced = dir / "outputdir" / infile if readFile(expected) != readFile(produced): echo "FAILURE: files differ: ", nimFile - discard execShellCmd("diff -uNdr " & expected & " " & produced) + echo diffFiles(expected, produced).output failures += 1 else: echo "SUCCESS: files identical: ", nimFile diff --git a/testament/categories.nim b/testament/categories.nim index ffee5eeb39..f1dee35708 100644 --- a/testament/categories.nim +++ b/testament/categories.nim @@ -665,8 +665,8 @@ proc runJoinedTest(r: var TResults, cat: Category, testsDir: string, options: st if buf != outputExpected: writeFile(outputExceptedFile, outputExpected) - discard execShellCmd("diff -uNdr $1 $2" % [outputExceptedFile, outputGottenFile]) - echo failString & "megatest output different!" + echo diffFiles(outputGottenFile, outputExceptedFile).output + echo failString & "megatest output different, see $1 vs $2" % [outputGottenFile, outputExceptedFile] # outputGottenFile, outputExceptedFile not removed on purpose for debugging. quit 1 else: diff --git a/testament/testament.nim b/testament/testament.nim index 9caa3f6b9b..0607ac41d1 100644 --- a/testament/testament.nim +++ b/testament/testament.nim @@ -17,6 +17,7 @@ from std/sugar import dup import compiler/nodejs import lib/stdtest/testutils from lib/stdtest/specialpaths import splitTestFile +from std/private/gitutils import diffStrings proc trimUnitSep(x: var string) = let L = x.len @@ -307,7 +308,7 @@ proc addResult(r: var TResults, test: TTest, target: TTarget, maybeStyledEcho styleBright, expected, "\n" maybeStyledEcho fgYellow, "Gotten:" maybeStyledEcho styleBright, given, "\n" - + echo diffStrings(expected, given).output if backendLogging and (isAppVeyor or isAzure): let (outcome, msg) =