Como fazer o patch ignorar pedaços já aplicados

14

Eu tenho um arquivo de patch muito grande que estou tentando aplicar ao meu código. O problema é que algumas das alterações no meu patch já existem no código. Existe uma maneira de fazer o patch ignorar normalmente as alterações que já foram aplicadas?

A -Nopção não faz o que eu quero. Se encontrar um pedaço já aplicado, ele gerará um arquivo rejeitado e não aplicará mais pedaços a esse arquivo. Quero que ele ignore esse pedaço e continue aplicando o restante do patch. A única vez que eu quero que ele gere um arquivo .rej é se um pedaço não pode ser aplicado e parece que já não foi aplicado.

Existe uma maneira de fazer isso?

Shum
fonte

Respostas:

7

Você precisará de patchutils instalados para isso.

Esse script dividirá um patch grande em pacotes separados menores, cada um deles contendo apenas um pedaço para um arquivo. Você pode aplicar esses patches com 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 : salve o script em hunks.she chame-o:

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

Acabei resolvendo isso usando uma solução semelhante à do artyom.

Etapa 1: explodir o patch em vários patches separados, um para cada pedaço.

Eu usei esse script para fazer isso:

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

Exemplo de uso:

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

Isso preencherá o diretório atual com arquivos chamados 0.diff 1.diff etc.

Etapa 2: aplique cada patch, descartando os patches já aplicados.

Eu usei esse script para fazer isso:

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

Exemplo de uso:

$ cd directory_containing_code
$ apply_patches.bash directory_containing_patch/foo

Isso excluirá qualquer um dos patches gerados anteriormente que se aplicam de forma limpa ou que já foram aplicados. Quaisquer correções deixadas foosão rejeições que precisam ser examinadas e mescladas manualmente.

Shum
fonte