]> git.ipfire.org Git - thirdparty/gcc.git/blame - contrib/gcc-changelog/git_email.py
gcc-changelog: Support 'Backported from master'.
[thirdparty/gcc.git] / contrib / gcc-changelog / git_email.py
CommitLineData
c10aa1f0
ML
1#!/usr/bin/env python3
2#
3# This file is part of GCC.
4#
5# GCC is free software; you can redistribute it and/or modify it under
6# the terms of the GNU General Public License as published by the Free
7# Software Foundation; either version 3, or (at your option) any later
8# version.
9#
10# GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11# WARRANTY; without even the implied warranty of MERCHANTABILITY or
12# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13# for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with GCC; see the file COPYING3. If not see
17# <http://www.gnu.org/licenses/>. */
18
19import os
20import sys
21from itertools import takewhile
22
23from dateutil.parser import parse
24
25from git_commit import GitCommit
26
27from unidiff import PatchSet
28
29DATE_PREFIX = 'Date: '
30FROM_PREFIX = 'From: '
31
32
33class GitEmail(GitCommit):
34 def __init__(self, filename, strict=False):
35 self.filename = filename
36 diff = PatchSet.from_filename(filename)
37 date = None
38 author = None
39
bb07057a
PMR
40 with open(self.filename, 'r') as f:
41 lines = f.read().splitlines()
c10aa1f0
ML
42 lines = list(takewhile(lambda line: line != '---', lines))
43 for line in lines:
44 if line.startswith(DATE_PREFIX):
45 date = parse(line[len(DATE_PREFIX):])
46 elif line.startswith(FROM_PREFIX):
47 author = GitCommit.format_git_author(line[len(FROM_PREFIX):])
48 header = list(takewhile(lambda line: line != '', lines))
49 body = lines[len(header) + 1:]
50
51 modified_files = []
52 for f in diff:
a634157d
PMR
53 # Strip "a/" and "b/" prefixes
54 source = f.source_file[2:]
55 target = f.target_file[2:]
56
c10aa1f0
ML
57 if f.is_added_file:
58 t = 'A'
59 elif f.is_removed_file:
60 t = 'D'
a634157d
PMR
61 elif f.is_rename:
62 # Consider that renamed files are two operations: the deletion
63 # of the original name and the addition of the new one.
64 modified_files.append((source, 'D'))
65 t = 'A'
c10aa1f0
ML
66 else:
67 t = 'M'
a634157d 68 modified_files.append((target, t))
c10aa1f0 69 super().__init__(None, date, author, body, modified_files,
2021af0c 70 strict=strict, commit_to_date_hook=lambda x: date)
c10aa1f0
ML
71
72
62963c60
JW
73# With zero arguments, process every patch file in the ./patches directory.
74# With one argument, process the named patch file.
75# Patch files must be in 'git format-patch' format.
c10aa1f0
ML
76if __name__ == '__main__':
77 if len(sys.argv) == 1:
78 allfiles = []
79 for root, _dirs, files in os.walk('patches'):
80 for f in files:
81 full = os.path.join(root, f)
82 allfiles.append(full)
83
84 success = 0
85 for full in sorted(allfiles):
86 email = GitEmail(full, False)
87 print(email.filename)
88 if email.success:
89 success += 1
90 print(' OK')
91 else:
92 for error in email.errors:
93 print(' ERR: %s' % error)
94
95 print()
96 print('Successfully parsed: %d/%d' % (success, len(allfiles)))
97 else:
98 email = GitEmail(sys.argv[1], False)
99 if email.success:
100 print('OK')
101 email.print_output()
102 else:
103 if not email.lines:
104 print('Error: patch contains no parsed lines', file=sys.stderr)
105 email.print_errors()
62963c60 106 sys.exit(1)