Jak zignorować przesunięte linie w diff


11

Obecnie pracuję nad narzędziem do generowania kodu źródłowego. Aby upewnić się, że moje zmiany nie wprowadzają żadnych nowych błędów, diffteoretycznie cennym narzędziem byłoby między wyjściem programu przed i po moich zmianach.

Jednak okazuje się to trudniejsze niż mogłoby się wydawać, ponieważ narzędzie wypisuje wiersze, w których kolejność nie ma znaczenia (np. importInstrukcje, deklaracje funkcji,…) w sposób pół losowo uporządkowany. Z tego powodu wynik diffjest zaśmiecony wieloma zmianami, które w rzeczywistości są tylko liniami przeniesionymi do innej pozycji w tym samym pliku.

Czy istnieje sposób, aby diff ignorował te ruchy i wyświetlał tylko te wiersze, które naprawdę zostały dodane lub usunięte?


Może łatwiej jest zmienić narzędzie do generowania funkcji i importowania deklaracji w określonej kolejności (np. Leksykograficznej, jeśli to możliwe w twoim języku)?
Daniel Beck

@Daniel Beck: Zobacz mój komentarz do odpowiedzi Gillesa poniżej.
dnadlinger,

Stary temat, ale podsumowując komentarze poniżej, w jaki sposób to diffnarzędzie byłoby w stanie oddzielić prawidłowe przeniesienia od niepoprawnych, ponieważ kolejność instrukcji w kodzie ma znaczenie, a przypadki, w których nie jest to prawdą, są ograniczone (import, deklaracja funkcji i klas, itp.)?
Joël

@ Joël: Odpowiedź jest prosta: wiedziałem, że zmiany generatora, które musiałem przetestować, nie wprowadziłyby żadnych błędów związanych ze zmianą kolejności linii. Oczywiście potrzebujesz narzędzia opartego na parserze dla języka docelowego, aby uniknąć fałszywych alarmów w ogólnym przypadku (lub po prostu kompleksowego zestawu testów dla twojego generatora), ale miał to być również szybki jednorazowy test do przeglądu kodu.
dnadlinger,

Odpowiedzi:


2

Możesz zrobić prosty diff, zapisać gdzieś wynik (aby uniknąć innego diff), zapętlić linie w obu wersjach, a następnie usunąć je z drugiej strony.

Spowodowało to powstanie osobnego projektu dla działającego kodu. Kod.


Nie jestem pewien, co dokładnie powinno to zrobić, ale wydaje się, że nie przynosi oczekiwanych rezultatów. Jak rozumiem pytanie, z dwóch przykładów w kodzie /tmp/oldi /tmp/newżadnych różnic nie byłby pożądany, ponieważ zostały przeniesione tylko linie. Ten kod daje jednak wyniki.
Ilari Kajaste

Naprawiono kod.
l0b0

Nie testowałem odpowiedzi, ponieważ już dawno skończyłem proces scalania, o którym mowa powyżej, ale na pierwszy rzut oka wygląda na to, że mógłby zadziałać.
dnadlinger,

4

Najpierw możesz spróbować je posortować. Coś jak:

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

Bash (i zsh) może to zrobić w jednym wierszu z podstawieniem procesu

diff <(sort file-a) <(sort file-b)

Może to być opcja, ale wygenerowane różnice nie byłyby wtedy bardzo przydatne, ponieważ straciłbym cały numer linii i informacje kontekstowe…
dnadlinger

Nawet jeśli wciąż mam nadzieję na lepsze rozwiązanie, zastosowałem to podejście do weryfikacji partii zmian, nad którymi pracowałem.
dnadlinger,

2
Mogę przewidzieć, gdzie to pominąłoby niektóre zmiany. Czasami zamówienie ma znaczenie, a czasem nie. Odrzucasz cały kontekst.
Rich Homolka

Dla refaktora zamawiającego, w którym chciałem się upewnić, że wszystko, co istniało, nadal działa, właśnie tego potrzebowałem.
ntrrobng

0

Wygląda na to, że masz kontrolę nad narzędziem. Następnie spraw, aby jego wynik był przewidywalny: zamiast emitować deklaracje w pół losowej kolejności, użyj (powiedzmy) kolejności alfabetycznej w ostateczności. Przyniesie to nie tylko korzyść polegającą na usunięciu bezużytecznego crufta z różnic, ale także na ułatwieniu odczytania i weryfikacji wyników narzędzia przez człowieka.


Przepraszam, ale ta odpowiedź w ogóle mi nie pomaga - gdybym była taka łatwa, od razu bym ją zmieniła. Ponadto łączę obecnie zmiany z projektu, z którego pierwotnie opracowano generator, więc dodanie tak daleko idącej zmiany skomplikowałoby ten proces jeszcze bardziej…
dnadlinger

0

Jeśli plik jest podzielony na sekcje, to tylko sekcje są nie w porządku, a istnieje wyrażenie regularne, którego można użyć do rozpoznania nagłówka sekcji, możesz umieścić pliki w sekcjach i porównać sekcje w parach.

Na przykład, właśnie to zrobiłem na dwóch zrzutach MySQL, aby porównać je po zmianie wielkości nazw niektórych baz danych (dlatego zrzut pokazał je w innej kolejności):

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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.