more NEWS items
[buildbot.git] / contrib / svn_watcher.py
blob182a41df83f4511bb16cd44762ac94ffa3d2bcb2
1 #!/usr/bin/python
3 # This is a program which will poll a (remote) SVN repository, looking for
4 # new revisions. It then uses the 'buildbot sendchange' command to deliver
5 # information about the Change to a (remote) buildmaster. It can be run from
6 # a cron job on a periodic basis, or can be told (with the 'watch' option) to
7 # automatically repeat its check every 10 minutes.
9 # This script does not store any state information, so to avoid spurious
10 # changes you must use the 'watch' option and let it run forever.
12 # You will need to provide it with the location of the buildmaster's
13 # PBChangeSource port (in the form hostname:portnum), and the svnurl of the
14 # repository to watch.
17 # 15.03.06 by John Pye
18 # 29.03.06 by Niklaus Giger, added support to run under windows, added invocation option
19 import subprocess
20 import xml.dom.minidom
21 import sys
22 import time
23 import os
24 if sys.platform == 'win32':
25 import win32pipe
27 def getoutput(cmd):
28 p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
29 return p.stdout.read()
31 def checkChanges(repo, master, verbose=False, oldRevision=-1):
32 cmd = ["svn", "log", "--non-interactive", "--xml", "--verbose",
33 "--limit=1", repo]
34 if verbose == True:
35 print "Getting last revision of repository: " + repo
37 if sys.platform == 'win32':
38 f = win32pipe.popen(cmd)
39 xml1 = ''.join(f.readlines())
40 f.close()
41 else:
42 xml1 = getoutput(cmd)
44 if verbose == True:
45 print "XML\n-----------\n"+xml1+"\n\n"
47 doc = xml.dom.minidom.parseString(xml1)
48 el = doc.getElementsByTagName("logentry")[0]
49 revision = el.getAttribute("revision")
50 author = "".join([t.data for t in
51 el.getElementsByTagName("author")[0].childNodes])
52 comments = "".join([t.data for t in
53 el.getElementsByTagName("msg")[0].childNodes])
55 pathlist = el.getElementsByTagName("paths")[0]
56 paths = []
57 for p in pathlist.getElementsByTagName("path"):
58 paths.append("".join([t.data for t in p.childNodes]))
60 if verbose == True:
61 print "PATHS"
62 print paths
64 if revision != oldRevision:
65 cmd = ["buildbot", "sendchange", "--master=%s"%master,
66 "--revision=%s"%revision, "--username=%s"%author,
67 "--comments=%s"%comments]
68 cmd += paths
70 if verbose == True:
71 print cmd
73 if sys.platform == 'win32':
74 f = win32pipe.popen(cmd)
75 print time.strftime("%H.%M.%S ") + "Revision "+revision+ ": "+ ''.join(f.readlines())
76 f.close()
77 else:
78 xml1 = getoutput(cmd)
79 else:
80 print time.strftime("%H.%M.%S ") + "nothing has changed since revision "+revision
82 return revision
84 if __name__ == '__main__':
85 if len(sys.argv) == 4 and sys.argv[3] == 'watch':
86 oldRevision = -1
87 print "Watching for changes in repo "+ sys.argv[1] + " master " + sys.argv[2]
88 while 1:
89 oldRevision = checkChanges(sys.argv[1], sys.argv[2], False, oldRevision)
90 time.sleep(10*60) # Check the repository every 10 minutes
92 elif len(sys.argv) == 3:
93 checkChanges(sys.argv[1], sys.argv[2], True )
94 else:
95 print os.path.basename(sys.argv[0]) + ": http://host/path/to/repo master:port [watch]"