Module Genspio.EDSL
type 'a t
= 'a Language.t
The type of a Genspio expression.
type str
= Language.byte_array
Type to encode arbitrary byte-arrays in the EDSL as
str t
values, OCaml literal strings or the outputs (as instdout
) of processes are byte-arrays.NUL-terminated “C-like” strings are encoded at a lower level than this EDSL (as
c_string t
values). C-strings cannot contain the'\x00'
character. The command line arguments of commands as well as the contents of environment variables must be C-strings. Genspio treats them properly by failing when a wrong byte-array needs to be converted to a C-string.
Literals
Comments
Basic system Commands
val call : str t list -> unit t
Call a command from its list of “arguments” (including the first argument being the actual command).
val exec : string list -> unit t
Like
call
but with string literals; i.e.exec ["a"; "b"]
is actuallycall [string "a"; string "b"]
which is the usual shell command"a b"
(with proper escaping).
val getenv : str t -> str t
Get the value of an environment variable as a string; it returns the empty string when the variable is not defined. If the argument is not a valid variable name, behavior is undefined.
val setenv : var:str t -> str t -> unit t
Set the value of an environment variable as a string; it returns the empty string is the variable is not defined.
If the
~var
argument is not a valid variable name or if the value does not fit in a shell variable (e.g. newlines), behavior is undefined.Also, the total environment of a UNIX process counts towards the total size of the arguments passed on to a sub-process (see usually the result of
"getconf ARG_MAX"
). Genspio does not check for that limit which is not that high in some operating systems (e.g. about 200 KiB on the MacOSX Sierra that the Travis CI runs …). You might prefer putting or accumulating things in atmp_file
.
Boolean Expressions
val (&&&) : bool t -> bool t -> bool t
val (|||) : bool t -> bool t -> bool t
val not : bool t -> bool t
val returns : 'a t -> value:int -> bool t
Check the return value of a command/expression/script.
val file_exists : str t -> bool t
Check whether a file exists, i.e. a shortcut for
call [str "test"; str "-f"; path] |> succeeds
.
module Bool : sig ... end
Conversions of the
bool t
type.
Integer Arithmetic
module Integer : sig ... end
Functions on
int t
values (arithmetic, comparisons, conversions, etc.).
EDSL Lists
module Elist : sig ... end
Functions on
'a list t
values.
String Manipulation
module Str : sig ... end
Control Flow
val nop : unit t
The silent “no-operation.”
val if_then_else : bool t -> unit t -> unit t -> unit t
val if_then : bool t -> unit t -> unit t
val seq : unit t list -> unit t
Sequence a list of expressions into an expression.
Switch Statements
val switch : [ `Case of bool t * unit t | `Default of unit t ] list -> unit t
Create a switch statement from a list of
case
and optionally adefault
(the function raises an exception if there are more than one default cases).
Redirections and File Descriptors
val to_fd : int t -> int t -> fd_redirection
Create a file-descriptor to file-descriptor redirection.
val to_file : int t -> str t -> fd_redirection
Create a file-descriptor to file redirection.
val with_redirections : unit t -> fd_redirection list -> unit t
Run a
unit t
expression after applying a list of file-descriptor redirections.The redirections are applied in the list's order (which means they can be more easily followed in reverse order), see the “Arbitrary Redirections” example.
Invalid cases, like redirecting to a file-descriptor has not been opened, lead to undefined behavior; see issue #41. If the shell is POSIX, the whole expression
with_redirections expr redirs
exits and its return value is in[1, 125]
; if the shell is"bash"
or"zsh"
, the failing redirection is just ignored andexpr
is executed with the remaining redirections if any.
val write_output : ?stdout:str t -> ?stderr:str t -> ?return_value:str t -> unit t -> unit t
Redirect selected streams or the return value to files (
stdout
,stderr
,return_value
are paths).
val write_stdout : path:str t -> unit t -> unit t
write_stdout ~path expr
iswrite_output expr ~stdout:path
.
val pipe : unit t list -> unit t
Pipe commands together (
"stdout"
into"stdin"
exactly like the" | "
operator).
val get_stdout : unit t -> str t
Get the contents of
stdout
into a byte array (in previous versions this function was calledoutput_as_string
).
val feed : string:str t -> unit t -> unit t
Feed some content (
~string
) into the"stdin"
filedescriptor of aunit t
expression.
Escaping The Execution Flow
val fail : string -> unit t
Expression that aborts the whole script/command immediately, it will try to output its argument to
stderr
(but this may be silent depending on the redirections active at a given time).
Temporary Files
type file
= < get : str t; set : str t -> unit t; append : str t -> unit t; delete : unit t; path : str t; >
Abstraction of a file, cf.
tmp_file
.
val tmp_file : ?tmp_dir:str t -> string -> file
Create a temporary file that may contain arbitrary strings (can be used as variable containing
string t
values).tmp_file "foo"
points to a path that is a function of the string"foo"
; it does not try to make temporary-files unique, on the contrary: two calls totmp_file "foo"
ensure that it is the same file.
Command Line Parsing
module Command_line : sig ... end
Typed command-line parsing for your shell scripts, à la
Printf
.scanf.
Additional Higher-Level Utilities
val loop_until_true : ?attempts:int -> ?sleep:int -> ?on_failed_attempt:(int t -> unit t) -> bool t -> bool t
loop_until_true eval_condition
tries to runeval_condition
in a loop until it succeeds. It makes~attempts
attemps (default 20), and sleeps forsleep
seconds (default 2) after each failed attempt. The argument~on_failed_attempt
can be used for instance to display something between each failed attempt and the call tosleep
, the default isfun nth -> printf (string "%d.") [Integer.to_string nth]
.
val silently : unit t -> unit t
silently expr
isexpr
withstdout
andstderr
redirected to"/dev/null"
.
val seq_and : 'a t list -> bool t
seq_and [a; b; c]
is likesucceeds a &&& succeeds b &&& succeeds c
.
val output_markdown_code : string -> unit t -> unit t
output_markdown_code "ocaml" (exec ["echo"; "let x = 42"])
runs its second argument within markdown-like code fences.
val cat_markdown : string -> str t -> unit t
cat_markdown tag path
outputs the contents of the file atpath
(with"cat"
) within a markdown code bloc.
val check_sequence : ?verbosity:[ `Announce of string | `Output_all | `Silent ] -> ?on_failure:(step:(string * unit t) -> stdout:str t -> stderr:str t -> unit t) -> ?on_success:(step:(string * unit t) -> stdout:str t -> stderr:str t -> unit t) -> ?tmpdir:string -> (string * unit t) list -> unit t
Run a sequence of expressions until the first that fails:
?verbosity
configures the output behavior,`Announce prompt
usesprompt
to output the name-tag of the command, the output of the command is redirected to temporary files (accessible through the~on_success
and~on_failure
functions). The default value is`Announce ">> "
.`Output_all
lets all the output of the commands go through.`Silent
is like`Announce _
but without even the “prompt” command annoucement.
?on_failure
configures what to do when encountering the first failure, the default is to display on stdout the name-tag of the failing command and outputting the contents of itsstdout
andstderr
log-files (if any) and then callexec ["false"]
.?on_success
is a similar function as?on_failure
, called before starting the next command, the default is to do nothing.?tmpdir
configures where to create the logging files.
val on_stdin_lines : (str t -> unit t) -> unit t
on_stdin_lines body
builds a loop that iterates over the lines of thestdin
file descriptor. The argument of `body` is the current line. Note that this is for text-like input,'\000'
characters in the input lead to undefined behavior.
val command_available : str t -> bool t
Call
"command -v"
to know if an executable is in"$PATH"
(note that"which"
is not POSIX, we use"command -v ..."
which is expected to return a failure if the command is not found).
val get_stdout_one_line : ?first_line:bool -> ?remove_spaces:bool -> unit t -> str t
Get the output of a command as a string without new lines, potentially cutting at the first line:
get_stdout ( (if first_line then u ||> exec ["head"; "-n"; "1"] else u) ||> exec ["tr"; "-d"; (if remove_spaces then " \\n" else "\\n")] )
val verbose_call : ?prefix:string -> ?verbose:bool t -> str t list -> unit t
Like
call
but print onstderr
the command being run.
val check_sequence_with_output : unit t list -> unit t
A shortcut for
check_sequence
with~verbosity:`Output_all
hence ignoring the “names” of the commands.
val exit : int -> unit t
Call
"exit ..."
, warning: depending on the compiler, the call maybe nested in various sub-shells, to really exit a script usefail
.
val ensure : string -> condition:bool t -> how:(string * unit t) list -> unit t
Ensure a
condition
:- Test the condition.
- If
true
do nothing, succeed - If
false
, run~how
withcheck_sequence
. - Test the condition again, if
true
succeed, iffalse
fail.
Failures happen thanks to the !
fail
call.
val greps_to : ?extended_re:bool -> str t -> unit t -> bool t
Test a string or regular expression again the output of an expression.
val pager : ?file_descriptor:str t -> ?disable:bool t -> ?default_command:unit t -> unit -> unit t
“Smart pager” command to pipe long outputs through, conditions are tested in this order:
- If
~disable
is provided it can be used to make the pager behave like"cat"
. - If the
~file_descriptor
(defaultstr "1"
) is not a terminal, the command will be"cat"
too. - If the environment variable
"PAGER"
it will be used as a shell command ("sh -c .."
). - The last resort default is
~default_command
(which by default value isexec ["more"]
).
- If
module Script_with_describe : functor (P : sig ... end) -> sig ... end
Make scripts that provide a
"--describe"
option/command.
module Dispatcher_script : sig ... end
Create a script that mostly behaves like
"git"
, it concatenates its name with its first argument to call"${0}-${1}"
.