monotone

monotone Mtn Source Tree

Root/contrib/ciabot_monotone_hookversion.py

  • Property mtn:execute set to true
1#!/usr/bin/env python
2#
3# Copyright (C) Nathaniel Smith <njs@pobox.com>
4# Timothy Brownawell <tbrownaw@gmail.com>
5# Thomas Moschny <thomas.moschny@gmx.de>
6# Licensed under the MIT license:
7# http://www.opensource.org/licenses/mit-license.html
8# I.e., do what you like, but keep copyright and there's NO WARRANTY.
9#
10# CIA bot client script for Monotone repositories, written in python. This
11# generates commit messages using CIA's XML commit format, and can deliver
12# them using either XML-RPC or email. Based on the script 'ciabot_svn.py' by
13# Micah Dowty <micah@navi.cx>.
14
15# This version is modified to be called by a server hook, instead of a cron job.
16
17# To use:
18# -- make a copy of it somewhere
19# -- edit the configuration values below
20# -- include ciabot_monotone_hookversion.lua in the server's monotonerc:
21
22class config:
23 def project_for_branch(self, branchname):
24 # Customize this to return your project name(s). If changes to the
25 # given branch are uninteresting -- i.e., changes to them should be
26 # ignored entirely -- then return the python constant None (which is
27 # distinct from the string "None", a valid but poor project name!).
28 #if branchname.startswith("net.venge.monotone-viz"):
29 # return "monotone-viz"
30 #elif branchname.startswith("net.venge.monotone.contrib.monotree"):
31 # return "monotree"
32 #elif branchname.startswith("net.venge.monotone"):
33 # return "monotone"
34 return "FIXME"
35
36 # The server to deliver XML-RPC messages to, if using XML-RPC delivery.
37 xmlrpc_server = "http://cia.navi.cx"
38
39 # The email address to deliver messages to, if using email delivery.
40 smtp_address = "cia@cia.navi.cx"
41
42 # The SMTP server to connect to, if using email delivery.
43 smtp_server = "localhost"
44
45 # The 'from' address to put on email, if using email delivery.
46 from_address = "cia-user@FIXME"
47
48 # Set to one of "xmlrpc", "email", "debug".
49 delivery = "debug"
50
51################################################################################
52
53import sys
54import re
55import os
56
57def escape_for_xml(text, is_attrib=0):
58 text = text.replace("&", "&amp;")
59 text = text.replace("<", "&lt;")
60 text = text.replace(">", "&gt;")
61 if is_attrib:
62 text = text.replace("'", "&apos;")
63 text = text.replace("\"", "&quot;")
64 return text
65
66TOKEN = re.compile(r'''
67 "(?P<str>(\\\\|\\"|[^"])*)"
68 |\[(?P<id>[a-f0-9]{40}|)\]
69 |(?P<key>\w+)
70 |(?P<ws>\s+)
71''', re.VERBOSE)
72
73def parse_basic_io(raw):
74 parsed = []
75 key = None
76 for m in TOKEN.finditer(raw):
77 if m.lastgroup == 'key':
78 if key:
79 parsed.append((key, values))
80 key = m.group('key')
81 values = []
82 elif m.lastgroup == 'id':
83 values.append(m.group('id'))
84 elif m.lastgroup == 'str':
85 value = m.group('str')
86 # dequote: replace \" with "
87 value = re.sub(r'\\"', '"', value)
88 # dequote: replace \\ with \
89 value = re.sub(r'\\\\', r'\\', value)
90 values.append(value)
91 if key:
92 parsed.append((key, values))
93 return parsed
94
95def send_message(message, c):
96 if c.delivery == "debug":
97 print message
98 elif c.delivery == "xmlrpc":
99 import xmlrpclib
100 xmlrpclib.ServerProxy(c.xmlrpc_server).hub.deliver(message)
101 elif c.delivery == "email":
102 import smtplib
103 smtp = smtplib.SMTP(c.smtp_server)
104 smtp.sendmail(c.from_address, c.smtp_address,
105 "From: %s\r\nTo: %s\r\n"
106 "Subject: DeliverXML\r\n\r\n%s"
107 % (c.from_address, c.smtp_address, message))
108 else:
109 sys.exit("delivery option must be one of 'debug', 'xmlrpc', 'email'")
110
111def send_change_for(rid, branch, author, log, rev, c):
112 message_tmpl = """<message>
113 <generator>
114 <name>Monotone CIA Bot client python script</name>
115 <version>0.1</version>
116 </generator>
117 <source>
118 <project>%(project)s</project>
119 <branch>%(branch)s</branch>
120 </source>
121 <body>
122 <commit>
123 <revision>%(rid)s</revision>
124 <author>%(author)s</author>
125 <files>%(files)s</files>
126 <log>%(log)s</log>
127 </commit>
128 </body>
129</message>"""
130
131 substs = {}
132 files = []
133 for key, values in parse_basic_io(rev):
134 if key == 'old_revision':
135 # start a new changeset
136 oldpath = None
137 if key == 'delete':
138 files.append('<file action="remove">%s</file>'
139 % escape_for_xml(values[0]))
140 elif key == 'rename':
141 oldpath = values[0]
142 elif key == 'to':
143 if oldpath:
144 files.append('<file action="rename" to="%s">%s</file>'
145 % (escape_for_xml(values[0]), escape_for_xml(oldpath)))
146 oldpath = None
147 elif key == 'add_dir':
148 files.append('<file action="add">%s</file>'
149 % escape_for_xml(values[0] + '/'))
150 elif key == 'add_file':
151 files.append('<file action="add">%s</file>'
152 % escape_for_xml(values[0]))
153 elif key == 'patch':
154 files.append('<file action="modify">%s</file>'
155 % escape_for_xml(values[0]))
156
157 substs["files"] = "\n".join(files)
158 changelog = log.strip()
159 project = c.project_for_branch(branch)
160 if project is None:
161 return
162 substs["author"] = escape_for_xml(author)
163 substs["project"] = escape_for_xml(project)
164 substs["branch"] = escape_for_xml(branch)
165 substs["rid"] = escape_for_xml(rid)
166 substs["log"] = escape_for_xml(changelog)
167
168 message = message_tmpl % substs
169 send_message(message, c)
170
171def main(progname, args):
172 if len(args) != 5:
173 sys.exit("Usage: %s revid branch author changelog revision_text" % (progname, ))
174 # We don't want to clutter the process table with zombies; but we also
175 # don't want to force the monotone server to wait around while we call the
176 # CIA server. So we fork -- the original process exits immediately, and
177 # the child continues (orphaned, so it will eventually be reaped by init).
178 if hasattr(os, "fork"):
179 if os.fork():
180 return
181 (rid, branch, author, log, rev, ) = args
182 c = config()
183 send_change_for(rid, branch, author, log, rev, c)
184
185if __name__ == "__main__":
186 main(sys.argv[0], sys.argv[1:])

Archive Download this file

Branches

Tags

Quick Links:     www.monotone.ca    -     Downloads    -     Documentation    -     Wiki    -     Code Forge    -     Build Status