judges 0.0.34 → 0.0.35

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: 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