]>
Commit | Line | Data |
---|---|---|
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 | ||
19 | import os | |
20 | import sys | |
21 | from itertools import takewhile | |
22 | ||
23 | from dateutil.parser import parse | |
24 | ||
25 | from git_commit import GitCommit | |
26 | ||
27 | from unidiff import PatchSet | |
28 | ||
29 | DATE_PREFIX = 'Date: ' | |
30 | FROM_PREFIX = 'From: ' | |
31 | ||
32 | ||
33 | class 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 |
76 | if __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) |