From 8dc690fddc1bace6b7af3f5e8af60c1625b067db Mon Sep 17 00:00:00 2001 From: Chris Laplante Date: Fri, 25 Dec 2020 13:16:49 -0500 Subject: contrib/git-hooks: add a sendemail-validate example hook that adds FROM: lines to outgoing patch emails This is useful for people using Microsoft Exchange / Office 360, which butchers patches causing author identity to be lost. Signed-off-by: Chris Laplante Signed-off-by: Richard Purdie --- contrib/git-hooks/sendemail-validate.sample | 78 +++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100755 contrib/git-hooks/sendemail-validate.sample (limited to 'contrib/git-hooks') diff --git a/contrib/git-hooks/sendemail-validate.sample b/contrib/git-hooks/sendemail-validate.sample new file mode 100755 index 0000000000..af5d55cb00 --- /dev/null +++ b/contrib/git-hooks/sendemail-validate.sample @@ -0,0 +1,78 @@ +#!/usr/bin/env python3 + +# Copyright (C) 2020 Agilent Technologies, Inc. +# Author: Chris Laplante + +# This sendemail-validate hook injects 'From: ' header lines into outgoing +# emails sent via 'git send-email', to ensure that accurate commit authorship +# information is present. It was created because some email servers +# (notably Microsoft Exchange / Office 360) seem to butcher outgoing patches, +# resulting in incorrect authorship. + +# Current limitations: +# 1. Assumes one per patch per email +# 2. Minimal error checking +# +# Installation: +# 1. Copy to .git/hooks/sendemail-validate +# 2. chmod +x .git/hooks/sendemail-validate + + +import enum +import re +import subprocess +import sys + + +class Subject(enum.IntEnum): + NOT_SEEN = 0 + CONSUMING = 1 + SEEN = 2 + + +def make_from_line(): + cmd = ["git", "var", "GIT_COMMITTER_IDENT"] + proc = subprocess.run(cmd, check=True, stdout=subprocess.PIPE, universal_newlines=True) + regex = re.compile(r"^(.*>).*$") + match = regex.match(proc.stdout) + assert match is not None + return "From: {0}".format(match.group(1)) + + +def main(): + email = sys.argv[1] + + with open(email, "r") as f: + email_lines = f.read().split("\n") + + subject_seen = Subject.NOT_SEEN + first_body_line = None + for i, line in enumerate(email_lines): + if (subject_seen == Subject.NOT_SEEN) and line.startswith("Subject: "): + subject_seen = Subject.CONSUMING + continue + if subject_seen == Subject.CONSUMING: + if not line.strip(): + subject_seen = Subject.SEEN + continue + if subject_seen == Subject.SEEN: + first_body_line = i + break + + assert subject_seen == Subject.SEEN + assert first_body_line is not None + + from_line = make_from_line() + # Only add FROM line if it is not already there + if email_lines[first_body_line] != from_line: + email_lines.insert(first_body_line, from_line) + email_lines.insert(first_body_line + 1, "") + with open(email, "w") as f: + f.write("\n".join(email_lines)) + + return 0 + + +if __name__ == "__main__": + sys.exit(main()) + -- cgit 1.2.3-korg