diff --git a/Ductus.FluentDocker/Commands/Compose.cs b/Ductus.FluentDocker/Commands/Compose.cs index 9dc3810a..42bbff45 100644 --- a/Ductus.FluentDocker/Commands/Compose.cs +++ b/Ductus.FluentDocker/Commands/Compose.cs @@ -544,7 +544,7 @@ public static CommandResponse> ComposeUpCommand(this DockerUri hos if (!string.IsNullOrEmpty(ca.ProjectDirectory)) { - composeArgs += $" --project-directory {ca.ProjectDirectory.Rendered}"; + composeArgs += $" --project-directory \"{ca.ProjectDirectory.Rendered}\""; } var options = ca.NoStart ? "--no-start" : "--detach"; @@ -603,7 +603,7 @@ public static CommandResponse> ComposeRm(this DockerUri host, stri args += $" -f \"{cf}\""; if (!string.IsNullOrEmpty(altProjectName)) - args += $" -p {altProjectName}"; + args += $" -p \"{altProjectName}\""; var options = string.Empty; options += " -f"; // Don't ask to confirm removal @@ -639,7 +639,7 @@ public static CommandResponse> ComposePs(this DockerUri host, stri args += $" -f \"{cf}\""; if (!string.IsNullOrEmpty(altProjectName)) - args += $" -p {altProjectName}"; + args += $" -p \"{altProjectName}\""; var options = string.Empty; if (null != services && 0 != services.Length) @@ -676,7 +676,7 @@ public static CommandResponse> ComposePull(this DockerUri host, Co args += $" -f \"{cf}\""; if (!string.IsNullOrEmpty(commandArgs.AltProjectName)) - args += $" -p {commandArgs.AltProjectName}"; + args += $" -p \"{commandArgs.AltProjectName}\""; var options = string.Empty; if (commandArgs.DownloadAllTagged) diff --git a/Ductus.FluentDocker/Executors/AsyncProcessExecutor.cs b/Ductus.FluentDocker/Executors/AsyncProcessExecutor.cs index 7be39932..80e6616b 100644 --- a/Ductus.FluentDocker/Executors/AsyncProcessExecutor.cs +++ b/Ductus.FluentDocker/Executors/AsyncProcessExecutor.cs @@ -1,8 +1,9 @@ -using System.Diagnostics; +using System.Diagnostics; using System.Text; using System.Threading; using System.Threading.Tasks; using Ductus.FluentDocker.Common; +using Ductus.FluentDocker.Extensions; using Ductus.FluentDocker.Model.Containers; namespace Ductus.FluentDocker.Executors @@ -18,6 +19,7 @@ public AsyncProcessExecutor(string command, string arguments, string workingdir _command = command; _arguments = arguments; _workingdir = workingdir; + CommandExtensions.FixSudoCommand(command, arguments, out _command, out _arguments); } public Task> Execute(CancellationToken cancellationToken = default(CancellationToken)) diff --git a/Ductus.FluentDocker/Executors/ProcessExecutor.cs b/Ductus.FluentDocker/Executors/ProcessExecutor.cs index 9df6dbb3..b0518347 100644 --- a/Ductus.FluentDocker/Executors/ProcessExecutor.cs +++ b/Ductus.FluentDocker/Executors/ProcessExecutor.cs @@ -16,16 +16,9 @@ namespace Ductus.FluentDocker.Executors public ProcessExecutor(string command, string arguments, string workingdir = null) { _workingdir = workingdir; - if (command.StartsWith("echo") || command.StartsWith("sudo")) - { - _command = CommandExtensions.DefaultShell; - _arguments = $"-c \"{command} {arguments}\""; - - return; - } - _command = command; _arguments = arguments; + CommandExtensions.FixSudoCommand(command, arguments, out _command, out _arguments); } public IDictionary Env { get; } = new Dictionary(); diff --git a/Ductus.FluentDocker/Executors/StreamProcessExecutor.cs b/Ductus.FluentDocker/Executors/StreamProcessExecutor.cs index 1a82dd95..4c815ebd 100644 --- a/Ductus.FluentDocker/Executors/StreamProcessExecutor.cs +++ b/Ductus.FluentDocker/Executors/StreamProcessExecutor.cs @@ -1,6 +1,7 @@ using System.Diagnostics; using System.Threading; using Ductus.FluentDocker.Common; +using Ductus.FluentDocker.Extensions; namespace Ductus.FluentDocker.Executors { @@ -16,6 +17,7 @@ public StreamProcessExecutor(string command, string arguments, string workingdir _command = command; _arguments = arguments; _workingdir = workingdir; + CommandExtensions.FixSudoCommand(command, arguments, out _command, out _arguments); } public ConsoleStream Execute(CancellationToken token = default) @@ -30,7 +32,9 @@ public ConsoleStream Execute(CancellationToken token = default) UseShellExecute = false, Arguments = _arguments, FileName = _command, - WorkingDirectory = _workingdir + WorkingDirectory = _workingdir, + StandardErrorEncoding = System.Text.Encoding.UTF8, + StandardOutputEncoding = System.Text.Encoding.UTF8, }, new T(), token); } } diff --git a/Ductus.FluentDocker/Extensions/CommandExtensions.cs b/Ductus.FluentDocker/Extensions/CommandExtensions.cs index e32edc0f..ecc80d04 100644 --- a/Ductus.FluentDocker/Extensions/CommandExtensions.cs +++ b/Ductus.FluentDocker/Extensions/CommandExtensions.cs @@ -83,6 +83,21 @@ public static void SetSudo(this SudoMechanism sudo, string password = null) _binaryResolver = new DockerBinariesResolver(_sudoMechanism, _sudoPassword); } + public static void FixSudoCommand(string command, string arguments, out string fixedCommand, out string fixedArguments) + { + if (command.StartsWith("echo") || command.StartsWith("sudo")) + { + fixedCommand = CommandExtensions.DefaultShell; + string escapedArguments = arguments.Replace("\"", "\"\\\"\""); + fixedArguments = $"-c \"{command} {escapedArguments}\""; + } + else + { + fixedCommand = command; + fixedArguments = arguments; + } + } + public static string ResolveBinary(this string dockerCommand, bool preferMachine = false, bool forceResolve = false) { if (forceResolve || null == _binaryResolver) diff --git a/Ductus.FluentDocker/Services/Extensions/ContainerExtensions.cs b/Ductus.FluentDocker/Services/Extensions/ContainerExtensions.cs index 03ecb33f..1b46b18c 100644 --- a/Ductus.FluentDocker/Services/Extensions/ContainerExtensions.cs +++ b/Ductus.FluentDocker/Services/Extensions/ContainerExtensions.cs @@ -23,10 +23,10 @@ public static class ContainerExtensions /// If continuous logs is wanted. /// The cancellation token for logs, especially needed when is set to true. /// A console stream to consume. - public static ConsoleStream Logs(this IContainerService service, bool follow = false, + public static ConsoleStream Logs(this IContainerService service, bool follow = false, bool showTimeStamps = false, CancellationToken token = default) { - return service.DockerHost.Logs(service.Id, token, follow); + return service.DockerHost.Logs(service.Id, token, follow, showTimeStamps); } ///