pretty_multitask 0.1.6 → 0.1.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f89845bbcbcee9e9914a0a3107ea41866183f4276dc2aaf0f2ebab16c166b7b6
4
- data.tar.gz: f154a0b734e97ce7ca92ffa81a33ac3391cbe39529c7e713127fbe2b447a789a
3
+ metadata.gz: e01812677f6e3b459a2202d578e1de026078513dca7cbe335b4916160a84c5e7
4
+ data.tar.gz: '0311972bb6ec45cb360e253a55cc70a756d626d19e370564827219bd8bceefe4'
5
5
  SHA512:
6
- metadata.gz: fdc1274cadfce484efde26c43cf6735f856273fc10c5d1ae9f0aed90427e191702613b5ab5d2344f183b7862229a2ac8490b09284e12730634b83c9305e5e90a
7
- data.tar.gz: 29f8a24249f62371c325fe9bc9c4e7397c7c38487891fbcbeda59be6ac8efeba3d150f2189afc147fab99fd6e85c817762a472e634148241a8fb80ec4c80e833
6
+ metadata.gz: 7db22eaa39c4efcd3f29d6a683c20af6184a9c15306e5c7c4af50e24a2d00c6e7b35dd57eeab7f3c5f6d2df7ba58657a2e94d8b2bc41e4afb9059bfa1fc8920b
7
+ data.tar.gz: 6d0001b6c098af0a0ba330d85afdec788d2ccec897b9c811735a3b70004218f3b8921079d589177171c47ca4e7043f37b52e6ff250948f8f9b77caffbd94b715
@@ -0,0 +1,35 @@
1
+ Style/SpecialGlobalVars:
2
+ Enabled: false
3
+
4
+ Style/ConditionalAssignment:
5
+ Enabled: false
6
+
7
+ Style/GuardClause:
8
+ Enabled: false
9
+
10
+ Layout/FirstArrayElementIndentation:
11
+ Enabled: false
12
+
13
+ Metrics/MethodLength:
14
+ Max: 35
15
+
16
+ Metrics/LineLength:
17
+ Max: 120
18
+ Exclude:
19
+ - test/**/*
20
+
21
+ Metrics/CyclomaticComplexity:
22
+ Max: 10
23
+
24
+ Metrics/AbcSize:
25
+ Max: 30
26
+
27
+ Security/MarshalLoad:
28
+ Exclude:
29
+ - lib/pretty_multitask/run_callable.rb
30
+
31
+ Layout/ElseAlignment:
32
+ Enabled: false
33
+ Metrics/BlockLength:
34
+ Exclude:
35
+ - '*.gemspec'
data/Gemfile CHANGED
@@ -1,6 +1,8 @@
1
- source "https://rubygems.org"
1
+ # frozen_string_literal: true
2
2
 
3
- git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
3
+ source 'https://rubygems.org'
4
+
5
+ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
4
6
 
5
7
  # Specify your gem's dependencies in pretty_multitask.gemspec
6
8
  gemspec
data/Rakefile CHANGED
@@ -1,10 +1,12 @@
1
- require "bundler/gem_tasks"
2
- require "rake/testtask"
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rake/testtask'
3
5
 
4
6
  Rake::TestTask.new(:test) do |t|
5
- t.libs << "test"
6
- t.libs << "lib"
7
- t.test_files = FileList["test/**/*_test.rb"]
7
+ t.libs << 'test'
8
+ t.libs << 'lib'
9
+ t.test_files = FileList['test/**/*_test.rb']
8
10
  end
9
11
 
10
- task :default => :test
12
+ task default: :test
@@ -1,7 +1,8 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
- require "bundler/setup"
4
- require "pretty_multitask"
4
+ require 'bundler/setup'
5
+ require 'pretty_multitask'
5
6
 
6
7
  # You can add fixtures and/or initialization code here to make experimenting
7
8
  # with your gem easier. You can also use a different console, if you like.
@@ -10,5 +11,5 @@ require "pretty_multitask"
10
11
  # require "pry"
11
12
  # Pry.start
12
13
 
13
- require "irb"
14
+ require 'irb'
14
15
  IRB.start(__FILE__)
