in Sources/TSCBasic/misc.swift [25:82]
func quote(argument: String) -> String {
if !argument.contains(where: { " \t\n\"".contains($0) }) {
return argument
}
// To escape the command line, we surround the argument with quotes.
// However, the complication comes due to how the Windows command line
// parser treats backslashes (\) and quotes (").
//
// - \ is normally treated as a literal backslash
// e.g. alpha\beta\gamma => alpha\beta\gamma
// - The sequence \" is treated as a literal "
// e.g. alpha\"beta => alpha"beta
//
// But then what if we are given a path that ends with a \?
//
// Surrounding alpha\beta\ with " would be "alpha\beta\" which would be
// an unterminated string since it ends on a literal quote. To allow
// this case the parser treats:
//
// - \\" as \ followed by the " metacharacter
// - \\\" as \ followed by a literal "
//
// In general:
// - 2n \ followed by " => n \ followed by the " metacharacter
// - 2n + 1 \ followed by " => n \ followed by a literal "
var quoted = "\""
var unquoted = argument.unicodeScalars
while !unquoted.isEmpty {
guard let firstNonBS = unquoted.firstIndex(where: { $0 != "\\" }) else {
// String ends with a backslash (e.g. first\second\), escape all
// the backslashes then add the metacharacter ".
let count = unquoted.count
quoted.append(String(repeating: "\\", count: 2 * count))
break
}
let count = unquoted.distance(from: unquoted.startIndex, to: firstNonBS)
if unquoted[firstNonBS] == "\"" {
// This is a string of \ followed by a " (e.g. first\"second).
// Escape the backslashes and the quote.
quoted.append(String(repeating: "\\", count: 2 * count + 1))
} else {
// These are just literal backslashes
quoted.append(String(repeating: "\\", count: count))
}
quoted.append(String(unquoted[firstNonBS]))
// Drop the backslashes and the following character
unquoted.removeFirst(count + 1)
}
quoted.append("\"")
return quoted
}