Comment faire pour que le patch ignore les mecs déjà appliqués

14

J'ai un très gros fichier de patch que j'essaie d'appliquer à mon code. Le problème est que certaines des modifications de mon patch existent déjà dans le code. Existe-t-il un moyen de faire en sorte que le correctif ignore gracieusement les modifications qui ont déjà été appliquées?

L' -Noption ne fait pas ce que je veux. S'il rencontre un morceau déjà appliqué, il générera un fichier de rejet et n'appliquera plus de morceaux à ce fichier. Je veux simplement ignorer ce morceau et continuer à appliquer le reste du patch. La seule fois où je veux qu'il génère un fichier .rej, c'est si un morceau ne peut pas être appliqué et ne semble pas déjà être appliqué.

Y a-t-il un moyen de faire cela?

Shum
la source

Réponses:

7

Vous aurez besoin de patchutils installés pour cela.

Ce script divisera un grand patch en petits cache séparés, chacun d'eux ne contenant qu'un seul morceau pour un fichier. Vous pouvez ensuite appliquer ces correctifs avec 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

Modifier : enregistrez le script dans hunks.shet appelez-le:

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

J'ai finalement résolu cela en utilisant une solution similaire à celle de artyom.

Étape 1: Décomposez le patch en de nombreux patchs séparés, un pour chaque morceau.

J'ai utilisé ce script pour ce faire:

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

Exemple d'utilisation:

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

Cela remplira le répertoire actuel avec des fichiers appelés 0.diff 1.diff et cetera.

Étape 2: appliquez chaque patch, en éliminant les patchs déjà appliqués.

J'ai utilisé ce script pour ce faire:

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

Exemple d'utilisation:

$ cd directory_containing_code
$ apply_patches.bash directory_containing_patch/foo

Cela supprimera tous les correctifs générés précédemment qui s'appliquent correctement ou qui ont déjà été appliqués. Tous les correctifs qui restent foosont des rejets qui doivent être examinés et fusionnés manuellement.

Shum
la source