@@ -1,4 +1,6 @@
1
- require "pretty_multitask/version"
1
+ # frozen_string_literal: true
2
+
3
+ require 'pretty_multitask/version'
2
4
  require 'tlopo/executor'
3
5
  require 'logger'
4
6
  require 'pty'
@@ -7,23 +9,28 @@ require 'io/wait'
7
9
  require 'socket'
8
10
  require 'timeout'
9
11
  require 'yaml'
12
+ require 'fileutils'
13
+ require 'set'
10
14
 
15
+ # Main module
11
16
  module PrettyMultitask
17
+ require "#{__dir__}/pretty_multitask/trapper"
12
18
  require "#{__dir__}/pretty_multitask/color"
13
19
  require "#{__dir__}/pretty_multitask/runner"
14
20
  require "#{__dir__}/pretty_multitask/run_callable"
15
21
  end
16
22
 
17
23
  def pretty_multitask(hash)
18
- name, tasks = hash.keys.first, hash.values.first
24
+ name = hash.keys.first
25
+ tasks = hash.values.first
19
26
  task name do
20
27
  jobs = []
21
28
  tasks.each do |t|
22
- job = Proc.new do
29
+ job = proc do
23
30
  Rake::Task[t].invoke
24
31
  nil
25
32
  end
26
- jobs.push({ name: t, cmd: job})
33
+ jobs.push({ name: t, cmd: job })
27
34
  end
28
35
  PrettyMultitask::Runner.new(jobs).run
29
36
  end
@@ -1,14 +1,18 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module PrettyMultitask
4
+ # Class to provide some ANSI colors
2
5
  class Color
3
6
  def self.green(str)
4
7
  "\e[32;1m#{str}\e[0m"
5
8
  end
9
+
6
10
  def self.yellow(str)
7
11
  "\e[33;1m#{str}\e[0m"
8
12
  end
13
+
9
14
  def self.red(str)
10
15
  "\e[31;1m#{str}\e[0m"
11
16
  end
12
17
  end
13
18
  end
14
-
@@ -1,24 +1,79 @@
1
- module PrettyMultitask
1
+ # frozen_string_literal: true
2
2
 
3
+ module PrettyMultitask
4
+ # This class will run a callable, and wrap it's output adding nice format
3
5
  class RunCallable
4
6
  def initialize(opts = {})
5
7
  @opts = opts
6
8
  end
7
-
9
+
8
10
  def run(opts = @opts)
9
11
  cmd = opts[:cmd]
10
12
  name = opts[:name]
11
- out = opts[:out] || STDOUT
12
- err = opts[:err] || STDERR
13
+ out = STDOUT
13
14
  @padding = opts[:padding]
14
15
  master, slave = PTY.open
15
16
  err_read, err_write = IO.pipe
16
-
17
+
17
18
  r, w = UNIXSocket.pair(:STREAM, 0)
18
-
19
+
20
+ pid = run_on_fork(cmd, err_write, master, w)
21
+ Trapper.trap pid
22
+
23
+ t_out = consume_and_print slave, out, name, false
24
+ t_err = consume_and_print err_read, out, name, true
25
+
26
+ chars = []
27
+ t = consume_and_store r, chars
28
+
29
+ Process.wait pid
30
+
31
+ wait_until_streams_are_ready [slave, err_read]
32
+
33
+ join_threads [t_out, t_err, t]
34
+
35
+ close_streams [master, slave, err_read, err_write]
36
+
37
+ result = Marshal.load(chars.join)
38
+ raise result[:error] if result[:error]
39
+
40
+ result[:result]
41
+ end
42
+
43
+ def consume_and_store(reader, store)
44
+ t = Thread.new do
45
+ sleep 0.1 until reader.ready?
46
+ 3.times do
47
+ store << reader.getc while reader.ready?
48
+ end
49
+ end
50
+ t
51
+ end
52
+
53
+ def wait_until_streams_are_ready(streams)
54
+ streams.each do |s|
55
+ loop { break unless s.ready? }
56
+ end
57
+ end
58
+
59
+ def join_threads(threads)
60
+ threads.each do |t|
61
+ begin
62
+ Timeout.timeout(0.1) { t.join }
63
+ rescue Timeout::Error
64
+ nil
65
+ end
66
+ end
67
+ end
68
+
69
+ def close_streams(streams)
70
+ streams.each(&:close)
71
+ end
72
+
73
+ def run_on_fork(cmd, err_w, out_w, socket_w)
19
74
  pid = fork do
