Skip to content
Draft
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
3 changes: 2 additions & 1 deletion lib/litestream/commands.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
require_relative "upstream"
require "shellwords"

module Litestream
module Commands
Expand Down Expand Up @@ -162,7 +163,7 @@ def prepare(command, argv = {}, database = nil)
end

def run(cmd, tabled_output:)
stdout = `#{cmd.join(" ")}`.chomp
stdout = `#{Shellwords.shelljoin(cmd)}`.chomp
return stdout unless tabled_output

keys, *rows = stdout.split("\n").map { _1.split(/\s+/) }
Expand Down
48 changes: 48 additions & 0 deletions test/litestream/test_commands.rb
Original file line number Diff line number Diff line change
Expand Up @@ -840,6 +840,54 @@ def test_wal_does_not_set_env_var_from_config_when_env_vars_already_set
end
end

class TestRunMethod < TestCommands
def test_run_method_handles_paths_with_spaces
# Create a command with a path containing spaces
cmd = ["/usr/bin/echo", "hello world", "/path with spaces/file.txt"]

# Stub the backtick execution to capture what would be executed
executed_command = nil
stubbed_backticks = proc do |command_string|
executed_command = command_string
"mocked output"
end

# Test that the command is properly escaped
Litestream::Commands.stub :`, stubbed_backticks do
result = Litestream::Commands.send(:run, cmd, tabled_output: false)

# The result should be the mocked output
assert_equal "mocked output", result

# Check that the executed command is properly escaped
# With fixed implementation using Shellwords.shelljoin
# This ensures spaces are properly handled
expected_command = "/usr/bin/echo hello\\ world /path\\ with\\ spaces/file.txt"
assert_equal expected_command, executed_command
end
end

def test_run_method_handles_simple_commands_without_spaces
# Test that simple commands still work
cmd = ["/usr/bin/echo", "hello", "world"]

executed_command = nil
stubbed_backticks = proc do |command_string|
executed_command = command_string
"simple output"
end

Litestream::Commands.stub :`, stubbed_backticks do
result = Litestream::Commands.send(:run, cmd, tabled_output: false)

assert_equal "simple output", result
# Simple commands should still work fine
expected_command = "/usr/bin/echo hello world"
assert_equal expected_command, executed_command
end
end
end

class TestOutput < ActiveSupport::TestCase
def test_output_formatting_generates_table_with_data
data = [
Expand Down