xref: /OK3568_Linux_fs/yocto/poky/contrib/git-hooks/sendemail-validate.sample (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1#!/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
79