judges 0.0.34 → 0.0.35

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7d6543b9b405aa797aa98883b8294c15e61215db07121c7c0e4616081f9457de
4
- data.tar.gz: 86c543a69bf748262f0f1072f151f8e1f3de9f8d015192699d811d809452328c
3
+ metadata.gz: 410f436fd79010f188d3768f992bef64ddc4a445773e2c790aacc059597ea227
4
+ data.tar.gz: d9eeba81aa97bb9f62ab370aee3e9a3fbaee752f5b1e41df5d33387aece0a151
5
5
  SHA512:
6
- metadata.gz: a487dade2d9e24c24298aab0132fdf653688a2133904c2cad712692762759e9fe8c3e9076e99d09b67a73b8a2580445600ffb2766db0a6d4ef01052de2163392
7
- data.tar.gz: 76111d01a21353718aadde66a0af44d5b341bce928c670704298118ffa8cd0d147e5d50ce21329d7a1adb69e0241243a6a2c3af273d0f6e126bb49fff9618c82
6
+ metadata.gz: 37e8c527a61456b50afba302d2747f43f97804a3831dd310543a3f3eacf810a985be3693d3219bbb0a8a12f8bc24c0e4f4ede6524afbfd5be7e7701a5783e453
7
+ data.tar.gz: 9e5be6b00df4e5decac97299579c3805b6f008a405213ab78f336df2bc272aec2a98c356ca605d7849dea34e2596c0b67ce43d04de727936948bf3ed07f64e81
data/.rubocop.yml CHANGED
@@ -40,6 +40,8 @@ Layout/MultilineMethodCallIndentation:
40
40
  Enabled: false
41
41
  Metrics/AbcSize:
42
42
  Enabled: false
43
+ Metrics/ClassLength:
44
+ Enabled: false
43
45
  Metrics/BlockLength:
44
46
  Enabled: false
45
47
  Metrics/CyclomaticComplexity:
data/Gemfile CHANGED
@@ -25,6 +25,7 @@ gemspec
25
25
 
26
26
  gem 'cucumber', '9.2.0', require: false
27
27
  gem 'minitest', '5.23.1', require: false
28
+ gem 'net-ping', '2.0.8', require: false
28
29
  gem 'rake', '13.2.1', require: false
29
30
  gem 'rspec-rails', '6.1.2', require: false
30
31
  gem 'rubocop', '1.64.0', require: false
@@ -32,4 +33,5 @@ gem 'rubocop-performance', '1.21.0', require: false
32
33
  gem 'rubocop-rspec', '2.29.2', require: false
33
34
  gem 'simplecov', '0.22.0', require: false
34
35
  gem 'simplecov-cobertura', '2.1.0', require: false
36
+ gem 'webmock', '3.19.1', require: false
35
37
  gem 'yard', '0.9.36', require: false
data/Gemfile.lock CHANGED
@@ -3,10 +3,13 @@ PATH
3
3
  specs:
4
4
  judges (0.0.0)
5
5
  backtrace (~> 0.3)
6
+ concurrent-ruby (= 1.2.3)
6
7
  factbase (~> 0.0.38)
7
8
  gli (~> 2.21)
9
+ iri (~> 0.8)
8
10
  loog (~> 0.2)
9
11
  nokogiri (~> 1.10)
12
+ typhoeus (~> 1.3)
10
13
 
11
14
  GEM
12
15
  remote: https://rubygems.org/
@@ -37,6 +40,8 @@ GEM
37
40
  minitest (>= 5.1)
38
41
  mutex_m
39
42
  tzinfo (~> 2.0)
43
+ addressable (2.8.6)
44
+ public_suffix (>= 2.0.2, < 6.0)
40
45
  ast (2.4.2)
41
46
  backtrace (0.4.0)
42
47
  base64 (0.2.0)
@@ -44,6 +49,9 @@ GEM
44
49
  builder (3.2.4)
