Merge lp:~stefan.goetz-deactivatedaccount/hipl/commitguard into lp:hipl
- commitguard
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | 6261 |
Proposed branch: | lp:~stefan.goetz-deactivatedaccount/hipl/commitguard |
Merge into: | lp:hipl |
Diff against target: |
581 lines (+533/-5) 6 files modified
.commitguards/author-attribution.guard (+31/-0) .commitguards/copyright-guard-space.guard (+27/-0) .commitguards/copyright-guard-space.py (+63/-0) .commitguards/copyright-year.guard (+36/-0) doc/HACKING (+27/-5) tools/bazaar/plugins/commitguard.py (+349/-0) |
To merge this branch: | bzr merge lp:~stefan.goetz-deactivatedaccount/hipl/commitguard |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Diego Biurrun | Needs Fixing | ||
René Hummen | Approve | ||
Stefan Götz | Pending | ||
Miika Komu | Pending | ||
Review via email: mp+89627@code.launchpad.net |
This proposal supersedes a proposal from 2012-01-19.
Commit message
Description of the change
Adds a bazaar pre-commit hook for checking file contents before a commit and to aborting the commit if necessary. Also includes a few guards that enforce some aspects of HIPL code style policy.
Diego Biurrun (diego-biurrun) wrote : Posted in a previous version of this proposal | # |
Stefan Götz (stefan.goetz-deactivatedaccount) wrote : Posted in a previous version of this proposal | # |
> Looks mostly good to me. I don't speak Python, so this review is
> necessarily superficial.
Thanks for the review(s)!
>> --- .commitguards/
>> +++ .commitguards/
>> @@ -0,0 +1,4 @@
>> +[guard]
>> +files=
>> +actions=amr
>> +command=if egrep -q "\*.*@author\b" "{}"; then echo "{}: files should not contain author attributions"; false; fi
>
> Do we really need to restrict this to certain file types?
Not really, no. I changed it so it applies to all files.
>> --- .commitguards/
>> +++ .commitguards/
>> @@ -0,0 +1,68 @@
>> +#!/usr/bin/env python
>> +# -*- coding: latin-1 -*-
>
> Please use UTF-8, this is the 21st century (for some time already).
You're right. Done (removed).
> I'm also not sure if you need to tell emacs about this, the file
> should be ASCII anyway.
This comment is also obeyed by the python interpreter. In fact, it is
necessary as soon as non-plain-ASCII characters are in a python script.
>> bazaar
> Bazaar
>
>> + The commitguard plugin offers the user to apply such a patch automatically
>> + for convenience.
>
> For added convenience the commitguard plugin offers the user the option
> of applying such a patch automatically.
Done.
Cheers,
Stefan
Miika Komu (miika-iki) wrote : Posted in a previous version of this proposal | # |
How does the differ from tools/bazaar/
Stefan Götz (stefan.goetz-deactivatedaccount) wrote : Posted in a previous version of this proposal | # |
> How does the differ from tools/bazaar/
stylecheck.py is specifically tailored towards running a code
beautifier, uncrustify in our case.
commitguard.py makes it much simpler to run arbitrary commands at
pre-commit time and adds a little bit of user convenience. This is
useful for checks that uncrustify cannot perform and is very easy to extend.
> And why do we need now two different hooks?
It would be possible to run uncrustify via the commitguard plugin
instead of the stylecheck plugin. However, some stylecheck features make
it much more usable with uncrustify than commitguard. In particular,
uncrustify can operate on multiple files with stylecheck while
commitguard aborts the commit after the first inconsistent file found,
which can be annoying if there several files need uncrustification.
I'd say that both plugins have their use.
Cheers,
Stefan
Miika Komu (miika-iki) wrote : Posted in a previous version of this proposal | # |
Hi,
On 01/19/2012 06:16 PM, Stefan Götz wrote:
>> How does the differ from tools/bazaar/
>
> stylecheck.py is specifically tailored towards running a code
> beautifier, uncrustify in our case.
>
> commitguard.py makes it much simpler to run arbitrary commands at
> pre-commit time and adds a little bit of user convenience. This is
> useful for checks that uncrustify cannot perform and is very easy to extend.
>
>> And why do we need now two different hooks?
>
> It would be possible to run uncrustify via the commitguard plugin
> instead of the stylecheck plugin. However, some stylecheck features make
> it much more usable with uncrustify than commitguard. In particular,
> uncrustify can operate on multiple files with stylecheck while
> commitguard aborts the commit after the first inconsistent file found,
> which can be annoying if there several files need uncrustification.
>
> I'd say that both plugins have their use.
sorry if I forgot some earlier discussions on the topic but until I see
a clear and concrete plan yet to replace stylecheck with commitguard, I
would suggest to sticking to a single tool (stylecheck.py) instead of
introducing another alternative as an extra maintenance burden.
Stefan Götz (stefan.goetz-deactivatedaccount) wrote : Posted in a previous version of this proposal | # |
> sorry if I forgot some earlier discussions on the topic but until I see
> a clear and concrete plan yet to replace stylecheck with commitguard, I
> would suggest to sticking to a single tool (stylecheck.py) instead of
> introducing another alternative as an extra maintenance burden.
Running uncrustify via commitguard results in a definite and annoying
loss of usability. Thus I strongly recommend keeping stylecheck around.
Otherwise, I'd be worried that users abandon the use of pre-commit hooks
altogether because using uncrustify became more cumbersome.
Note that the commitguard plugin, as is, runs checks that are orthogonal
to what uncrustify does. So this plugin is useful to HIPL developers in
itself. I'm not sure whether this became sufficiently clear.
How about this: I'll create a commit guard that runs uncrustify but
leave it disabled. Should the maintenance burden of having both
commitguard and stylecheck become a real issue, we could always drop
stylecheck at that point. Ok?
Stefan
Miika Komu (miika-iki) wrote : Posted in a previous version of this proposal | # |
Hi,
On 20/01/12 16:52, Stefan Götz wrote:
>> sorry if I forgot some earlier discussions on the topic but until I see
>> a clear and concrete plan yet to replace stylecheck with commitguard, I
>> would suggest to sticking to a single tool (stylecheck.py) instead of
>> introducing another alternative as an extra maintenance burden.
>
> Running uncrustify via commitguard results in a definite and annoying
> loss of usability. Thus I strongly recommend keeping stylecheck around.
> Otherwise, I'd be worried that users abandon the use of pre-commit hooks
> altogether because using uncrustify became more cumbersome.
>
> Note that the commitguard plugin, as is, runs checks that are orthogonal
> to what uncrustify does. So this plugin is useful to HIPL developers in
> itself. I'm not sure whether this became sufficiently clear.
thanks for making this explicit, I understood this now better. I guess
there's more policies coming to the commitguard plugin?
> How about this: I'll create a commit guard that runs uncrustify but
> leave it disabled.
If it's orthogonal instead of redundant, then no need to.
> Should the maintenance burden of having both
> commitguard and stylecheck become a real issue, we could always drop
> stylecheck at that point. Ok?
Ok.
Miika Komu (miika-iki) wrote : Posted in a previous version of this proposal | # |
So go ahead with this one.
René Hummen (rene-hummen) wrote : Posted in a previous version of this proposal | # |
Thanks a lot for the automated commit guards. Very good documentation and extensibility!
I just got a suggested workflow that would allow merging of the stylechecker with this script:
1) Make a local copy of the files touched in the current commit.
2) Apply the commit guards (including uncrustify) one after the other to each of the local copies.
2.1) Tell the user which guard failed on which file.
2.2) Apply an eventual change of a commit guard to the local copy.
3) After all commit guards have been executed (and the corresponding changes have been applied to the local copies incrementally), show the user the diff between the local files and the files in the commit.
3.1) Apply diff, if accepted by the user.
I know that this workflow would require some restructuring of the code. Hence, I don't mind having two scripts for now. However, the benefit would be a single pre-commit hook and the check of all committed files with _all_ hooks in one go. Right now, we need to commit as often as the commit contains "errors" until finally the commit is pushed to the repository.
Additionally, it might be worth having an install_
Diego Biurrun (diego-biurrun) wrote : Posted in a previous version of this proposal | # |
On Thu, Jan 19, 2012 at 04:16:56PM +0000, Stefan Götz wrote:
> > And why do we need now two different hooks?
>
> It would be possible to run uncrustify via the commitguard plugin
> instead of the stylecheck plugin. However, some stylecheck features make
> it much more usable with uncrustify than commitguard. In particular,
> uncrustify can operate on multiple files with stylecheck while
> commitguard aborts the commit after the first inconsistent file found,
> which can be annoying if there several files need uncrustification.
This is a considerable shortcoming IMO. Ideally all issues in all
files should be detected and be complained about. Otherwise you have
to run through multiple iterations of commit guard as you fix issue
after issue...
Diego
Stefan Götz (stefan.goetz-deactivatedaccount) wrote : Posted in a previous version of this proposal | # |
Hi Rene!
> I just got a suggested workflow that would allow merging of the stylechecker with this script:
> 1) Make a local copy of the files touched in the current commit.
> 2) Apply the commit guards (including uncrustify) one after the other to each of the local copies.
> 2.1) Tell the user which guard failed on which file.
> 2.2) Apply an eventual change of a commit guard to the local copy.
> 3) After all commit guards have been executed (and the corresponding changes have been applied to the local copies incrementally), show the user the diff between the local files and the files in the commit.
> 3.1) Apply diff, if accepted by the user.
That makes a lot of sense and is certainly more usable than the current
approach. I'll work on it on the usability branch.
> Additionally, it might be worth having an install_
Yeah, well, I don't think the difference between a single cp command and a
script will change something about usage and acceptance - so I'll let someone
else write that script :)
Stefan
Miika Komu (miika-iki) wrote : Posted in a previous version of this proposal | # |
I just realized that the only the documentation is in the script itself and there's nothing in the HACKING - is this intentional?
René Hummen (rene-hummen) wrote : | # |
I should be mentioned in HACKING. There is already some hint at stylecheck. So this would be the right location to tell developers to use commitguard as well.
Otherwise, I am fine with the script.
Stefan Götz (stefan.goetz-deactivatedaccount) wrote : | # |
> Review: Approve
>
> I should be mentioned in HACKING.
I agree. I think you mixed up the 'approve' and the 'needs fixing'
buttons, though ;-)
Diego Biurrun (diego-biurrun) wrote : | # |
On Mon, Jan 23, 2012 at 10:39:49AM +0000, René Hummen wrote:
> Review: Approve
>
> I should be mentioned in HACKING.
I want to be mentioned in HACKING as well!
SCNR, Diego
René Hummen (rene-hummen) wrote : | # |
On 23.01.2012, at 12:46, Stefan Götz wrote:
>> Review: Approve
>>
>> I should be mentioned in HACKING.
>
> I agree. I think you mixed up the 'approve' and the 'needs fixing'
> buttons, though ;-)
While the "I" should of course be an "It", I approved your proposal because I don't require a new merge proposal for the additional text in HACKING.
--
Dipl.-Inform. Rene Hummen, Ph.D. Student
Chair of Communication and Distributed Systems
RWTH Aachen University, Germany
tel: +49 241 80 20772
web: http://
- 6250. By Diego Biurrun
-
Ignore test/check_hipd unit test executable.
- 6251. By Diego Biurrun
-
hipd: Fix some typos that the DEB package lintian program complained about.
- 6252. By Diego Biurrun
-
debian: Abort on errors during dnsproxy postinst script.
- 6253. By Diego Biurrun
-
debian: Register HIPL documentation with doc-base.
- 6254. By Diego Biurrun
-
debian: Extend package descriptions.
- 6255. By Diego Biurrun
-
packaging: Add dependency of hipdnsproxy on hipd.
hipdnsproxy reads etc/hip/hosts, which only exists if hipd is installed.
- 6256. By Diego Biurrun
-
hadb: Vastly simplify match_peer_addr().
- 6257. By Diego Biurrun
-
Rename nsupdate.pl ---> nsupdate.
It's more sensible to leave out the unnecessary language extension from the
program name. It does not really add information and would have to be
changed in the case the program was rewritten some day. - 6258. By Miika Komu
-
A bug fix to hipfw unit tests on 32-bit machines
Fixed bug id #918374 in launchpad. Now two failing hipfw tests are
disabled on 32-bit machines. Tested on both 32-bit and 64-bit machines. - 6259. By Stefan Götz
-
Compare host IDs across all address bytes instead of comparing only the first few bytes equal to the width of a pointer.
Diego Biurrun (diego-biurrun) wrote : | # |
review needs-fixing
On Mon, Jan 23, 2012 at 06:56:27AM +0000, Stefan Götz wrote:
> Stefan Götz has proposed merging lp:~stefan.goetz/hipl/commitguard into lp:hipl.
>
> Requested reviews:
> Miika Komu (miika-iki)
> Diego Biurrun (diego-biurrun)
This looks good to me as far as I can review Python code.
A few questions remain:
- Should we merge all guard declarations into a single config file?
- Does the commitguard script still abort after the first violation
or does it report all violations? Does it abort after the first
violating file?
> --- .commitguards/
> +++ .commitguards/
> @@ -0,0 +1,65 @@
> +#!/usr/bin/env python
> +
> +#
> +# Copyright (c) 2012 Aalto University and RWTH Aachen University.
> +#
> +# Permission is hereby granted, free of charge, to any person
> +# obtaining a copy of this software and associated documentation
> +# files (the "Software"), to deal in the Software without
> +# restriction, including without limitation the rights to use,
> +# copy, modify, merge, publish, distribute, sublicense, and/or sell
> +# copies of the Software, and to permit persons to whom the
> +# Software is furnished to do so, subject to the following
> +# conditions:
> +#
> +# The above copyright notice and this permission notice shall be
> +# included in all copies or substantial portions of the Software.
> +#
> +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
> +# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
> +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
> +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
> +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> +# OTHER DEALINGS IN THE SOFTWARE.
> +#
nit++: we usually have no empty line after the shebang or empty
comment lines after the license header.
> --- .commitguards/
> +++ .commitguards/
> @@ -0,0 +1,36 @@
> +
> +[guard]
> +files=
> +actions=amr
> +command=
> + CR_TOKEN=" Copyright \(c\) "
> + CR_HOLDER=" Aalto "
> + Y=$(date +%Y)
> + if ! egrep "$CR_TOKEN.
egrep is GNU-specific, 'grep -E' should be more portable.
I'd use ${} for referencing variables here. There can be tricky sideeffects
when variable references are not followed by whitespace. The special
characters used here should not cause issues, but the poor sould that
modifies the command could step into a trap.
> + echo "{}: The copyright statement is not up-to-date"
> + L=$(( $Y - 1 ))
> + sed -r "/ Copyright \(c\) / { /\b$Y\b/ ! { /-$L / s/-$L /-$Y /; s/ $L / $L-$Y /; /\b$Y\b/ ! s/ ([0-9, -]+) ([a-zA-Z]+)/ \1, $Y \2/ } }" "{}" | diff -u "{}" - >&2
Hmmm, more GNUisms, -r is not a POSIX option for sed.
What are these \b patterns that you use? I cannot find them in any
manual.
> --- tools/bazaar/
- 6260. By Stefan Götz
-
Merge lp:~stefan.goetz/hipl/hidb-db, approved by Rene and Diego
Stefan Götz (stefan.goetz-deactivatedaccount) wrote : | # |
Hi Diego!
Thanks for the review!
> - Should we merge all guard declarations into a single config file?
Technically, that's possible. I don't see any big advantages or
disadvantages with a central vs. separate files.
> - Does the commitguard script still abort after the first violation
> or does it report all violations? Does it abort after the first
> violating file?
Yes. I've started working on this issue in the commitguard-
branch, though.
>> +# OTHER DEALINGS IN THE SOFTWARE.
>> +#
>
> nit++: we usually have no empty line after the shebang or empty
> comment lines after the license header.
Fixed
>> + if ! egrep "$CR_TOKEN.
>
> egrep is GNU-specific, 'grep -E' should be more portable.
Fixed
> I'd use ${} for referencing variables here.
Fixed
> Hmmm, more GNUisms, -r is not a POSIX option for sed.
Fixed
> What are these \b patterns that you use? I cannot find them in any
> manual.
Word delimiters. I removed them.
>> +1) A set of file-name patterns the guard is to be applied to.
>
> filename
>
>> + The configuration value is a regular expression.
>
> I think that would be a POSIX extended regular expression.
>
>> + characters a, m, and r, representing added, modified, and renamed files
>
> 'a', 'm', and 'r'
>
>> + Before executing this command, all occurrences of the sub-string {} are
>
> substring
>
>> + For added convenience, the commitguard plugin offers the user to apply such
>> + a patch straight away.
>
> offers the user the option of applying such
Fixed
> Is there a reason why you have moved each sentence to a separate line?
When a line is changed, only that sentence needs to be rewrapped instead
of a whole paragraph.
Cheers,
Stefan
Diego Biurrun (diego-biurrun) wrote : | # |
On Wed, Jan 25, 2012 at 09:48:52PM +0100, Stefan Götz wrote:
> > - Should we merge all guard declarations into a single config file?
>
> Technically, that's possible. I don't see any big advantages or
> disadvantages with a central vs. separate files.
Me neither.
> > - Does the commitguard script still abort after the first violation
> > or does it report all violations? Does it abort after the first
> > violating file?
>
> Yes. I've started working on this issue in the commitguard-
> branch, though.
So what's your plan? Merge once the usability branch is ready or
merge this one first, then the usability branch?
> > What are these \b patterns that you use? I cannot find them in any
> > manual.
>
> Word delimiters. I removed them.
I'm still mildly curious - where did you find them documented?
Diego
Stefan Götz (stefan.goetz-deactivatedaccount) wrote : | # |
Hi Diego!
> So what's your plan? Merge once the usability branch is ready or
> merge this one first, then the usability branch?
The plan is to merge the commitguard branch now because a) the plugin is
useful in its current state, b) the plugin is not enabled by default so
it doesn't hurt, and c) early merging avoids bitrot.
That depends on your 'approve' vote, though. If you think that this
branch is now ready for merging, please approve the merge request.
>>> What are these \b patterns that you use? I cannot find them in any
>>> manual.
The grep man-page (http://
Cheers,
Stefan
- 6281. By Stefan Götz
-
Briefly mention the commitguard (and the stylecheck) plugin in doc/HACKING
- 6282. By Stefan Götz
-
Remove empty leading and trailing comment lines in copyright blocks.
- 6283. By Stefan Götz
-
Remove GNU-isms from scripts
- 6284. By Stefan Götz
-
Fix grammar in documentation
- 6285. By Stefan Götz
-
Place references to shell variables into curly braces to avoid expansion problems
- 6286. By Stefan Götz
-
Remove '\b' from regular expression for portability
Preview Diff
1 | === added directory '.commitguards' |
2 | === added file '.commitguards/author-attribution.guard' |
3 | --- .commitguards/author-attribution.guard 1970-01-01 00:00:00 +0000 |
4 | +++ .commitguards/author-attribution.guard 2012-01-27 06:18:23 +0000 |
5 | @@ -0,0 +1,31 @@ |
6 | +# Copyright (c) 2012 Aalto University and RWTH Aachen University. |
7 | +# |
8 | +# Permission is hereby granted, free of charge, to any person |
9 | +# obtaining a copy of this software and associated documentation |
10 | +# files (the "Software"), to deal in the Software without |
11 | +# restriction, including without limitation the rights to use, |
12 | +# copy, modify, merge, publish, distribute, sublicense, and/or sell |
13 | +# copies of the Software, and to permit persons to whom the |
14 | +# Software is furnished to do so, subject to the following |
15 | +# conditions: |
16 | +# |
17 | +# The above copyright notice and this permission notice shall be |
18 | +# included in all copies or substantial portions of the Software. |
19 | +# |
20 | +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
21 | +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES |
22 | +# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
23 | +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
24 | +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
25 | +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
26 | +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
27 | +# OTHER DEALINGS IN THE SOFTWARE. |
28 | + |
29 | +[guard] |
30 | +files=.* |
31 | +actions=amr |
32 | +command= |
33 | + if AUTHORS="$(egrep "@author\b" "{}")"; then |
34 | + echo "{}: files should not contain author attributions such as '$(echo "${AUTHORS}" | head -n 1)'" |
35 | + false |
36 | + fi |
37 | |
38 | === added file '.commitguards/copyright-guard-space.guard' |
39 | --- .commitguards/copyright-guard-space.guard 1970-01-01 00:00:00 +0000 |
40 | +++ .commitguards/copyright-guard-space.guard 2012-01-27 06:18:23 +0000 |
41 | @@ -0,0 +1,27 @@ |
42 | +# Copyright (c) 2012 Aalto University and RWTH Aachen University. |
43 | +# |
44 | +# Permission is hereby granted, free of charge, to any person |
45 | +# obtaining a copy of this software and associated documentation |
46 | +# files (the "Software"), to deal in the Software without |
47 | +# restriction, including without limitation the rights to use, |
48 | +# copy, modify, merge, publish, distribute, sublicense, and/or sell |
49 | +# copies of the Software, and to permit persons to whom the |
50 | +# Software is furnished to do so, subject to the following |
51 | +# conditions: |
52 | +# |
53 | +# The above copyright notice and this permission notice shall be |
54 | +# included in all copies or substantial portions of the Software. |
55 | +# |
56 | +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
57 | +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES |
58 | +# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
59 | +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
60 | +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
61 | +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
62 | +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
63 | +# OTHER DEALINGS IN THE SOFTWARE. |
64 | + |
65 | +[guard] |
66 | +files=\.(c|h|am|ac|in|py|sh|guard)$ |
67 | +actions=amr |
68 | +command=copyright-guard-space.py "{}" |
69 | |
70 | === added file '.commitguards/copyright-guard-space.py' |
71 | --- .commitguards/copyright-guard-space.py 1970-01-01 00:00:00 +0000 |
72 | +++ .commitguards/copyright-guard-space.py 2012-01-27 06:18:23 +0000 |
73 | @@ -0,0 +1,63 @@ |
74 | +#!/usr/bin/env python |
75 | + |
76 | +# Copyright (c) 2012 Aalto University and RWTH Aachen University. |
77 | +# |
78 | +# Permission is hereby granted, free of charge, to any person |
79 | +# obtaining a copy of this software and associated documentation |
80 | +# files (the "Software"), to deal in the Software without |
81 | +# restriction, including without limitation the rights to use, |
82 | +# copy, modify, merge, publish, distribute, sublicense, and/or sell |
83 | +# copies of the Software, and to permit persons to whom the |
84 | +# Software is furnished to do so, subject to the following |
85 | +# conditions: |
86 | +# |
87 | +# The above copyright notice and this permission notice shall be |
88 | +# included in all copies or substantial portions of the Software. |
89 | +# |
90 | +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
91 | +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES |
92 | +# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
93 | +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
94 | +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
95 | +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
96 | +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
97 | +# OTHER DEALINGS IN THE SOFTWARE. |
98 | + |
99 | +# |
100 | +# Test whether a copyright comment block is followed by a blank line |
101 | +# |
102 | + |
103 | +import os, re, sys |
104 | + |
105 | +class CommentStyle: |
106 | + def __init__(self, header, body, footer): |
107 | + self.header = header |
108 | + self.body = body |
109 | + self.footer = footer |
110 | + |
111 | + |
112 | +c_style = CommentStyle(' \* Copyright ', ' \*', ' \*/') |
113 | +hash_style = CommentStyle('# Copyright ', '#', '#.*') |
114 | + |
115 | +styles = { |
116 | + '.c': c_style, |
117 | + '.h': c_style, |
118 | + '.am': hash_style, |
119 | + '.ac': hash_style, |
120 | + '.in': hash_style, |
121 | + '.py': hash_style, |
122 | + '.sh': hash_style, |
123 | +} |
124 | + |
125 | +extension = os.path.splitext(sys.argv[1])[1] |
126 | +if extension in styles: |
127 | + style = styles[extension] |
128 | + pattern = re.compile('^' + style.header + '[^\n]*\n(^' + style.body + '[^\n]*\n)+^' + style.footer + '\n\n', re.MULTILINE) |
129 | + |
130 | + fh = open(sys.argv[1], 'r') |
131 | + match = pattern.search(fh.read()) |
132 | + fh.close() |
133 | + |
134 | + if not match: |
135 | + print 'The copyright header in file %s should be followed by an empty line' % (sys.argv[1]) |
136 | + sys.exit(1) |
137 | |
138 | === added file '.commitguards/copyright-year.guard' |
139 | --- .commitguards/copyright-year.guard 1970-01-01 00:00:00 +0000 |
140 | +++ .commitguards/copyright-year.guard 2012-01-27 06:18:23 +0000 |
141 | @@ -0,0 +1,36 @@ |
142 | +# Copyright (c) 2012 Aalto University and RWTH Aachen University. |
143 | +# |
144 | +# Permission is hereby granted, free of charge, to any person |
145 | +# obtaining a copy of this software and associated documentation |
146 | +# files (the "Software"), to deal in the Software without |
147 | +# restriction, including without limitation the rights to use, |
148 | +# copy, modify, merge, publish, distribute, sublicense, and/or sell |
149 | +# copies of the Software, and to permit persons to whom the |
150 | +# Software is furnished to do so, subject to the following |
151 | +# conditions: |
152 | +# |
153 | +# The above copyright notice and this permission notice shall be |
154 | +# included in all copies or substantial portions of the Software. |
155 | +# |
156 | +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
157 | +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES |
158 | +# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
159 | +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
160 | +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
161 | +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
162 | +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
163 | +# OTHER DEALINGS IN THE SOFTWARE. |
164 | + |
165 | +[guard] |
166 | +files=\.(c|h|am|ac|in|py|sh|guard)$ |
167 | +actions=amr |
168 | +command= |
169 | + CR_TOKEN=" Copyright \(c\) " |
170 | + CR_HOLDER=" Aalto " |
171 | + Y=$(date +%Y) |
172 | + if ! grep -E "${CR_TOKEN}.*${CR_HOLDER}" "{}" | grep -Eq "[^0-9]${Y}[^0-9]"; then |
173 | + echo "{}: The copyright statement is not up-to-date" |
174 | + L=$(( ${Y} - 1 )) |
175 | + sed "/ Copyright (c) / { /[^0-9]${Y}[^0-9]/ ! { /-${L} / s/-${L} /-${Y} /; s/ ${L} / ${L}-${Y} /; /[^0-9]${Y}[^0-9]/ ! s/ \([0-9, -]\+\) \([a-zA-Z]\+\)/ \1, ${Y} \2/ } }" "{}" | diff -u "{}" - >&2 |
176 | + false |
177 | + fi |
178 | |
179 | === modified file 'doc/HACKING' |
180 | --- doc/HACKING 2012-01-15 15:36:14 +0000 |
181 | +++ doc/HACKING 2012-01-27 06:18:23 +0000 |
182 | @@ -45,6 +45,17 @@ |
183 | bzr whoami "#FIRST_NAME# #LAST_NAME# <#EMAIL_ADDRESS#>" |
184 | |
185 | |
186 | +Bazaar plugins |
187 | +-------------- |
188 | + |
189 | +HIPL comes with Bazaar plugins which are very strongly recommended because |
190 | +they help with improving code style and quality. |
191 | +They can be installed with the following commands: |
192 | + |
193 | +#> mkdir -p ~/.bazaar/plugins |
194 | +#> cp tools/bazaar/plugins/* ~/.bazaar/plugins/ |
195 | + |
196 | + |
197 | Creating a local shared repository (optional, but recommended) |
198 | -------------------------------------------------------------- |
199 | |
200 | @@ -620,11 +631,22 @@ |
201 | Style Checking |
202 | -------------- |
203 | |
204 | -As a tool to help with good style, please use the stylecheck pre-commit |
205 | -hook found in tools/bazaar/plugins/stylecheck.py - this script contains its own |
206 | -documentation, including how to set it up. |
207 | - |
208 | -You are strongly recommended to use this hook based on the code beautifier |
209 | +As a tool to help with good style, please use the pre-commit hooks in the |
210 | +directory tools/bazaar/plugins/ - installing them should be as easy as |
211 | +copying them to your Bazaar plugin directory: |
212 | + |
213 | +#> cp tools/bazaar/plugins/* ~/.bazaar/plugins/ |
214 | + |
215 | +Currently, there are two bazaar plugins: |
216 | +- The commit guard plugin implements a set of pre-commit hooks that check |
217 | + general style conventions in HIPL, e.g., that all files must have UNIX- |
218 | + style line breaks. |
219 | +- The stylecheck plugin specifically uses a code beautifier to check for |
220 | + C code-style violations. More on it below. |
221 | + |
222 | +Both scripts contain their own documentation, including how to set them up. |
223 | + |
224 | +You are strongly recommended to use stylecheck based on the code beautifier |
225 | uncrustify because it gets things right almost all the time. So you can and |
226 | should throw all code at uncrustify (via the commit hook) to have it checked. |
227 | |
228 | |
229 | === added file 'tools/bazaar/plugins/commitguard.py' |
230 | --- tools/bazaar/plugins/commitguard.py 1970-01-01 00:00:00 +0000 |
231 | +++ tools/bazaar/plugins/commitguard.py 2012-01-27 06:18:23 +0000 |
232 | @@ -0,0 +1,349 @@ |
233 | +#!/usr/bin/env python |
234 | + |
235 | +# Copyright (c) 2012 Aalto University and RWTH Aachen University. |
236 | +# |
237 | +# Permission is hereby granted, free of charge, to any person |
238 | +# obtaining a copy of this software and associated documentation |
239 | +# files (the "Software"), to deal in the Software without |
240 | +# restriction, including without limitation the rights to use, |
241 | +# copy, modify, merge, publish, distribute, sublicense, and/or sell |
242 | +# copies of the Software, and to permit persons to whom the |
243 | +# Software is furnished to do so, subject to the following |
244 | +# conditions: |
245 | +# |
246 | +# The above copyright notice and this permission notice shall be |
247 | +# included in all copies or substantial portions of the Software. |
248 | +# |
249 | +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
250 | +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES |
251 | +# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
252 | +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
253 | +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
254 | +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
255 | +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
256 | +# OTHER DEALINGS IN THE SOFTWARE. |
257 | + |
258 | +_commitguard_tutorial = """ |
259 | +Bazaar plugin for checking code modifications at pre-commit time. |
260 | + |
261 | +About |
262 | +----- |
263 | + |
264 | +Installation |
265 | +------------ |
266 | +Copy this file into the Bazaar plugin directory (usually .bazaar/plugins/ in |
267 | +your home directory) or add the directory this file resides in to the |
268 | +environment variable BZR_PLUGIN_PATH (export BZR_PLUGIN_PATH="<dir>") before |
269 | +running 'bzr commit'. |
270 | + |
271 | +The pre-commit checks (or 'guards') are described in configuration files with |
272 | +the extension .guard. This script looks for such files in two directories: |
273 | + 1) $HOME/.bazaar/plugins/commitguards/ |
274 | + 2) <repository>/.commitguards/ |
275 | +This allows to set up commit guards both per user and per repository. |
276 | + |
277 | +Usage |
278 | +----- |
279 | +This hook is called automatically when running the command 'bzr commit' after |
280 | +the commit message has been provided. All available commit guards are then |
281 | +applied to the files in the commit. If a file fails a commit guard, the |
282 | +commit is aborted with an error message detailing the failure. The commit |
283 | +message is printed again for convenience. A commit guard can optionally |
284 | +suggest a patch to the file so that it meets the guard's requirements. |
285 | + |
286 | +At the moment, a commit is aborted on the first failing commit guard. |
287 | + |
288 | +Commit Guards |
289 | +------------- |
290 | +Commit guards are described in plain-text configuration files in .ini |
291 | +style with the extension .guard. The basic format of these files is |
292 | + |
293 | +[guard] |
294 | +files=<value> |
295 | +actions=<value> |
296 | +command=<value> |
297 | + |
298 | +Each guard configuration file provides three pieces of information about a |
299 | +commit guard: |
300 | + |
301 | +1) A set of filename patterns the guard is to be applied to. |
302 | + The configuration key is 'files'. |
303 | + The configuration value is a POSIX extended regular expression. |
304 | + For example, the entry 'files=\.(c|C)$' makes sure that the guard is applied |
305 | + to all files with the extension .c or .C |
306 | + |
307 | +2) A set of commit actions specifying if the guard is to be applied to |
308 | + added, modified, and/or renamed files. |
309 | + The configuration key is 'actions'. |
310 | + The configuration value is a string consisting of one or more of the |
311 | + characters 'a', 'm', and 'r', representing added, modified, and renamed files |
312 | + respectively. |
313 | + For example, the entry 'actions=am' makes sure that the guard is applied to |
314 | + new and modified files in a commit but not to renamed files. |
315 | + |
316 | +3) A command that is executed and which implements the actual guard action. |
317 | + The configuration key is 'command'. |
318 | + The configuration value is a string containing a shell command. |
319 | + Before executing this command, all occurrences of the substring {} are |
320 | + replaced with the name of the (added, modified, or renamed) file in the |
321 | + repository and commit to apply the guard to. |
322 | + If the guard considers the given file valid as is, the command should exit |
323 | + with an exit code of 0. |
324 | + In this case, the remaining guards are applied to the remaining files in the |
325 | + commit. |
326 | + If the guard considers a given file as invalid, it should exit with a |
327 | + non-zero exit code. |
328 | + In this case, it may print a message to stdout to inform the user why the |
329 | + commit was aborted. |
330 | + Optionally, the command may print a patch in unified diff format on stderr |
331 | + that, if applied, would bring the file into compliance with the guard's |
332 | + requirements. |
333 | + For added convenience, the commitguard plugin offers the user the option of |
334 | + applying such a patch straight away. |
335 | + Helper executables can be placed into the same directory as a .guard file. |
336 | + The guard command can then invoke these executables as if they were system |
337 | + commands. |
338 | + |
339 | + |
340 | + |
341 | +""" |
342 | + |
343 | +version_info = (0, 1, 0, 'dev', 0) |
344 | +plugin_name = 'commitguard' |
345 | + |
346 | +from bzrlib import branch, help_topics |
347 | +import bzrlib |
348 | +import subprocess |
349 | +import os |
350 | +import os.path |
351 | +import sys |
352 | +import tempfile |
353 | +import re |
354 | +import ConfigParser |
355 | + |
356 | + |
357 | +def get_local_file_name(branch, file_name): |
358 | + """Determine the absolute path of the file in a local Bazaar working branch. |
359 | + |
360 | + Arguments: |
361 | + branch -- an instance of bzrlib's Branch representing a local working |
362 | + branch. file_name is resolved relative to the base location of branch. |
363 | + file_name -- a string containing the relative path of a file in the file |
364 | + tree of branch. |
365 | + |
366 | + This function returns a string that contains the absolute path of the |
367 | + specified file. This file is the actual on-disk working copy and can be |
368 | + accessed and modified. If file_name does not exist in branch or the |
369 | + corresponding local file cannot be found, a RuntimeError is raised. |
370 | + |
371 | + """ |
372 | + base = branch.base |
373 | + if base.startswith('file://'): |
374 | + base = base[7:] |
375 | + local_file_name = os.path.join(base, file_name) |
376 | + if os.path.exists(local_file_name): |
377 | + return local_file_name |
378 | + else: |
379 | + raise RuntimeError("The file '%s' in branch '%s' could not be found at \ |
380 | +'%s' as expected!" % (file_name, branch, local_file_name)) |
381 | + |
382 | + |
383 | + |
384 | +class Guard(object): |
385 | + """A tool that inspects the new state a commit introduces and allows or |
386 | + aborts the commit. |
387 | + |
388 | + Each instance of this class wraps a 'guard' tool which may analyse and check |
389 | + the set of modifications of a commit. It may then let the commit pass or |
390 | + prevent it. |
391 | + |
392 | + """ |
393 | + def __init__(self, cfg_file_name): |
394 | + """Creates and initializes a Guard object and its attributes. |
395 | + |
396 | + If the initialization fails, e.g., because a tool is not available or |
397 | + the configuration is invalid, an Exception is raised. |
398 | + |
399 | + cfg_file_name -- The path of a guard configuration file from which to |
400 | + initialize this object. |
401 | + |
402 | + """ |
403 | + self.configure(cfg_file_name) |
404 | + |
405 | + def configure(self, cfg_file_name): |
406 | + """Initialize a Guard object from a configuration file. |
407 | + |
408 | + cfg_file_name -- The path of a guard configuration file from which to |
409 | + initialize this object. |
410 | + |
411 | + """ |
412 | + config = ConfigParser.RawConfigParser() |
413 | + config.read(cfg_file_name) |
414 | + self.files = re.compile(config.get('guard', 'files'), re.IGNORECASE) |
415 | + self.actions = config.get('guard', 'actions') |
416 | + self.command = unicode(config.get('guard', 'command'), encoding='utf-8') |
417 | + self.filename = cfg_file_name |
418 | + self.dirname = os.path.dirname(cfg_file_name) |
419 | + |
420 | + def applies_to(self, file_name, file_action): |
421 | + """Checks whether this guard applies to a given file or not. |
422 | + |
423 | + file_name -- the name of the file in the working repository which is |
424 | + compared against this guard's file name pattern (not case sensitive). |
425 | + file_action -- one of the characters 'a', 'm', or 'r' to indicate |
426 | + whether a commit adds, modifies, or renames the given file. In the case |
427 | + of a renamed file, the file_name parameter is expected to be the new |
428 | + name of the file. |
429 | + |
430 | + This function returns True if the given file name and action match this |
431 | + guard and False otherwise. |
432 | + |
433 | + """ |
434 | + return file_action in self.actions and self.files.search(file_name) is not None |
435 | + |
436 | + def run(self, local_file_name, action, msg, diff): |
437 | + """Execute a guard to determine whether a commit may proceed or not. |
438 | + |
439 | + Arguments: |
440 | + local_file_name -- the path of a local file to run the guard on. The |
441 | + guard may not modify this file. |
442 | + file_action -- one of the characters 'a', 'm', or 'r' to indicate |
443 | + whether a commit adds, modifies, or renames the given file. In the case |
444 | + of a renamed file, the local_file_name parameter is expected to be the |
445 | + new name of the file. |
446 | + msg -- a file-like object to which the guard may write a message for the |
447 | + user. |
448 | + diff -- a file-like object to which the guard may write a patch in |
449 | + unified diff format which shows how to modify the file contents in order |
450 | + to comply with this guard and let the commit proceed. |
451 | + |
452 | + If this function returns true, the commit may proceed. If it returns |
453 | + false, the commit is aborted. |
454 | + |
455 | + """ |
456 | + if self.applies_to(local_file_name, action): |
457 | + cmd = self.command.replace('{}', local_file_name) |
458 | + env = os.environ |
459 | + if not self.dirname in env['PATH']: |
460 | + env['PATH'] += (':' + self.dirname) |
461 | + p = subprocess.Popen(cmd, |
462 | + shell = True, |
463 | + stdout = msg, |
464 | + stderr = diff, |
465 | + env = env) |
466 | + return p.wait() == 0 |
467 | + else: |
468 | + return True |
469 | + |
470 | + |
471 | +def create_guards_from_dir(cfgdir, guards): |
472 | + for wroot, wdirs, wfiles in os.walk(cfgdir): |
473 | + for f in wfiles: |
474 | + if f.endswith('.guard'): |
475 | + guards.append(Guard(os.path.join(wroot, f))) |
476 | + return guards |
477 | + |
478 | + |
479 | +def create_guards(branch): |
480 | + guards = [] |
481 | + cfgdirs = [os.path.join(os.path.expanduser('~'), '.bazaar/plugins/commitguards')] |
482 | + try: |
483 | + cfgdirs.append(get_local_file_name(branch, '.commitguards')) |
484 | + except: |
485 | + pass |
486 | + for cfgdir in cfgdirs: |
487 | + if os.path.exists(cfgdir): |
488 | + create_guards_from_dir(cfgdir, guards) |
489 | + return guards |
490 | + |
491 | + |
492 | +def get_commit_files(tree_delta): |
493 | + """From all modifications in a commit, retrieve those files which should be |
494 | + run through the guards. |
495 | + |
496 | + That is: added, modified, and renamed files, ignoring meta-data changes. |
497 | + |
498 | + The return value is a list of tuples. Each tuple consists of a the path name |
499 | + of a file in the Bazaar repository tree as the first element and the |
500 | + character 'a', 'm', or 'r' indicating the action this commit performs on the |
501 | + file. |
502 | + |
503 | + """ |
504 | + # include added, modified, and renamed, skip removed and changed |
505 | + files = [(path, 'a') for path, file_id, kind in tree_delta.added if kind == 'file'] |
506 | + files.extend([(path, 'm') for (path, file_id, kind, text_modified, _) in |
507 | + tree_delta.modified if kind == 'file']) |
508 | + files.extend([(newpath, 'r') for (oldpath, newpath, file_id, kind, text_modified, _) in |
509 | + tree_delta.renamed if kind == 'file']) |
510 | + return files |
511 | + |
512 | + |
513 | +def get_commit_message(local, master, revid): |
514 | + """Returns the commit message of a branch revision.""" |
515 | + branch = local or master |
516 | + revision = branch.repository.get_revision(revid) |
517 | + return revision.message |
518 | + |
519 | + |
520 | +def apply_patch(diff_file): |
521 | + """Apply a patch to a local Bazaar branch. |
522 | + |
523 | + diff_file -- a file-like object from which the patch can be read. The patch |
524 | + is expected to be in unified diff format. |
525 | + |
526 | + If applying the beautification fails, a CalledProcessError is raised. |
527 | + |
528 | + """ |
529 | + subprocess.check_call(['patch', '-p0', '-i', diff_file.name]) |
530 | + |
531 | + |
532 | +def pre_commit_hook(local, master, old_revno, old_revid, future_revno, |
533 | + future_revid, tree_delta, future_tree): |
534 | + """Run the files modified by this commit through the configured guards and |
535 | + abort the commit if the guards veto it. |
536 | + |
537 | + This is the pre-commit hook interface of bzrlib. |
538 | + |
539 | + """ |
540 | + guards = create_guards(local or master) |
541 | + |
542 | + veto = False |
543 | + diff_file = tempfile.NamedTemporaryFile(prefix = plugin_name + "-diff-") |
544 | + |
545 | + for tree_file_name, action in get_commit_files(tree_delta): |
546 | + local_file_name = get_local_file_name(local or master, tree_file_name) |
547 | + for guard in guards: |
548 | + if not guard.run(local_file_name, action, sys.stdout, diff_file): |
549 | + veto = True |
550 | + break |
551 | + |
552 | + if veto: |
553 | + break |
554 | + |
555 | + if veto: |
556 | + diff_file.flush() |
557 | + if diff_file.tell(): |
558 | + print "\nThe following patch is suggested so as to comply with the commit guard requirements:\n" |
559 | + diff_file.seek(0) |
560 | + print diff_file.read() |
561 | + print "\nWould you like to apply these changes to your local branch now? [y/N] ", |
562 | + reply = sys.stdin.readline() |
563 | + if reply.strip() == 'y': |
564 | + apply_patch(diff_file) |
565 | + print "Changes successfully applied.\n" |
566 | + diff_file.close() |
567 | + |
568 | + msg_file = tempfile.NamedTemporaryFile(prefix = 'commit-msg-%d-' % future_revno, delete = False) |
569 | + msg_file.write(get_commit_message(local, master, future_revid)) |
570 | + msg_file.close() |
571 | + |
572 | + raise bzrlib.errors.BzrError("This commit has been aborted. The original commit message, stored in %s, was:\n--\n%s\n--" % (msg_file.name, get_commit_message(local, master, future_revid))) |
573 | + diff_file.close() |
574 | + |
575 | + |
576 | +help_topics.topic_registry.register(plugin_name + '-tutorial', |
577 | + _commitguard_tutorial, |
578 | + 'How to use the plugin ' + plugin_name) |
579 | + |
580 | +branch.Branch.hooks.install_named_hook('pre_commit', pre_commit_hook, |
581 | + plugin_name) |
review needs-fixing
On Thu, Jan 19, 2012 at 07:36:24AM +0000, Stefan Götz wrote:
> Stefan Götz has proposed merging lp:~stefan.goetz/hipl/commitguard into lp:hipl.
Looks mostly good to me. I don't speak Python, so this review is
necessarily superficial.
> --- .commitguards/ author- attribution. guard 1970-01-01 00:00:00 +0000 author- attribution. guard 2012-01-19 07:35:28 +0000 \.(c|h| am|ac|in| py|sh)$
> +++ .commitguards/
> @@ -0,0 +1,4 @@
> +[guard]
> +files=
> +actions=amr
> +command=if egrep -q "\*.*@author\b" "{}"; then echo "{}: files should not contain author attributions"; false; fi
Do we really need to restrict this to certain file types?
> --- .commitguards/ copyright- guard-space. py 1970-01-01 00:00:00 +0000 copyright- guard-space. py 2012-01-19 07:35:28 +0000
> +++ .commitguards/
> @@ -0,0 +1,68 @@
> +#!/usr/bin/env python
> +# -*- coding: latin-1 -*-
Please use UTF-8, this is the 21st century (for some time already).
I'm also not sure if you need to tell emacs about this, the file
should be ASCII anyway.
> --- .commitguards/ copyright- year.guard 1970-01-01 00:00:00 +0000 copyright- year.guard 2012-01-19 07:35:28 +0000 \.(c|h| am|ac|in| py|sh)$ *$CR_HOLDER" "{}" | egrep -q "\b$Y\b"; then echo "{}: The copyright statement is not up-to-date"; sed -r "/ Copyright \(c\) / { /\b$Y\b/ ! s/ ([0-9, -]+) ([a-zA-Z]+)/ $Y \2/ }" "{}" | diff -u "{}" - >&2; false; fi bazaar/ plugins/ commitguard. py' plugins/ commitguard. py 1970-01-01 00:00:00 +0000 plugins/ commitguard. py 2012-01-19 07:35:28 +0000
> +++ .commitguards/
> @@ -0,0 +1,4 @@
> +[guard]
> +files=
> +actions=amr
> +command=CR_TOKEN=" Copyright \(c\) "; CR_HOLDER=" Aalto "; Y=$(date +%Y); if ! egrep "$CR_TOKEN.
>
> === added file 'tools/
> --- tools/bazaar/
> +++ tools/bazaar/
> @@ -0,0 +1,353 @@
> +#!/usr/bin/env python
> +# -*- coding: latin-1 -*-
ditto
> +_commitguard_ tutorial = """
> +Bazaar plugin for checking code modifications at pre-commit time.
> +
> +About
> +-----
> +
> +Installation
> +------------
> +Copy this file into the bazaar plugin directory (usually .bazaar/plugins/ in
Bazaar
> + The commitguard plugin offers the user to apply such a patch automatically
> + for convenience.
For added convenience the commitguard plugin offers the user the option
of applying such a patch automatically.
Diego