X-Git-Url: http://git.annexia.org/?a=blobdiff_plain;f=goaljobs.ml;h=1aa8c0d9fd9562ba52aa04a3ea7d540c15248ccf;hb=7967057ada774e1b953de38a8d73f6009ce602ef;hp=282c29e982ce445ca8c4c56cf074f5b20ee89cf8;hpb=b71fd4c0029678140d2496ac52f7b79f1ad96fe1;p=goaljobs.git diff --git a/goaljobs.ml b/goaljobs.ml index 282c29e..1aa8c0d 100644 --- a/goaljobs.ml +++ b/goaljobs.ml @@ -19,6 +19,11 @@ open Unix open Printf +open Goaljobs_config + +let (//) = Filename.concat +let quote = Filename.quote + type goal_result_t = Goal_OK | Goal_failed of string exception Goal_result of goal_result_t @@ -60,7 +65,44 @@ let more_recent objs srcs = ) 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 = @@ -128,6 +170,11 @@ let memory_set = Hashtbl.replace memory 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 @@ -149,8 +196,79 @@ let goal_url_exists url = 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 [] + +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"