"""从 git diff 补丁中只保留指定序号的 hunk,用于精确暂存(git add -p 是交互式的,脚本里用不了)。
|
|
用法:
|
python split-hunks.py <补丁文件> <保留的hunk序号,逗号分隔> [--list]
|
--list 只列出 hunk 序号与首行,不输出补丁
|
"""
|
import sys
|
|
# 必须强制 UTF-8 且不做换行翻译:否则中文上下文行会被按 GBK 写坏、\n 被写成 \r\n,
|
# 两者都会让 git apply 匹配不上(纯 ASCII 的补丁不会暴露这个问题,容易误判)
|
try:
|
sys.stdout.reconfigure(encoding='utf-8', newline='')
|
except Exception:
|
pass
|
|
path = sys.argv[1]
|
if len(sys.argv) < 3:
|
print(__doc__)
|
sys.exit(1)
|
list_only = '--list' in sys.argv
|
keep = set()
|
if not list_only:
|
keep = {int(x) for x in sys.argv[2].split(',') if x.strip() != ''}
|
|
lines = open(path, encoding='utf-8', errors='surrogateescape').read().split('\n')
|
header, hunks, cur = [], [], None
|
for ln in lines:
|
if ln.startswith('@@'):
|
if cur is not None:
|
hunks.append(cur)
|
cur = [ln]
|
elif cur is None:
|
header.append(ln)
|
else:
|
cur.append(ln)
|
if cur is not None:
|
hunks.append(cur)
|
|
if list_only:
|
for i, h in enumerate(hunks):
|
print(f' [{i}] {h[0]}')
|
sys.exit(0)
|
|
out = list(header)
|
for i, h in enumerate(hunks):
|
if i in keep:
|
out.extend(h)
|
# 结尾补回换行
|
sys.stdout.write('\n'.join(out))
|