20
- STDERR.reopen err_write
21
- STDOUT.reopen master
75
+ STDERR.reopen err_w
76
+ STDOUT.reopen out_w
22
77
  begin
23
78
  result = cmd.call
24
79
  obj = { result: result, error: nil }
@@ -27,43 +82,12 @@ module PrettyMultitask
27
82
  new_error.set_backtrace e.backtrace
28
83
  Logger.new(STDERR).error new_error
29
84
  obj = { result: nil, error: new_error }
30
- File.open('/tmp/error','w+'){|f| f.puts obj.to_yaml}
31
- w.puts Marshal.dump(obj), 0
85
+ socket_w.puts Marshal.dump(obj), 0
32
86
  end
33
- w.puts Marshal.dump(obj), 0
34
- w.close
87
+ socket_w.puts Marshal.dump(obj), 0
88
+ socket_w.close
35
89
  end
36
-
37
- t_out = consume_and_print slave, out, name, false
38
- t_err = consume_and_print err_read, out, name, true
39
-
40
- %i[slave err_read].each do |e|
41
- loop { break unless binding.local_variable_get(e).ready? }
42
- end
43
-
44
- begin
45
- Timeout.timeout(0.1) do
46
- %i[t_out t_err].each { |e| binding.local_variable_get(e).join }
47
- end
48
- rescue Timeout::Error
49
- nil
50
- end
51
-
52
- %i[master slave err_read err_write].each { |e| binding.local_variable_get(e).close }
53
-
54
- chars = []
55
- t = Thread.new do
56
- sleep 0.1 until r.ready?
57
- chars << r.getc while r.ready?
58
- end
59
-
60
- Process.wait pid
61
- Timeout.timeout(1) { t.join }
62
-
63
- result = Marshal.load(chars.join)
64
- raise result[:error] if result[:error]
65
-
66
- result[:result]
90
+ pid
67
91
  end
68
92
 
69
93
  def consume_and_print(reader, writer, name, error = false)
@@ -74,10 +98,12 @@ module PrettyMultitask
74
98
  colored = Color.green format(fmt, name) unless error
75
99
  reader.each_line do |line|
76
100
  writer.write "#{colored} #{line}"
77
- File.open(@opts[:out_file],'a+') do |f|
101
+ next unless @opts[:out_file]
102
+
103
+ File.open(@opts[:out_file], 'a+') do |f|
78
104
  f.puts "#{colored} #{line}" if error
79
105
  f.puts "#{colored} #{line}" unless error
80
- end if @opts[:out_file]
106
+ end
81
107
  end
82
108
  rescue Errno::EIO
83
109
  nil
@@ -1,46 +1,54 @@
1
- module PrettyMultitask
1
+ # frozen_string_literal: true
2
2
 
3
- LOGGER ||= Logger.new STDOUT
3
+ module PrettyMultitask
4
+ # This class will run multiple callables in parallel using RunCallable which add a nice format
4
5
  class Runner
6
+ LOGGER ||= Logger.new STDOUT
5
7
  def initialize(jobs)
6
8
  @jobs = jobs
7
9
  @jobs.each do |j|
8
- [:name, :cmd ].each {|o| raise "#{o} must be specified for job #{j}" unless j[o] }
10
+ %i[name cmd].each { |o| raise "#{o} must be specified for job #{j}" unless j[o] }
9
11
  j[:out_file] = "/tmp/#{j[:name]}-#{Time.now.strftime('%s.%N')}"
12
+ FileUtils.touch j[:out_file]
10
13
  end
11
14
  end
12
-
15
+
13
16
  def run
14
17
  exec = Tlopo::Executor.new 10
