blob: af5d55cb0010a582c9771e66cb95f475a5637799 [file] [log] [blame]
Andrew Geisslerd1e89492021-02-12 15:35:20 -06001#!/usr/bin/env python3
2
3# Copyright (C) 2020 Agilent Technologies, Inc.
4# Author: Chris Laplante <chris.laplante@agilent.com>
5
6# This sendemail-validate hook injects 'From: ' header lines into outgoing
7# emails sent via 'git send-email', to ensure that accurate commit authorship
8# information is present. It was created because some email servers
9# (notably Microsoft Exchange / Office 360) seem to butcher outgoing patches,
10# resulting in incorrect authorship.
11
12# Current limitations:
13# 1. Assumes one per patch per email
14# 2. Minimal error checking
15#
16# Installation:
17# 1. Copy to .git/hooks/sendemail-validate
18# 2. chmod +x .git/hooks/sendemail-validate
19
20
21import enum
22import re
23import subprocess
24import sys
25
26
27class Subject(enum.IntEnum):
28 NOT_SEEN = 0
29 CONSUMING = 1
30 SEEN = 2
31
32
33def make_from_line():
34 cmd = ["git", "var", "GIT_COMMITTER_IDENT"]
35 proc = subprocess.run(cmd, check=True, stdout=subprocess.PIPE, universal_newlines=True)
36 regex = re.compile(r"^(.*>).*$")
37 match = regex.match(proc.stdout)
38 assert match is not None
39 return "From: {0}".format(match.group(1))
40
41
42def main():
43 email = sys.argv[1]
44
45 with open(email, "r") as f:
46 email_lines = f.read().split("\n")
47
48 subject_seen = Subject.NOT_SEEN
49 first_body_line = None
50 for i, line in enumerate(email_lines):
51 if (subject_seen == Subject.NOT_SEEN) and line.startswith("Subject: "):
52 subject_seen = Subject.CONSUMING
53 continue
54 if subject_seen == Subject.CONSUMING:
55 if not line.strip():
56 subject_seen = Subject.SEEN
57 continue
58 if subject_seen == Subject.SEEN:
59 first_body_line = i
60 break
61
62 assert subject_seen == Subject.SEEN
63 assert first_body_line is not None
64
65 from_line = make_from_line()
66 # Only add FROM line if it is not already there
67 if email_lines[first_body_line] != from_line:
68 email_lines.insert(first_body_line, from_line)
69 email_lines.insert(first_body_line + 1, "")
70 with open(email, "w") as f:
71 f.write("\n".join(email_lines))
72
73 return 0
74
75
76if __name__ == "__main__":
77 sys.exit(main())
78