/[rdesktop]/sourceforge.net/trunk/CVSROOT/syncmail
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /sourceforge.net/trunk/CVSROOT/syncmail

Parent Directory Parent Directory | Revision Log Revision Log


Revision 41 - (show annotations)
Sat Apr 6 05:11:05 2002 UTC (22 years, 1 month ago) by matthewc
File size: 7195 byte(s)
Setting up syncmail (3.18) to report CVS changes to rdesktop-cvs.

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 BINARY_EXPLANATION_LINES = [
81 "(This appears to be a binary file; contents omitted.)\n"
82 ]
83
84
85 def usage(code, msg=''):
86 print __doc__ % globals()
87 if msg:
88 print msg
89 sys.exit(code)
90
91
92
93 def calculate_diff(filespec, contextlines):
94 try:
95 file, oldrev, newrev = string.split(filespec, ',')
96 except ValueError:
97 # No diff to report
98 return '***** Bogus filespec: %s' % filespec
99 if oldrev == 'NONE':
100 try:
101 if os.path.exists(file):
102 fp = open(file)
103 else:
104 update_cmd = 'cvs -fn update -r %s -p %s' % (newrev, file)
105 fp = os.popen(update_cmd)
106 lines = fp.readlines()
107 fp.close()
108 # Is this a binary file? Let's look at the first few
109 # lines to figure it out:
110 for line in lines[:5]:
111 for c in string.rstrip(line):
112 if c < ' ' or c > chr(127):
113 lines = BINARY_EXPLANATION_LINES[:]
114 break
115 lines.insert(0, '--- NEW FILE: %s ---\n' % file)
116 except IOError, e:
117 lines = ['***** Error reading new file: ',
118 str(e), '\n***** file: ', file, ' cwd: ', os.getcwd()]
119 elif newrev == 'NONE':
120 lines = ['--- %s DELETED ---\n' % file]
121 else:
122 # This /has/ to happen in the background, otherwise we'll run into CVS
123 # lock contention. What a crock.
124 if contextlines > 0:
125 difftype = "-C " + str(contextlines)
126 else:
127 difftype = "-u"
128 diffcmd = "/usr/bin/cvs -f diff -kk %s --minimal -r %s -r %s '%s'" % (
129 difftype, oldrev, newrev, file)
130 fp = os.popen(diffcmd)
131 lines = fp.readlines()
132 sts = fp.close()
133 # ignore the error code, it always seems to be 1 :(
134 ## if sts:
135 ## return 'Error code %d occurred during diff\n' % (sts >> 8)
136 if len(lines) > DIFF_TRUNCATE_IF_LARGER:
137 removedlines = len(lines) - DIFF_HEAD_LINES - DIFF_TAIL_LINES
138 del lines[DIFF_HEAD_LINES:-DIFF_TAIL_LINES]
139 lines.insert(DIFF_HEAD_LINES,
140 '[...%d lines suppressed...]\n' % removedlines)
141 return string.join(lines, '')
142
143
144
145 def blast_mail(mailcmd, filestodiff, contextlines):
146 # cannot wait for child process or that will cause parent to retain cvs
147 # lock for too long. Urg!
148 if not os.fork():
149 # in the child
150 # give up the lock you cvs thang!
151 time.sleep(2)
152 fp = os.popen(mailcmd, 'w')
153 fp.write(sys.stdin.read())
154 fp.write('\n')
155 # append the diffs if available
156 for file in filestodiff:
157 fp.write(calculate_diff(file, contextlines))
158 fp.write('\n')
159 fp.close()
160 # doesn't matter what code we return, it isn't waited on
161 os._exit(0)
162
163
164
165 # scan args for options
166 def main():
167 contextlines = 2
168 try:
169 opts, args = getopt.getopt(sys.argv[1:], 'hC:cu',
170 ['context=', 'cvsroot=', 'help'])
171 except getopt.error, msg:
172 usage(1, msg)
173
174 # parse the options
175 for opt, arg in opts:
176 if opt in ('-h', '--help'):
177 usage(0)
178 elif opt == '--cvsroot':
179 os.environ['CVSROOT'] = arg
180 elif opt in ('-C', '--context'):
181 contextlines = int(arg)
182 elif opt == '-c':
183 if contextlines <= 0:
184 contextlines = 2
185 elif opt == '-u':
186 contextlines = 0
187
188 # What follows is the specification containing the files that were
189 # modified. The argument actually must be split, with the first component
190 # containing the directory the checkin is being made in, relative to
191 # $CVSROOT, followed by the list of files that are changing.
192 if not args:
193 usage(1, 'No CVS module specified')
194 SUBJECT = args[0]
195 specs = string.split(args[0])
196 del args[0]
197
198 # The remaining args should be the email addresses
199 if not args:
200 usage(1, 'No recipients specified')
201
202 # Now do the mail command
203 PEOPLE = string.join(args)
204 mailcmd = MAILCMD % vars()
205
206 print 'Mailing %s...' % PEOPLE
207 if specs == ['-', 'Imported', 'sources']:
208 return
209 if specs[-3:] == ['-', 'New', 'directory']:
210 del specs[-3:]
211 elif len(specs) > 2:
212 L = specs[:2]
213 for s in specs[2:]:
214 prev = L[-1]
215 if string.count(prev, ",") < 2:
216 L[-1] = "%s %s" % (prev, s)
217 else:
218 L.append(s)
219 specs = L
220 print 'Generating notification message...'
221 blast_mail(mailcmd, specs[1:], contextlines)
222 print 'Generating notification message... done.'
223
224
225
226 if __name__ == '__main__':
227 main()
228 sys.exit(0)

Properties

Name Value
svn:executable *

  ViewVC Help
Powered by ViewVC 1.1.26