monotone

monotone Mtn Source Tree

Root/contrib/monotone-mail-notify.lua

1-- Create a file "notify" next to "read-permissions" and ensure
2-- its contents are in the same format as "read-permissions",
3-- except that the values for allow and deny must be real email
4-- addresses.
5--
6-- This will splat out files in _base. Use the .sh file from
7-- cron to process those files
8--
9-- Copyright (c) 2007, Matthew Sackman (matthew at wellquite dot org)
10-- LShift Ltd (http://www.lshift.net)
11-- Thomas Keller <me@thomaskeller.biz>
12-- Whoever wrote the function "get_netsync_read_permitted"
13-- License: GPLv2 or later
14
15_from = "monotone@my.domain.please.change.me"
16_base = "/tmp/notify/"
17
18function get_notify_recipients(branch)
19 local emailfile = io.open(get_confdir() .. "/notify", "r")
20 if (emailfile == nil) then return nil end
21 local dat = emailfile:read("*a")
22 io.close(emailfile)
23 local res = parse_basic_io(dat)
24 if res == nil then
25 io.stderr:write("file notify cannot be parsed\n")
26 return nil
27 end
28
29 local results = {}
30 local denied = {}
31 local matches = false
32 local cont = false
33 for i, item in pairs(res)
34 do
35 -- legal names: pattern, allow, deny, continue
36 if item.name == "pattern" then
37 if matches and not cont then return table.toarray(results) end
38 matches = false
39 cont = false
40 for j, val in pairs(item.values) do
41 if globish_match(val, branch) then matches = true end
42 end
43 elseif item.name == "allow" then if matches then
44 for j, val in pairs(item.values) do
45 if nil == denied[val] then results[val] = val end
46 end
47 end elseif item.name == "deny" then if matches then
48 for j, val in pairs(item.values) do
49 denied[val] = val
50 end
51 end elseif item.name == "continue" then if matches then
52 cont = true
53 for j, val in pairs(item.values) do
54 if val == "false" or val == "no" then cont = false end
55 end
56 end elseif item.name ~= "comment" then
57 io.stderr:write("unknown symbol in notify: " .. item.name .. "\n")
58 end
59 end
60 return table.toarray(results)
61end
62
63function table.toarray(t)
64 local t1 = {}
65 for j, val in pairs(t) do
66 table.insert(t1, val)
67 end
68 return t1
69end
70
71_emails_to_send = {}
72
73function note_netsync_start (session_id, my_role, sync_type, remote_host, remote_keyname, includes, excludes)
74 _emails_to_send[session_id] = {}
75end
76
77function note_netsync_revision_received (new_id, revision, certs, session_id)
78 if _emails_to_send[session_id] == nil then
79 -- no session present
80 return
81 end
82
83 local rev_data = {["certs"] = {}, ["revision"] = new_id, ["manifest"] = revision}
84 for _,cert in ipairs(certs) do
85 if cert["name"] == "branch" then
86 rev_data["recipients"] = get_notify_recipients(cert["value"])
87 end
88 if cert["name"] ~= nil then
89 if nil == rev_data["certs"][cert["name"]] then
90 rev_data["certs"][cert["name"]] = {}
91 end
92 table.insert(rev_data["certs"][cert["name"]], cert["value"])
93 end
94 end
95 _emails_to_send[session_id][new_id] = rev_data
96end
97
98do
99 local saved_note_netsync_end = note_netsync_end
100
101 function note_netsync_end (session_id, status, bytes_in, bytes_out, certs_in, certs_out, revs_in, revs_out, keys_in, keys_out, ...)
102 if saved_note_netsync_end then
103 saved_note_netsync_end(session_id, status,
104 bytes_in, bytes_out,
105 certs_in, certs_out,
106 revs_in, revs_out,
107 keys_in, keys_out,
108 unpack(arg))
109 end
110
111
112 if _emails_to_send[session_id] == nil then
113 -- no session present
114 return
115 end
116
117 if status ~= 200 then
118 -- some error occured, no further processing takes place
119 return
120 end
121
122 if _emails_to_send[session_id] == "" then
123 -- we got no interesting revisions
124 return
125 end
126
127 for rev_id,rev_data in pairs(_emails_to_send[session_id]) do
128 if # (rev_data["recipients"]) > 0 then
129 local subject = make_subject_line(rev_data)
130 local reply_to = ""
131 for j,auth in pairs(rev_data["certs"]["author"]) do
132 reply_to = reply_to .. auth
133 if j < # (rev_data["certs"]["author"]) then reply_to = reply_to .. ", " end
134 end
135
136 local now = os.time()
137
138 local outputFileRev = io.open(_base .. rev_data["revision"] .. now .. ".rev.txt", "w+")
139 local outputFileHdr = io.open(_base .. rev_data["revision"] .. now .. ".hdr.txt", "w+")
140
141 local to = ""
142 for j,addr in pairs(rev_data["recipients"]) do
143 to = to .. addr
144 if j < # (rev_data["recipients"]) then to = to .. ", " end
145 end
146
147 outputFileHdr:write("BCC: " .. to .. "\n")
148 outputFileHdr:write("From: " .. _from .. "\n")
149 outputFileHdr:write("Subject: " .. subject .. "\n")
150 outputFileHdr:write("Reply-To: " .. reply_to .. "\n")
151 outputFileHdr:close()
152
153 outputFileRev:write(summarize_certs(rev_data))
154 outputFileRev:close()
155 end
156 end
157
158 _emails_to_send[session_id] = nil
159 end
160end
161
162function summarize_certs(t)
163 local str = "revision: " .. t["revision"] .. "\n"
164 local changelog
165 for name,values in pairs(t["certs"]) do
166 local formatted_value = ""
167 for j,val in pairs(values) do
168 formatted_value = formatted_value .. name .. ":"
169 if string.match(val, "\n")
170 then formatted_value = formatted_value .. "\n"
171 else formatted_value = formatted_value .. (string.rep(" ", 20 - (# name))) end
172 formatted_value = formatted_value .. val .. "\n"
173 end
174 if name == "changelog" then changelog = formatted_value else str = str .. formatted_value end
175 end
176 if nil ~= changelog then str = str .. changelog end
177 return (str .. "manifest:\n" .. t["manifest"])
178end
179
180function make_subject_line(t)
181 local str = ""
182 for j,val in pairs(t["certs"]["branch"]) do
183 str = str .. val
184 if j < # t["certs"]["branch"] then str = str .. ", " end
185 end
186 return str .. ": " .. t["revision"]
187end
188
189function table.print(T)
190 local done = {}
191 local function tprint_r(T, prefix)
192 for k,v in pairs(T) do
193 print(prefix..tostring(k),'=',tostring(v))
194 if type(v) == 'table' then
195 if not done[v] then
196 done[v] = true
197 tprint_r(v, prefix.." ")
198 end
199 end
200 end
201 end
202 done[T] = true
203 tprint_r(T, "")
204end

Archive Download this file

Branches

Tags

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