45
50
  concurrent-ruby (1.2.3)
46
51
  connection_pool (2.4.1)
52
+ crack (1.0.0)
53
+ bigdecimal
54
+ rexml
47
55
  crass (1.0.6)
48
56
  cucumber (9.2.0)
49
57
  builder (~> 3.2)
@@ -74,6 +82,8 @@ GEM
74
82
  docile (1.4.0)
75
83
  drb (2.2.1)
76
84
  erubi (1.12.0)
85
+ ethon (0.16.0)
86
+ ffi (>= 1.15.0)
77
87
  factbase (0.0.38)
78
88
  json (~> 2.7)
79
89
  loog (~> 0.2)
@@ -82,12 +92,14 @@ GEM
82
92
  ffi (1.16.3)
83
93
  ffi (1.16.3-x64-mingw-ucrt)
84
94
  gli (2.21.1)
95
+ hashdiff (1.1.0)
85
96
  i18n (1.14.5)
86
97
  concurrent-ruby (~> 1.0)
87
98
  io-console (0.7.2)
88
99
  irb (1.13.1)
89
100
  rdoc (>= 4.0.0)
90
101
  reline (>= 0.4.2)
102
+ iri (0.8.0)
91
103
  json (2.7.2)
92
104
  language_server-protocol (3.17.0.3)
93
105
  loofah (2.22.0)
@@ -98,6 +110,7 @@ GEM
98
110
  minitest (5.23.1)
99
111
  multi_test (1.1.0)
100
112
  mutex_m (0.2.0)
113
+ net-ping (2.0.8)
101
114
  nokogiri (1.16.5-arm64-darwin)
102
115
  racc (~> 1.4)
103
116
  nokogiri (1.16.5-x64-mingw-ucrt)
@@ -112,6 +125,7 @@ GEM
112
125
  racc
113
126
  psych (5.1.2)
114
127
  stringio
128
+ public_suffix (5.0.5)
115
129
  racc (1.8.0)
116
130
  rack (3.0.11)
117
131
  rack-session (2.0.0)
@@ -204,9 +218,15 @@ GEM
204
218
  sys-uname (1.2.3)
205
219
  ffi (~> 1.1)
206
220
  thor (1.3.1)
221
+ typhoeus (1.4.1)
222
+ ethon (>= 0.9.0)
207
223
  tzinfo (2.0.6)
208
224
  concurrent-ruby (~> 1.0)
209
225
  unicode-display_width (2.5.0)
226
+ webmock (3.19.1)
227
+ addressable (>= 2.8.0)
228
+ crack (>= 0.3.2)
229
+ hashdiff (>= 0.4.0, < 2.0.0)
210
230
  webrick (1.8.1)
211
231
  yaml (0.3.0)
212
232
  yard (0.9.36)
@@ -222,6 +242,7 @@ DEPENDENCIES
222
242
  cucumber (= 9.2.0)
223
243
  judges!
224
244
  minitest (= 5.23.1)
245
+ net-ping (= 2.0.8)
225
246
  rake (= 13.2.1)
226
247
  rspec-rails (= 6.1.2)
227
248
  rubocop (= 1.64.0)
@@ -229,6 +250,7 @@ DEPENDENCIES
229
250
  rubocop-rspec (= 2.29.2)
230
251
  simplecov (= 0.22.0)
231
252
  simplecov-cobertura (= 2.1.0)
253
+ webmock (= 3.19.1)
232
254
  yard (= 0.9.36)
233
255
 
234
256
  BUNDLED WITH
data/bin/judges CHANGED
@@ -147,6 +147,42 @@ class App
147
147
  Judges::Test.new(loog).run(options, args)
148
148
  end
149
149
  end
