# # add_file "contrib/ciabot_monotone_hookversion.py" # # patch ".mt-attrs" # from [f64f76c6bd0167f72362edd8c47724dffbe31907] # to [43c90c1b09c5f7a6d60f0fa6ce6e4eb67911789a] # # patch "ChangeLog" # from [2c317bf9f24509c9cf8a705ef5a360316918de18] # to [16768c3e61cd01848429d635a3cd40271fd353c3] # # patch "commands.cc" # from [55800638c9bd2da0aa48ab46d06beba1d5845c32] # to [59ff7fa5fa25b87fd469695fa7efa6cc197a23b0] # # patch "contrib/ciabot_monotone_hookversion.py" # from [] # to [3fc87a62b0d4ed9900f6735ebef812fc9948bc93] # # patch "lua.cc" # from [f8a4f1818ea770532218416cb55752238c1f3ce3] # to [fc053070a0c0a106e6f9a3e5678ef2a427ad1fcd] # # patch "lua.hh" # from [db3bb1c0a41f36d245e8f1cdbbada5b7a42f7dae] # to [950e24bc4b2c16b258f00aee0c4923ae93f256df] # # patch "monotone.texi" # from [b9423f2c78e69bf6307613fd2c4efc81427a92b9] # to [9b7b9ab00d31aead6a87466ff1a2d843c54084a8] # # patch "netsync.cc" # from [e1c2726ff08eb0cc2c7a40cb5b391517d4f2fa95] # to [5a4a894840cdd806535dd34121a150ea8d7a0870] # ======================================================================== --- .mt-attrs f64f76c6bd0167f72362edd8c47724dffbe31907 +++ .mt-attrs 43c90c1b09c5f7a6d60f0fa6ce6e4eb67911789a @@ -1,6 +1,9 @@ file "contrib/ciabot_monotone.py" execute "true" + file "contrib/ciabot_monotone_hookversion.py" +execute "true" + file "contrib/color-logs.sh" execute "true" ======================================================================== --- ChangeLog 2c317bf9f24509c9cf8a705ef5a360316918de18 +++ ChangeLog 16768c3e61cd01848429d635a3cd40271fd353c3 @@ -1,3 +1,12 @@ +2005-09-14 Timothy Brownawell + + * contrib/ciabot_monotone_hookversion.py: CIA bot client script + meant to be called from the note_netsync_revision_received hook. + * lua.{cc,hh}: hook_note_commit and hook_note_netsync_revision_received + now take the text of the revision as an argument. + * netsync.cc, commands.cc: Give hooks new argument. + * monotone.texi: Update documentation for those hooks. + 2005-09-11 Benoît Dejean * database.cc ======================================================================== --- commands.cc 55800638c9bd2da0aa48ab46d06beba1d5845c32 +++ commands.cc 59ff7fa5fa25b87fd469695fa7efa6cc197a23b0 @@ -2418,7 +2418,9 @@ decode_base64(i->inner().value, vtmp); certs.insert(make_pair(i->inner().name, vtmp)); } - app.lua.hook_note_commit(rid, certs); + revision_data rdat; + app.db.get_revision(rid, rdat); + app.lua.hook_note_commit(rid, rdat, certs); } } ======================================================================== --- contrib/ciabot_monotone_hookversion.py +++ contrib/ciabot_monotone_hookversion.py 3fc87a62b0d4ed9900f6735ebef812fc9948bc93 @@ -0,0 +1,149 @@ +#!/usr/bin/env python +# +# Copyright (C) Nathaniel Smith +# Timothy Brownawell +# Licensed under the MIT license: +# http://www.opensource.org/licenses/mit-license.html +# I.e., do what you like, but keep copyright and there's NO WARRANTY. +# +# CIA bot client script for Monotone repositories, written in python. This +# generates commit messages using CIA's XML commit format, and can deliver +# them using either XML-RPC or email. Based on the script 'ciabot_svn.py' by +# Micah Dowty . + +# This version is modified to be called by a server hook, instead of a cron job. + +# To use: +# -- make a copy of it somewhere +# -- edit the configuration values below +# -- put the following in the server's monotonerc: +# function note_netsync_revision_received(rid, rdat, certs) +# local branch, author, changelog +# for i, cert in pairs(certs) +# do +# if (cert.name == "branch") then +# branch = cert.value +# end +# if (cert.name == "author") then +# author = cert.value +# end +# if (cert.name == "changelog") then +# changelog = cert.value +# end +# end +# local exe = "/path/to/this/script" +# spawn(exe, rid, branch, author, changelog, rdat) +# return +# end + +class config: + def project_for_branch(self, branchname): + # Customize this to return your project name(s). If changes to the + # given branch are uninteresting -- i.e., changes to them should be + # ignored entirely -- then return the python constant None (which is + # distinct from the string "None", a valid but poor project name!). + #if branchname.startswith("net.venge.monotone-viz"): + # return "monotone-viz" + #elif branchname.startswith("net.venge.monotone.contrib.monotree"): + # return "monotree" + #else: + # return "monotone" + return "FIXME" + + # The server to deliver XML-RPC messages to, if using XML-RPC delivery. + xmlrpc_server = "http://cia.navi.cx" + + # The email address to deliver messages to, if using email delivery. + smtp_address = "address@hidden" + + # The SMTP server to connect to, if using email delivery. + smtp_server = "localhost" + + # The 'from' address to put on email, if using email delivery. + from_address = "address@hidden" + + # Set to one of "xmlrpc", "email", "debug". + delivery = "debug" + +################################################################################ + +import sys + +def escape_for_xml(text, is_attrib=0): + text = text.replace("&", "&") + text = text.replace("<", "<") + text = text.replace(">", ">") + if is_attrib: + text = text.replace("'", "'") + text = text.replace("\"", """) + return text + +def send_message(message, c): + if c.delivery == "debug": + print message + elif c.delivery == "xmlrpc": + import xmlrpclib + xmlrpclib.ServerProxy(c.xmlrpc_server).hub.deliver(message) + elif c.delivery == "email": + import smtplib + smtp = smtplib.SMTP(c.smtp_server) + smtp.sendmail(c.from_address, c.smtp_address, + "From: %s\r\nTo: %s\r\n" + "Subject: DeliverXML\r\n\r\n%s" + % (c.from_address, c.smtp_address, message)) + else: + sys.exit("delivery option must be one of 'debug', 'xmlrpc', 'email'") + +def send_change_for(rid, branch, author, log, rev, c): + message_tmpl = """ + + Monotone CIA Bot client python script + 0.1 + + + %(project)s + %(branch)s + + + + %(rid)s + %(author)s + %(files)s + %(log)s + + +""" + + substs = {} + + # Stupid way to pull out everything inside quotes (which currently + # uniquely identifies filenames inside a changeset). + pieces = rev.split('"') + files = [] + for i in range(len(pieces)): + if (i % 2) == 1: + if pieces[i] not in files: + files.append(pieces[i]) + substs["files"] = "\n".join(["%s" % escape_for_xml(f) for f in files]) + changelog = log.strip() + project = c.project_for_branch(branch) + if project is None: + return + substs["author"] = escape_for_xml(author) + substs["project"] = escape_for_xml(project) + substs["branch"] = escape_for_xml(branch) + substs["rid"] = escape_for_xml(rid) + substs["log"] = escape_for_xml(changelog) + + message = message_tmpl % substs + send_message(message, c) + +def main(progname, args): + if len(args) != 5: + sys.exit("Usage: %s revid branch author changelog revision_text" % (progname, )) + (rid, branch, author, log, rev, ) = args + c = config() + send_change_for(rid, branch, author, log, rev, c) + +if __name__ == "__main__": + main(sys.argv[0], sys.argv[1:]) ======================================================================== --- lua.cc f8a4f1818ea770532218416cb55752238c1f3ce3 +++ lua.cc fc053070a0c0a106e6f9a3e5678ef2a427ad1fcd @@ -1298,12 +1298,14 @@ bool lua_hooks::hook_note_commit(revision_id const & new_id, + revision_data const & rdat, map const & certs) { Lua ll(st); ll .func("note_commit") - .push_str(new_id.inner()()); + .push_str(new_id.inner()()) + .push_str(rdat.inner()()); ll.push_table(); @@ -1315,12 +1317,13 @@ ll.set_table(); } - ll.call(2, 0); + ll.call(3, 0); return ll.ok(); } bool lua_hooks::hook_note_netsync_revision_received(revision_id const & new_id, + revision_data const & rdat, set > > const & certs) @@ -1328,7 +1331,8 @@ Lua ll(st); ll .func("note_netsync_revision_received") - .push_str(new_id.inner()()); + .push_str(new_id.inner()()) + .push_str(rdat.inner()()); ll.push_table(); @@ -1351,7 +1355,7 @@ ll.set_table(); } - ll.call(2, 0); + ll.call(3, 0); return ll.ok(); } ======================================================================== --- lua.hh db3bb1c0a41f36d245e8f1cdbbada5b7a42f7dae +++ lua.hh 950e24bc4b2c16b258f00aee0c4923ae93f256df @@ -125,9 +125,11 @@ // notification hooks bool hook_note_commit(revision_id const & new_id, + revision_data const & rdat, std::map const & certs); bool hook_note_netsync_revision_received(revision_id const & new_id, + revision_data const & rdat, std::set > > const & certs); ======================================================================== --- monotone.texi b9423f2c78e69bf6307613fd2c4efc81427a92b9 +++ monotone.texi 9b7b9ab00d31aead6a87466ff1a2d843c54084a8 @@ -5584,10 +5584,12 @@ definitions. @ftable @code address@hidden note_commit (@var{new_id}, @var{certs}) address@hidden note_commit (@var{new_id}, @var{revision}, @var{certs}) Called by monotone after the version @var{new_id} is committed. The -second parameter, @var{certs}, is a lua table containing the set of +second parameter, @var{revision} is the text of the revision, what would +be given by "monotone cat revision @var{new_id}". The +third parameter, @var{certs}, is a lua table containing the set of certificate names and values committed along with this version. There is no default definition for this hook. @@ -5598,10 +5600,12 @@ commit-notification systems such as mailing lists or news services. It should not perform any security-critical operations. address@hidden note_netsync_revision_received (@var{new_id}, @var{certs}) address@hidden note_netsync_revision_received (@var{new_id}, @var{revision}, @var{certs}) Called by monotone after the revision @var{new_id} is recieved through -netsync. @var{certs} is a lua table containing one subtable for each +netsync. @var{revision} is the text of the revision, what would be given +by "monotone cat revision @var{new_id}". @var{certs} is a lua table +containing one subtable for each cert attached to the revision @var{new_id}. These subtables have fields named "key", "name", and "value", containing the signing key for the cert, the name of the cert, and the value of the cert. There is no default ======================================================================== --- netsync.cc e1c2726ff08eb0cc2c7a40cb5b391517d4f2fa95 +++ netsync.cc 5a4a894840cdd806535dd34121a150ea8d7a0870 @@ -587,7 +587,9 @@ decode_base64(j->value, vtmp); certs.insert(make_pair(j->key, make_pair(j->name, vtmp))); } - app.lua.hook_note_netsync_revision_received(*i, certs); + revision_data rdat; + app.db.get_revision(*i, rdat); + app.lua.hook_note_netsync_revision_received(*i, rdat, certs); } //Certs (not attached to a new revision) for (vector::iterator i = unattached_certs.begin();