So ignorieren Sie verschobene Linien in einem Diff

11

Ich arbeite derzeit an einem Tool zur Generierung von Quellcode. Um sicherzustellen, dass meine Änderungen keine neuen Fehler verursachen, wäre ein diffzwischen der Ausgabe des Programms vor und nach meinen Änderungen theoretisch ein wertvolles Werkzeug.

Dies stellt sich jedoch als schwieriger heraus, als man denkt, da das Tool Zeilen, bei denen die Reihenfolge keine Rolle spielt (wie importAnweisungen, Funktionsdeklarationen usw.), in halb zufälliger Reihenfolge ausgibt . Aus diesem Grund ist die Ausgabe von diffmit vielen Änderungen überfüllt, bei denen es sich tatsächlich nur um Zeilen handelt, die an eine andere Position in derselben Datei verschoben wurden.

Gibt es eine Möglichkeit, diff dazu zu bringen, diese Bewegungen zu ignorieren und nur die Zeilen auszugeben, die wirklich hinzugefügt oder entfernt wurden?

dnadlinger
quelle
Vielleicht ist es einfacher, Ihr Tool zu ändern, um Funktionen zu generieren und Deklarationen in einer bestimmten Reihenfolge (z. B. lexikografisch, wenn möglich in Ihrer Sprache) zu importieren?
Daniel Beck
@ Daniel Beck: Siehe meinen Kommentar zu Gilles 'Antwort unten.
Dnadlinger
Altes Thema, aber Kommentaren unten zusammenfassen, wie würde dieses diffTool in der Lage sein , gültig bewegt sich von ungültigen zu trennen, wie Reihenfolge der Anweisungen im Code tut Angelegenheit, und Fälle , in denen dies nicht der Fall ist , sind begrenzt (Importe, Erklärung von Funktionen und Klassen, usw.) ?
Joël
@ Joël: Die Antwort ist einfach, dass ich wusste, dass die Generatoränderungen, die ich testen musste, keine Fehler im Zusammenhang mit der Änderung der Zeilenreihenfolge hervorrufen würden. Natürlich benötigen Sie ein Tool, das auf einem Parser für die Zielsprache basiert, um Fehlalarme im allgemeinen Fall zu vermeiden (oder einfach eine umfassende Testsuite für Ihren Generator), aber dies sollte zusätzlich eine schnelle einmalige Überprüfung sein zur Codeüberprüfung.
Dnadlinger

Antworten:

2

Sie können ein einfaches Diff erstellen, das Ergebnis irgendwo speichern (um ein weiteres Diff zu vermeiden), die Linien in beiden Versionen durchlaufen und diese dann von der anderen Seite entfernen.

Dies führte zu einem separaten Projekt für den Arbeitscode. Der Code.

l0b0
quelle
Ich bin mir nicht sicher, was das genau tun soll, aber es scheint nicht die gewünschten Ergebnisse zu erzielen. Als ich die Frage, aus den beiden Beispielen in den Code verstehen /tmp/oldund /tmp/newohne diff Ergebnisse würden gesucht werden , da nur Linien gibt es , die herum bewegt haben. Dieser Code führt jedoch zu Ergebnissen.
Ilari Kajaste
Der Code wurde korrigiert.
10.
Ich habe die Antwort noch nicht getestet, als ich den oben erwähnten Zusammenführungsprozess vor langer Zeit abgeschlossen habe, aber auf den ersten Blick sieht es so aus, als ob es funktionieren könnte.
Dnadlinger
4

Sie können versuchen, sie zuerst zu sortieren. Etwas wie:

sort file-a > s-file-a
sort file-b > s-file-b
diff s-file-a s-file-b

Bash (und zsh) können dies in einer Zeile mit Prozessersetzung tun

diff <(sort file-a) <(sort file-b)
cYrus
quelle
Dies könnte eine Option sein, aber die generierten Unterschiede wären dann nicht sehr nützlich, da ich alle Zeilennummern und Kontextinformationen verlieren würde…
dnadlinger
Auch wenn ich immer noch auf eine bessere Lösung hoffe, habe ich diesen Ansatz gewählt, um die Menge an Änderungen zu überprüfen, an denen ich gearbeitet habe.
Dnadlinger
2
Ich kann vorhersehen, wo dies einige Änderungen verpassen würde. Manchmal ist Ordnung wichtig, manchmal nicht. Sie verwerfen den gesamten Kontext.
Rich Homolka
Für einen bestellenden Refactor, bei dem ich sicherstellen wollte, dass alles, was existiert, noch funktioniert, war dies genau das, was ich brauchte.
ntrrobng
0

Es hört sich so an, als hätten Sie die Kontrolle über das Werkzeug. Machen Sie dann die Ausgabe vorhersehbar: Verwenden Sie als letztes Mittel die alphabetische Reihenfolge, anstatt Deklarationen in einer halbzufälligen Reihenfolge auszugeben. Dies hat nicht nur den Vorteil, dass nutzlose Kruft von Unterschieden entfernt wird, sondern auch, dass die Ausgabe des Werkzeugs für einen Menschen leichter lesbar und verifizierbar ist.

Gilles 'SO - hör auf böse zu sein'
quelle
Entschuldigung, aber diese Antwort hilft mir überhaupt nicht - wenn es so einfach wäre, würde ich es sofort ändern. Darüber hinaus
füge
0

Wenn die Datei in Abschnitte unterteilt ist, sind nur die Abschnitte nicht in der richtigen Reihenfolge, und es gibt einen regulären Ausdruck, mit dem Sie den Abschnittskopf erkennen können. Sie können die Dateien in ihre Abschnitte aufteilen und die Abschnitte dann paarweise vergleichen.

Zum Beispiel habe ich dies nur bei zwei MySQL-Dumps durchgeführt, um sie zu vergleichen, nachdem einige der Datenbanknamen die Groß- und Kleinschreibung geändert hatten (und der Dump sie daher in einer anderen Reihenfolge auflistete):

csplit all-07sep2015-11:19:12.sql '/Current Database/-1' '{*}'  # split the dump made before the change, creating files xx00, xx01, ...
csplit -f yy all-07sep2015-12:26:12.sql '/Current Database/-1' '{*}' # split the dump made after the change, creating files yy00, yy01, ...
fgrep 'Current Database' xx?? yy?? | perl -lne 'BEGIN{my %foo}; /(^....).*`(.*)`/ and push(@{$foo{lc($2)}}, $1); END {printf("diff -di %s %s\n", @{$_}) for values %foo}' | sh -x | less  # match the pairs and compare them with diff
Reinierpost
quelle