150
+
151
+ desc 'Push the factbase to the server'
152
+ command :push do |c|
153
+ c.desc 'Authentication token'
154
+ c.flag([:token])
155
+ c.desc 'The IP/hostname of the server'
156
+ c.flag([:host], default_value: 'www.zerocracy.com')
157
+ c.desc 'The TCP port number of the server'
158
+ c.flag([:port], default_value: 443)
159
+ c.desc 'Connection and read time in seconds'
160
+ c.flag([:timeout], default_value: 30)
161
+ c.desc 'Shall SSL be used?'
162
+ c.switch([:ssl], default_value: true)
163
+ c.action do |global, options, args|
164
+ require_relative '../lib/judges/commands/push'
165
+ Judges::Push.new(loog).run(options, args)
166
+ end
167
+ end
168
+
169
+ desc 'Pull the factbase from the server'
170
+ command :pull do |c|
171
+ c.desc 'Authentication token'
172
+ c.flag([:token])
173
+ c.desc 'The IP/hostname of the server'
174
+ c.flag([:host], default_value: 'www.zerocracy.com')
175
+ c.desc 'The TCP port number of the server'
176
+ c.flag([:port], default_value: 443)
177
+ c.desc 'Connection and read time in seconds'
178
+ c.flag([:timeout], default_value: 30)
179
+ c.desc 'Shall SSL be used?'
180
+ c.switch([:ssl], default_value: true)
181
+ c.action do |global, options, args|
182
+ require_relative '../lib/judges/commands/pull'
183
+ Judges::Pull.new(loog).run(options, args)
184
+ end
185
+ end
150
186
  end
151
187
 
152
188
  exit App.run(ARGV)
@@ -0,0 +1,12 @@
1
+ Feature: Pull
2
+ I want to pull a factbase
3
+
4
+ Scenario: Pull a small factbase
5
+ Given We are online
6
+ Given I make a temp directory
7
+ Then I run bin/judges with "--verbose pull --token 00000000-0000-0000-0000-000000000000 simple simple.fb"
8
+ Then Stdout contains "Pulled"
9
+ And Exit code is zero
10
+ Then I run bin/judges with "inspect simple.fb"
11
+ And Exit code is zero
12
+
@@ -0,0 +1,11 @@
1
+ Feature: Push
2
+ I want to push a factbase
3
+
4
+ Scenario: Push a small factbase
5
+ Given We are online
6
+ Given I make a temp directory
7
+ Then I run bin/judges with "--verbose eval simple.fb '$fb.insert.foo = 42'"
8
+ Then I run bin/judges with "push --token 00000000-0000-0000-0000-000000000000 simple simple.fb"
9
+ Then Stdout contains "Pushed"
10
+ And Exit code is zero
11
+
@@ -21,6 +21,7 @@
21
21
  # SOFTWARE.
22
22
 
23
23
  require 'tmpdir'
24
+ require 'net/ping'
24
25
  require 'English'
25
26
 
26
27
  Before do
@@ -34,6 +35,10 @@ After do
34
35
  end
35
36
  end
36
37
 
38
+ Given(/^We are online$/) do
39
+ pending unless Net::Ping::External.new('8.8.8.8').ping?
40
+ end
41
+
37
42
  Given(/^I make a temp directory$/) do
38
43
  @tmp = Dir.mktmpdir('test')
39
44
  FileUtils.mkdir_p(@tmp)
data/judges.gemspec CHANGED
@@ -26,7 +26,7 @@ Gem::Specification.new do |s|
26
26
  s.required_rubygems_version = Gem::Requirement.new('>= 0') if s.respond_to? :required_rubygems_version=
27
27
  s.required_ruby_version = '>=3.2'
28
28
  s.name = 'judges'
29
- s.version = '0.0.34'
29
+ s.version = '0.0.35'
30
30
  s.license = 'MIT'
31
31
  s.summary = 'Command-Line Tool for a Factbase'
32
32
  s.description =
@@ -43,9 +43,12 @@ Gem::Specification.new do |s|
43
43
  s.rdoc_options = ['--charset=UTF-8']
44
44
  s.extra_rdoc_files = ['README.md', 'LICENSE.txt']
