Commit 5b03930

mo khan <mo@mokhan.ca>
2021-02-05 22:28:11
feat: split classes into separate files
1 parent 17b7973
exe/jive
@@ -1,4 +1,4 @@
 #!/usr/bin/env -S ruby --disable-gems
 # frozen_string_literal: true
 
-require "jive"
+require "jive/cli"
lib/jive/batch_runner.rb
@@ -0,0 +1,70 @@
+# frozen_string_literal: true
+
+module Jive
+  class BatchRunner
+    attr_reader :runner, :stdout
+
+    def initialize(runner: Runner.new, stdout: $stdout)
+      @runner = runner
+      @stdout = stdout
+    end
+
+    def run(tasks)
+      stream_output_for(runner, tasks)
+      stdout.puts "==================================================="
+      print_result_for(runner)
+    end
+
+    private
+
+    def stream_output_for(runner, tasks)
+      runner.run(tasks) do |command, &run|
+        stdout.puts
+        stdout.puts "$ #{command.join(" ")}"
+        result = run.call
+        stdout.print result.stdout
+        stdout.print result.stderr
+        stdout.puts "==> Finished in #{result.duration} seconds"
+        stdout.puts
+      end
+    end
+
+    def print_result_for(runner)
+      if runner.all_success_and_clean?
+        stdout.puts "Passed successfully."
+        0
+      elsif runner.all_success?
+        stdout.puts "Passed successfully, but we have warnings:"
+        stdout.puts
+        emit_warnings_for(runner)
+        2
+      else
+        stdout.puts "Something failed:"
+        emit_warnings_for(runner)
+        emit_errors_for(runner)
+        1
+      end
+    end
+
+    def emit_warnings_for(runner)
+      runner.warned_results.each do |result|
+        stdout.puts
+        stdout.puts "**** #{result.command.join(" ")} had the following warning(s):"
+        stdout.puts
+        stdout.puts result.stderr
+        stdout.puts
+      end
+    end
+
+    def emit_errors_for(runner)
+      runner.failed_results.each do |result|
+        stdout.puts
+        stdout.puts "**** #{result.command.join(" ")} failed with the following error(s):"
+        stdout.puts
+        stdout.puts result.stdout
+        stdout.puts result.stderr
+        stdout.puts
+      end
+    end
+  end
+end
lib/jive/cli.rb
@@ -0,0 +1,4 @@
+# frozen_string_literal: true
+
+require "thor"
+require "jive"
lib/jive/popen.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+module Jive
+  module Popen
+    Result = Struct.new(:command, :stdout, :stderr, :status, :duration)
+
+    def self.popen(command, path = nil, env = {}, &block)
+      result = popen_with_detail(command, path, env, &block)
+
+      ["#{result.stdout}#{result.stderr}", result.status&.exitstatus]
+    end
+
+    def self.popen_with_detail(command, path = Dir.pwd, env = {})
+      FileUtils.mkdir_p(path) unless File.directory?(path)
+
+      captured_stdout = ""
+      captured_stderr = ""
+      exit_status = nil
+      start = Time.now
+
+      Open3.popen3(env.merge("PWD" => path), *Array(command),
+                   { chdir: path }) do |stdin, stdout, stderr, wait_thr|
+                     out_reader = Thread.new { stdout.read }
+                     err_reader = Thread.new { stderr.read }
+
+                     yield(stdin) if block_given?
+
+                     stdin.close
+                     captured_stdout = out_reader.value
+                     captured_stderr = err_reader.value
+                     exit_status = wait_thr.value
+                   end
+      Result.new(command, captured_stdout, captured_stderr, exit_status,
+                 Time.now - start)
+    end
+  end
+end
lib/jive/runner.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+module Jive
+  class Runner
+    attr_reader :results
+
+    def initialize
+      @results = []
+    end
+
+    def run(commands, &block)
+      commands.each do |command|
+        block.call(command) do
+          cmd_result = Popen.popen_with_detail(command)
+          results << cmd_result
+          cmd_result
+        end
+      end
+    end
+
+    def all_success_and_clean?
+      all_success? && all_stderr_empty?
+    end
+
+    def all_success?
+      results.all? { |result| result.status.success? }
+    end
+
+    def all_stderr_empty?
+      results.all? { |result| result.stderr.empty? }
+    end
+
+    def failed_results
+      results.reject { |result| result.status.success? }
+    end
+
+    def warned_results
+      results.select do |result|
+        result.status.success? && !result.stderr.empty?
+      end
+    end
+  end
+end
lib/jive.rb
@@ -1,146 +1,17 @@
 # frozen_string_literal: true
 
 require "fileutils"
-require "jive/version"
 require "open3"
 
+require "jive/batch_runner"
+require "jive/popen"
+require "jive/runner"
+require "jive/version"
+
 module Jive
   class Error < StandardError; end
 
   def self.run(tasks)
     Jive::BatchRunner.new.run(tasks)
   end
