В конце концов я решил эту проблему, используя решение, похожее на решение Артема.
Шаг 1: Разнесите патч на множество отдельных патчей, по одному на каждый кусок.
Я использовал этот скрипт, чтобы сделать это:
#!/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()
Пример использования:
$ cd directory_containing_patch
$ mkdir foo
$ cd foo
$ explode.py ../huge_patch.diff
Это заполнит текущий каталог файлами с именем 0.diff 1.diff и так далее.
Шаг 2: примените каждый патч, отбрасывая уже примененные патчи.
Я использовал этот скрипт, чтобы сделать это:
#!/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
Пример использования:
$ cd directory_containing_code
$ apply_patches.bash directory_containing_patch/foo
Это приведет к удалению любых ранее созданных исправлений, которые были применены корректно или уже были применены. Любые оставленные исправления foo
являются отклонениями, которые необходимо вручную проверить и объединить.