#!/usr/bin/env python3 # dev/gofmt_keep_crlf.py # # 运行 gofmt -w,但保留文件原始行尾(CRLF / LF),避免 gofmt 把 CRLF 文件整文件 # 重写成 LF 造成的万行级 diff 污染。 # # 用法: # python dev/gofmt_keep_crlf.py [file2 ...] # git diff --name-only | grep '\.go$' | xargs python dev/gofmt_keep_crlf.py # # 实现要点:先把源文件按 LF 写入临时副本交给 gofmt,gofmt 输出也是 LF; # 若原文件是 CRLF,再把输出整体换回 CRLF 写回,从而只保留真实的格式化改动。 import os import sys import subprocess GOFMT = r"C:/Program Files/Go/bin/gofmt" def fmt_one(path): with open(path, "rb") as f: data = f.read() crlf = b"\r\n" in data tmp = path + ".gofmt.tmp" with open(tmp, "wb") as f: f.write(data.replace(b"\r\n", b"\n")) try: r = subprocess.run([GOFMT, "-w", tmp], capture_output=True) if r.returncode != 0: sys.stderr.write( "gofmt FAILED on %s:\n%s\n" % (path, r.stderr.decode("utf-8", "replace")) ) return False with open(tmp, "rb") as f: out = f.read() finally: try: os.remove(tmp) except OSError: pass if crlf: out = out.replace(b"\r\n", b"\n").replace(b"\n", b"\r\n") with open(path, "wb") as f: f.write(out) return True def main(): files = [a for a in sys.argv[1:] if a.strip()] if not files: sys.stderr.write("usage: gofmt_keep_crlf.py [file ...]\n") return 2 ok = True for p in files: if not fmt_one(p): ok = False return 0 if ok else 1 if __name__ == "__main__": sys.exit(main())