diff options
-rw-r--r-- | CVSROOT/loginfo | 4 | ||||
-rwxr-xr-x | CVSROOT/syncmail | 210 |
2 files changed, 214 insertions, 0 deletions
diff --git a/CVSROOT/loginfo b/CVSROOT/loginfo index 5a59f0a544..67cdc2749b 100644 --- a/CVSROOT/loginfo +++ b/CVSROOT/loginfo | |||
@@ -24,3 +24,7 @@ | |||
24 | #DEFAULT (echo ""; id; echo %s; date; cat) >> $CVSROOT/CVSROOT/commitlog | 24 | #DEFAULT (echo ""; id; echo %s; date; cat) >> $CVSROOT/CVSROOT/commitlog |
25 | # or | 25 | # or |
26 | #DEFAULT (echo ""; id; echo %{sVv}; date; cat) >> $CVSROOT/CVSROOT/commitlog | 26 | #DEFAULT (echo ""; id; echo %{sVv}; date; cat) >> $CVSROOT/CVSROOT/commitlog |
27 | ^firmware $CVSROOT/CVSROOT/syncmail -C4 -u %{sVv} rockbox-cvs@cool.haxx.se | ||
28 | ^uisimulator $CVSROOT/CVSROOT/syncmail -C4 -u %{sVv} rockbox-cvs@cool.haxx.se | ||
29 | ^tools $CVSROOT/CVSROOT/syncmail -C4 -u %{sVv} rockbox-cvs@cool.haxx.se | ||
30 | ^CVSROOT $CVSROOT/CVSROOT/syncmail -C4 -u %{sVv} zagor@users.sourceforge.net | ||
diff --git a/CVSROOT/syncmail b/CVSROOT/syncmail new file mode 100755 index 0000000000..ba6cc90d06 --- /dev/null +++ b/CVSROOT/syncmail | |||
@@ -0,0 +1,210 @@ | |||
1 | #! /usr/bin/python | ||
2 | # -*- Python -*- | ||
3 | |||
4 | """Complicated notification for CVS checkins. | ||
5 | |||
6 | This script is used to provide email notifications of changes to the CVS | ||
7 | repository. These email changes will include context diffs of the changes. | ||
8 | Really big diffs will be trimmed. | ||
9 | |||
10 | This script is run from a CVS loginfo file (see $CVSROOT/CVSROOT/loginfo). To | ||
11 | set this up, create a loginfo entry that looks something like this: | ||
12 | |||
13 | mymodule /path/to/this/script %%s some-email-addr@your.domain | ||
14 | |||
15 | In this example, whenever a checkin that matches `mymodule' is made, this | ||
16 | script is invoked, which will generate the diff containing email, and send it | ||
17 | to some-email-addr@your.domain. | ||
18 | |||
19 | Note: This module used to also do repository synchronizations via | ||
20 | rsync-over-ssh, but since the repository has been moved to SourceForge, | ||
21 | this is no longer necessary. The syncing functionality has been ripped | ||
22 | out in the 3.0, which simplifies it considerably. Access the 2.x versions | ||
23 | to refer to this functionality. Because of this, the script is misnamed. | ||
24 | |||
25 | It no longer makes sense to run this script from the command line. Doing so | ||
26 | will only print out this usage information. | ||
27 | |||
28 | Usage: | ||
29 | |||
30 | %(PROGRAM)s [options] <%%S> email-addr [email-addr ...] | ||
31 | |||
32 | Where options is: | ||
33 | |||
34 | --cvsroot=<path> | ||
35 | Use <path> as the environment variable CVSROOT. Otherwise this | ||
36 | variable must exist in the environment. | ||
37 | |||
38 | --help | ||
39 | -h | ||
40 | Print this text. | ||
41 | |||
42 | --context=# | ||
43 | -C # | ||
44 | Include # lines of context around lines that differ (default: 2). | ||
45 | |||
46 | -c | ||
47 | Produce a context diff (default). | ||
48 | |||
49 | -u | ||
50 | Produce a unified diff (smaller, but harder to read). | ||
51 | |||
52 | <%%S> | ||
53 | CVS %%s loginfo expansion. When invoked by CVS, this will be a single | ||
54 | string containing the directory the checkin is being made in, relative | ||
55 | to $CVSROOT, followed by the list of files that are changing. If the | ||
56 | %%s in the loginfo file is %%{sVv}, context diffs for each of the | ||
57 | modified files are included in any email messages that are generated. | ||
58 | |||
59 | email-addrs | ||
60 | At least one email address. | ||
61 | |||
62 | """ | ||
63 | |||
64 | import os | ||
65 | import sys | ||
66 | import string | ||
67 | import time | ||
68 | import getopt | ||
69 | |||
70 | # Notification command | ||
71 | MAILCMD = '/bin/mail -s "cvs: %(SUBJECT)s" %(PEOPLE)s 2>&1 > /dev/null' | ||
72 | |||
73 | # Diff trimming stuff | ||
74 | DIFF_HEAD_LINES = 20 | ||
75 | DIFF_TAIL_LINES = 20 | ||
76 | DIFF_TRUNCATE_IF_LARGER = 1000 | ||
77 | |||
78 | PROGRAM = sys.argv[0] | ||
79 | |||
80 | |||
81 | |||
82 | def usage(code, msg=''): | ||
83 | print __doc__ % globals() | ||
84 | if msg: | ||
85 | print msg | ||
86 | sys.exit(code) | ||
87 | |||
88 | |||
89 | |||
90 | def calculate_diff(filespec, contextlines): | ||
91 | try: | ||
92 | file, oldrev, newrev = string.split(filespec, ',') | ||
93 | except ValueError: | ||
94 | # No diff to report | ||
95 | return '***** Bogus filespec: %s' % filespec | ||
96 | if oldrev == 'NONE': | ||
97 | try: | ||
98 | if os.path.exists(file): | ||
99 | fp = open(file) | ||
100 | else: | ||
101 | update_cmd = 'cvs -fn update -r %s -p %s' % (newrev, file) | ||
102 | fp = os.popen(update_cmd) | ||
103 | lines = fp.readlines() | ||
104 | fp.close() | ||
105 | lines.insert(0, '--- NEW FILE: %s ---\n' % file) | ||
106 | except IOError, e: | ||
107 | lines = ['***** Error reading new file: ', | ||
108 | str(e), '\n***** file: ', file, ' cwd: ', os.getcwd()] | ||
109 | elif newrev == 'NONE': | ||
110 | lines = ['--- %s DELETED ---\n' % file] | ||
111 | else: | ||
112 | # This /has/ to happen in the background, otherwise we'll run into CVS | ||
113 | # lock contention. What a crock. | ||
114 | if contextlines > 0: | ||
115 | difftype = "-C " + str(contextlines) | ||
116 | else: | ||
117 | difftype = "-uN" | ||
118 | diffcmd = '/usr/bin/cvs -f diff -kk %s -r %s -r %s %s' % ( | ||
119 | difftype, oldrev, newrev, file) | ||
120 | fp = os.popen(diffcmd) | ||
121 | lines = fp.readlines() | ||
122 | sts = fp.close() | ||
123 | # ignore the error code, it always seems to be 1 :( | ||
124 | ## if sts: | ||
125 | ## return 'Error code %d occurred during diff\n' % (sts >> 8) | ||
126 | if len(lines) > DIFF_TRUNCATE_IF_LARGER: | ||
127 | removedlines = len(lines) - DIFF_HEAD_LINES - DIFF_TAIL_LINES | ||
128 | del lines[DIFF_HEAD_LINES:-DIFF_TAIL_LINES] | ||
129 | lines.insert(DIFF_HEAD_LINES, | ||
130 | '[...%d lines suppressed...]\n' % removedlines) | ||
131 | return string.join(lines, '') | ||
132 | |||
133 | |||
134 | |||
135 | def blast_mail(mailcmd, filestodiff, contextlines): | ||
136 | # cannot wait for child process or that will cause parent to retain cvs | ||
137 | # lock for too long. Urg! | ||
138 | if not os.fork(): | ||
139 | # in the child | ||
140 | # give up the lock you cvs thang! | ||
141 | time.sleep(2) | ||
142 | fp = os.popen(mailcmd, 'w') | ||
143 | fp.write(sys.stdin.read()) | ||
144 | fp.write('\n') | ||
145 | # append the diffs if available | ||
146 | for file in filestodiff: | ||
147 | fp.write(calculate_diff(file, contextlines)) | ||
148 | fp.write('\n') | ||
149 | fp.close() | ||
150 | # doesn't matter what code we return, it isn't waited on | ||
151 | os._exit(0) | ||
152 | |||
153 | |||
154 | |||
155 | # scan args for options | ||
156 | def main(): | ||
157 | contextlines = 2 | ||
158 | try: | ||
159 | opts, args = getopt.getopt(sys.argv[1:], 'hC:cu', | ||
160 | ['context=', 'cvsroot=', 'help']) | ||
161 | except getopt.error, msg: | ||
162 | usage(1, msg) | ||
163 | |||
164 | # parse the options | ||
165 | for opt, arg in opts: | ||
166 | if opt in ('-h', '--help'): | ||
167 | usage(0) | ||
168 | elif opt == '--cvsroot': | ||
169 | os.environ['CVSROOT'] = arg | ||
170 | elif opt in ('-C', '--context'): | ||
171 | contextlines = int(arg) | ||
172 | elif opt == '-c': | ||
173 | if contextlines <= 0: | ||
174 | contextlines = 2 | ||
175 | elif opt == '-u': | ||
176 | contextlines = 0 | ||
177 | |||
178 | # What follows is the specification containing the files that were | ||
179 | # modified. The argument actually must be split, with the first component | ||
180 | # containing the directory the checkin is being made in, relative to | ||
181 | # $CVSROOT, followed by the list of files that are changing. | ||
182 | if not args: | ||
183 | usage(1, 'No CVS module specified') | ||
184 | SUBJECT = args[0] | ||
185 | specs = string.split(args[0]) | ||
186 | del args[0] | ||
187 | |||
188 | # The remaining args should be the email addresses | ||
189 | if not args: | ||
190 | usage(1, 'No recipients specified') | ||
191 | |||
192 | # Now do the mail command | ||
193 | PEOPLE = string.join(args) | ||
194 | mailcmd = MAILCMD % vars() | ||
195 | |||
196 | print 'Mailing %s...' % PEOPLE | ||
197 | if specs == ['-', 'Imported', 'sources']: | ||
198 | return | ||
199 | if specs[-3:] == ['-', 'New', 'directory']: | ||
200 | del specs[-3:] | ||
201 | print 'Generating notification message...' | ||
202 | blast_mail(mailcmd, specs[1:], contextlines) | ||
203 | print 'Generating notification message... done.' | ||
204 | |||
205 | |||
206 | |||
207 | if __name__ == '__main__': | ||
208 | main() | ||
209 | sys.exit(0) | ||
210 | |||