Como fazer o patch ignorar pedaços já aplicados

12

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

A opção -N não faz o que eu quero. Se encontrar um pedaço já aplicado, ele gerará um arquivo rejeitado e não aplicará mais nenhum pedaço nesse arquivo. Eu quero apenas ignorar esse pedaço e continuar aplicando o resto do patch. A única vez que eu quero gerar um arquivo .rej é se um pedaço não pode ser aplicado e não parece já estar aplicado.

Existe uma maneira de fazer isso?

    
por Shum 22.02.2013 / 04:42

2 respostas

7

Você precisará de patchutils instalados para isso.

Esse script dividirá um patch grande em paches separados menores, cada um contendo apenas um hunk 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.sh e chame-o:

./hunks.sh path/to/big.diff path/to/output/directory
    
por 22.02.2013 / 07:03
2

Eu finalmente resolvi isso usando uma solução semelhante à do artyom.

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

Eu usei este 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 et cetera.

Passo 2: Aplique cada patch, descartando os patches já aplicados.

Eu usei este 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 sejam aplicados com clareza ou que já tenham sido aplicados. Quaisquer correções deixadas em foo são rejeições que precisam ser examinadas e mescladas manualmente.

    
por 22.02.2013 / 09:50

Tags