open Unix
open Printf
+open Goaljobs_config
+
type goal_result_t = Goal_OK | Goal_failed of string
exception Goal_result of goal_result_t
) objs
)
-let url_exists url = goal_failed "url_exists not implemented!"
+let url_exists url =
+ (* http://stackoverflow.com/questions/12199059/how-to-check-if-an-url-exists-with-the-shell-and-probably-curl *)
+ let cmd =
+ sprintf "curl --output /dev/null --silent --head --fail %s" (quote url) in
+ match Sys.command cmd with
+ | 0 -> true
+ | 1 -> false
+ | r ->
+ let msg = sprintf "curl error testing '%s' (exit code %d)" url r in
+ goal_failed msg
+
+let file_contains_string filename str =
+ let cmd = sprintf "grep -q %s %s" (quote str) (quote filename) in
+ match Sys.command cmd with
+ | 0 -> true
+ | 1 -> false
+ | r ->
+ let msg = sprintf "grep error testing for '%s' in '%s' (exit code %d)"
+ str filename r in
+ goal_failed msg
+
+let url_contains_string url str =
+ let tmp = Filename.temp_file "goaljobsurl" "" in
+ let cmd =
+ sprintf "curl --output %s --silent --fail %s" (quote tmp) (quote url) in
+ (match Sys.command cmd with
+ | 0 -> ()
+ | 1 ->
+ let msg = sprintf "curl failed to download URL '%s'" url in
+ goal_failed msg
+ | r ->
+ let msg = sprintf "curl error testing '%s' (exit code %d)" url r in
+ goal_failed msg
+ );
+ let r = file_contains_string tmp str in
+ unlink tmp;
+ r
+
let sh fs =
let do_sh cmd =
let memory_get k = try Some (Hashtbl.find memory k) with Not_found -> None
let memory_delete = Hashtbl.remove memory
+let published_goals = ref []
+let publish name fn = published_goals := (name, fn) :: !published_goals
+let get_goal name =
+ try Some (List.assoc name !published_goals) with Not_found -> None
+
let goal_file_exists filename =
if not (file_exists filename) then (
let msg = sprintf "file '%s' required but not found" filename in
let msg = sprintf "url_exists: URL '%s' required but does not exist" url in
goal_failed msg
)
+let goal_file_contains_string filename str =
+ if not (file_contains_string filename str) then (
+ let msg = sprintf "file_contains_string: file '%s' is required to contain string '%s'" filename str in
+ goal_failed msg
+ )
+let goal_url_contains_string url str =
+ if not (url_contains_string url str) then (
+ let msg = sprintf "url_contains_string: URL '%s' is required to contain string '%s'" url str in
+ goal_failed msg
+ )
let goal_memory_exists k =
if not (memory_exists k) then (
let msg = sprintf "memory_exists: key '%s' required but does not exist" k in
goal_failed msg
)
+
+(* Run the program. *)
+let init () =
+ let prog = Sys.executable_name in
+ let prog = Filename.basename prog in
+
+ let args = ref [] in
+
+ let display_version () =
+ printf "%s %s\n" package_name package_version;
+ exit 0
+ in
+
+ let list_goals () =
+ let names = !published_goals in
+ let names = List.map fst names in
+ let names = List.sort compare names in
+ List.iter print_endline names
+ in
+
+ let argspec = Arg.align [
+ "--goals", Arg.Unit list_goals, " List all goals";
+ "-l", Arg.Unit list_goals, " List all goals";
+ "-V", Arg.Unit display_version, " Display version number and exit";
+ "--version", Arg.Unit display_version, " Display version number and exit";
+ ] in
+ let anon_fun str = args := str :: !args in
+ let usage_msg = sprintf "\
+%s: a script generated by goaljobs
+
+List all goals: %s -l
+Run a single goal like this: %s <name-of-goal> [<goal-args ...>]
+
+For more information see the goaljobs(1) man page.
+
+Options:
+" prog prog prog in
+
+ Arg.parse argspec anon_fun usage_msg;
+
+ let args = List.rev !args in
+
+ (* Was a goal named on the command line? *)
+ match args with
+ | name :: args ->
+ (match get_goal name with
+ | Some fn -> fn args
+ | None ->
+ eprintf "error: no goal called '%s' was found.\n" name;
+ eprintf "Use %s -l to list all published goals in this script.\n" name;
+ exit 1
+ )
+ | [] ->
+ (* Does a published 'all' goal exist? *)
+ match get_goal "all" with
+ | Some fn -> fn []
+ | None ->
+ (* No published 'all' goal. This is only a warning, because
+ * other top-level code may exist in the script.
+ *)
+ eprintf "warning: no 'all' goal found.\n"