Skip to content

Instantly share code, notes, and snippets.

@vbfox
Last active January 20, 2016 14:34
Show Gist options
  • Save vbfox/ba82be78a16b45ed27ad to your computer and use it in GitHub Desktop.
Save vbfox/ba82be78a16b45ed27ad to your computer and use it in GitHub Desktop.
Fix dotcover args in FAKE to be correctly passed to CreateProcess
/// Escape arguments in a form that programs parsing it as Microsoft C Runtime will successfuly understand
/// Rules taken from http://www.daviddeley.com/autohotkey/parameters/parameters.htm#WINARGV
module MsvcrCommandLine =
open System.Text
let escapeArg (arg : string) (builder : StringBuilder) =
let needQuote = arg.Contains(" ") || arg.Contains("\t")
let rec escape (builder: StringBuilder) pos =
if pos >= arg.Length then
()
else
let c = arg.[pos]
let isLast = pos = arg.Length-1
match c with
| '"' -> // Quotes are escaped
escape (builder.Append(@"\""")) (pos + 1)
| '\\' when isLast && needQuote -> // Backslash ending a quoted arg need escape
escape (builder.Append(@"\\")) (pos + 1)
| '\\' when not isLast -> // Backslash followed by quote need to be escaped
let nextC = arg.[pos+1]
match nextC with
| '"' ->
escape (builder.Append(@"\\\""")) (pos + 2)
| _ ->
escape (builder.Append(c)) (pos + 1)
| _ ->
escape (builder.Append(c)) (pos + 1)
if needQuote then builder.Append('"') |> ignore
escape builder 0
if needQuote then builder.Append('"') |> ignore
let escape args =
let builder = StringBuilder()
args |> Seq.iteri (fun i arg ->
if (i <> 0) then builder.Append(' ') |> ignore
escapeArg arg builder)
builder.ToString()
type cmdLine = {
Args : string list
}
module CmdLine =
open System
let empty = { Args = List.empty }
let inline append (value : obj) (cmdLine : cmdLine) =
let s =
match value with
| :? String as sv -> sv
| _ -> sprintf "%A" value
{ cmdLine with Args = s :: cmdLine.Args }
let inline appendIfTrue cond value cmdLine =
if cond then cmdLine |> append value else cmdLine
let inline appendIfNotNullOrEmpty value s cmdLine =
appendIfTrue (not (String.IsNullOrEmpty(value))) (s+value) cmdLine
let inline argsInOrder cmdLine = cmdLine.Args |> List.rev
let inline toStringForMsvcr cmdLine = MsvcrCommandLine.escape (argsInOrder cmdLine)
let fixupDotCoverArgs (parameters : DotCover.DotCoverParams) =
let newCustomParameters =
CmdLine.empty
|> CmdLine.appendIfNotNullOrEmpty parameters.TargetExecutable "/TargetExecutable="
|> CmdLine.appendIfNotNullOrEmpty (parameters.TargetArguments.Trim()) "/TargetArguments="
|> CmdLine.appendIfNotNullOrEmpty parameters.TargetWorkingDir "/TargetWorkingDir="
|> CmdLine.appendIfNotNullOrEmpty parameters.Filters "/Filters="
|> CmdLine.appendIfNotNullOrEmpty parameters.AttributeFilters "/AttributeFilters="
|> CmdLine.appendIfNotNullOrEmpty parameters.Output "/Output="
|> CmdLine.toStringForMsvcr
|> (fun x -> x + " " + parameters.CustomParameters)
{ parameters with
TargetExecutable = ""
TargetArguments = ""
TargetWorkingDir = ""
Filters = ""
AttributeFilters = ""
Output = ""
CustomParameters = newCustomParameters
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment