Cómo hacer que el parche ignore los trozos ya aplicados

14

Tengo un archivo de parche muy grande que estoy tratando de aplicar a mi código. El problema es que algunos de los cambios en mi parche ya existen en el código. ¿Hay alguna manera de hacer que el parche ignore con gracia los cambios que ya se han aplicado?

La -Nopción no hace lo que quiero. Si encuentra un trozo ya aplicado, generará un archivo de rechazo y no aplicará más trozos a ese archivo. Quiero que ignore ese trozo y continúe aplicando el resto del parche. La única vez que quiero que genere un archivo .rej es si un trozo no se puede aplicar y parece que ya no se ha aplicado.

¿Hay alguna forma de hacer esto?

Shum
fuente

Respuestas:

7

Necesitará patchutils instalados para esto.

Este script dividirá un parche grande en parches separados más pequeños, cada uno de los cuales contiene solo un trozo para un archivo. Luego puede aplicar estos parches con patch --forward.

#!/bin/sh -eu

PATCH=$1
OUTDIR=$2

test -f "$PATCH" && test -d "$OUTDIR"

TDIR=$(mktemp -d)
trap 'rm -rf $TDIR' 0

INDEX=0
TEMPHUNK=$TDIR/current_hunk

lsdiff $1 | while read FNAME
do
    HUNK=1
    while :
    do
        filterdiff --annotate --hunks=$HUNK -i "$FNAME" "$PATCH" > "$TEMPHUNK"
        HUNK=$((HUNK+1))
        test -s "$TEMPHUNK" && \
            {
                mv "$TEMPHUNK" "$OUTDIR/$INDEX.diff"
                INDEX=$((INDEX+1))
            } || break
    done
done

Editar : guardar guión en hunks.shy llamarlo:

./hunks.sh path/to/big.diff path/to/output/directory
artyom
fuente
2

Eventualmente resolví esto usando una solución similar a la de artyom.

Paso 1: Explota el parche en muchos parches separados, uno para cada trozo.

Usé este script para hacer esto:

#!/usr/bin/python2

import sys

header = []
writing_header = False
patchnum = 0

patch = open(sys.argv[1], "r")
out = open("/dev/null", "w")

for line in patch.readlines():
    if line.startswith("diff"):
        header = []
        writing_header = True
    if line.startswith("@@"):
        out.close()
        out = open(str(patchnum) + ".diff", "w")
        patchnum += 1
        writing_header = False
        out.writelines(header)
    if writing_header:
        header.append(line)
    else:
        out.write(line)

out.close()

Ejemplo de uso:

$ cd directory_containing_patch
$ mkdir foo
$ cd foo
$ explode.py ../huge_patch.diff

Esto llenará el directorio actual con archivos llamados 0.diff 1.diff, etc.

Paso 2: aplique cada parche, descartando los parches ya aplicados.

Usé este script para hacer esto:

#!/bin/bash

if [[ $# -ne 1 || ! -d "${1}/" ]]; then
    echo "Usage: $0 dirname"
    exit 1
fi

find "$1" -name \*.diff | while read f; do
    OUTPUT=$(patch -s -p1 -r- -i"$f")
    if [ $? -eq 0 ]; then
        rm "$f"
    else
        if echo "$OUTPUT" | grep -q "Reversed (or previously applied) patch detected!"; then
            rm "$f"
        fi
    fi
done

Ejemplo de uso:

$ cd directory_containing_code
$ apply_patches.bash directory_containing_patch/foo

Esto eliminará cualquiera de los parches generados previamente que se apliquen limpiamente o que ya se hayan aplicado. Los parches que quedan fooson rechazos que deben examinarse y fusionarse manualmente.

Shum
fuente