Cómo ignorar líneas movidas en un diff


11

Actualmente estoy trabajando en una herramienta de generación de código fuente. Para asegurarme de que mis cambios no introducen ningún error nuevo, un diffentre el resultado del programa antes y después de mis cambios sería, en teoría, una herramienta valiosa.

Sin embargo, esto resulta ser más difícil de lo que uno podría pensar, porque la herramienta genera líneas donde el orden no importa (como importdeclaraciones, declaraciones de funciones, ...) de una manera ordenada de forma semi aleatoria. Debido a esto, la salida de diffestá abarrotada de muchos cambios que, de hecho, son solo líneas movidas a otra posición en el mismo archivo.

¿Hay alguna manera de hacer que diff ignore estos movimientos y solo muestre las líneas que realmente se han agregado o eliminado?


¿Quizás sea más fácil cambiar su herramienta para generar funciones e importar declaraciones en un orden específico (por ejemplo, lexicográfico, si es posible en su idioma)?
Daniel Beck

@Daniel Beck: Vea mi comentario a la respuesta de Gilles a continuación.
dnadlinger

Tema anterior, pero para resumir los comentarios a continuación, ¿cómo podría esta diffherramienta separar movimientos válidos de los inválidos, ya que el orden de las instrucciones en el código es importante y los casos en que esto no es cierto son limitados (importaciones, declaración de funciones y clases, etc.)
Joël

@ Joël: La respuesta es simplemente que sabía que los cambios en el generador que tuve que probar no introducirían ningún error relacionado con el cambio del orden de las líneas. Por supuesto, necesita una herramienta basada en un analizador sintáctico para el idioma de destino para evitar falsos positivos en el caso general (o simplemente un conjunto de pruebas completo para su generador), pero se suponía que esto era una verificación rápida adicional. al código de revisión.
dnadlinger

Respuestas:


2

Puede hacer un simple diff, almacenar el resultado en algún lugar (para evitar otro diff), recorrer las líneas en cualquiera de las versiones y luego eliminarlas del otro lado.

Esto generó un proyecto separado para el código de trabajo. El código.


No estoy seguro de qué se supone que debe hacer exactamente, pero no parece producir los resultados deseados. Según tengo entendido la pregunta, de los dos ejemplos en el código /tmp/oldy /tmp/newno se querrían resultados de diferencia ya que solo hay líneas que se han movido. Sin embargo, este código produce resultados.
Ilari Kajaste

Se arregló el código.
l0b0

No probé la respuesta cuando terminé el proceso de fusión mencionado anteriormente hace mucho tiempo, pero de un vistazo al código parece que podría funcionar.
dnadlinger

4

Puedes intentar ordenarlos primero. Algo como:

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

Bash (y zsh) puede hacer esto en una línea con la sustitución del proceso

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

Esto podría ser una opción, pero los diferenciales generadas no sería muy útil entonces, porque iba a perder todo el número de línea y la información de contexto ...
dnadlinger

Incluso si todavía espero una mejor solución, seguí este enfoque para verificar el lote de cambios en los que había estado trabajando.
dnadlinger

2
Puedo prever dónde esto perdería algunos cambios. A veces el orden importa, a veces no. Descarta todo el contexto.
Rich Homolka

Para un refactorizador de pedidos en el que quería asegurarme de que todo lo que existía todavía funciona, esto era exactamente lo que necesitaba.
ntrrobng

0

Parece que tienes control sobre la herramienta. Luego haga que su salida sea predecible: en lugar de emitir declaraciones en un orden semialeatorio, use (por ejemplo) el orden alfabético como último recurso. Esto no solo tendrá el beneficio de eliminar el crujido inútil de las diferencias, sino también de hacer que la salida de la herramienta sea más fácil de leer y verificar para un ser humano.


Lo siento, pero esta respuesta no me ayuda en absoluto: si fuera tan fácil, la cambiaría de inmediato. Por otra parte, actualmente estoy fusionando los cambios de un proyecto generador se bifurcó originalmente de, por lo que añadir tal vez cambio de gran alcance que complicaría aún más ese proceso ...
dnadlinger

0

Si el archivo está estructurado en secciones, son solo las secciones que están fuera de orden, y existe una expresión regular que puede usar para reconocer el encabezado de la sección, puede dividir los archivos en sus secciones y luego comparar las secciones por pares.

Por ejemplo, acabo de hacer esto en dos volcados de MySQL para compararlos después de que algunos de los nombres de la base de datos hayan cambiado de mayúsculas y minúsculas (y, por lo tanto, el volcado los enumeró en un orden diferente):

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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.