-
-  module Popen
-    Result = Struct.new(:command, :stdout, :stderr, :status, :duration)
-
-    def self.popen(command, path = nil, env = {}, &block)
-      result = popen_with_detail(command, path, env, &block)
-
-      ["#{result.stdout}#{result.stderr}", result.status&.exitstatus]
-    end
-
-    def self.popen_with_detail(command, path = Dir.pwd, env = {})
-      FileUtils.mkdir_p(path) unless File.directory?(path)
-
-      captured_stdout = ""
-      captured_stderr = ""
-      exit_status = nil
-      start = Time.now
-
-      Open3.popen3(env.merge("PWD" => path), *Array(command),
-                   { chdir: path }) do |stdin, stdout, stderr, wait_thr|
-        out_reader = Thread.new { stdout.read }
-        err_reader = Thread.new { stderr.read }
-
-        yield(stdin) if block_given?
-
-        stdin.close
-        captured_stdout = out_reader.value
-        captured_stderr = err_reader.value
-        exit_status = wait_thr.value
-      end
-      Result.new(command, captured_stdout, captured_stderr, exit_status,
-                 Time.now - start)
-    end
-  end
-
-  class BatchRunner
-    attr_reader :runner, :stdout
-
-    def initialize(runner: Runner.new, stdout: $stdout)
-      @runner = runner
-      @stdout = stdout
-    end
-
-    def run(tasks, verbose: true)
-      runner.run(tasks) do |command, &run|
-        stdout.puts
-        stdout.puts "$ #{command.join(" ")}"
-        result = run.call
-        stdout.print result.stdout if verbose
-        stdout.print result.stderr if verbose
-        stdout.puts "==> Finished in #{result.duration} seconds"
-        stdout.puts
-      end
-      stdout.puts "==================================================="
-      if runner.all_success_and_clean?
-        stdout.puts "Passed successfully."
-        0
-      elsif runner.all_success?
-        stdout.puts "Passed successfully, but we have warnings:"
-        stdout.puts
-        emit_warnings
-        2
-      else
-        stdout.puts "Something failed:"
-        emit_warnings
-        emit_errors
-        1
-      end
-    end
-
-    private
-
-    def emit_warnings
-      runner.warned_results.each do |result|
-        stdout.puts
-        stdout.puts "**** #{result.command.join(" ")} had the following warning(s):"
-        stdout.puts
-        stdout.puts result.stderr
-        stdout.puts
-      end
-    end
-
-    def emit_errors
-      runner.failed_results.each do |result|
-        stdout.puts
-        stdout.puts "**** #{result.command.join(" ")} failed with the following error(s):"
-        stdout.puts
-        stdout.puts result.stdout
-        stdout.puts result.stderr
-        stdout.puts
-      end
-    end
-  end
-
-  class Runner
-    attr_reader :results
-
-    def initialize
-      @results = []
-    end
-
-    def run(commands, &block)
-      commands.each do |command|
-        block.call(command) do
-          cmd_result = Popen.popen_with_detail(command)
-          results << cmd_result
-          cmd_result
-        end
-      end
-    end
-
-    def all_success_and_clean?
-      all_success? && all_stderr_empty?
-    end
-
-    def all_success?
-      results.all? { |result| result.status.success? }
-    end
-
-    def all_stderr_empty?
-      results.all? { |result| result.stderr.empty? }
-    end
-
-    def failed_results
-      results.reject { |result| result.status.success? }
-    end
-
-    def warned_results
-      results.select do |result|
-        result.status.success? && !result.stderr.empty?
-      end
-    end
-  end
 end
test/integration/jive_test.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+require "test_helper"
+
+class JiveTest < Minitest::Test
+  def test_run_exits_with_exit_code_zero
+    assert_equal 0, Jive.run([["echo", "."]])
+  end
+end
.rubocop.yml
@@ -1,9 +1,20 @@
 AllCops:
+  NewCops: enable
   TargetRubyVersion: 2.5
 
 Layout/LineLength:
   Max: 120
 
+Metrics/AbcSize:
+  Exclude:
+    - lib/jive/batch_runner.rb
+    - lib/jive/popen.rb
+
+Metrics/MethodLength:
+  Exclude:
+    - lib/jive/batch_runner.rb
+    - lib/jive/popen.rb
+
 Style/Documentation:
   Enabled: false
 
Gemfile
@@ -8,3 +8,5 @@ gemspec
 gem "minitest", "~> 5.0"
 gem "rake", "~> 13.0"
 gem "rubocop", "~> 1.7"
+gem "rubocop-minitest", "~> 0.1"
+gem "rubocop-rake", "~> 0.5"
Gemfile.lock
@@ -27,6 +27,10 @@ GEM
       unicode-display_width (>= 1.4.0, < 3.0)
     rubocop-ast (1.4.1)
       parser (>= 2.7.1.5)
+    rubocop-minitest (0.10.3)
+      rubocop (>= 0.87, < 2.0)
+    rubocop-rake (0.5.1)
+      rubocop
     ruby-progressbar (1.11.0)
     thor (1.1.0)
     unicode-display_width (2.0.0)
@@ -39,6 +43,8 @@ DEPENDENCIES
   minitest (~> 5.0)
   rake (~> 13.0)
   rubocop (~> 1.7)
+  rubocop-minitest (~> 0.1)
+  rubocop-rake (~> 0.5)
 
 BUNDLED WITH
    2.2.8