fasten 0.12.4 → 0.14.4
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 +4 -4
- data/.gitignore +2 -0
- data/.rubocop.yml +7 -3
- data/.ruby-version +1 -1
- data/.tool-versions +1 -1
- data/.travis.yml +2 -2
- data/CODE_OF_CONDUCT.md +3 -3
- data/Gemfile +4 -0
- data/Gemfile.lock +49 -37
- data/README.md +1 -1
- data/fasten.gemspec +11 -11
- data/lib/fasten/defaults.rb +2 -2
- data/lib/fasten/runner.rb +15 -2
- data/lib/fasten/std_thread_proxy.rb +28 -12
- data/lib/fasten/support/fork_worker.rb +7 -18
- data/lib/fasten/support/logger.rb +9 -5
- data/lib/fasten/support/state.rb +51 -1
- data/lib/fasten/support/stats.rb +15 -13
- data/lib/fasten/support/thread_worker.rb +0 -1
- data/lib/fasten/support/ui.rb +1 -1
- data/lib/fasten/support/yaml.rb +8 -6
- data/lib/fasten/task.rb +20 -3
- data/lib/fasten/task_manager.rb +7 -3
- data/lib/fasten/ui/console.rb +1 -1
- data/lib/fasten/ui/curses.rb +63 -14
- data/lib/fasten/version.rb +1 -1
- data/lib/fasten/worker.rb +1 -0
- metadata +19 -31
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 790a1d8191184aff7cc7db302aa2675d7222321fadc2762f23037f1ee31c4673
|
|
4
|
+
data.tar.gz: 19d21a87a855fdcb23a07ffd6ccb5787eaf33dfb1ce9eba8edb2e49ffa06ee62
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 19539cc0b6f947655a61533020107d8b7e023a3ed69de5aa7b88979f21c2d9ee71a9549c2f1d704880f23f7c666ac57a60ed86724c17c1f34bbe74c9f848b0c5
|
|
7
|
+
data.tar.gz: b3b679c630152b39a489748ace2293992ddef25791698599fe8302257898aec2b47d6ebd4e030e3ac1d75829b18d07581aa7e83995db5a7ef7993c9da8b4055b
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
Layout/LineLength:
|
|
2
2
|
Max: 160
|
|
3
3
|
Style/Documentation:
|
|
4
4
|
Enabled: false
|
|
@@ -23,10 +23,14 @@ Style:
|
|
|
23
23
|
Metrics/AbcSize:
|
|
24
24
|
Max: 25
|
|
25
25
|
Metrics/MethodLength:
|
|
26
|
-
Max:
|
|
26
|
+
Max: 20
|
|
27
27
|
Metrics/ParameterLists:
|
|
28
28
|
Max: 8
|
|
29
|
-
Layout/
|
|
29
|
+
Layout/HashAlignment:
|
|
30
30
|
EnforcedHashRocketStyle: table
|
|
31
31
|
Style/FormatStringToken:
|
|
32
32
|
Enabled: false
|
|
33
|
+
|
|
34
|
+
AllCops:
|
|
35
|
+
NewCops: enable
|
|
36
|
+
TargetRubyVersion: 2.6
|
data/.ruby-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
ruby-2.6.
|
|
1
|
+
ruby-2.6.6
|
data/.tool-versions
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
ruby 2.6.
|
|
1
|
+
ruby 2.6.6
|
data/.travis.yml
CHANGED
data/CODE_OF_CONDUCT.md
CHANGED
|
@@ -68,7 +68,7 @@ members of the project's leadership.
|
|
|
68
68
|
## Attribution
|
|
69
69
|
|
|
70
70
|
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
|
71
|
-
available at [
|
|
71
|
+
available at [https://contributor-covenant.org/version/1/4][version]
|
|
72
72
|
|
|
73
|
-
[homepage]:
|
|
74
|
-
[version]:
|
|
73
|
+
[homepage]: https://contributor-covenant.org
|
|
74
|
+
[version]: https://contributor-covenant.org/version/1/4/
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
fasten (0.
|
|
4
|
+
fasten (0.14.4)
|
|
5
5
|
binding_of_caller
|
|
6
6
|
hirb
|
|
7
7
|
os
|
|
@@ -10,59 +10,71 @@ PATH
|
|
|
10
10
|
GEM
|
|
11
11
|
remote: https://rubygems.org/
|
|
12
12
|
specs:
|
|
13
|
-
ast (2.4.
|
|
14
|
-
binding_of_caller (0.
|
|
13
|
+
ast (2.4.2)
|
|
14
|
+
binding_of_caller (1.0.0)
|
|
15
15
|
debug_inspector (>= 0.0.1)
|
|
16
|
-
coderay (1.1.
|
|
17
|
-
curses (1.
|
|
18
|
-
debug_inspector (
|
|
19
|
-
diff-lcs (1.
|
|
16
|
+
coderay (1.1.3)
|
|
17
|
+
curses (1.4.1)
|
|
18
|
+
debug_inspector (1.1.0)
|
|
19
|
+
diff-lcs (1.4.4)
|
|
20
20
|
hirb (0.7.3)
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
method_source (~> 0.9.0)
|
|
21
|
+
method_source (1.0.0)
|
|
22
|
+
os (1.1.1)
|
|
23
|
+
parallel (1.20.1)
|
|
24
|
+
parser (3.0.1.1)
|
|
25
|
+
ast (~> 2.4.1)
|
|
26
|
+
pry (0.14.1)
|
|
27
|
+
coderay (~> 1.1)
|
|
28
|
+
method_source (~> 1.0)
|
|
30
29
|
rainbow (3.0.0)
|
|
31
|
-
rake (
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
rspec-
|
|
36
|
-
|
|
37
|
-
rspec-
|
|
38
|
-
rspec-
|
|
30
|
+
rake (12.3.3)
|
|
31
|
+
regexp_parser (2.1.1)
|
|
32
|
+
rexml (3.2.5)
|
|
33
|
+
rspec (3.10.0)
|
|
34
|
+
rspec-core (~> 3.10.0)
|
|
35
|
+
rspec-expectations (~> 3.10.0)
|
|
36
|
+
rspec-mocks (~> 3.10.0)
|
|
37
|
+
rspec-core (3.10.1)
|
|
38
|
+
rspec-support (~> 3.10.0)
|
|
39
|
+
rspec-expectations (3.10.1)
|
|
39
40
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
40
|
-
rspec-support (~> 3.
|
|
41
|
-
rspec-mocks (3.
|
|
41
|
+
rspec-support (~> 3.10.0)
|
|
42
|
+
rspec-mocks (3.10.2)
|
|
42
43
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
43
|
-
rspec-support (~> 3.
|
|
44
|
-
rspec-support (3.
|
|
45
|
-
rubocop (
|
|
46
|
-
jaro_winkler (~> 1.5.1)
|
|
44
|
+
rspec-support (~> 3.10.0)
|
|
45
|
+
rspec-support (3.10.2)
|
|
46
|
+
rubocop (1.16.0)
|
|
47
47
|
parallel (~> 1.10)
|
|
48
|
-
parser (>=
|
|
48
|
+
parser (>= 3.0.0.0)
|
|
49
49
|
rainbow (>= 2.2.2, < 4.0)
|
|
50
|
+
regexp_parser (>= 1.8, < 3.0)
|
|
51
|
+
rexml
|
|
52
|
+
rubocop-ast (>= 1.7.0, < 2.0)
|
|
50
53
|
ruby-progressbar (~> 1.7)
|
|
51
|
-
unicode-display_width (>= 1.4.0, <
|
|
52
|
-
|
|
53
|
-
|
|
54
|
+
unicode-display_width (>= 1.4.0, < 3.0)
|
|
55
|
+
rubocop-ast (1.7.0)
|
|
56
|
+
parser (>= 3.0.1.1)
|
|
57
|
+
rubocop-rake (0.5.1)
|
|
58
|
+
rubocop
|
|
59
|
+
rubocop-rspec (2.3.0)
|
|
60
|
+
rubocop (~> 1.0)
|
|
61
|
+
rubocop-ast (>= 1.1.0)
|
|
62
|
+
ruby-progressbar (1.11.0)
|
|
63
|
+
unicode-display_width (2.0.0)
|
|
54
64
|
|
|
55
65
|
PLATFORMS
|
|
56
66
|
ruby
|
|
57
67
|
|
|
58
68
|
DEPENDENCIES
|
|
59
|
-
bundler (~> 1.17.1)
|
|
60
69
|
curses
|
|
61
70
|
fasten!
|
|
71
|
+
os
|
|
62
72
|
pry
|
|
63
|
-
rake (~>
|
|
73
|
+
rake (~> 12.0)
|
|
64
74
|
rspec (~> 3.0)
|
|
65
75
|
rubocop
|
|
76
|
+
rubocop-rake
|
|
77
|
+
rubocop-rspec
|
|
66
78
|
|
|
67
79
|
BUNDLED WITH
|
|
68
|
-
1.17.
|
|
80
|
+
1.17.2
|
data/README.md
CHANGED
|
@@ -40,7 +40,7 @@ It has been released so people can try it and make feature requests, comments an
|
|
|
40
40
|
- [x] Press ⬅️ or ➡️ keys to dynamically increase/decrease number of jobs
|
|
41
41
|
- [ ] Use ⬆️ and ⬇️ to select tasks
|
|
42
42
|
- [ ] Calculate ETA, assuming all tasks take same time
|
|
43
|
-
- [
|
|
43
|
+
- [x] Calculate ETA, based on saved tasks statistics
|
|
44
44
|
- [ ] Live tail -f of selected tasks
|
|
45
45
|
|
|
46
46
|
### UI/Console
|
data/fasten.gemspec
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
3
|
-
require 'fasten/version'
|
|
1
|
+
require_relative 'lib/fasten/version'
|
|
4
2
|
require 'os'
|
|
5
3
|
|
|
6
4
|
Gem::Specification.new do |spec|
|
|
@@ -13,29 +11,31 @@ Gem::Specification.new do |spec|
|
|
|
13
11
|
spec.description = 'Fasten your seatbelts! Run jobs in parallel, intelligently.'
|
|
14
12
|
spec.homepage = 'https://github.com/a0/a0-fasten-ruby/'
|
|
15
13
|
spec.license = 'MIT'
|
|
14
|
+
spec.required_ruby_version = Gem::Requirement.new('>= 2.6.0')
|
|
15
|
+
|
|
16
|
+
spec.metadata['allowed_push_host'] = 'https://rubygems.org'
|
|
17
|
+
|
|
18
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
|
19
|
+
spec.metadata['source_code_uri'] = spec.homepage
|
|
20
|
+
spec.metadata['source_code_uri'] = 'https://github.com/a0/a0-fasten-ruby/CHANGELOG.md'
|
|
16
21
|
|
|
17
22
|
# Specify which files should be added to the gem when it is released.
|
|
18
23
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
|
19
|
-
spec.files
|
|
24
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
|
20
25
|
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features|demo)/}) }
|
|
21
26
|
end
|
|
22
27
|
spec.bindir = 'exe'
|
|
23
28
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
24
29
|
spec.require_paths = ['lib']
|
|
25
30
|
|
|
26
|
-
spec.add_development_dependency 'bundler', '~> 1.17.1'
|
|
27
31
|
spec.add_development_dependency 'curses' unless OS.windows?
|
|
28
32
|
spec.add_development_dependency 'pry'
|
|
29
|
-
spec.add_development_dependency 'rake', '~> 10.0'
|
|
30
|
-
spec.add_development_dependency 'rspec', '~> 3.0'
|
|
31
33
|
spec.add_development_dependency 'rubocop'
|
|
34
|
+
spec.add_development_dependency 'rubocop-rake'
|
|
35
|
+
spec.add_development_dependency 'rubocop-rspec'
|
|
32
36
|
|
|
33
37
|
spec.add_runtime_dependency 'binding_of_caller'
|
|
34
38
|
spec.add_runtime_dependency 'hirb'
|
|
35
39
|
spec.add_runtime_dependency 'os'
|
|
36
40
|
spec.add_runtime_dependency 'parallel'
|
|
37
|
-
|
|
38
|
-
raise 'RubyGems 2.0 or newer is required to protect against public gem pushes.' unless spec.respond_to?(:metadata)
|
|
39
|
-
|
|
40
|
-
spec.metadata['allowed_push_host'] = 'https://rubygems.org'
|
|
41
41
|
end
|
data/lib/fasten/defaults.rb
CHANGED
|
@@ -35,13 +35,13 @@ module Fasten
|
|
|
35
35
|
|
|
36
36
|
require 'fasten/ui/curses'
|
|
37
37
|
|
|
38
|
-
@default_ui_mode =
|
|
38
|
+
@default_ui_mode = $stdin.tty? && $stdout.tty? ? :curses : :console
|
|
39
39
|
rescue StandardError, LoadError
|
|
40
40
|
@default_ui_mode = :console
|
|
41
41
|
end
|
|
42
42
|
|
|
43
43
|
def default_developer
|
|
44
|
-
|
|
44
|
+
$stdin.tty? && $stdout.tty?
|
|
45
45
|
end
|
|
46
46
|
|
|
47
47
|
def default_priority
|
data/lib/fasten/runner.rb
CHANGED
|
@@ -37,7 +37,6 @@ module Fasten
|
|
|
37
37
|
end
|
|
38
38
|
|
|
39
39
|
initialize_stats
|
|
40
|
-
initialize_logger
|
|
41
40
|
end
|
|
42
41
|
|
|
43
42
|
def task(name, **opts, &block)
|
|
@@ -51,9 +50,12 @@ module Fasten
|
|
|
51
50
|
end
|
|
52
51
|
|
|
53
52
|
def perform
|
|
53
|
+
initialize_logger
|
|
54
|
+
StdThreadProxy.install if use_threads
|
|
54
55
|
self.state = :RUNNING
|
|
55
56
|
log_ini self, running_counters
|
|
56
57
|
load_stats
|
|
58
|
+
touch_task_logs
|
|
57
59
|
|
|
58
60
|
run_ui do
|
|
59
61
|
perform_loop
|
|
@@ -66,9 +68,20 @@ module Fasten
|
|
|
66
68
|
|
|
67
69
|
stats_summary if summary
|
|
68
70
|
ensure
|
|
71
|
+
StdThreadProxy.uninstall if use_threads
|
|
72
|
+
close_logger
|
|
69
73
|
save_stats
|
|
70
74
|
end
|
|
71
75
|
|
|
76
|
+
def touch_task_logs
|
|
77
|
+
FileUtils.mkdir_p "#{fasten_dir}/log/task/"
|
|
78
|
+
tasks.each do |task|
|
|
79
|
+
path = "#{fasten_dir}/log/task/#{task.name}.log"
|
|
80
|
+
puts "Fasten: creating log #{path}"
|
|
81
|
+
FileUtils.touch path
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
72
85
|
def map(list, &block)
|
|
73
86
|
list.each do |item|
|
|
74
87
|
task item.to_s, request: item, &block
|
|
@@ -218,7 +231,7 @@ module Fasten
|
|
|
218
231
|
end
|
|
219
232
|
|
|
220
233
|
def find_or_create_worker(worker_class:)
|
|
221
|
-
worker = workers.find { |item| item.
|
|
234
|
+
worker = workers.find { |item| item.instance_of?(worker_class) && item.running_task.nil? }
|
|
222
235
|
|
|
223
236
|
unless worker
|
|
224
237
|
@worker_id = (@worker_id || 0) + 1
|
|
@@ -1,24 +1,28 @@
|
|
|
1
1
|
module Fasten
|
|
2
2
|
class StdThreadProxy
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
attr_reader :fasten_original
|
|
4
|
+
|
|
5
|
+
def initialize(fasten_original)
|
|
6
|
+
@fasten_original = fasten_original
|
|
5
7
|
end
|
|
6
8
|
|
|
7
|
-
def respond_to?(
|
|
8
|
-
target = Thread.current[:FASTEN_STD_THREAD_PROXY] || @
|
|
9
|
-
target.send :respond_to?,
|
|
9
|
+
def respond_to?(*args)
|
|
10
|
+
target = Thread.current[:FASTEN_STD_THREAD_PROXY] || @fasten_original
|
|
11
|
+
target.send :respond_to?, *args
|
|
10
12
|
end
|
|
11
13
|
|
|
12
14
|
private
|
|
13
15
|
|
|
14
|
-
def respond_to_missing?(
|
|
15
|
-
target = Thread.current[:FASTEN_STD_THREAD_PROXY] || @
|
|
16
|
-
target.send :respond_to_missing?,
|
|
16
|
+
def respond_to_missing?(*args)
|
|
17
|
+
target = Thread.current[:FASTEN_STD_THREAD_PROXY] || @fasten_original
|
|
18
|
+
target.send :respond_to_missing?, *args
|
|
17
19
|
end
|
|
18
20
|
|
|
19
|
-
def method_missing(method, *args, &block)
|
|
20
|
-
target = Thread.current[:FASTEN_STD_THREAD_PROXY] || @
|
|
21
|
+
def method_missing(method, *args, &block)
|
|
22
|
+
target = Thread.current[:FASTEN_STD_THREAD_PROXY] || @fasten_original
|
|
21
23
|
target.send method, *args, &block
|
|
24
|
+
rescue StandardError => e
|
|
25
|
+
raise e
|
|
22
26
|
end
|
|
23
27
|
|
|
24
28
|
class << self
|
|
@@ -28,8 +32,9 @@ module Fasten
|
|
|
28
32
|
oldverbose = $VERBOSE
|
|
29
33
|
$VERBOSE = nil
|
|
30
34
|
|
|
31
|
-
Object.const_set :STDOUT, StdThreadProxy.new(STDOUT)
|
|
32
|
-
Object.const_set :STDERR, StdThreadProxy.new(STDERR)
|
|
35
|
+
Object.const_set :STDOUT, StdThreadProxy.new(STDOUT) # rubocop:disable Style/GlobalStdStream
|
|
36
|
+
Object.const_set :STDERR, StdThreadProxy.new(STDERR) # rubocop:disable Style/GlobalStdStream
|
|
37
|
+
|
|
33
38
|
$stdout = StdThreadProxy.new $stdout
|
|
34
39
|
$stderr = StdThreadProxy.new $stderr
|
|
35
40
|
|
|
@@ -49,7 +54,18 @@ module Fasten
|
|
|
49
54
|
def uninstall
|
|
50
55
|
return unless @installed
|
|
51
56
|
|
|
57
|
+
oldverbose = $VERBOSE
|
|
58
|
+
$VERBOSE = nil
|
|
59
|
+
|
|
60
|
+
Object.const_set :STDOUT, STDOUT.fasten_original if STDOUT.is_a? StdThreadProxy # rubocop:disable Style/GlobalStdStream
|
|
61
|
+
Object.const_set :STDERR, STDERR.fasten_original if STDERR.is_a? StdThreadProxy # rubocop:disable Style/GlobalStdStream
|
|
62
|
+
|
|
63
|
+
$stdout = $stdout.fasten_original if $stdout.is_a? StdThreadProxy
|
|
64
|
+
$stderr = $stderr.fasten_original if $stderr.is_a? StdThreadProxy
|
|
65
|
+
|
|
52
66
|
@installed = nil
|
|
67
|
+
ensure
|
|
68
|
+
$VERBOSE = oldverbose
|
|
53
69
|
end
|
|
54
70
|
end
|
|
55
71
|
end
|
|
@@ -75,12 +75,8 @@ module Fasten
|
|
|
75
75
|
end
|
|
76
76
|
|
|
77
77
|
def redirect_std(path)
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
@saved_stdout_instance = $stdout.clone
|
|
81
|
-
@saved_stderr_instance = $stderr.clone
|
|
82
|
-
@saved_stdout_constant = STDOUT.clone
|
|
83
|
-
@saved_stderr_constant = STDERR.clone
|
|
78
|
+
@saved_stdout_constant ||= $stdout.clone
|
|
79
|
+
@saved_stderr_constant ||= $stderr.clone
|
|
84
80
|
|
|
85
81
|
FileUtils.mkdir_p File.dirname(path)
|
|
86
82
|
@redirect_log = File.new path, 'a'
|
|
@@ -88,22 +84,15 @@ module Fasten
|
|
|
88
84
|
|
|
89
85
|
$stdout.reopen @redirect_log
|
|
90
86
|
$stderr.reopen @redirect_log
|
|
91
|
-
|
|
92
|
-
|
|
87
|
+
|
|
88
|
+
logger.reopen(@redirect_log)
|
|
93
89
|
end
|
|
94
90
|
|
|
95
91
|
def restore_std
|
|
96
|
-
oldverbose = $VERBOSE
|
|
97
|
-
$VERBOSE = nil
|
|
98
|
-
|
|
99
|
-
$stdout = @saved_stdout_instance
|
|
100
|
-
$stderr = @saved_stderr_instance
|
|
101
|
-
Object.const_set :STDOUT, @saved_stdout_constant
|
|
102
|
-
Object.const_set :STDERR, @saved_stderr_constant
|
|
103
|
-
|
|
104
92
|
@redirect_log.close
|
|
105
|
-
|
|
106
|
-
$
|
|
93
|
+
|
|
94
|
+
$stdout.reopen @saved_stdout_constant
|
|
95
|
+
$stderr.reopen @saved_stderr_constant
|
|
107
96
|
end
|
|
108
97
|
end
|
|
109
98
|
end
|
|
@@ -26,14 +26,18 @@ module Fasten
|
|
|
26
26
|
if log_file
|
|
27
27
|
self.log_file = log_file
|
|
28
28
|
else
|
|
29
|
-
|
|
30
|
-
FileUtils.mkdir_p File.dirname(
|
|
31
|
-
self.log_file = File.new(log_path, 'a')
|
|
32
|
-
self.log_file.sync = true
|
|
29
|
+
self.log_file ||= "#{fasten_dir}/log/#{kind}/#{name}.log"
|
|
30
|
+
FileUtils.mkdir_p File.dirname(self.log_file)
|
|
33
31
|
end
|
|
32
|
+
|
|
33
|
+
close_logger
|
|
34
34
|
self.logger = ::Logger.new self.log_file, level: Fasten.logger.level, progname: Fasten.logger.progname
|
|
35
35
|
end
|
|
36
36
|
|
|
37
|
+
def close_logger
|
|
38
|
+
logger.close if logger.is_a? ::Logger
|
|
39
|
+
end
|
|
40
|
+
|
|
37
41
|
def log_ini(object, message = nil)
|
|
38
42
|
object.ini ||= Time.new
|
|
39
43
|
log_info "Ini #{object.state} #{object.class} #{object} #{message}"
|
|
@@ -51,7 +55,7 @@ end
|
|
|
51
55
|
|
|
52
56
|
Fasten.logger ||=
|
|
53
57
|
begin
|
|
54
|
-
Logger.new
|
|
58
|
+
Logger.new $stdout, level: Logger::DEBUG, progname: $PROGRAM_NAME
|
|
55
59
|
rescue StandardError
|
|
56
60
|
nil
|
|
57
61
|
end
|
data/lib/fasten/support/state.rb
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
require 'digest'
|
|
2
|
+
|
|
1
3
|
module Fasten
|
|
2
4
|
module Support
|
|
3
5
|
module State
|
|
4
|
-
attr_accessor :error, :ini, :fin, :dif, :
|
|
6
|
+
attr_accessor :error, :ini, :fin, :dif, :runner
|
|
5
7
|
attr_writer :state
|
|
6
8
|
|
|
7
9
|
def state
|
|
@@ -27,6 +29,54 @@ module Fasten
|
|
|
27
29
|
def quitting?
|
|
28
30
|
state == :QUITTING
|
|
29
31
|
end
|
|
32
|
+
|
|
33
|
+
def last_stat
|
|
34
|
+
return @last_stat if defined? @last_stat
|
|
35
|
+
|
|
36
|
+
return {} unless @runner
|
|
37
|
+
|
|
38
|
+
@last_stat = runner.stats_last(self)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def last_avg
|
|
42
|
+
@last_avg ||= last_stat['avg']
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def last_err
|
|
46
|
+
@last_err ||= last_stat['err']
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def deps
|
|
50
|
+
return @deps if defined? @deps
|
|
51
|
+
|
|
52
|
+
str = deps_str
|
|
53
|
+
|
|
54
|
+
@deps = str && Digest::SHA1.hexdigest(str)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def deps_str
|
|
58
|
+
if is_a? Fasten::Task
|
|
59
|
+
deps_str_task
|
|
60
|
+
elsif is_a? Fasten::Runner
|
|
61
|
+
deps_str_runner
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def deps_str_task
|
|
66
|
+
if after.is_a? Array
|
|
67
|
+
after.sort_by do |task|
|
|
68
|
+
task.is_a?(Fasten::Task) ? task.name : task
|
|
69
|
+
end&.join(', ')
|
|
70
|
+
else
|
|
71
|
+
after
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def deps_str_runner
|
|
76
|
+
tasks.sort_by(&:name).map do |task|
|
|
77
|
+
[task.name, task.deps_str].compact.join(': ')
|
|
78
|
+
end.join("\n")
|
|
79
|
+
end
|
|
30
80
|
end
|
|
31
81
|
end
|
|
32
82
|
end
|
data/lib/fasten/support/stats.rb
CHANGED
|
@@ -5,8 +5,8 @@ require 'fileutils'
|
|
|
5
5
|
module Fasten
|
|
6
6
|
module Support
|
|
7
7
|
module Stats
|
|
8
|
-
attr_writer :stats_data, :stats_entries
|
|
9
|
-
attr_reader :stats_path
|
|
8
|
+
# attr_writer :stats_data, :stats_entries
|
|
9
|
+
# attr_reader :stats_path
|
|
10
10
|
|
|
11
11
|
def initialize_stats
|
|
12
12
|
return unless stats
|
|
@@ -20,14 +20,17 @@ module Fasten
|
|
|
20
20
|
def load_stats
|
|
21
21
|
return unless @stats_path && File.exist?(@stats_path)
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
CSV.foreach(@stats_path, headers: true) do |row|
|
|
23
|
+
@stats_data = []
|
|
24
|
+
CSV.foreach(@stats_path, headers: true, converters: [:all]) do |row|
|
|
25
25
|
stats_data << row.to_h
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
@tasks.each do |task|
|
|
29
|
-
|
|
29
|
+
task.runner = self
|
|
30
|
+
task.last_stat
|
|
30
31
|
end
|
|
32
|
+
self.runner = self
|
|
33
|
+
last_stat
|
|
31
34
|
|
|
32
35
|
@tasks.waiting = nil
|
|
33
36
|
rescue StandardError
|
|
@@ -37,7 +40,7 @@ module Fasten
|
|
|
37
40
|
def save_stats
|
|
38
41
|
return unless @stats_path && stats_data
|
|
39
42
|
|
|
40
|
-
keys = %w[state kind name run cnt avg std err ini fin]
|
|
43
|
+
keys = %w[state kind name run cnt avg std err ini fin deps]
|
|
41
44
|
|
|
42
45
|
CSV.open(@stats_path, 'wb') do |csv|
|
|
43
46
|
csv << keys
|
|
@@ -55,6 +58,7 @@ module Fasten
|
|
|
55
58
|
'ini' => target.ini.to_f,
|
|
56
59
|
'fin' => target.fin.to_f,
|
|
57
60
|
'run' => target.fin - target.ini,
|
|
61
|
+
'deps' => target.deps,
|
|
58
62
|
'worker' => target.respond_to?(:worker) ? target.worker.name : nil }
|
|
59
63
|
end
|
|
60
64
|
|
|
@@ -73,7 +77,7 @@ module Fasten
|
|
|
73
77
|
stats_data << entry
|
|
74
78
|
stats_entries << entry
|
|
75
79
|
|
|
76
|
-
history =
|
|
80
|
+
history = stats_run_history(entry)
|
|
77
81
|
|
|
78
82
|
update_stats(history, entry)
|
|
79
83
|
end
|
|
@@ -120,14 +124,12 @@ module Fasten
|
|
|
120
124
|
task: hformat(sub), runner: hformat(tot, sub), saved: hformat(sub - tot, sub), jobs: jobs.to_s)
|
|
121
125
|
end
|
|
122
126
|
|
|
123
|
-
def
|
|
124
|
-
stats_data.select { |
|
|
127
|
+
def stats_run_history(entry)
|
|
128
|
+
stats_data.select { |item| %w[state kind name deps].all? { |key| item[key] == entry[key] } }.map { |item| item['run'] }
|
|
125
129
|
end
|
|
126
130
|
|
|
127
|
-
def stats_last(
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
item.last = stats_data.select { |e| e['kind'] == item.kind && e['name'] == item.name }.last || {}
|
|
131
|
+
def stats_last(target)
|
|
132
|
+
stats_data.select { |item| %w[kind name deps].all? { |key| item[key] == target.send(key) } }.last || {}
|
|
131
133
|
end
|
|
132
134
|
|
|
133
135
|
def update_stats(history, entry)
|
data/lib/fasten/support/ui.rb
CHANGED
|
@@ -6,7 +6,7 @@ module Fasten
|
|
|
6
6
|
def ui
|
|
7
7
|
require 'fasten/ui/curses'
|
|
8
8
|
|
|
9
|
-
@ui ||= if ui_mode.to_s == 'curses' &&
|
|
9
|
+
@ui ||= if ui_mode.to_s == 'curses' && $stdin.tty? && $stdout.tty?
|
|
10
10
|
Fasten::UI::Curses.new(runner: self)
|
|
11
11
|
else
|
|
12
12
|
Fasten::UI::Console.new(runner: self)
|
data/lib/fasten/support/yaml.rb
CHANGED
|
@@ -5,9 +5,10 @@ module Fasten
|
|
|
5
5
|
module Yaml
|
|
6
6
|
def load_yaml(path)
|
|
7
7
|
items = YAML.safe_load(File.read(path)).each do |name, params|
|
|
8
|
-
|
|
8
|
+
case params
|
|
9
|
+
when String
|
|
9
10
|
params = { after: params }
|
|
10
|
-
|
|
11
|
+
when Hash
|
|
11
12
|
transform_params(params)
|
|
12
13
|
else
|
|
13
14
|
params = {}
|
|
@@ -38,15 +39,16 @@ module Fasten
|
|
|
38
39
|
protected
|
|
39
40
|
|
|
40
41
|
def transform_params(params)
|
|
41
|
-
params.keys
|
|
42
|
-
|
|
42
|
+
keys = params.keys
|
|
43
|
+
|
|
44
|
+
keys.each do |key|
|
|
45
|
+
val = params.delete key
|
|
43
46
|
|
|
44
47
|
if val.is_a?(String) && (match = %r{^/(.+)/$}.match(val))
|
|
45
48
|
val = Regexp.new(match[1])
|
|
46
49
|
end
|
|
47
50
|
|
|
48
|
-
params[
|
|
49
|
-
params.delete(k)
|
|
51
|
+
params[key.to_sym] = val
|
|
50
52
|
end
|
|
51
53
|
end
|
|
52
54
|
end
|
data/lib/fasten/task.rb
CHANGED
|
@@ -4,8 +4,7 @@ module Fasten
|
|
|
4
4
|
class Task
|
|
5
5
|
include Fasten::Support::State
|
|
6
6
|
|
|
7
|
-
attr_accessor :name, :after, :shell, :ruby, :worker_class
|
|
8
|
-
attr_accessor :dependants, :depends, :request, :response, :worker, :run_score, :weight, :block
|
|
7
|
+
attr_accessor :name, :after, :shell, :ruby, :worker_class, :dependants, :depends, :request, :response, :worker, :run_score, :weight, :block
|
|
9
8
|
|
|
10
9
|
def initialize(name:, shell: nil, ruby: nil, block: nil, request: nil, after: nil, weight: 1, worker_class: nil)
|
|
11
10
|
self.name = name
|
|
@@ -16,6 +15,20 @@ module Fasten
|
|
|
16
15
|
self.after = after
|
|
17
16
|
self.weight = weight
|
|
18
17
|
self.worker_class = worker_class
|
|
18
|
+
|
|
19
|
+
# ObjectSpace.define_finalizer(self) do
|
|
20
|
+
# puts "I am dying! pid: #{Process.pid} thread: #{Thread.current} TASK #{@name}"
|
|
21
|
+
# end
|
|
22
|
+
|
|
23
|
+
block&.object_id
|
|
24
|
+
# block && begin
|
|
25
|
+
|
|
26
|
+
# # puts "block_id: #{block.object_id} for task #{@name}"
|
|
27
|
+
# end
|
|
28
|
+
|
|
29
|
+
# block && ObjectSpace.define_finalizer(block) do
|
|
30
|
+
# puts "I am dying! pid: #{Process.pid} thread: #{Thread.current} TASK #{@name} BLOCK"
|
|
31
|
+
# end
|
|
19
32
|
end
|
|
20
33
|
|
|
21
34
|
def marshal_dump
|
|
@@ -24,7 +37,11 @@ module Fasten
|
|
|
24
37
|
|
|
25
38
|
def marshal_load(data)
|
|
26
39
|
@name, @state, @ini, @fin, @dif, @request, @response, @shell, @ruby, block_id, @error = data
|
|
27
|
-
@block =
|
|
40
|
+
@block = begin
|
|
41
|
+
ObjectSpace._id2ref block_id.to_i if block_id
|
|
42
|
+
rescue StandardError
|
|
43
|
+
# pass
|
|
44
|
+
end
|
|
28
45
|
|
|
29
46
|
raise "Sorry, unable to get block for task #{self}, please try using threads" if block_id && !@block.is_a?(Proc)
|
|
30
47
|
end
|
data/lib/fasten/task_manager.rb
CHANGED
|
@@ -2,7 +2,7 @@ module Fasten
|
|
|
2
2
|
class TaskManager < Array # rubocop:disable Metrics/ClassLength
|
|
3
3
|
attr_reader :done, :failed, :pending, :running, :targets, :runner
|
|
4
4
|
|
|
5
|
-
def initialize(targets: []
|
|
5
|
+
def initialize(runner:, targets: [])
|
|
6
6
|
super()
|
|
7
7
|
|
|
8
8
|
@map = {}
|
|
@@ -120,6 +120,10 @@ module Fasten
|
|
|
120
120
|
mark_needed(task)
|
|
121
121
|
end
|
|
122
122
|
|
|
123
|
+
setup_pending
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def setup_pending
|
|
123
127
|
@pending.reject { |task| task.state == :NEED }.each do |task|
|
|
124
128
|
@pending.delete task
|
|
125
129
|
delete task
|
|
@@ -159,8 +163,8 @@ module Fasten
|
|
|
159
163
|
when :dependants_avg
|
|
160
164
|
@waiting.sort_by!.with_index do |task, index|
|
|
161
165
|
task.state = :WAIT
|
|
162
|
-
last_avg = task.
|
|
163
|
-
[-task.run_score, -last_avg
|
|
166
|
+
last_avg = task.last_avg || 0
|
|
167
|
+
[-task.run_score, -last_avg, index]
|
|
164
168
|
end
|
|
165
169
|
else
|
|
166
170
|
raise "Unknown priority #{@runner.priority}"
|
data/lib/fasten/ui/console.rb
CHANGED
|
@@ -49,7 +49,7 @@ module Fasten
|
|
|
49
49
|
return unless old.count != orig.count
|
|
50
50
|
|
|
51
51
|
(orig - old).each do |task|
|
|
52
|
-
puts "Time: #{hformat Time.new - runner.ini} #{message} #{hformat task.dif} Task #{task}"
|
|
52
|
+
puts "Time: #{hformat Time.new - runner.ini} #{message} #{hformat task.dif} #{task.worker} Task #{task}"
|
|
53
53
|
old << task
|
|
54
54
|
end
|
|
55
55
|
end
|
data/lib/fasten/ui/curses.rb
CHANGED
|
@@ -16,6 +16,8 @@ module Fasten
|
|
|
16
16
|
|
|
17
17
|
SPINNER_STR = '⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏'
|
|
18
18
|
SPINNER_LEN = SPINNER_STR.length
|
|
19
|
+
MOON_STR = '🌑🌒🌓🌔🌕'
|
|
20
|
+
MOON_LEN = MOON_STR.length
|
|
19
21
|
PROGRESSBAR_STR = ' ▏▎▍▌▋▊▉'
|
|
20
22
|
PROGRESSBAR_LEN = PROGRESSBAR_STR.length
|
|
21
23
|
|
|
@@ -37,7 +39,7 @@ module Fasten
|
|
|
37
39
|
|
|
38
40
|
def draw_title
|
|
39
41
|
ui_text_aligned(0, :left, 'Fasten your seatbelts!')
|
|
40
|
-
ui_text_aligned(0, :center, name
|
|
42
|
+
ui_text_aligned(0, :center, "#{name} #{$PID}")
|
|
41
43
|
ui_text_aligned(0, :right, Time.new.to_s)
|
|
42
44
|
end
|
|
43
45
|
|
|
@@ -125,11 +127,12 @@ module Fasten
|
|
|
125
127
|
end
|
|
126
128
|
|
|
127
129
|
def ui_jobs_summary
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
130
|
+
running = tasks.running.count
|
|
131
|
+
waiting = tasks.waiting.count
|
|
132
|
+
working = workers.count
|
|
133
|
+
idle = working - running
|
|
131
134
|
|
|
132
|
-
"Procs running: #{
|
|
135
|
+
"Procs running: #{running} idle: #{idle} waiting: #{waiting} #{runner.use_threads ? 'threads' : 'processes'}: #{jobs}"
|
|
133
136
|
end
|
|
134
137
|
|
|
135
138
|
def ui_jobs
|
|
@@ -194,6 +197,22 @@ module Fasten
|
|
|
194
197
|
end
|
|
195
198
|
end
|
|
196
199
|
|
|
200
|
+
def ui_task_clock(task, cur, avg)
|
|
201
|
+
return unless task.ini
|
|
202
|
+
|
|
203
|
+
dif = cur - task.ini
|
|
204
|
+
avg = avg.to_f
|
|
205
|
+
if task.ini && avg.positive?
|
|
206
|
+
percent = dif / avg
|
|
207
|
+
index = (percent * MOON_LEN).to_i
|
|
208
|
+
index = MOON_LEN - 1 if index > MOON_LEN - 1
|
|
209
|
+
|
|
210
|
+
format ' %.2f s %s ', dif, MOON_STR[index]
|
|
211
|
+
else
|
|
212
|
+
format ' %.2f s ', dif
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
|
|
197
216
|
def ui_task_color(task)
|
|
198
217
|
rev = task == selected ? A_REVERSE : 0
|
|
199
218
|
|
|
@@ -219,6 +238,9 @@ module Fasten
|
|
|
219
238
|
|
|
220
239
|
str ||= icon ? "#{icon} #{task}" : task.to_s
|
|
221
240
|
|
|
241
|
+
delta = x + str.length - n_cols
|
|
242
|
+
str = str[0...-delta] if delta.positive?
|
|
243
|
+
|
|
222
244
|
attrset attrs if attrs
|
|
223
245
|
addstr str
|
|
224
246
|
attroff attrs if attrs
|
|
@@ -231,14 +253,38 @@ module Fasten
|
|
|
231
253
|
worker.spinner = (worker.spinner + 1) % SPINNER_LEN if worker.running?
|
|
232
254
|
end
|
|
233
255
|
|
|
256
|
+
cur = Time.new
|
|
257
|
+
|
|
234
258
|
count_done = tasks.done.count
|
|
235
259
|
count_total = tasks.count
|
|
236
260
|
tl = count_total.to_s.length
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
261
|
+
percentstr = count_total.positive? && " #{(count_done * 100 / count_total).to_i}%"
|
|
262
|
+
elapsed_str = format ' %.2f s', (dif = cur - runner.ini) if runner.ini
|
|
263
|
+
|
|
264
|
+
@stat_str ||= begin
|
|
265
|
+
@runner_last_avg = runner.last_avg
|
|
266
|
+
if runner.last_avg && runner.last_err
|
|
267
|
+
format '≈ %.2f s ± %.2f', runner.last_avg, runner.last_err
|
|
268
|
+
elsif runner.last_avg
|
|
269
|
+
format '≈ %.2f s', runner.last_avg
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
end_str = [elapsed_str, @stat_str].compact.join(' ')
|
|
274
|
+
|
|
275
|
+
if @runner_last_avg
|
|
276
|
+
a = dif
|
|
277
|
+
b = @runner_last_avg
|
|
278
|
+
else
|
|
279
|
+
a = count_done
|
|
280
|
+
b = count_total
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
col_ini = ui_text_aligned(2, :left, format("Tasks %#{tl}d/%d%s", count_done, count_total, percentstr)) + 1
|
|
284
|
+
col_fin = n_cols - 1 - end_str.length
|
|
285
|
+
ui_text_aligned(2, :right, end_str)
|
|
240
286
|
|
|
241
|
-
ui_progressbar(2, col_ini, col_fin,
|
|
287
|
+
ui_progressbar(2, col_ini, col_fin, a, b)
|
|
242
288
|
|
|
243
289
|
max = 2
|
|
244
290
|
list = tasks.sort_by.with_index { |x, index| [x.run_score, index] }
|
|
@@ -260,13 +306,16 @@ module Fasten
|
|
|
260
306
|
end
|
|
261
307
|
else
|
|
262
308
|
x = max + 1
|
|
263
|
-
|
|
309
|
+
last_avg = task.last_avg
|
|
310
|
+
last_err = task.last_err
|
|
264
311
|
if task.dif
|
|
265
312
|
str = format ' %.2f s', task.dif
|
|
266
|
-
elsif
|
|
267
|
-
str = format '≈ %.2f s ± %.2f %s',
|
|
268
|
-
elsif
|
|
269
|
-
str = format '≈ %.2f s %s',
|
|
313
|
+
elsif last_avg && last_err
|
|
314
|
+
str = format '%s ≈ %.2f s ± %.2f %s', ui_task_clock(task, cur, last_avg), last_avg, last_err, task.worker&.name
|
|
315
|
+
elsif last_avg
|
|
316
|
+
str = format '%s ≈ %.2f s %s', ui_task_clock(task, cur, last_avg), last_avg, task.worker&.name
|
|
317
|
+
else
|
|
318
|
+
str = ui_task_clock(task, cur, 0)
|
|
270
319
|
end
|
|
271
320
|
ui_task_string(task, 3 + index, x, str: str) if str
|
|
272
321
|
end
|
data/lib/fasten/version.rb
CHANGED
data/lib/fasten/worker.rb
CHANGED
metadata
CHANGED
|
@@ -1,29 +1,15 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: fasten
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.14.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Aldrin Martoq
|
|
8
|
-
autorequire:
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2021-06-07 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
|
-
- !ruby/object:Gem::Dependency
|
|
14
|
-
name: bundler
|
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
|
16
|
-
requirements:
|
|
17
|
-
- - "~>"
|
|
18
|
-
- !ruby/object:Gem::Version
|
|
19
|
-
version: 1.17.1
|
|
20
|
-
type: :development
|
|
21
|
-
prerelease: false
|
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
-
requirements:
|
|
24
|
-
- - "~>"
|
|
25
|
-
- !ruby/object:Gem::Version
|
|
26
|
-
version: 1.17.1
|
|
27
13
|
- !ruby/object:Gem::Dependency
|
|
28
14
|
name: curses
|
|
29
15
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -53,35 +39,35 @@ dependencies:
|
|
|
53
39
|
- !ruby/object:Gem::Version
|
|
54
40
|
version: '0'
|
|
55
41
|
- !ruby/object:Gem::Dependency
|
|
56
|
-
name:
|
|
42
|
+
name: rubocop
|
|
57
43
|
requirement: !ruby/object:Gem::Requirement
|
|
58
44
|
requirements:
|
|
59
|
-
- - "
|
|
45
|
+
- - ">="
|
|
60
46
|
- !ruby/object:Gem::Version
|
|
61
|
-
version: '
|
|
47
|
+
version: '0'
|
|
62
48
|
type: :development
|
|
63
49
|
prerelease: false
|
|
64
50
|
version_requirements: !ruby/object:Gem::Requirement
|
|
65
51
|
requirements:
|
|
66
|
-
- - "
|
|
52
|
+
- - ">="
|
|
67
53
|
- !ruby/object:Gem::Version
|
|
68
|
-
version: '
|
|
54
|
+
version: '0'
|
|
69
55
|
- !ruby/object:Gem::Dependency
|
|
70
|
-
name:
|
|
56
|
+
name: rubocop-rake
|
|
71
57
|
requirement: !ruby/object:Gem::Requirement
|
|
72
58
|
requirements:
|
|
73
|
-
- - "
|
|
59
|
+
- - ">="
|
|
74
60
|
- !ruby/object:Gem::Version
|
|
75
|
-
version: '
|
|
61
|
+
version: '0'
|
|
76
62
|
type: :development
|
|
77
63
|
prerelease: false
|
|
78
64
|
version_requirements: !ruby/object:Gem::Requirement
|
|
79
65
|
requirements:
|
|
80
|
-
- - "
|
|
66
|
+
- - ">="
|
|
81
67
|
- !ruby/object:Gem::Version
|
|
82
|
-
version: '
|
|
68
|
+
version: '0'
|
|
83
69
|
- !ruby/object:Gem::Dependency
|
|
84
|
-
name: rubocop
|
|
70
|
+
name: rubocop-rspec
|
|
85
71
|
requirement: !ruby/object:Gem::Requirement
|
|
86
72
|
requirements:
|
|
87
73
|
- - ">="
|
|
@@ -199,7 +185,9 @@ licenses:
|
|
|
199
185
|
- MIT
|
|
200
186
|
metadata:
|
|
201
187
|
allowed_push_host: https://rubygems.org
|
|
202
|
-
|
|
188
|
+
homepage_uri: https://github.com/a0/a0-fasten-ruby/
|
|
189
|
+
source_code_uri: https://github.com/a0/a0-fasten-ruby/CHANGELOG.md
|
|
190
|
+
post_install_message:
|
|
203
191
|
rdoc_options: []
|
|
204
192
|
require_paths:
|
|
205
193
|
- lib
|
|
@@ -207,7 +195,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
207
195
|
requirements:
|
|
208
196
|
- - ">="
|
|
209
197
|
- !ruby/object:Gem::Version
|
|
210
|
-
version:
|
|
198
|
+
version: 2.6.0
|
|
211
199
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
212
200
|
requirements:
|
|
213
201
|
- - ">="
|
|
@@ -215,7 +203,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
215
203
|
version: '0'
|
|
216
204
|
requirements: []
|
|
217
205
|
rubygems_version: 3.0.3
|
|
218
|
-
signing_key:
|
|
206
|
+
signing_key:
|
|
219
207
|
specification_version: 4
|
|
220
208
|
summary: Fasten your seatbelts! Run jobs in parallel, intelligently.
|
|
221
209
|
test_files: []
|