Fixed up to work with mod_caml 1.3.0-2.
[cocanwiki.git] / scripts / cocanwiki_diff.ml
1 (* COCANWIKI - a wiki written in Objective CAML.
2  * Written by Richard W.M. Jones <rich@merjis.com>.
3  * Copyright (C) 2004 Merjis Ltd.
4  * $Id: cocanwiki_diff.ml,v 1.4 2004/09/20 10:56:47 rich Exp $
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; see the file COPYING.  If not, write to
18  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  *)
21
22 open Apache
23 open Registry
24 open Cgi
25 open Printf
26
27 open Cocanwiki_files
28
29 (* Convenience code for generating diffs between versions.  See diff.ml
30  * and edit.ml which both use this code.
31  *)
32 let page_for_diff css sections =
33   (String.concat ""
34      (List.map (fun (sectionname, content) ->
35                   "HEADING: " ^ sectionname ^ "\n\n" ^
36                   content ^ "\n\n") sections)) ^
37   "CSS:\n\n" ^ css
38
39 let diff_cmd old_page new_page =
40   let new_filename = output_tempfile new_page in
41   let old_filename = output_tempfile old_page in
42
43   let cmd = sprintf "diff -u %s %s ||:" old_filename new_filename in
44   let diff = pget cmd in
45
46   let diff =
47     match diff with
48         _ :: _ :: diff -> diff
49       | diff -> diff in
50
51   unlink new_filename; unlink old_filename;
52   String.concat "\n" diff
53
54 let get_version_for_diff (dbh : Dbi.connection) version =
55   if version = 0 then "" else (
56     let sth = dbh#prepare_cached "select coalesce (css, '') as css
57                                     from pages where id = ?" in
58     sth#execute [`Int version];
59
60     let css = sth#fetch1string () in
61
62     let sth = dbh#prepare_cached "select coalesce (sectionname, ''), content
63                                     from contents where pageid = ?
64                                    order by ordering" in
65     sth#execute [`Int version];
66
67     let sections =
68       sth#map (function
69                    [`String sectionname; `String content] ->
70                      sectionname, content
71                  | _ -> assert false) in
72     let page = page_for_diff css sections in
73
74     page
75   )
76
77 let get_diff (dbh : Dbi.connection) hostid page ?old_version ~version () =
78   let old_version =
79     match old_version with
80       | Some version -> version
81       | None ->
82           let sth = dbh#prepare_cached "select id from pages
83                                          where hostid = ?
84                                            and url_deleted = ? and id < ?
85                                          order by 1 desc limit 1" in
86           sth#execute [`Int hostid; `String page; `Int version];
87
88           try sth#fetch1int ()
89           with Not_found -> 0 in
90
91   (* Get the two versions. *)
92   let new_page = get_version_for_diff dbh version in
93   let old_page = get_version_for_diff dbh old_version in
94
95   (* Compute the diff of the two versions. *)
96   let diff = diff_cmd old_page new_page in
97   diff, old_version