2010-10-10 21 views
29

Parfois, pour une raison quelconque, je dois produire des fichiers patch (sous Linux) qui sont dans la mauvaise direction. Je sais que je peux faire face à cela en utilisant le -R commutateur lors de l'application via patch, mais ce serait bien s'il y avait un moyen d'inverser définitivement le fichier patch. Y a-t-il un utilitaire qui peut le faire, ou par ex. une regex qui serait garantie de fonctionner?Inverser de façon permanente un fichier patch

MISE À JOUR

Lie Ryan a suggested a neat way of doing this. Cependant, il nécessite l'accès au (x) fichier (s) source (s) d'origine. Donc, je suppose que je devrais mettre à jour ma question pour indiquer que je suis plus après une manière de réaliser ceci donné seulement le patch-dossier lui-même.

Répondre

44

Vous pouvez utiliser l'outil interdiff(1) de patchutils. En particulier, la page de manuel pour interdiff dit:

Pour inverser un patch, utilisez/dev/null pour diff2.

Ainsi,

$ interdiff file.patch /dev/null > reversed.patch 
+0

ne fonctionne pas. J'ai essayé d'appliquer le correctif inversé au fichier corrigé avec le correctif avant, et cela échoue. Cela ne produit donc pas un correctif inversé correct, du moins pas pour tous les correctifs. Je ne sais pas si interdiff est cassé ou cette méthode est juste fausse – matteo

+0

Je vois, ceci * est * censé fonctionner selon la page de manuel d'interdiff, donc c'est un bug dans interdiff – matteo

14

Essayez:

patch -R file.txt file.patch 
diff file.txt.orig file.txt > file.patch.rev 
// you can then `rm file.txt.orig file.patch` 

EDIT:

Pour inverser un diff unifié, vous devez changer trois choses:

  • l'en-tête correctif
  • l'en-tête de morceau
  • le + à - et - à +

Alors voici comment un en-tête de patch pour un ressemble:

--- b.asm 2010-09-24 12:03:43.000000000 +1000  
+++ a.asm 2010-09-24 23:28:43.000000000 +1000 

vous avez besoin pour inverser il ressemble à ceci:

--- a.asm 2010-09-24 23:28:43.000000000 +1000 
+++ b.asm 2010-09-24 12:03:43.000000000 +1000  

fondamentalement changer l'ordre, et le commutateur + ++ à --- et vice versa.

Ensuite, l'en-tête de morceau:

@@ -29,5 +27,7 @@ 

Vous devez inverser les chiffres, donc ressembler à ceci:

@@ -27,7 +29,5 @@ 

essentiellement, passer les paires de nombres

et dernier, changez chaque ligne commençant par + et chaque ligne commençant par -.

EDIT:

pour passer l'en-tête de morceau, vous pouvez le faire:

sed -e "s/@@ -\([0-9]\+,[0-9]\+\) +\([0-9]\+,[0-9]\+\) @@/@@ -\2 +\1 @@/" 

changer + - et - à +, vous pouvez faire:

sed -e "s/^+/P/" -e "s/^-/+/" -e "s/^P/-/" 

FINALEMENT:

pour inverser l'en-tête de patch, on:

head -2 orig.diff | tac | sed -e "s/+++/PPP/" -e "s/---/+++/" -e "s/PPP/---/" > head 
tail orig.diff -n+3 > tail 
cat head tail > headtail 
rm head tail 

Alors, enfin, notre script (rapide et sale) ressemble à:

#!/usr/bin/env sh 
F="$1" 
head -2 $F | tac | sed -e "s/+++/PPP/" -e "s/---/+++/" -e "s/PPP/---/" > $F.head 
tail $F -n+3 | sed -e "s/@@ -\([0-9]\+,[0-9]\+\) +\([0-9]\+,[0-9]\+\) @@/@@ -\2 +\1 @@/" -e "s/^+/P/" -e "s/^-/+/" -e "s/^P/-/" > $F.tail 
cat $F.head $F.tail 
rm $F.head $F.tail 

Je l'ai testé, et il semble fonctionner.

cependant, pour rendre les choses plus maintenable, et plus propre:

#!/usr/bin/env sh 
swap() { 
    sed -e "s/^$1/PPP/" -e "s/^$2/$1/" -e "s/^PPP/$2/" 
} 
file_header() { 
    head -2 $1 | tac | swap +++ --- 
} 
fix_chunk_header() { 
    sed -e "s/@@ -\([0-9]\+,[0-9]\+\) +\([0-9]\+,[0-9]\+\) @@/@@ -\2 +\1 @@/" 
} 
fix_lines() { 
    swap + - 
} 
file="$1" 
file_header $file 
tail $file -n+3 | fix_chunk_header | fix_lines 
+0

+1: Je n'avais pas pensé à cela. Mais par intérêt, y a-t-il un moyen de le faire sans avoir accès aux fichiers originaux? –

+0

@Oli Charlesworth: Le fichier file.txt.orig est une sauvegarde automatique générée par patch lorsque vous l'appelez en première ligne. J'utilise simplement cette sauvegarde pour régénérer le patch inversé. –

+0

@Lie Ryan: Ce que je voulais dire, comment pourrais-je le faire si j'avais * seulement * le patch-fichier? –

0

J'avais appliqué un patch patch -N -p0 < path/file.patch mais j'ai commencé à faire face aux problèmes de compilation en raison de code réduit tout ce que je ne faisais que pour exécuter cette commande patch -p0 -R < path/file.patch. J'ai renvoyé cette link