1 |
W dniu nie, 04.02.2018 o godzinie 09∶51 -0800, użytkownik Brian Dolbec |
2 |
napisał: |
3 |
> On Fri, 2 Feb 2018 23:53:05 +0100 |
4 |
> Michał Górny <mgorny@g.o> wrote: |
5 |
> |
6 |
> > Add a check for common mistakes in commit messages. For now, it is |
7 |
> > pretty rough and exits immediately but it should be integrated with |
8 |
> > the editor in the future. |
9 |
> > --- |
10 |
> > repoman/pym/repoman/actions.py | 68 |
11 |
> > ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 |
12 |
> > insertions(+) |
13 |
> > |
14 |
> > diff --git a/repoman/pym/repoman/actions.py |
15 |
> > b/repoman/pym/repoman/actions.py index b76a6e466..97a71d0f5 100644 |
16 |
> > --- a/repoman/pym/repoman/actions.py |
17 |
> > +++ b/repoman/pym/repoman/actions.py |
18 |
> > @@ -124,6 +124,15 @@ class Actions(object): |
19 |
> > |
20 |
> > commitmessage = commitmessage.rstrip() |
21 |
> > |
22 |
> > + res, expl = self.verify_commit_message(commitmessage) |
23 |
> > + if not res: |
24 |
> > + print(bad("RepoMan does not like your commit |
25 |
> > message:")) |
26 |
> > + print(expl) |
27 |
> > + if self.options.force: |
28 |
> > + print('(but proceeding due to |
29 |
> > --force)') |
30 |
> > + else: |
31 |
> > + sys.exit(1) |
32 |
> > + |
33 |
> > # Update copyright for new and changed files |
34 |
> > year = time.strftime('%Y', time.gmtime()) |
35 |
> > for fn in chain(mynew, mychanged): |
36 |
> > @@ -585,3 +594,62 @@ class Actions(object): |
37 |
> > print("* no commit message? aborting |
38 |
> > commit.") sys.exit(1) |
39 |
> > return commitmessage |
40 |
> > + |
41 |
> > + footer_re = re.compile(r'^[\w-]+:') |
42 |
> > + |
43 |
> > + def verify_commit_message(self, msg): |
44 |
> > + """ |
45 |
> > + Check whether the message roughly complies with |
46 |
> > GLEP66. Returns |
47 |
> > + (True, None) if it does, (False, <explanation>) if |
48 |
> > it does not. |
49 |
> > + """ |
50 |
> > + |
51 |
> > + problems = [] |
52 |
> > + paras = msg.strip().split('\n\n') |
53 |
> > + summary = paras.pop(0) |
54 |
> > + |
55 |
> > + if '\n' in summary.strip(): |
56 |
> > + problems.append('commit message must start |
57 |
> > with a *single* line of summary, followed by empty line') |
58 |
> > + if ':' not in summary: |
59 |
> > + problems.append('summary line must start |
60 |
> > with a logical unit name, e.g. "cat/pkg:"') |
61 |
> > + # accept 69 overall or unit+50, in case of very long |
62 |
> > package names |
63 |
> > + if len(summary.strip()) > 69 and |
64 |
> > len(summary.split(':', 1)[-1]) > 50: |
65 |
> > + problems.append('summary line is too long |
66 |
> > (max 69 characters)') + |
67 |
> > + multiple_footers = False |
68 |
> > + gentoo_bug_used = False |
69 |
> > + bug_closes_without_url = False |
70 |
> > + body_too_long = False |
71 |
> > + |
72 |
> > + found_footer = False |
73 |
> > + for p in paras: |
74 |
> > + lines = p.splitlines() |
75 |
> > + # if all lines look like footer material, we |
76 |
> > assume it's footer |
77 |
> > + # else, we assume it's body text |
78 |
> > + if all(self.footer_re.match(l) for l in |
79 |
> > lines if l.strip()): |
80 |
> > + # multiple footer-like blocks? |
81 |
> > + if found_footer: |
82 |
> > + multiple_footers = True |
83 |
> > + found_footer = True |
84 |
> > + for l in lines: |
85 |
> > + if |
86 |
> > l.startswith('Gentoo-Bug'): |
87 |
> > + gentoo_bug_used = |
88 |
> > True |
89 |
> > + elif l.startswith('Bug:') or |
90 |
> > l.startswith('Closes:'): |
91 |
> > + if 'http://' not in |
92 |
> > l and 'https://' not in l: |
93 |
> > + |
94 |
> > bug_closes_without_url = True |
95 |
> > + else: |
96 |
> > + for l in lines: |
97 |
> > + if len(l.strip()) > 72: |
98 |
> > + body_too_long = True |
99 |
> > + |
100 |
> > + if multiple_footers: |
101 |
> > + problems.append('multiple footer-style |
102 |
> > blocks found, please combine them into one') |
103 |
> > + if gentoo_bug_used: |
104 |
> > + problems.append('please replace Gentoo-Bug |
105 |
> > with GLEP 66-compliant Bug/Closes') |
106 |
> > + if bug_closes_without_url: |
107 |
> > + problems.append('Bug/Closes footers require |
108 |
> > full URL') |
109 |
> > + if body_too_long: |
110 |
> > + problems.append('body lines should be |
111 |
> > wrapped at 72 characters') + |
112 |
> > + if problems: |
113 |
> > + return (False, '\n'.join('- %s' % x for x in |
114 |
> > problems)) |
115 |
> > + return (True, None) |
116 |
> |
117 |
> |
118 |
> I know there are not a lot of repoman unit tests, but, can you please |
119 |
> create some to test this? That way it doesn't get any worse. |
120 |
> |
121 |
> In the PR, you mentioned adding in an editor call to re-edit the |
122 |
> message. This would be a good thing and I know is not that difficult |
123 |
> to accomplish. Is this coming in another patch? |
124 |
> |
125 |
|
126 |
I'm still wondering how to implement it best. In particular, how to |
127 |
handle the non-EDITOR (stdin) branch? |
128 |
|
129 |
-- |
130 |
Best regards, |
131 |
Michał Górny |