45
45
  s.add_runtime_dependency 'backtrace', '~> 0.3'
46
+ s.add_runtime_dependency 'concurrent-ruby', '1.2.3'
46
47
  s.add_runtime_dependency 'factbase', '~>0.0.38'
47
48
  s.add_runtime_dependency 'gli', '~>2.21'
49
+ s.add_runtime_dependency 'iri', '~>0.8'
48
50
  s.add_runtime_dependency 'loog', '~>0.2'
49
51
  s.add_runtime_dependency 'nokogiri', '~> 1.10'
52
+ s.add_runtime_dependency 'typhoeus', '~>1.3'
50
53
  s.metadata['rubygems_mfa_required'] = 'true'
51
54
  end
@@ -0,0 +1,171 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2024 Yegor Bugayenko
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the 'Software'), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in all
13
+ # copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ # SOFTWARE.
22
+
23
+ require 'typhoeus'
24
+ require 'iri'
25
+ require 'loog'
26
+ require_relative '../judges'
27
+ require_relative '../judges/elapsed'
28
+
29
+ # Baza.
30
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
31
+ # Copyright:: Copyright (c) 2024 Yegor Bugayenko
32
+ # License:: MIT
33
+ class Judges::Baza
34
+ # rubocop:disable Metrics/ParameterLists
35
+ def initialize(host, port, token, ssl: true, timeout: 5, loog: Loog::NULL)
36
+ # rubocop:enable Metrics/ParameterLists
37
+ @host = host
38
+ @port = port
39
+ @ssl = ssl
40
+ @token = token
41
+ @timeout = timeout
42
+ @loog = loog
43
+ end
44
+
45
+ def push(name, data)
46
+ id = 0
47
+ elapsed(@loog) do
48
+ ret = Typhoeus::Request.put(
49
+ home.append('push').append(name).to_s,
50
+ body: data,
51
+ headers: headers.merge(
52
+ 'Content-type' => 'application/x-www-form-urlencoded'
53
+ ),
54
+ connecttimeout: @timeout,
55
+ timeout: @timeout
56
+ )
57
+ check_code(ret)
58
+ id = ret.body.to_i
59
+ throw :"Pushed #{data.size} bytes to #{@host}, job ID is ##{id}"
60
+ end
61
+ id
62
+ end
63
+
64
+ def pull(id)
65
+ data = 0
66
+ elapsed(@loog) do
67
+ Tempfile.open do |file|
68
+ File.open(file, 'wb') do |f|
69
+ request = Typhoeus::Request.new(
70
+ home.append('pull').append("#{id}.fb").to_s,
71
+ headers:,
72
+ connecttimeout: @timeout,
73
+ timeout: @timeout
74
+ )
75
+ request.on_body do |chunk|
76
+ f.write(chunk)
77
+ end
78
+ request.run
79
+ check_code(request.response)
80
+ end
81
+ data = File.binread(file)
82
+ throw :"Pulled #{data.size} bytes of job ##{id} factbase at #{@host}"
83
+ end
84
+ end
85
+ data
86
+ end
87
+
88
+ # The job with this ID is finished already?
89
+ def finished?(id)
90
+ finished = false
91
+ elapsed(@loog) do
92
+ ret = Typhoeus::Request.get(
93
+ home.append('finished').append(id).to_s,
94
+ headers:
95
+ )
96
+ check_code(ret)
97
+ finished = ret.body == 'yes'
98
+ throw :"The job ##{id} is #{finished ? '' : 'not yet '}finished at #{@host}"
99
+ end
100
+ finished
101
+ end
102
+
103
+ def recent(name)
104
+ job = 0
105
+ elapsed(@loog) do
106
+ ret = Typhoeus::Request.get(
107
+ home.append('recent').append("#{name}.txt").to_s,
108
+ headers:
109
+ )
110
+ check_code(ret)
111
+ job = ret.body.to_i
112
+ throw :"The recent \"#{name}\" job's ID is ##{job} at #{@host}"
113
+ end
114
+ job
115
+ end
116
+
117
+ def name_exists?(name)
118
+ exists = 0
119
+ elapsed(@loog) do
120
+ ret = Typhoeus::Request.get(
121
+ home.append('exists').append(name).to_s,
122
+ headers:
123
+ )
124
+ check_code(ret)
125
+ exists = ret.body == 'yes'
126
+ throw :"The name \"#{name}\" #{exists ? 'exists' : "doesn't exist"} at #{@host}"
127
+ end
128
+ exists
129
+ end
130
+
131
+ private
132
+
133
+ def headers
134
+ {
135
+ 'User-Agent': "judges #{Judges::VERSION}",
136
+ Connection: 'close',
137
+ 'X-Zerocracy-Token': @token
138
+ }
139
+ end
140
+
141
+ def home
142
+ Iri.new('')
143
+ .host(@host)
144
+ .port(@port)
145
+ .scheme(@ssl ? 'https' : 'http')
146
+ end
147
+
148
+ def check_code(ret, allowed = [200])
149
+ allowed = [allowed] unless allowed.is_a?(Array)
150
+ mtd = (ret.request.original_options[:method] || '???').upcase
151
+ url = ret.effective_url
152
+ @loog.debug(
153
+ "#{mtd} #{url} -> #{ret.code}\n " \
154
+ "#{(ret.headers || {}).map { |k, v| "#{k}: #{v}" }.join("\n ")}"
155
+ )
156
+ return if allowed.include?(ret.code)
157
+ msg =
158
+ "Invalid response code ##{ret.code} " \
159
+ "at #{mtd} #{url} (#{ret.headers['X-Zerocracy-Flash']})"
160
+ if ret.code == 503
161
+ msg +=
162
+ ', most probably it\'s an internal error on the server, ' \
163
+ 'please report this to https://github.com/yegor256/judges'
164
+ elsif ret.code == 404
165
+ msg +=
166
+ ', most probably you are trying to reach a wrong server, which doesn\'t ' \
167
+ 'have the URL that it is expected to have'
168
+ end
169
+ raise msg
170
+ end
171
+ end
@@ -48,7 +48,7 @@ class Judges::Print
48
48
  end