15
-
16
- longest= 0
17
- @jobs.each {|job| longest = job[:name].length if job[:name].length > longest }
18
- @jobs.each {|job| job[:padding] = longest }
19
-
18
+
19
+ @jobs.each { |job| job[:padding] = longest_jobname }
20
20
  @jobs.each do |j|
21
21
  task = proc { j[:exit_status] = RunCallable.new(j).run }
22
22
  exec.schedule task
23
23
  end
24
24
  errors = exec.run.errors
25
-
25
+
26
+ print_out
27
+
28
+ unless errors.empty?
29
+ errors.each { |e| LOGGER.error e }
30
+ raise 'Found errors'
31
+ end
32
+ end
33
+
34
+ def print_out
26
35
  @jobs.each do |j|
27
36
  label = "[ #{j[:name]} ]"
28
37
  width = IO.console.winsize[-1]
29
- left = '='*((width - label.length)/2)
38
+ left = '=' * ((width - label.length) / 2)
30
39
  right = j[:name].length.even? ? left : left + '='
31
40
  puts "\n"
32
- puts Color.yellow left + label + right
41
+ puts Color.yellow left + label + right
33
42
  puts File.read j[:out_file]
34
- puts Color.yellow "="*width
43
+ puts Color.yellow '=' * width
35
44
  File.delete j[:out_file]
36
45
  end
37
-
38
- unless errors.empty?
39
- errors.each {|e| LOGGER.error e}
40
- raise 'Found errors'
41
- end
42
46
  end
43
-
44
- end
45
47
 
48
+ def longest_jobname
49
+ longest = 0
50
+ @jobs.each { |job| longest = job[:name].length if job[:name].length > longest }
51
+ longest
52
+ end
53
+ end
46
54
  end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PrettyMultitask
4
+ module Trapper
5
+ module_function
6
+
7
+ PIDS ||= Set.new
8
+ def trap(pid)
9
+ PIDS << pid
10
+ %w[SIGINT SIGTERM SIGHUP].each do |sig|
11
+ Signal.trap(sig) do
12
+ begin
13
+ PIDS.each { |pid| Process.kill sig, pid }
14
+ rescue Errno::ESRCH
15
+ nil
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module PrettyMultitask
2
- VERSION = "0.1.6"
4
+ VERSION = '0.1.11'
3
5
  end
@@ -1,38 +1,40 @@
1
- # coding: utf-8
2
- lib = File.expand_path("../lib", __FILE__)
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('lib', __dir__)
3
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require "pretty_multitask/version"
5
+ require 'pretty_multitask/version'
5
6
 
6
7
  Gem::Specification.new do |spec|
7
- spec.name = "pretty_multitask"
8
+ spec.name = 'pretty_multitask'
8
9
  spec.version = PrettyMultitask::VERSION
9
- spec.authors = ["Tiago Lopo Da Silva"]
10
- spec.email = ["tiagolopo@yahoo.com.br"]
10
+ spec.authors = ['Tiago Lopo Da Silva']
11
+ spec.email = ['tiagolopo@yahoo.com.br']
11
12
 
12
- spec.summary = %q{Multitask with pretty output for Rake}
13
- spec.description = %q{Multitask with pretty output for Rake}
14
- spec.homepage = "https://github.com/tlopo-ruby/tlopo-executor"
15
- spec.license = "MIT"
13
+ spec.summary = 'Multitask with pretty output for Rake'
14
+ spec.description = 'Multitask with pretty output for Rake'
15
+ spec.homepage = 'https://github.com/tlopo-ruby/tlopo-executor'
16
+ spec.license = 'MIT'
16
17
 
17
18
  # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
18
19
  # to allow pushing to a single host or delete this section to allow pushing to any host.
19
20
  if spec.respond_to?(:metadata)
20
- #spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
21
+ # spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
21
22
  else
22
- raise "RubyGems 2.0 or newer is required to protect against " \
23
- "public gem pushes."
23
+ raise 'RubyGems 2.0 or newer is required to protect against ' \
24
+ 'public gem pushes.'
24
25
  end
25
26
 
26
- spec.files = `git ls-files -z`.split("\x0").reject do |f|
27
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
27
28
  f.match(%r{^(test|spec|features)/})
