2010-10-10 17 views
29

A volte, per qualsiasi motivo, devo produrre file di patch (sotto Linux) che sono nella direzione sbagliata. So che posso affrontare questo problema utilizzando lo switch -R quando lo si applica tramite patch, ma sarebbe bello se ci fosse un modo per invertire definitivamente il file di patch. Esiste un'utilità che può eseguire questa operazione, ad es. una regex che sarebbe garantita per funzionare?Inversione permanente di un file di patch

UPDATE

Lie Ryan ha suggested a neat way of doing this. Tuttavia, richiede l'accesso ai file di origine originali. Quindi suppongo che dovrei aggiornare la mia domanda per affermare che sono più in grado di ottenere questo dato solo il file di patch stesso.

risposta

44

È possibile utilizzare lo strumento interdiff(1) da patchutils. In particolare, la pagina man per interdiff dice:

Per invertire una patch, utilizzare/dev/null per diff2.

Quindi,

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

non funziona. Ho provato ad applicare la patch invertita al file corretto con la patch forward, e fallisce. Quindi questo non produce una patch invertita corretta, almeno non per tutte le patch. Non so se l'interdiff è rotto o questo metodo è solo sbagliato – matteo

+0

Vedo, questo * è * dovrebbe funzionare secondo la pagina man di interdiff, quindi è un bug in interdiff – matteo

14

Prova:

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:

Per invertire un diff unificato, è necessario cambiare tre cose:

  • la patch intestazione intestazione
  • il pezzo
  • il + a - e - a +

Quindi, ecco come un colpo di testa patch per un aspetto:

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

è necessario invertire esso in modo che assomiglia a questo:

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

passare sostanzialmente l'ordine, e l'interruttore + ++ a --- e viceversa.

Avanti, l'intestazione pezzo:

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

È necessario invertire i numeri, in modo da apparire come questo:

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

fondamentalmente, passare le coppie di numeri

e ultimo, cambia ogni riga che inizia con + e ogni riga che inizia con -.

EDIT:

per passare l'intestazione pezzo, si può fare:

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

per passare + a - e - a +, si può fare:

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

infine:

per invertire l'intestazione di patch, effettuare:

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 

Così, finalmente, il nostro script (veloce e sporco) si presenta come:

#!/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 

ho provato e sembra funzionare.

però, per rendere le cose più gestibile, e più pulito:

#!/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: Non avevo pensato a questo. Ma per interesse, c'è un modo per farlo senza accedere ai file originali? –

+0

@Oli Charlesworth: Il file file.txt.orig sono di backup automatico generato dal patch quando si chiama in prima linea. Semplicemente uso quel backup per rigenerare la patch invertita. –

+0

@Lie Ryan: Volevo dire, come potrei farlo se io * solo * ho la patch-file? –

0

avevo applicato un cerotto patch -N -p0 < path/file.patch ma ho iniziato di fronte problemi di compilazione a causa di codice incompleto tutto quello che ho fatto è stato per eseguire questo comando patch -p0 -R < path/file.patch. Deferito tale link