Cara mengabaikan garis yang dipindahkan dalam diff

11

Saat ini saya sedang mengerjakan alat pembuat kode sumber. Untuk memastikan bahwa perubahan saya tidak memperkenalkan bug baru, diffantara hasil dari program sebelum dan sesudah perubahan saya secara teoritis akan menjadi alat yang berharga.

Namun, ini ternyata lebih sulit daripada yang mungkin dipikirkan, karena alat menghasilkan garis di mana urutannya tidak penting (seperti importpernyataan, deklarasi fungsi, ...) dengan cara yang dipesan secara semi-acak. Karena ini, output dari diffberantakan dengan banyak perubahan yang sebenarnya hanya garis yang dipindahkan ke posisi lain di file yang sama.

Apakah ada cara untuk membuat diff mengabaikan gerakan ini dan hanya menampilkan garis yang benar-benar telah ditambahkan atau dihapus?

dnadlinger
sumber
Mungkin lebih mudah untuk mengubah alat Anda untuk menghasilkan fungsi dan mengimpor deklarasi dalam urutan tertentu (misalnya leksikografis, jika mungkin dalam bahasa Anda)?
Daniel Beck
@Daniel Beck: Lihat komentar saya untuk jawaban Gilles di bawah ini.
dnadlinger
Subjek lama, tetapi untuk merangkum komentar di bawah, bagaimana diffalat ini dapat memisahkan perpindahan yang valid dari yang tidak valid, karena Urutan instruksi dalam kode memang penting, dan kasus-kasus di mana ini tidak benar terbatas (impor, deklarasi fungsi dan kelas, dll)?
Joël
@ Joël: Jawabannya adalah saya tahu bahwa perubahan generator yang saya uji tidak akan memperkenalkan bug yang berhubungan dengan mengubah urutan baris. Tentu saja, Anda memerlukan alat yang didasarkan pada parser untuk bahasa target untuk menghindari kesalahan positif dalam kasus umum (atau hanya test suite komprehensif untuk generator Anda), tetapi ini seharusnya merupakan pemeriksaan sekali saja yang cepat sebagai tambahan untuk meninjau kode.
dnadlinger

Jawaban:

2

Anda bisa melakukan diff sederhana, menyimpan hasilnya di suatu tempat (untuk menghindari diff lain), loop melalui garis-garis di kedua versi, lalu hapus yang dari sisi lain.

Ini melahirkan proyek terpisah untuk kode kerja. Kode.

l0b0
sumber
Saya tidak yakin apa yang seharusnya dilakukan dengan tepat, tetapi sepertinya tidak menghasilkan hasil yang diinginkan. Seperti yang saya pahami pertanyaannya, dari dua contoh dalam kode /tmp/olddan /tmp/newtidak ada hasil yang berbeda yang diinginkan karena hanya ada baris yang telah dipindahkan. Namun kode ini menghasilkan hasil.
Ilari Kajaste
Memperbaiki kode.
l0b0
Belum menguji jawabannya ketika saya menyelesaikan proses penggabungan yang disebutkan di atas sejak lama, tetapi dari pandangan sekilas pada kode sepertinya itu bisa bekerja.
dnadlinger
4

Anda dapat mencoba mengurutkannya terlebih dahulu. Sesuatu seperti:

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

Bash (dan zsh) dapat melakukan ini dalam satu baris dengan substitusi proses

diff <(sort file-a) <(sort file-b)
cYrus
sumber
Ini mungkin pilihan, tetapi diff yang dihasilkan tidak akan sangat berguna saat itu, karena saya akan kehilangan semua nomor baris dan informasi konteks ...
dnadlinger
Bahkan jika saya masih berharap untuk solusi yang lebih baik, saya pergi dengan pendekatan ini untuk memverifikasi sejumlah perubahan yang telah saya kerjakan.
dnadlinger
2
Saya dapat memperkirakan di mana ini akan melewatkan beberapa perubahan. Kadang-kadang pesanan penting, kadang tidak. Anda membuang semua konteks.
Rich Homolka
Untuk refactor pemesanan tempat saya ingin memastikan semua yang ada masih ada, inilah yang saya butuhkan.
ntrrobng
0

Sepertinya Anda memiliki kendali atas alat ini. Kemudian buat hasilnya dapat diprediksi: alih-alih memancarkan deklarasi dalam urutan semi-acak, gunakan (katakanlah) urutan abjad sebagai pilihan terakhir. Ini tidak hanya bermanfaat untuk menghilangkan cacat yang tidak berguna dari diffs, tetapi juga membuat keluaran alat lebih mudah dibaca dan diverifikasi untuk manusia.

Gilles 'SANGAT berhenti menjadi jahat'
sumber
Maaf, tapi jawaban ini sama sekali tidak membantu saya - jika mudah, saya akan segera mengubahnya. Selain itu, saya saat ini menggabungkan perubahan dari sebuah proyek yang awalnya dibuat oleh generator, jadi menambahkan perubahan yang agak jauh akan memperumit proses itu bahkan lebih ...
dnadlinger
0

Jika file terstruktur menjadi beberapa bagian, itu hanya bagian yang rusak, dan ada ekspresi reguler yang bisa Anda gunakan untuk mengenali bagian header, Anda bisa csplit file ke dalam bagian-bagian mereka dan kemudian membandingkan bagian-bagian secara berpasangan.

Sebagai contoh, saya hanya melakukan ini pada dua dump MySQL untuk membandingkannya setelah beberapa nama database mengubah huruf (dan oleh karena itu dump mendaftarkannya dalam urutan yang berbeda):

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
sumber