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
6 changes: 3 additions & 3 deletions lib/cli/ui/spinner/spin_group.rb
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ class Task
# * +title+ - Title of the task
# * +block+ - Block for the task, will be provided with an instance of the spinner
#
#: (String title, final_glyph: ^(bool success) -> (Glyph | String), merged_output: bool, duplicate_output_to: IO, work_queue: WorkQueue) { (Task task) -> untyped } -> void
#: (String title, final_glyph: ^(bool success) -> (Glyph | String), merged_output: bool, duplicate_output_to: io_like?, work_queue: WorkQueue) { (Task task) -> untyped } -> void
def initialize(title, final_glyph:, merged_output:, duplicate_output_to:, work_queue:, &block)
@title = title
@final_glyph = final_glyph
Expand Down Expand Up @@ -300,12 +300,12 @@ def inset_width
# spin_group.add('Title') { |spinner| sleep 1.0 }
# spin_group.wait
#
#: (String title, ?final_glyph: ^(bool success) -> (Glyph | String), ?merged_output: bool, ?duplicate_output_to: IO) { (Task task) -> void } -> void
#: (String title, ?final_glyph: ^(bool success) -> (Glyph | String), ?merged_output: bool, ?duplicate_output_to: io_like?) { (Task task) -> void } -> void
def add(
title,
final_glyph: DEFAULT_FINAL_GLYPH,
merged_output: false,
duplicate_output_to: File.new(File::NULL, 'w'),
duplicate_output_to: nil,
&block
)
@m.synchronize do
Expand Down
10 changes: 7 additions & 3 deletions lib/cli/ui/stdout_router.rb
Original file line number Diff line number Diff line change
Expand Up @@ -184,11 +184,11 @@ def outermost_uncaptured?
end
end

#: (?with_frame_inset: bool, ?merged_output: bool, ?duplicate_output_to: IO) { -> void } -> void
#: (?with_frame_inset: bool, ?merged_output: bool, ?duplicate_output_to: io_like?) { -> void } -> void
def initialize(
with_frame_inset: true,
merged_output: false,
duplicate_output_to: File.open(File::NULL, 'w'),
duplicate_output_to: nil,
&block
)
@with_frame_inset = with_frame_inset
Expand Down Expand Up @@ -225,7 +225,11 @@ def run
case stream
when :stdout
@out.write(data)
@duplicate_output_to.write(data)
begin
@duplicate_output_to&.write(data)
rescue IOError
# Ignore
end
when :stderr
@err.write(data)
else raise
Expand Down
12 changes: 12 additions & 0 deletions test/cli/ui/spinner/spin_group_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,18 @@ def test_spin_group_auto_debrief_false
assert_equal('', err)
end

def test_spin_group_tasks_do_not_open_null_device
capture_io do
CLI::UI::StdoutRouter.ensure_activated
File.expects(:new).with(File::NULL, 'w').never

sg = SpinGroup.new(auto_debrief: false)
sg.add('task') { true }

assert(sg.wait)
end
end

def test_spin_group_success_debrief
capture_io do
CLI::UI::StdoutRouter.ensure_activated
Expand Down
34 changes: 34 additions & 0 deletions test/cli/ui/stdout_router_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,40 @@ def test_current_id
end
end

def test_capture_does_not_open_null_device
File.expects(:open).with(File::NULL, 'w').never
StdoutRouter::Capture.new {}
end

def test_capture_duplicate_output_to
capture_io do
StdoutRouter.with_enabled do
dup = StringIO.new
cap = StdoutRouter::Capture.new(duplicate_output_to: dup) { print('hello') }
cap.run
assert_equal('hello', cap.stdout)
assert_equal('hello', dup.string)
refute_predicate(dup, :closed?) # the capture doesn't own the handle
end
end
end

def test_capture_ignores_closed_duplicate_output
capture_io do
StdoutRouter.with_enabled do
dup = StringIO.new
cap = StdoutRouter::Capture.new(duplicate_output_to: dup) do
dup.close
print('hello')
end

cap.run

assert_equal('hello', cap.stdout)
end
end
end

def test_frame_can_autoload_after_router_is_enabled
script = <<~RUBY
require 'stringio'
Expand Down
Loading