Gentoo Archives: gentoo-portage-dev

From: "Michał Górny" <mgorny@g.o>
To: gentoo-portage-dev@l.g.o
Subject: Re: [gentoo-portage-dev] [PATCH] repoman: Add commit message verification
Date: Sun, 04 Feb 2018 17:58:29
Message-Id: 1517767101.17862.0.camel@gentoo.org
In Reply to: Re: [gentoo-portage-dev] [PATCH] repoman: Add commit message verification by Brian Dolbec
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

Replies