49
49
  FileUtils.mkdir_p(File.dirname(o))
50
50
  if !opts['force'] && File.exist?(o)
51
- if File.mtime(f) < File.mtime(o)
51
+ if File.mtime(f) <= File.mtime(o)
52
52
  @loog.info("No need to print to #{o.to_rel}, since it's up to date (#{File.size(o)} bytes)")
53
53
  return
54
54
  end
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2024 Yegor Bugayenko
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the 'Software'), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in all
13
+ # copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ # SOFTWARE.
22
+
23
+ require 'typhoeus'
24
+ require 'iri'
25
+ require_relative '../../judges'
26
+ require_relative '../../judges/impex'
27
+ require_relative '../../judges/baza'
28
+
29
+ # Pull.
30
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
31
+ # Copyright:: Copyright (c) 2024 Yegor Bugayenko
32
+ # License:: MIT
33
+ class Judges::Pull
34
+ def initialize(loog)
35
+ @loog = loog
36
+ end
37
+
38
+ def run(opts, args)
39
+ raise 'Exactly two arguments required' unless args.size == 2
40
+ fb = Factbase.new
41
+ baza = Judges::Baza.new(
42
+ opts['host'], opts['port'].to_i, opts['token'],
43
+ ssl: opts['ssl'],
44
+ timeout: (opts['timeout'] || 5).to_i,
45
+ loog: @loog
46
+ )
47
+ name = args[0]
48
+ elapsed(@loog) do
49
+ if baza.name_exists?(name)
50
+ fb.import(baza.pull(wait(baza, baza.recent(name))))
51
+ Judges::Impex.new(@loog, args[1]).export(fb)
52
+ throw :"Pulled #{fb.size} facts by the name '#{name}'"
53
+ else
54
+ throw :"There is nothing to pull, the name '#{name}' is absent on the server"
55
+ end
56
+ end
57
+ end
58
+
59
+ private
60
+
61
+ def wait(baza, id)
62
+ start = Time.now
63
+ loop do
64
+ break if baza.finished?(id)
65
+ sleep 1
66
+ raise 'Time is over, the job is still not finished' if Time.now - start > 10 * 60
67
+ end
68
+ id
69
+ end
70
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2024 Yegor Bugayenko
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the 'Software'), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in all
13
+ # copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ # SOFTWARE.
22
+
23
+ require 'typhoeus'
24
+ require 'iri'
25
+ require_relative '../../judges'
26
+ require_relative '../../judges/impex'
27
+ require_relative '../../judges/baza'
28
+
29
+ # Push.
30
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
31
+ # Copyright:: Copyright (c) 2024 Yegor Bugayenko
32
+ # License:: MIT
33
+ class Judges::Push
34
+ def initialize(loog)
35
+ @loog = loog
36
+ end
37
+
38
+ def run(opts, args)
39
+ raise 'Exactly two arguments required' unless args.size == 2
40
+ name = args[0]
41
+ fb = Judges::Impex.new(@loog, args[1]).import
42
+ baza = Judges::Baza.new(
43
+ opts['host'], opts['port'].to_i, opts['token'],
44
+ ssl: opts['ssl'],
45
+ timeout: (opts['timeout'] || 5).to_i,
46
+ loog: @loog
47
+ )
48
+ elapsed(@loog) do
49
+ id = baza.push(name, fb.export)
50
+ throw :"Pushed #{fb.size} facts, job ID is #{id}"
51
+ end
52
+ end
53
+ end
@@ -57,9 +57,12 @@ class Judges::Update
57
57
  end
