From 9ce592c8c90894fc4df054e3e5488ba327b0dfdb Mon Sep 17 00:00:00 2001 From: Martijn Laarman Date: Mon, 8 Jan 2024 20:58:07 +0100 Subject: [PATCH] ensure timeouts propagate to invocations --- examples/ScratchPad.Fs/Program.fs | 44 +++++++++----------- src/Proc.Fs/Bindings.fs | 69 +++++++++++-------------------- 2 files changed, 43 insertions(+), 70 deletions(-) diff --git a/examples/ScratchPad.Fs/Program.fs b/examples/ScratchPad.Fs/Program.fs index b68f6b4..aba6e22 100644 --- a/examples/ScratchPad.Fs/Program.fs +++ b/examples/ScratchPad.Fs/Program.fs @@ -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" @@ -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 } @@ -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!" diff --git a/src/Proc.Fs/Bindings.fs b/src/Proc.Fs/Bindings.fs index 1858915..37420a8 100644 --- a/src/Proc.Fs/Bindings.fs +++ b/src/Proc.Fs/Bindings.fs @@ -12,8 +12,7 @@ type ExecOptions = { WorkingDirectory: string option Environment: Map option - Timeout: TimeSpan option - + Timeout: TimeSpan ValidExitCodeClassifier: (int -> bool) option NoWrapInThread: bool option @@ -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) @@ -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) @@ -62,7 +63,7 @@ type ShellBuilder() = [] member inline this.Timeout(opts, timeout) = - { opts with Timeout = Some timeout } + { opts with Timeout = timeout } [] member inline this.WaitForStreamReadersTimeout(opts, timeout) = @@ -80,43 +81,19 @@ type ShellBuilder() = member this.ExecuteWithArguments(opts, binary, [] 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 [] 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 - - [] - member this.Run2(opts, binary, [] args: string array) = - let opts = { opts with Binary = binary; Arguments = Some (args |> List.ofArray)} - let execArgs = execArgs opts - Proc.Exec(execArgs) |> ignore - - [] - 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 - - [] - member this.Run2(opts) = - let execArgs = execArgs opts - Proc.Exec(execArgs) |> ignore - -let temp = TempBuilder() - - type ExecBuilder() = member t.Yield _ = ExecOptions.Empty @@ -129,7 +106,7 @@ type ExecBuilder() = member this.Execute(opts, binary, [] 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 ///Runs using immediately /// the computation build thus far, not specified directly @@ -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 /// /// Runs the the computation build thus far. @@ -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 ///Supply external to bootstrap [] @@ -190,7 +167,7 @@ type ExecBuilder() = [] member this.Timeout(opts, timeout) = - { opts with Timeout = Some timeout } + { opts with Timeout = timeout } [] member this.WaitForStreamReadersTimeout(opts, timeout) = @@ -216,7 +193,7 @@ 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 @@ -224,7 +201,7 @@ type ExecBuilder() = 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 @@ -232,47 +209,47 @@ type ExecBuilder() = [] member this.Output(opts) = let startArguments = startArgs opts - Proc.Start(startArguments) + Proc.Start(startArguments, opts.Timeout) [] member this.InvokeArgs(opts, [] 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 [] 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 [] 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 [] member this.ReturnStatus(opts, binary, [] 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 [] member this.ReturnStatus(opts) = let execArgs = execArgs opts - Proc.Exec(execArgs).GetValueOrDefault 1 + Proc.Exec(execArgs, opts.Timeout).GetValueOrDefault 1 [] member this.ReturnOutput(opts, binary, [] 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) [] member this.ReturnOutput(opts) = let startArgs = startArgs opts - Proc.Start(startArgs) + Proc.Start(startArgs, opts.Timeout) let exec = ExecBuilder()