28
29
  end
29
- spec.bindir = "exe"
30
+ spec.bindir = 'exe'
30
31
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
31
- spec.require_paths = ["lib"]
32
+ spec.require_paths = ['lib']
32
33
 
33
- spec.add_dependency "tlopo-executor", "~> 0.1.0"
34
+ spec.add_dependency 'tlopo-executor', '~> 0.1.0'
35
+ spec.add_dependency 'io-console', '~> 0.4'
34
36
 
35
- spec.add_development_dependency "bundler", "~> 1.15"
36
- spec.add_development_dependency "rake", "~> 10.0"
37
- spec.add_development_dependency "minitest", "~> 5.0"
37
+ spec.add_development_dependency 'bundler', '~> 1.15'
38
+ spec.add_development_dependency 'minitest', '~> 5.0'
39
+ spec.add_development_dependency 'rake', '~> 12.3.3'
38
40
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pretty_multitask
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
4
+ version: 0.1.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tiago Lopo Da Silva
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-04-09 00:00:00.000000000 Z
11
+ date: 2020-09-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: tlopo-executor
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: 0.1.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: io-console
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.4'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.4'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: bundler
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -39,33 +53,33 @@ dependencies:
39
53
  - !ruby/object:Gem::Version
40
54
  version: '1.15'
41
55
  - !ruby/object:Gem::Dependency
42
- name: rake
56
+ name: minitest
43
57
  requirement: !ruby/object:Gem::Requirement
44
58
  requirements:
45
59
  - - "~>"
46
60
  - !ruby/object:Gem::Version
47
- version: '10.0'
61
+ version: '5.0'
48
62
  type: :development
49
63
  prerelease: false
50
64
  version_requirements: !ruby/object:Gem::Requirement
51
65
  requirements:
52
66
  - - "~>"
53
67
  - !ruby/object:Gem::Version
54
- version: '10.0'
68
+ version: '5.0'
55
69
  - !ruby/object:Gem::Dependency
56
- name: minitest
70
+ name: rake
57
71
  requirement: !ruby/object:Gem::Requirement
58
72
  requirements:
59
73
  - - "~>"
60
74
  - !ruby/object:Gem::Version
61
- version: '5.0'
75
+ version: 12.3.3
62
76
  type: :development
63
77
  prerelease: false
64
78
  version_requirements: !ruby/object:Gem::Requirement
65
79
  requirements:
66
80
  - - "~>"
67
81
  - !ruby/object:Gem::Version
68
- version: '5.0'
82
+ version: 12.3.3
69
83
  description: Multitask with pretty output for Rake
70
84
  email:
71
85
  - tiagolopo@yahoo.com.br
@@ -74,6 +88,7 @@ extensions: []
74
88
  extra_rdoc_files: []
75
89
  files:
76
90
  - ".gitignore"
91
+ - ".rubocop.yml"
77
92
  - ".travis.yml"
78
93
  - CODE_OF_CONDUCT.md
79
94
  - Gemfile
@@ -86,13 +101,14 @@ files:
86
101
  - lib/pretty_multitask/color.rb
87
102
  - lib/pretty_multitask/run_callable.rb
88
103
  - lib/pretty_multitask/runner.rb
104
+ - lib/pretty_multitask/trapper.rb
89
105
  - lib/pretty_multitask/version.rb
90
106
  - pretty_multitask.gemspec
91
107
  homepage: https://github.com/tlopo-ruby/tlopo-executor
92
108
  licenses:
93
109
  - MIT
94
110
  metadata: {}
95
- post_install_message:
111
+ post_install_message:
96
112
  rdoc_options: []
97
113
  require_paths:
98
114
  - lib
@@ -107,8 +123,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
107
123
  - !ruby/object:Gem::Version
108
124
  version: '0'
109
125
  requirements: []
110
- rubygems_version: 3.0.3
111
- signing_key:
126
+ rubygems_version: 3.1.2
127
+ signing_key:
112
128
  specification_version: 4
113
129
  summary: Multitask with pretty output for Rake
114
130
  test_files: []