| rev | line source | 
| bsw@2 | 1 slot.put_into("title", _"Diff") | 
| bsw@2 | 2 | 
| bsw@2 | 3 local old_draft_id = param.get("old_draft_id", atom.integer) | 
| bsw@2 | 4 local new_draft_id = param.get("new_draft_id", atom.integer) | 
| bsw@2 | 5 | 
| bsw@10 | 6 if not old_draft_id or not new_draft_id then | 
| bsw@10 | 7   slot.put( _"Please choose two versions of the draft to compare") | 
| bsw@10 | 8   return | 
| bsw@10 | 9 end | 
| bsw@10 | 10 | 
| bsw@10 | 11 if old_draft_id == new_draft_id then | 
| bsw@10 | 12   slot.put( _"Please choose two different versions of the draft to compare") | 
| bsw@10 | 13   return | 
| bsw@10 | 14 end | 
| bsw@10 | 15 | 
| bsw@2 | 16 if old_draft_id > new_draft_id then | 
| bsw@2 | 17   local tmp = old_draft_id | 
| bsw@2 | 18   old_draft_id = new_draft_id | 
| bsw@2 | 19   new_draft_id = tmp | 
| bsw@2 | 20 end | 
| bsw@2 | 21 | 
| bsw@2 | 22 local old_draft = Draft:by_id(old_draft_id) | 
| bsw@2 | 23 local new_draft = Draft:by_id(new_draft_id) | 
| bsw@2 | 24 | 
| bsw@2 | 25 local key = multirand.string(26, "123456789bcdfghjklmnpqrstvwxyz"); | 
| bsw@2 | 26 | 
| bsw@2 | 27 local old_draft_filename = encode.file_path(request.get_app_basepath(), 'tmp', "diff-" .. key .. "-old.tmp") | 
| bsw@2 | 28 local new_draft_filename = encode.file_path(request.get_app_basepath(), 'tmp', "diff-" .. key .. "-new.tmp") | 
| bsw@2 | 29 | 
| bsw@2 | 30 local old_draft_file = assert(io.open(old_draft_filename, "w")) | 
| bsw@2 | 31 old_draft_file:write(old_draft.content) | 
| bsw@2 | 32 old_draft_file:write("\n") | 
| bsw@2 | 33 old_draft_file:close() | 
| bsw@2 | 34 | 
| bsw@2 | 35 local new_draft_file = assert(io.open(new_draft_filename, "w")) | 
| bsw@2 | 36 new_draft_file:write(new_draft.content) | 
| bsw@2 | 37 new_draft_file:write("\n") | 
| bsw@2 | 38 new_draft_file:close() | 
| bsw@2 | 39 | 
| bsw@2 | 40 local output, err, status = os.pfilter(nil, "sh", "-c", "diff -U 100000 '" .. old_draft_filename .. "' '" .. new_draft_filename .. "' | grep -v ^--- | grep -v ^+++ | grep -v ^@") | 
| bsw@2 | 41 | 
| bsw@2 | 42 os.remove(old_draft_filename) | 
| bsw@2 | 43 os.remove(new_draft_filename) | 
| bsw@2 | 44 | 
| bsw@2 | 45 if not status then | 
| bsw@2 | 46   ui.field.text{ value = _"The drafts do not differ" } | 
| bsw@2 | 47 else | 
| bsw@2 | 48   slot.put('<table class="diff">') | 
| bsw@2 | 49   slot.put('<tr><th width="50%">' .. _"Old draft revision" .. '</th><th width="50%">' .. _"New draft revision" .. '</th></tr>') | 
| bsw@39 | 50 | 
| bsw@2 | 51   local last_state = "unchanged" | 
| bsw@2 | 52   local lines = {} | 
| bsw@2 | 53   local removed_lines = nil | 
| bsw@39 | 54 | 
| bsw@39 | 55   local function process_line(line) | 
| bsw@2 | 56     local state = "unchanged" | 
| bsw@2 | 57     local char = line:sub(1,1) | 
| bsw@2 | 58     line = line:sub(2) | 
| bsw@2 | 59     state = "unchanged" | 
| bsw@2 | 60     if char == "-" then | 
| bsw@2 | 61       state = "-" | 
| bsw@2 | 62     elseif char == "+" then | 
| bsw@2 | 63       state = "+" | 
| bsw@39 | 64     elseif char == "!" then | 
| bsw@39 | 65       state = "eof" | 
| bsw@2 | 66     end | 
| bsw@2 | 67     if last_state == "unchanged" then | 
| bsw@2 | 68       if state == "unchanged" then | 
| bsw@2 | 69         lines[#lines+1] = line | 
| bsw@39 | 70       elseif (state == "-") or (state == "+") or (state == "eof") then | 
| bsw@39 | 71         local text = table.concat(lines, "\n") | 
| bsw@39 | 72         slot.put("<tr><td>", text, "</td><td>", encode.html_newlines(encode.html(text)), "</td></tr>") | 
| bsw@2 | 73         lines = { line } | 
| bsw@2 | 74       end | 
| bsw@2 | 75     elseif last_state == "-" then | 
| bsw@2 | 76       if state == "-" then | 
| bsw@2 | 77         lines[#lines+1] = line | 
| bsw@2 | 78       elseif state == "+" then | 
| bsw@2 | 79         removed_lines = lines | 
| bsw@2 | 80         lines = { line } | 
| bsw@39 | 81       elseif (state == "unchanged") or (state == "eof") then | 
| bsw@39 | 82         local text = table.concat(lines,"\n") | 
| bsw@39 | 83         slot.put('<tr><td class="removed">', encode.html_newlines(encode.html(text)), "</td><td></td></tr>") | 
| bsw@2 | 84         lines = { line } | 
| bsw@2 | 85       end | 
| bsw@2 | 86     elseif last_state == "+" then | 
| bsw@2 | 87       if state == "+" then | 
| bsw@2 | 88         lines[#lines+1] = line | 
| bsw@39 | 89       elseif (state == "-") or (state == "unchanged") or (state == "eof") then | 
| bsw@2 | 90         if removed_lines then | 
| bsw@39 | 91           local text = table.concat(lines, "\n") | 
| bsw@39 | 92           local removed_text = table.concat(removed_lines, "\n") | 
| bsw@39 | 93           slot.put('<tr><td class="removed">', encode.html_newlines(encode.html(removed_text)), '</td><td class="added">', encode.html_newlines(encode.html(text)), "</td></tr>") | 
| bsw@2 | 94         else | 
| bsw@39 | 95           local text = table.concat(lines, "\n") | 
| bsw@39 | 96           slot.put('<tr><td></td><td class="added">', encode.html_newlines(encode.html(text)), "</td></tr>") | 
| bsw@2 | 97         end | 
| bsw@2 | 98         removed_lines = nil | 
| bsw@2 | 99         lines = { line } | 
| bsw@2 | 100       end | 
| bsw@2 | 101     end | 
| bsw@2 | 102     last_state = state | 
| bsw@39 | 103   end | 
| bsw@39 | 104 | 
| bsw@39 | 105   output = output .. " " | 
| bsw@39 | 106   output = output:gsub("[^\n\r]+", function(line) | 
| bsw@39 | 107     process_line(line) | 
| bsw@2 | 108   end) | 
| bsw@39 | 109   process_line("!") | 
| bsw@39 | 110 | 
| bsw@2 | 111   slot.put("</table>") | 
| bsw@2 | 112 end | 
| bsw@2 | 113 |