58
58
  diff = cycle(opts, packs, fb, options)
59
59
  impex.export(fb)
60
- break if diff.zero?
60
+ if diff.zero?
61
+ @loog.info("The update cycle ##{c} has made no changes to the factbase, let's stop")
62
+ break
63
+ end
61
64
  if !opts['max-cycles'].nil? && c >= opts['max-cycles']
62
- @loog.info('Too many cycles already, as set by --max-cycles, breaking')
65
+ @loog.info("Too many cycles already, as set by --max-cycles=#{opts['max-cycles']}, breaking")
63
66
  break
64
67
  end
65
68
  @loog.info(
data/lib/judges.rb CHANGED
@@ -25,5 +25,5 @@
25
25
  # Copyright:: Copyright (c) 2024 Yegor Bugayenko
26
26
  # License:: MIT
27
27
  module Judges
28
- VERSION = '0.0.34'
28
+ VERSION = '0.0.35'
29
29
  end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2024 Yegor Bugayenko
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the 'Software'), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in all
13
+ # copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ # SOFTWARE.
22
+
23
+ require 'minitest/autorun'
24
+ require 'webmock/minitest'
25
+ require 'loog'
26
+ require 'factbase'
27
+ require_relative '../../lib/judges'
28
+ require_relative '../../lib/judges/commands/pull'
29
+
30
+ # Test.
31
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
32
+ # Copyright:: Copyright (c) 2024 Yegor Bugayenko
33
+ # License:: MIT
34
+ class TestPull < Minitest::Test
35
+ def test_pull_simple_factbase
36
+ WebMock.disable_net_connect!
37
+ stub_request(:get, 'http://example.org/exists/foo').to_return(body: 'yes')
38
+ stub_request(:get, 'http://example.org/recent/foo.txt').to_return(body: '42')
39
+ stub_request(:get, 'http://example.org/finished/42').to_return(body: 'yes')
40
+ fb = Factbase.new
41
+ fb.insert.foo = 42
42
+ stub_request(:get, 'http://example.org/pull/42.fb').to_return(body: fb.export)
43
+ Dir.mktmpdir do |d|
44
+ file = File.join(d, 'base.fb')
45
+ Judges::Pull.new(Loog::NULL).run(
46
+ {
47
+ 'token' => '000',
48
+ 'host' => 'example.org',
49
+ 'port' => 80,
50
+ 'ssl' => false
51
+ },
52
+ ['foo', file]
53
+ )
54
+ fb = Factbase.new
55
+ fb.import(File.binread(file))
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2024 Yegor Bugayenko
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the 'Software'), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in all
13
+ # copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ # SOFTWARE.
22
+
23
+ require 'minitest/autorun'
24
+ require 'webmock/minitest'
25
+ require 'loog'
26
+ require_relative '../../lib/judges'
27
+ require_relative '../../lib/judges/commands/push'
28
+
29
+ # Test.
30
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
31
+ # Copyright:: Copyright (c) 2024 Yegor Bugayenko
32
+ # License:: MIT
33
+ class TestPush < Minitest::Test
34
+ def test_push_simple_factbase
35
+ WebMock.disable_net_connect!
36
+ stub_request(:put, 'https://example.org/push/foo').to_return(
37
+ status: 200, body: '42'
38
+ )
39
+ Dir.mktmpdir do |d|
40
+ file = File.join(d, 'base.fb')
41
+ fb = Factbase.new
42
+ fb.insert.foo_bar = 42
43
+ File.binwrite(file, fb.export)
44
+ Judges::Push.new(Loog::NULL).run(
45
+ {
46
+ 'token' => '000',
47
+ 'host' => 'example.org',
48
+ 'port' => 443,
49
+ 'ssl' => true
50
+ },
51
+ ['foo', file]
52
+ )
53
+ end
54
+ end
55
+
56
+ def test_fails_on_http_error
57
+ WebMock.disable_net_connect!
58
+ stub_request(:put, 'http://example.org/push/foo').to_return(status: 500)
59
+ Dir.mktmpdir do |d|
60
+ file = File.join(d, 'base.fb')
61
+ fb = Factbase.new
62
+ fb.insert.foo_bar = 42
63
+ File.binwrite(file, fb.export)
64
+ assert_raises do
65
+ Judges::Push.new(Loog::NULL).run(
66
+ {
67
+ 'token' => '000',
68
+ 'host' => 'example.org',
69
+ 'port' => 80,
70
+ 'ssl' => false
71
+ },
72
+ ['foo', file]
73
+ )
74
+ end
75
+ end
76
+ end
77
+ end
data/test/test_baza.rb ADDED
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2024 Yegor Bugayenko
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the 'Software'), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in all
13
+ # copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ # SOFTWARE.
22
+
23
+ require 'minitest/autorun'
24
+ require 'webmock/minitest'
25
+ require 'loog'
26
+ require_relative '../lib/judges'
27
+ require_relative '../lib/judges/baza'
28
+
29
+ # Test.
30
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
31
+ # Copyright:: Copyright (c) 2024 Yegor Bugayenko
32
+ # License:: MIT
33
+ class TestBaza < Minitest::Test
34
+ def test_simple_push
35
+ WebMock.disable_net_connect!
36
+ stub_request(:put, 'https://example.org/push/simple').to_return(
37
+ status: 200, body: '42'
38
+ )
39
+ assert_equal(
40
+ 42,
41
+ Judges::Baza.new('example.org', 443, '000').push('simple', 'hello, world!')
42
+ )
43
+ end
44
+
45
+ def test_simple_recent_check
46
+ WebMock.disable_net_connect!
47
+ stub_request(:get, 'https://example.org/recent/simple.txt').to_return(
48
+ status: 200, body: '42'
49
+ )
50
+ assert_equal(
51
+ 42,
52
+ Judges::Baza.new('example.org', 443, '000').recent('simple')
53
+ )
54
+ end
55
+
56
+ def test_simple_exists_check
57
+ WebMock.disable_net_connect!
58
+ stub_request(:get, 'https://example.org/exists/simple').to_return(
59
+ status: 200, body: 'yes'
60
+ )
61
+ assert(
62
+ Judges::Baza.new('example.org', 443, '000').name_exists?('simple')
63
+ )
64
+ end
65
+
66
+ def test_simple_pull
67
+ WebMock.disable_net_connect!
68
+ stub_request(:get, 'https://example.org/pull/333.fb').to_return(
69
+ status: 200, body: 'hello, world!'
70
+ )
71
+ assert(
72
+ Judges::Baza.new('example.org', 443, '000').pull(333).start_with?('hello')
73
+ )
74
+ end
75
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: judges
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.34
4
+ version: 0.0.35
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yegor Bugayenko
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-05-27 00:00:00.000000000 Z
11
+ date: 2024-05-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: backtrace
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: concurrent-ruby
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '='
32
+ - !ruby/object:Gem::Version
33
+ version: 1.2.3
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '='
39
+ - !ruby/object:Gem::Version
40
+ version: 1.2.3
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: factbase
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -52,6 +66,20 @@ dependencies:
52
66
  - - "~>"
