Comment ignorer les lignes déplacées dans un diff

11

Je travaille actuellement sur un outil de génération de code source. Pour être sûr que mes modifications n'introduisent aucun nouveau bogue, un diffentre la sortie du programme avant et après mes modifications serait théoriquement un outil précieux.

Cependant, cela s'avère plus difficile qu'on ne pourrait le penser, car l'outil génère des lignes où l'ordre n'a pas d'importance (comme les importinstructions, les déclarations de fonctions,…) de manière semi-aléatoire. Pour cette raison, la sortie de diffest encombrée de nombreuses modifications qui ne sont en fait que des lignes déplacées vers une autre position dans le même fichier.

Existe-t-il un moyen de faire en sorte que diff ignore ces mouvements et ne produise que les lignes qui ont vraiment été ajoutées ou supprimées?

dnadlinger
la source
Peut-être est-il plus facile de changer votre outil pour générer des fonctions et importer des déclarations dans un ordre spécifique (par exemple lexicographique, si possible dans votre langue)?
Daniel Beck
@Daniel Beck: Voir mon commentaire sur la réponse de Gilles ci-dessous.
dnadlinger
Ancien sujet, mais pour résumer les commentaires ci-dessous, comment cet diffoutil pourrait-il séparer les mouvements valides des mouvements invalides, car l'ordre des instructions dans le code est important et les cas où cela n'est pas vrai sont limités (importations, déclaration de fonctions et de classes, etc.) ?
Joël
@ Joël: La réponse est simplement que je savais que les changements de générateur que je devais tester n'introduiraient pas de bugs liés au changement de l'ordre des lignes. Bien sûr, vous avez besoin d'un outil basé sur un analyseur pour la langue cible pour éviter les faux positifs dans le cas général (ou simplement une suite de tests complète pour votre générateur), mais cela était censé être une vérification ponctuelle rapide en plus pour réviser le code.
dnadlinger

Réponses:

2

Vous pouvez faire un simple diff, stocker le résultat quelque part (pour éviter un autre diff), parcourir les lignes dans l'une ou l'autre version, puis supprimer celles de l'autre côté.

Cela a engendré un projet distinct pour le code de travail. Le code.

l0b0
la source
Je ne sais pas exactement ce que cela est censé faire exactement, mais cela ne semble pas produire les résultats souhaités. Si je comprends bien la question, à partir des deux exemples dans le code /tmp/oldet /tmp/newaucun résultat de comparaison ne serait souhaité car il n'y a que des lignes qui ont été déplacées. Ce code produit cependant des résultats.
Ilari Kajaste
Correction du code.
l0b0
Je n'ai pas testé la réponse car j'ai terminé le processus de fusion mentionné ci-dessus il y a longtemps, mais d'un coup d'œil au code, il semble que cela pourrait fonctionner.
dnadlinger
4

Vous pouvez essayer de les trier en premier. Quelque chose comme:

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

Bash (et zsh) peut le faire en une seule ligne avec substitution de processus

diff <(sort file-a) <(sort file-b)
cYrus
la source
Cela pourrait être une option, mais les différences générées ne seraient alors pas très utiles, car je perdrais tout le numéro de ligne et les informations de contexte…
dnadlinger
Même si j'espère toujours une meilleure solution, j'ai choisi cette approche pour vérifier le lot de modifications sur lesquelles je travaillais.
dnadlinger
2
Je peux prévoir où cela manquerait certains changements. Parfois, l'ordre compte, parfois non. Vous jetez tout contexte.
Rich Homolka
Pour un refactoring de commande où je voulais m'assurer que tout ce qui existait existe toujours, c'était exactement ce dont j'avais besoin.
ntrrobng
0

Il semble que vous ayez le contrôle de l'outil. Rendez ensuite sa sortie prévisible: au lieu d'émettre des déclarations dans un ordre semi-aléatoire, utilisez (disons) l'ordre alphabétique en dernier recours. Cela aura non seulement l'avantage de supprimer la cruauté inutile des diffs, mais aussi de rendre la sortie de l'outil plus facile à lire et à vérifier pour un être humain.

Gilles 'SO- arrête d'être méchant'
la source
Désolé, mais cette réponse ne m'aide pas du tout - si c'était si facile, je la changerais tout de suite. De plus, je suis en train de fusionner des modifications à partir d'un projet dont le générateur était originellement issu, donc l'ajout d'un changement d'une telle
ampleur
0

Si le fichier est structuré en sections, ce ne sont que les sections qui ne fonctionnent pas et qu'il existe une expression régulière que vous pouvez utiliser pour reconnaître l'en-tête de section, vous pouvez diviser les fichiers en leurs sections, puis comparer les sections par paire.

Par exemple, je viens de le faire sur deux vidages MySQL pour les comparer après que certains noms de base de données ont changé de casse (et donc le vidage les a listés dans un ordre différent):

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
la source