*
* Use 'copy_host --help' for usage.
*
- * $Id: copy_host.ml,v 1.3 2006/09/11 10:01:07 rich Exp $
+ * $Id: copy_host.ml,v 1.4 2006/12/11 15:28:50 rich Exp $
*)
open Printf
Copy a host from the local database server to another. The copy
will have the same canonical and alternate hostnames:
- copy_host -short mysite.example.com -ddbhost anotherdb.example.com
+ copy_host -shost mysite.example.com -ddbhost anotherdb.example.com
TERMINOLOGY
or '-ddb***' parameters, but instead use environment variables,
or run this program on the database server itself.
+TESTING
+
+Use -dryrun as a parameter to test the copy. This does everything
+and then rolls back the database at the end.
+
+STAGING SERVER
+
+It is possible to use this script to implement a staging server.
+
+The basic setup is that you have two hosts (called for example
+'staging.example.com' and 'www.example.com' where the latter
+is the live site). Create the staging host first (or use
+copy_host to duplicate it from the live host if you already
+have one). Do all editing on the staging server.
+
+When you are satisfied with the state of the staging server
+and are ready to go live, use the following command:
+
+ copy_host -shost staging.example.com -dhost www.example.com,example.com \
+ -overwrite -disableedit -enableviewanon
+
+The key options to take note of are:
+
+ -overwrite If the dhost already exists, it can be overwritten.
+ (In fact what happens is that the existing destination
+ host is renamed to a unique name like 'deleted-<timestamp>')
+
+ -disableedit This disables the editing capability of all users on
+ the destination host. This stops users from accidentally
+ editing the live site.
+
+ -enableviewanon This enables anonymous viewing on the destination
+ host (assuming that the staging server is configured to
+ only allow logged in users to view, which is usually the
+ right thing to do).
+
OPTIONS
"
let sdbdatabase = ref "cocanwiki"
let ddbdatabase = ref "cocanwiki"
let dryrun = ref false
+let overwrite = ref false
+let disableedit = ref false
+let enableviewanon = ref false
let argspec = [
"-shost", Arg.Set_string shost,
"Destination database name (default: cocanwiki).";
"-dryrun", Arg.Set dryrun,
"Rollback database changes at the end.";
+ "-overwrite", Arg.Set overwrite,
+ "Allow the destination host to be overwritten.";
+ "-disableedit", Arg.Set disableedit,
+ "Disable users.can_edit on the destination host.";
+ "-enableviewanon", Arg.Set enableviewanon,
+ "Enable hosts.view_anon on the destination host.";
]
let error _ = raise (Arg.Bad "Use --help for help.")
let sdbdatabase = match !sdbdatabase with "" -> None | s -> Some s
let ddbdatabase = match !ddbdatabase with "" -> None | s -> Some s
let dryrun = !dryrun
+let overwrite = !overwrite
+let disableedit = !disableedit
+let enableviewanon = !enableviewanon
(* Get column names from a table. *)
let columns dbh table_name =
let i = Int32.to_string i in
Some i
+let value_of_bool b =
+ let b = string_of_bool b in
+ Some b
+
let () =
print_endline "Connecting to databases ...";
print_endline " Source ...";
| [] -> scanonical_hostname, shostnames
| x :: xs -> x, (x :: xs) in
+ (* Does the destination host already exist? *)
+ let dhost_exists, old_dhostid =
+ let rows =
+ PGSQL(ddbh)
+ "select hostid from hostnames where name = $dcanonical_hostname" in
+ match rows with
+ | [dhostid] -> true, dhostid
+ | _ -> false, (-1_l) in
+ if dhost_exists then (
+ if overwrite then (
+ (* Rename the destination host. *)
+ let name = sprintf "deleted-%g" (Unix.time ()) in
+
+ printf "Renaming old host %s to %s\n%!" dcanonical_hostname name;
+
+ PGSQL(ddbh)
+ "update hosts set canonical_hostname = $name where id = $old_dhostid";
+ PGSQL(ddbh)
+ "delete from hostnames where hostid = $old_dhostid";
+ PGSQL(ddbh)
+ "insert into hostnames (hostid, name) values ($old_dhostid, $name)";
+ ) else
+ failwith "Destination host exists. Did you mean to use -overwrite?"
+ );
+
print_endline "Create new host ...";
let columns, rows =
(Some dcanonical_hostname) in
assert (List.length columns = nr_columns - 1);
assert (List.length rows = 1);
+ let columns, rows =
+ if enableviewanon then
+ update_column columns rows "view_anon" (value_of_bool true)
+ else
+ columns, rows in
let serials = insert_serial ddbh "hosts" columns rows "id" in
assert (List.length serials = 1);
let dhostid = List.hd serials in
remove_column columns rows "id" in
let columns, rows =
update_column columns rows "hostid" (value_of_int32 dhostid) in
+ let columns, rows =
+ if disableedit then
+ update_column columns rows "can_edit" (value_of_bool false)
+ else
+ columns, rows in
let new_ids =
insert_serial ddbh "users" columns rows "id" in