53
67
  - !ruby/object:Gem::Version
54
68
  version: '2.21'
69
+ - !ruby/object:Gem::Dependency
70
+ name: iri
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '0.8'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '0.8'
55
83
  - !ruby/object:Gem::Dependency
56
84
  name: loog
57
85
  requirement: !ruby/object:Gem::Requirement
@@ -80,6 +108,20 @@ dependencies:
80
108
  - - "~>"
81
109
  - !ruby/object:Gem::Version
82
110
  version: '1.10'
111
+ - !ruby/object:Gem::Dependency
112
+ name: typhoeus
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '1.3'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '1.3'
83
125
  description: A command-line tool that runs a collection of \"judges\" against a \"factbase,\"
84
126
  modifying it and updating. Also, helps printing a factbase, merge with another one,
85
127
  inspect, and so on. Also, helps run automated tests for a set of judges.
@@ -118,6 +160,8 @@ files:
118
160
  - features/join.feature
119
161
  - features/misc.feature
120
162
  - features/print.feature
163
+ - features/pull.feature
164
+ - features/push.feature
121
165
  - features/step_definitions/steps.rb
122
166
  - features/support/env.rb
123
167
  - features/test.feature
@@ -130,12 +174,15 @@ files:
130
174
  - fixtures/try/try.rb
