monotone

monotone Mtn Source Tree

Root/std_hooks.lua

1
2-- this is the standard set of lua hooks for monotone;
3-- user-provided files can override it or add to it.
4
5function temp_file()
6 local tdir
7 tdir = os.getenv("TMPDIR")
8 if tdir == nil then tdir = os.getenv("TMP") end
9 if tdir == nil then tdir = os.getenv("TEMP") end
10 if tdir == nil then tdir = "/tmp" end
11 return mkstemp(string.format("%s/mt.XXXXXX", tdir))
12end
13
14function execute(path, ...)
15 local pid
16 local ret = -1
17 pid = spawn(path, unpack(arg))
18 ret, pid = wait(pid)
19 return ret
20end
21
22
23
24-- attributes are persistent metadata about files (such as execute
25-- bit, ACLs, various special flags) which we want to have set and
26-- re-set any time the files are modified. the attributes themselves
27-- are stored in a file .mt-attrs, in the working copy (and
28-- manifest). each (f,k,v) triple in an atribute file turns into a
29-- call to attr_functions[k](f,v) in lua.
30
31if (attr_functions == nil) then
32 attr_functions = {}
33end
34
35
36attr_functions["execute"] =
37 function(filename, value)
38 if (value == "true") then
39 make_executable(filename)
40 end
41 end
42
43
44function ignore_file(name)
45 if (string.find(name, "%.a$")) then return true end
46 if (string.find(name, "%.so$")) then return true end
47 if (string.find(name, "%.o$")) then return true end
48 if (string.find(name, "%.la$")) then return true end
49 if (string.find(name, "%.lo$")) then return true end
50 if (string.find(name, "%.aux$")) then return true end
51 if (string.find(name, "%.bak$")) then return true end
52 if (string.find(name, "%.orig$")) then return true end
53 if (string.find(name, "%.rej$")) then return true end
54 if (string.find(name, "%~$")) then return true end
55 if (string.find(name, "/core$")) then return true end
56 if (string.find(name, "^CVS/")) then return true end
57 if (string.find(name, "/CVS/")) then return true end
58 if (string.find(name, "^%.svn/")) then return true end
59 if (string.find(name, "/%.svn/")) then return true end
60 if (string.find(name, "^SCCS/")) then return true end
61 if (string.find(name, "/SCCS/")) then return true end
62 return false;
63end
64
65
66function edit_comment(basetext, user_log_message)
67 local exe = "vi"
68 local visual = os.getenv("VISUAL")
69 if (visual ~= nil) then exe = visual end
70 local editor = os.getenv("EDITOR")
71 if (editor ~= nil) then exe = editor end
72
73 local tmp, tname = temp_file()
74 if (tmp == nil) then return nil end
75 basetext = "MT: " .. string.gsub(basetext, "\n", "\nMT: ") .. "\n"
76 tmp:write(user_log_message)
77 tmp:write(basetext)
78 io.close(tmp)
79
80 if (execute(exe, tname) ~= 0) then
81 os.remove(tname)
82 return nil
83 end
84
85 tmp = io.open(tname, "r")
86 if (tmp == nil) then os.remove(tname); return nil end
87 local res = ""
88 local line = tmp:read()
89 while(line ~= nil) do
90 if (not string.find(line, "^MT:")) then
91 res = res .. line .. "\n"
92 end
93 line = tmp:read()
94 end
95 io.close(tmp)
96 os.remove(tname)
97 return res
98end
99
100
101function non_blocking_rng_ok()
102 return true
103end
104
105
106function persist_phrase_ok()
107 return true
108end
109
110-- trust evaluation hooks
111
112function intersection(a,b)
113 local s={}
114 local t={}
115 for k,v in pairs(a) do s[v] = 1 end
116 for k,v in pairs(b) do if s[v] ~= nil then table.insert(t,v) end end
117 return t
118end
119
120function get_revision_cert_trust(signers, id, name, val)
121 return true
122end
123
124function get_manifest_cert_trust(signers, id, name, val)
125 return true
126end
127
128function get_file_cert_trust(signers, id, name, val)
129 return true
130end
131
132function accept_testresult_change(old_results, new_results)
133 for test,res in pairs(old_results)
134 do
135 if res == true and new_results[test] ~= true
136 then
137 return false
138 end
139 end
140 return true
141end
142
143-- merger support
144
145function merge2_meld_cmd(lfile, rfile)
146 return
147 function()
148 return execute("meld", lfile, rfile)
149 end
150end
151
152function merge3_meld_cmd(lfile, afile, rfile)
153 return
154 function()
155 return execute("meld", lfile, afile, rfile)
156 end
157end
158
159
160function merge2_vim_cmd(vim, lfile, rfile, outfile)
161 return
162 function()
163 return execute(vim, "-f", "-d", "-c", string.format("file %s", outfile),
164 lfile, rfile)
165 end
166end
167
168function merge3_vim_cmd(vim, lfile, afile, rfile, outfile)
169 return
170 function()
171 return execute(vim, "-f", "-d", "-c", string.format("file %s", outfile),
172 lfile, afile, rfile)
173 end
174end
175
176function merge2_emacs_cmd(emacs, lfile, rfile, outfile)
177 local elisp = "(ediff-merge-files \"%s\" \"%s\" nil \"%s\")"
178 return
179 function()
180 return execute(emacs, "-no-init-file", "-eval",
181 string.format(elisp, lfile, rfile, outfile))
182 end
183end
184
185function merge3_emacs_cmd(emacs, lfile, afile, rfile, outfile)
186 local elisp = "(ediff-merge-files-with-ancestor \"%s\" \"%s\" \"%s\" nil \"%s\")"
187 local cmd_fmt = "%s -no-init-file -eval " .. elisp
188 return
189 function()
190 execute(emacs, "-no-init-file", "-eval",
191 string.format(elisp, lfile, rfile, afile, outfile))
192 end
193end
194
195function merge2_xxdiff_cmd(left_path, right_path, merged_path, lfile, rfile, outfile)
196 return
197 function()
198 return execute("xxdiff",
199 "--title1", left_path,
200 "--title2", right_path,
201 lfile, rfile,
202 "--merged-filename", outfile)
203 end
204end
205
206function merge3_xxdiff_cmd(left_path, anc_path, right_path, merged_path,
207 lfile, afile, rfile, outfile)
208 return
209 function()
210 return execute("xxdiff",
211 "--title1", left_path,
212 "--title2", right_path,
213 "--title3", merged_path,
214 lfile, afile, rfile,
215 "--merge",
216 "--merged-filename", outfile)
217 end
218end
219
220function write_to_temporary_file(data)
221 tmp, filename = temp_file()
222 if (tmp == nil) then
223 return nil
224 end;
225 tmp:write(data)
226 io.close(tmp)
227 return filename
228end
229
230function read_contents_of_file(filename)
231 tmp = io.open(filename, "r")
232 if (tmp == nil) then
233 return nil
234 end
235 local data = tmp:read("*a")
236 io.close(tmp)
237 return data
238end
239
240function program_exists_in_path(program)
241 return existsonpath(program) == 0
242end
243
244function merge2(left_path, right_path, merged_path, left, right)
245 local lfile = nil
246 local rfile = nil
247 local outfile = nil
248 local data = nil
249 local meld_exists = false
250
251 lfile = write_to_temporary_file(left)
252 rfile = write_to_temporary_file(right)
253 outfile = write_to_temporary_file("")
254
255 if lfile ~= nil and
256 rfile ~= nil and
257 outfile ~= nil
258 then
259 local cmd = nil
260 if program_exists_in_path("meld") then
261 meld_exists = true
262 io.write(string.format("\nWARNING: 'meld' was choosen to perform external 2-way merge.\n" ..
263 "You should merge all changes to *LEFT* file due to limitation of program\n" ..
264 "arguments.\n\n"))
265 cmd = merge2_meld_cmd(lfile, rfile)
266 elseif program_exists_in_path("xxdiff") then
267 cmd = merge2_xxdiff_cmd(left_path, right_path, merged_path,
268 lfile, rfile, outfile)
269 elseif program_exists_in_path("emacs") then
270 cmd = merge2_emacs_cmd("emacs", lfile, rfile, outfile)
271 elseif program_exists_in_path("xemacs") then
272 cmd = merge2_emacs_cmd("xemacs", lfile, rfile, outfile)
273 elseif os.getenv("DISPLAY") ~=nil and program_exists_in_path("gvim") then
274 cmd = merge2_vim_cmd("gvim", lfile, rfile, outfile)
275 elseif program_exists_in_path("vim") then
276 cmd = merge2_vim_cmd("vim", lfile, rfile, outfile)
277 end
278
279 if cmd ~= nil
280 then
281 io.write(string.format("executing external 2-way merge command\n"))
282 cmd()
283 if meld_exists then
284 data = read_contents_of_file(lfile)
285 else
286 data = read_contents_of_file(outfile)
287 end
288 if string.len(data) == 0
289 then
290 data = nil
291 end
292 else
293 io.write("no external 2-way merge command found\n")
294 end
295 end
296
297 os.remove(lfile)
298 os.remove(rfile)
299 os.remove(outfile)
300
301 return data
302end
303
304function merge3(anc_path, left_path, right_path, merged_path, ancestor, left, right)
305 local afile = nil
306 local lfile = nil
307 local rfile = nil
308 local outfile = nil
309 local data = nil
310 local meld_exists = false
311
312 lfile = write_to_temporary_file(left)
313 afile = write_to_temporary_file(ancestor)
314 rfile = write_to_temporary_file(right)
315 outfile = write_to_temporary_file("")
316
317 if lfile ~= nil and
318 rfile ~= nil and
319 afile ~= nil and
320 outfile ~= nil
321 then
322 local cmd = nil
323 if program_exists_in_path("meld") then
324 meld_exists = true
325 io.write(string.format("\nWARNING: 'meld' was choosen to perform external 3-way merge.\n" ..
326 "You should merge all changes to *CENTER* file due to limitation of program\n" ..
327 "arguments.\n\n"))
328 cmd = merge3_meld_cmd(lfile, afile, rfile)
329 elseif program_exists_in_path("xxdiff") then
330 cmd = merge3_xxdiff_cmd(left_path, anc_path, right_path, merged_path,
331 lfile, afile, rfile, outfile)
332 elseif program_exists_in_path("emacs") then
333 cmd = merge3_emacs_cmd("emacs", lfile, afile, rfile, outfile)
334 elseif program_exists_in_path("xemacs") then
335 cmd = merge3_emacs_cmd("xemacs", lfile, afile, rfile, outfile)
336 elseif os.getenv("DISPLAY") ~=nil and program_exists_in_path("gvim") then
337 cmd = merge3_vim_cmd("gvim", lfile, afile, rfile, outfile)
338 elseif program_exists_in_path("vim") then
339 cmd = merge3_vim_cmd("vim", lfile, afile, rfile, outfile)
340 end
341
342 if cmd ~= nil
343 then
344 io.write(string.format("executing external 3-way merge command\n"))
345 cmd()
346 if meld_exists then
347 data = read_contents_of_file(afile)
348 else
349 data = read_contents_of_file(outfile)
350 end
351 if string.len(data) == 0
352 then
353 data = nil
354 end
355 else
356 io.write("no external 3-way merge command found\n")
357 end
358 end
359
360 os.remove(lfile)
361 os.remove(rfile)
362 os.remove(afile)
363 os.remove(outfile)
364
365 return data
366end
367
368
369-- expansion of values used in selector completion
370
371function expand_selector(str)
372
373 -- simple date patterns
374 if string.find(str, "^19%d%d%-%d%d")
375 or string.find(str, "^20%d%d%-%d%d")
376 then
377 return ("d:" .. str)
378 end
379
380 -- something which looks like an email address
381 if string.find(str, "[%w%-_]+@[%w%-_]+")
382 then
383 return ("a:" .. str)
384 end
385
386 -- something which looks like a branch name
387 if string.find(str, "[%w%-]+%.[%w%-]+")
388 then
389 return ("b:" .. str)
390 end
391
392 -- a sequence of nothing but hex digits
393 if string.find(str, "^%x+$")
394 then
395 return ("i:" .. str)
396 end
397
398 -- "yesterday", the source of all hangovers
399 if str == "yesterday"
400 then
401 local t = os.time(os.date('!*t'))
402 return os.date("d:%F", t - 86400)
403 end
404
405 -- "CVS style" relative dates such as "3 weeks ago"
406 local trans = {
407 minute = 60;
408 hour = 3600;
409 day = 86400;
410 week = 604800;
411 month = 2678400;
412 year = 31536000
413 }
414 local pos, len, n, type = string.find(str, "(%d+) ([minutehordaywk]+)s? ago")
415 if trans[type] ~= nil
416 then
417 local t = os.time(os.date('!*t'))
418 return os.date("d:%F", t - (n * trans[type]))
419 end
420
421 return nil
422end

Archive Download this file

Branches

Tags

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