Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ensure timeouts propagate to invocations #11

Merged
merged 1 commit into from
Jan 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 20 additions & 24 deletions examples/ScratchPad.Fs/Program.fs
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,8 @@ let _ = shell {
exec "uname"
}

let a: string list = [""]
temp { run }
temp { run "x" }
temp { run "x" "x" }
temp { run "x" [] }
temp { run "x" a }

let dotnetVersion = exec {
binary "dotnet"
arguments "--help"
filter_output (fun l -> l.Line.Contains "clean")
filter (fun l -> l.Line.Contains "clean")
}

printfn "Found lines %i" dotnetVersion.Length


exec { run "dotnet" "--help"}
exec {
binary "dotnet"
arguments "--help"
Expand All @@ -31,7 +16,7 @@ exec {
send_control_c false
timeout (TimeSpan.FromSeconds(10))
thread_wrap false
validExitCode (fun i -> i <> 0)
validExitCode (fun i -> i = 0)
run
}

Expand All @@ -46,17 +31,28 @@ let helpOutput = exec {
arguments "--help"
output
}
let dotnetVersion = exec {
binary "dotnet"
arguments "--help"
filter_output (fun l -> l.Line.Contains "clean")
filter (fun l -> l.Line.Contains "clean")
}

printfn "Found lines %i" dotnetVersion.Length

let dotnet = exec { binary "dotnet" }

let x = exec {
options dotnet
let dotnetOptions = exec { binary "dotnet" }
exec {
options dotnetOptions
run_args ["restore"; "--help"]
}

let args: string list = [""]
exec { run "dotnet" " "}
let args: string list = ["--help"]
exec { run "dotnet" "--help"}
exec { run "dotnet" args }

let _ = shell { exec "dotnet" a }
let statusCode = exec { exit_code_of "dotnet" " "}
let _ = shell { exec "dotnet" args }
let statusCode = exec { exit_code_of "dotnet" "--help"}


printfn "That's all folks!"
69 changes: 23 additions & 46 deletions src/Proc.Fs/Bindings.fs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ type ExecOptions = {
WorkingDirectory: string option
Environment: Map<string, string> option

Timeout: TimeSpan option

Timeout: TimeSpan
ValidExitCodeClassifier: (int -> bool) option

NoWrapInThread: bool option
Expand All @@ -25,13 +24,14 @@ with
{
Binary = ""; Arguments = None; Find = None;
LineOutFilter = None; WorkingDirectory = None; Environment = None
Timeout = None
Timeout = TimeSpan(0, 0, 0, 0, -1)
ValidExitCodeClassifier = None;
NoWrapInThread = None; SendControlCFirst = None; WaitForStreamReadersTimeout = None;
}

let private startArgs (opts: ExecOptions) =
let startArguments = StartArguments(opts.Binary, opts.Arguments |> Option.defaultValue [])
let args = opts.Arguments |> Option.defaultValue []
let startArguments = StartArguments(opts.Binary, args)
opts.LineOutFilter |> Option.iter(fun f -> startArguments.LineOutFilter <- f)
opts.Environment |> Option.iter(fun e -> startArguments.Environment <- e)
opts.WorkingDirectory |> Option.iter(fun d -> startArguments.WorkingDirectory <- d)
Expand All @@ -41,7 +41,8 @@ let private startArgs (opts: ExecOptions) =
startArguments

let private execArgs (opts: ExecOptions) =
let execArguments = ExecArguments(opts.Binary, opts.Arguments |> Option.defaultValue [])
let args = opts.Arguments |> Option.defaultValue []
let execArguments = ExecArguments(opts.Binary, args)
opts.Environment |> Option.iter(fun e -> execArguments.Environment <- e)
opts.WorkingDirectory |> Option.iter(fun d -> execArguments.WorkingDirectory <- d)
opts.ValidExitCodeClassifier |> Option.iter(fun f -> execArguments.ValidExitCodeClassifier <- f)
Expand All @@ -62,7 +63,7 @@ type ShellBuilder() =

[<CustomOperation("timeout")>]
member inline this.Timeout(opts, timeout) =
{ opts with Timeout = Some timeout }
{ opts with Timeout = timeout }

[<CustomOperation("stream_reader_wait_timeout")>]
member inline this.WaitForStreamReadersTimeout(opts, timeout) =
Expand All @@ -80,43 +81,19 @@ type ShellBuilder() =
member this.ExecuteWithArguments(opts, binary, [<ParamArray>] args: string array) =
let opts = { opts with Binary = binary; Arguments = Some (args |> List.ofArray) }
let execArgs = execArgs opts
Proc.Exec(execArgs) |> ignore
Proc.Exec(execArgs, opts.Timeout) |> ignore
opts

[<CustomOperation("exec")>]
member this.ExecuteWithArguments(opts, binary, args: string list) =
let opts = { opts with Binary = binary; Arguments = Some args }
let execArgs = execArgs opts
Proc.Exec(execArgs) |> ignore
Proc.Exec(execArgs, opts.Timeout) |> ignore
opts


let shell = ShellBuilder()

type TempBuilder() =

member t.Yield _ = ExecOptions.Empty

[<CustomOperation("run")>]
member this.Run2(opts, binary, [<ParamArray>] args: string array) =
let opts = { opts with Binary = binary; Arguments = Some (args |> List.ofArray)}
let execArgs = execArgs opts
Proc.Exec(execArgs) |> ignore

[<CustomOperation("run")>]
member this.Run2(opts, binary, args: string list) =
let opts = { opts with Binary = binary; Arguments = Some args}
let execArgs = execArgs opts
Proc.Exec(execArgs) |> ignore

[<CustomOperation("run")>]
member this.Run2(opts) =
let execArgs = execArgs opts
Proc.Exec(execArgs) |> ignore

let temp = TempBuilder()


type ExecBuilder() =

member t.Yield _ = ExecOptions.Empty
Expand All @@ -129,7 +106,7 @@ type ExecBuilder() =
member this.Execute(opts, binary, [<ParamArray>] arguments: string array) =
let opts = { opts with Binary = binary; Arguments = Some (arguments |> List.ofArray)}
let execArgs = execArgs opts
Proc.Exec(execArgs) |> ignore
Proc.Exec(execArgs, opts.Timeout) |> ignore

///<summary>Runs <paramref name="binary"/> using <paramref name="arguments"/> immediately</summary>
/// <param name="opts"><see cref="ExecOptions"/> the computation build thus far, not specified directly</param>
Expand All @@ -139,7 +116,7 @@ type ExecBuilder() =
member this.Execute(opts, binary, arguments: string list) =
let opts = { opts with Binary = binary; Arguments = Some arguments}
let execArgs = execArgs opts
Proc.Exec(execArgs) |> ignore
Proc.Exec(execArgs, opts.Timeout) |> ignore

///<summary>
/// Runs the <see cref="ExecOptions"/> the computation build thus far.
Expand All @@ -149,7 +126,7 @@ type ExecBuilder() =
member this.Execute(opts) =
if opts.Binary = "" then failwithf "No binary specified to exec computation expression"
let execArgs = execArgs opts
Proc.Exec(execArgs) |> ignore
Proc.Exec(execArgs, opts.Timeout) |> ignore

///<summary>Supply external <see cref="ExecOptions"/> to bootstrap</summary>
[<CustomOperation("options")>]
Expand Down Expand Up @@ -190,7 +167,7 @@ type ExecBuilder() =

[<CustomOperation("timeout")>]
member this.Timeout(opts, timeout) =
{ opts with Timeout = Some timeout }
{ opts with Timeout = timeout }

[<CustomOperation("stream_reader_wait_timeout")>]
member this.WaitForStreamReadersTimeout(opts, timeout) =
Expand All @@ -216,63 +193,63 @@ type ExecBuilder() =
member this.Find(opts, find: LineOut -> bool) =
let opts = { opts with Find = Some find }
let startArguments = startArgs opts
let result = Proc.Start(startArguments)
let result = Proc.Start(startArguments, opts.Timeout)
result.ConsoleOut
|> Seq.find find

[<CustomOperation("filter")>]
member this.Filter(opts, find: LineOut -> bool) =
let opts = { opts with Find = Some find }
let startArguments = startArgs opts
let result = Proc.Start(startArguments)
let result = Proc.Start(startArguments, opts.Timeout)
result.ConsoleOut
|> Seq.filter find
|> List.ofSeq

[<CustomOperation("output")>]
member this.Output(opts) =
let startArguments = startArgs opts
Proc.Start(startArguments)
Proc.Start(startArguments, opts.Timeout)

[<CustomOperation("run_args")>]
member this.InvokeArgs(opts, [<ParamArray>] arguments: string array) =
let opts = { opts with Arguments = Some (arguments |> List.ofArray) }
let execArgs = execArgs opts
Proc.Exec(execArgs) |> ignore
Proc.Exec(execArgs, opts.Timeout) |> ignore

[<CustomOperation("run_args")>]
member this.InvokeArgs(opts, arguments: string list) =
let opts = { opts with Arguments = Some arguments}
let execArgs = execArgs opts
Proc.Exec(execArgs) |> ignore
Proc.Exec(execArgs, opts.Timeout) |> ignore

[<CustomOperation("exit_code_of")>]
member this.ReturnStatus(opts, binary, arguments: string list) =
let opts = { opts with Binary = binary; Arguments = Some arguments}
let execArgs = execArgs opts
Proc.Exec(execArgs).GetValueOrDefault 1
Proc.Exec(execArgs, opts.Timeout).GetValueOrDefault 1

[<CustomOperation("exit_code_of")>]
member this.ReturnStatus(opts, binary, [<ParamArray>] arguments: string array) =
let opts = { opts with Binary = binary; Arguments = Some (arguments |> List.ofArray)}
let execArgs = execArgs opts
Proc.Exec(execArgs).GetValueOrDefault 1
Proc.Exec(execArgs, opts.Timeout).GetValueOrDefault 1

[<CustomOperation("exit_code")>]
member this.ReturnStatus(opts) =
let execArgs = execArgs opts
Proc.Exec(execArgs).GetValueOrDefault 1
Proc.Exec(execArgs, opts.Timeout).GetValueOrDefault 1

[<CustomOperation("output_of")>]
member this.ReturnOutput(opts, binary, [<ParamArray>] arguments: string array) =
let opts = { opts with Binary = binary; Arguments = Some (arguments |> List.ofArray)}
let execArgs = startArgs opts
Proc.Start(execArgs)
Proc.Start(execArgs, opts.Timeout)

[<CustomOperation("output_of")>]
member this.ReturnOutput(opts) =
let startArgs = startArgs opts
Proc.Start(startArgs)
Proc.Start(startArgs, opts.Timeout)


let exec = ExecBuilder()
Expand Down
Loading