131
175
  - judges.gemspec
132
176
  - lib/judges.rb
177
+ - lib/judges/baza.rb
133
178
  - lib/judges/categories.rb
134
179
  - lib/judges/commands/eval.rb
135
180
  - lib/judges/commands/import.rb
136
181
  - lib/judges/commands/inspect.rb
137
182
  - lib/judges/commands/join.rb
138
183
  - lib/judges/commands/print.rb
184
+ - lib/judges/commands/pull.rb
185
+ - lib/judges/commands/push.rb
139
186
  - lib/judges/commands/test.rb
140
187
  - lib/judges/commands/trim.rb
141
188
  - lib/judges/commands/update.rb
@@ -153,12 +200,15 @@ files:
153
200
  - test/commands/test_inspect.rb
154
201
  - test/commands/test_join.rb
155
202
  - test/commands/test_print.rb
203
+ - test/commands/test_pull.rb
204
+ - test/commands/test_push.rb
156
205
  - test/commands/test_test.rb
157
206
  - test/commands/test_trim.rb
158
207
  - test/commands/test_update.rb
159
208
  - test/fb/test_if_absent.rb
160
209
  - test/fb/test_once.rb
161
210
  - test/test__helper.rb
211
+ - test/test_baza.rb
162
212
  - test/test_categories.rb
163
213
  - test/test_impex.rb
164
214
  - test/test_judges.rb