zold 0.16.27 → 0.16.28

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/bin/zold +19 -8
  4. data/fixtures/scripts/distribute-wallet.sh +1 -1
  5. data/fixtures/scripts/pull-on-start.sh +1 -1
  6. data/fixtures/scripts/push-and-pull.sh +1 -1
  7. data/fixtures/scripts/spread-wallets.sh +1 -1
  8. data/lib/zold/commands/alias.rb +4 -1
  9. data/lib/zold/commands/calculate.rb +4 -1
  10. data/lib/zold/commands/clean.rb +1 -1
  11. data/lib/zold/commands/create.rb +6 -3
  12. data/lib/zold/commands/diff.rb +4 -1
  13. data/lib/zold/commands/fetch.rb +4 -1
  14. data/lib/zold/commands/invoice.rb +4 -1
  15. data/lib/zold/commands/list.rb +12 -4
  16. data/lib/zold/commands/merge.rb +8 -1
  17. data/lib/zold/commands/next.rb +4 -1
  18. data/lib/zold/commands/node.rb +6 -3
  19. data/lib/zold/commands/pay.rb +4 -1
  20. data/lib/zold/commands/propagate.rb +4 -1
  21. data/lib/zold/commands/pull.rb +4 -1
  22. data/lib/zold/commands/push.rb +4 -1
  23. data/lib/zold/commands/remote.rb +6 -3
  24. data/lib/zold/commands/remove.rb +4 -1
  25. data/lib/zold/commands/routines/reconnect.rb +1 -1
  26. data/lib/zold/commands/routines/spread.rb +1 -1
  27. data/lib/zold/commands/show.rb +7 -3
  28. data/lib/zold/commands/taxes.rb +4 -1
  29. data/lib/zold/commands/thread_badge.rb +47 -0
  30. data/lib/zold/copies.rb +1 -1
  31. data/lib/zold/endless.rb +1 -1
  32. data/lib/zold/http.rb +3 -3
  33. data/lib/zold/key.rb +3 -0
  34. data/lib/zold/log.rb +52 -111
  35. data/lib/zold/metronome.rb +12 -10
  36. data/lib/zold/node/async_entrance.rb +2 -2
  37. data/lib/zold/node/entrance.rb +1 -1
  38. data/lib/zold/node/farm.rb +1 -1
  39. data/lib/zold/node/farmers.rb +1 -1
  40. data/lib/zold/node/front.rb +5 -5
  41. data/lib/zold/node/nodup_entrance.rb +1 -1
  42. data/lib/zold/node/spread_entrance.rb +1 -1
  43. data/lib/zold/node/sync_entrance.rb +1 -1
  44. data/lib/zold/patch.rb +2 -2
  45. data/lib/zold/remotes.rb +1 -1
  46. data/lib/zold/signature.rb +5 -1
  47. data/lib/zold/sync_wallets.rb +1 -1
  48. data/lib/zold/upgrades.rb +1 -1
  49. data/lib/zold/verbose_thread.rb +1 -1
  50. data/lib/zold/version.rb +1 -1
  51. data/lib/zold/version_file.rb +1 -1
  52. data/lib/zold/wallet.rb +2 -2
  53. data/resources/root.pub +14 -0
  54. data/test/commands/test_list.rb +2 -1
  55. data/test/commands/test_remote.rb +35 -4
  56. data/test/commands/test_show.rb +1 -1
  57. data/test/fake_home.rb +1 -1
  58. data/test/node/fake_node.rb +3 -2
  59. data/test/node/test_farm.rb +1 -1
  60. data/test/test__helper.rb +4 -3
  61. data/test/test_dir_items.rb +1 -1
  62. data/test/test_http.rb +44 -6
  63. data/test/test_key.rb +7 -0
  64. data/test/test_log.rb +12 -1
  65. data/test/test_remotes.rb +1 -1
  66. data/test/test_signature.rb +1 -0
  67. data/test/test_verbose_thread.rb +3 -3
  68. data/test/test_zold.rb +4 -3
  69. data/zold.gemspec +3 -2
  70. metadata +8 -5
@@ -24,6 +24,7 @@ require 'rainbow'
24
24
  require 'slop'
25
25
  require 'json'
26
26
  require 'net/http'
27
+ require_relative 'thread_badge'
27
28
  require_relative 'args'
28
29
  require_relative '../age'
29
30
  require_relative '../size'
@@ -39,7 +40,9 @@ require_relative '../json_page'
39
40
  module Zold
40
41
  # Wallet pushing command
41
42
  class Push
42
- def initialize(wallets:, remotes:, log: Log::Quiet.new)
43
+ prepend ThreadBadge
44
+
45
+ def initialize(wallets:, remotes:, log: Log::NULL)
43
46
  @wallets = wallets
44
47
  @remotes = remotes
45
48
  @log = log
@@ -27,6 +27,7 @@ require 'net/http'
27
27
  require 'json'
28
28
  require 'time'
29
29
  require 'zold/score'
30
+ require_relative 'thread_badge'
30
31
  require_relative 'args'
31
32
  require_relative '../node/farm'
32
33
  require_relative '../log'
@@ -44,7 +45,9 @@ require_relative '../gem'
44
45
  module Zold
45
46
  # Remote command
46
47
  class Remote
47
- def initialize(remotes:, farm: Farm::Empty.new, log: Log::Quiet.new)
48
+ prepend ThreadBadge
49
+
50
+ def initialize(remotes:, farm: Farm::Empty.new, log: Log::NULL)
48
51
  @remotes = remotes
49
52
  @farm = farm
50
53
  @log = log
@@ -103,9 +106,9 @@ Available options:"
103
106
  'The amount of update cycles to run, in order to fetch as many nodes as possible (default: 2)',
104
107
  default: 2
105
108
  o.string '--network',
106
- "The name of the network we work in (default: #{Wallet::MAIN_NETWORK}",
109
+ "The name of the network we work in (default: #{Wallet::MAINET}",
107
110
  required: true,
108
- default: Wallet::MAIN_NETWORK
111
+ default: Wallet::MAINET
109
112
  o.bool '--reboot',
110
113
  'Exit if any node reports version higher than we have',
111
114
  default: false
@@ -22,6 +22,7 @@
22
22
 
23
23
  require 'slop'
24
24
  require 'rainbow'
25
+ require_relative 'thread_badge'
25
26
  require_relative 'args'
26
27
  require_relative '../log'
27
28
 
@@ -32,7 +33,9 @@ require_relative '../log'
32
33
  module Zold
33
34
  # REMOVE command
34
35
  class Remove
35
- def initialize(wallets:, log: Log::Quiet.new)
36
+ prepend ThreadBadge
37
+
38
+ def initialize(wallets:, log: Log::NULL)
36
39
  @wallets = wallets
37
40
  @log = log
38
41
  end
@@ -32,7 +32,7 @@ module Zold
32
32
  module Routines
33
33
  # Reconnect to the network
34
34
  class Reconnect
35
- def initialize(opts, remotes, farm = Farm::Empty.new, network: 'test', log: Log::Quiet.new)
35
+ def initialize(opts, remotes, farm = Farm::Empty.new, network: 'test', log: Log::NULL)
36
36
  @opts = opts
37
37
  @remotes = remotes
38
38
  @farm = farm
@@ -33,7 +33,7 @@ module Zold
33
33
  module Routines
34
34
  # Spread them
35
35
  class Spread
36
- def initialize(opts, wallets, remotes, log: Log::Quiet.new)
36
+ def initialize(opts, wallets, remotes, log: Log::NULL)
37
37
  @opts = opts
38
38
  @wallets = wallets
39
39
  @remotes = remotes
@@ -22,6 +22,7 @@
22
22
 
23
23
  require 'slop'
24
24
  require 'rainbow'
25
+ require_relative 'thread_badge'
25
26
  require_relative 'args'
26
27
  require_relative '../log'
27
28
  require_relative '../id'
@@ -35,8 +36,11 @@ require_relative '../wallet'
35
36
  module Zold
36
37
  # Show command
37
38
  class Show
38
- def initialize(wallets:, log: Log::Quiet.new)
39
+ prepend ThreadBadge
40
+
41
+ def initialize(wallets:, copies:, log: Log::NULL)
39
42
  @wallets = wallets
43
+ @copies = copies
40
44
  @log = log
41
45
  end
42
46
 
@@ -49,7 +53,7 @@ Available options:"
49
53
  mine = Args.new(opts, @log).take || return
50
54
  if mine.empty?
51
55
  require_relative 'list'
52
- List.new(wallets: @wallets, log: @log).run(args)
56
+ List.new(wallets: @wallets, copies: @copies, log: @log).run(args)
53
57
  else
54
58
  total = Amount::ZERO
55
59
  mine.map { |i| Id.new(i) }.each do |id|
@@ -69,7 +73,7 @@ Available options:"
69
73
  @log.info(t.to_text)
70
74
  end
71
75
  msg = "The balance of #{wallet}: #{balance}"
72
- msg += " (net:#{wallet.network})" if wallet.network != Wallet::MAIN_NETWORK
76
+ msg += " (net:#{wallet.network})" if wallet.network != Wallet::MAINET
73
77
  @log.info(msg)
74
78
  balance
75
79
  end
@@ -24,6 +24,7 @@ require 'slop'
24
24
  require 'json'
25
25
  require 'rainbow'
26
26
  require 'zold/score'
27
+ require_relative 'thread_badge'
27
28
  require_relative 'args'
28
29
  require_relative 'pay'
29
30
  require_relative '../log'
@@ -51,7 +52,9 @@ module Zold
51
52
  # just selects the most suitable wallet to transfer taxes to and sends
52
53
  # the payment. More details you can find in the White Paper.
53
54
  class Taxes
54
- def initialize(wallets:, remotes:, log: Log::Quiet.new)
55
+ prepend ThreadBadge
56
+
57
+ def initialize(wallets:, remotes:, log: Log::NULL)
55
58
  @wallets = wallets
56
59
  @remotes = remotes
57
60
  @log = log
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright (c) 2018 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 NONINFINGEMENT. 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
+ # Thread badge.
24
+ # Author:: Yegor Bugayenko (yegor256@gmail.com)
25
+ # Copyright:: Copyright (c) 2018 Yegor Bugayenko
26
+ # License:: MIT
27
+ module Zold
28
+ # This module should be included in each command, in order to label
29
+ # the current Thread correctly, when the command is running. This is mostly
30
+ # useful for debugging/testing purposes - want to be able to see what's
31
+ # going on in the thread when it gets stuck with a Futex.
32
+ #
33
+ # Since all commands have exactly the same external interface and implement
34
+ # the method "run," we catch all calls to this method and label the
35
+ # current thread properly. We label it back when it's over.
36
+ module ThreadBadge
37
+ def run(args = [])
38
+ before = Thread.current.name || ''
39
+ Thread.current.name = "#{before}:#{self.class.name.gsub(/^Zold::/, '')}"
40
+ begin
41
+ super(args)
42
+ ensure
43
+ Thread.current.name = before
44
+ end
45
+ end
46
+ end
47
+ end
@@ -39,7 +39,7 @@ module Zold
39
39
  # Extension for copy files
40
40
  EXT = '.zc'
41
41
 
42
- def initialize(dir, log: Log::Quiet.new)
42
+ def initialize(dir, log: Log::NULL)
43
43
  @dir = dir
44
44
  @log = log
45
45
  end
@@ -31,7 +31,7 @@ require_relative 'age'
31
31
  module Zold
32
32
  # Endless loop
33
33
  class Endless
34
- def initialize(title, log: Log::Quiet.new)
34
+ def initialize(title, log: Log::NULL)
35
35
  @title = title
36
36
  @log = log
37
37
  end
@@ -67,7 +67,7 @@ module Zold
67
67
  @network = network
68
68
  end
69
69
 
70
- def get(timeout: READ_TIMEOUT + CONNECT_TIMEOUT)
70
+ def get(timeout: READ_TIMEOUT)
71
71
  base_url = "#{@uri.scheme}://#{@uri.host}:#{@uri.port}"
72
72
  session = Patron::Session.new(
73
73
  timeout: timeout,
@@ -82,7 +82,7 @@ module Zold
82
82
  Error.new(e)
83
83
  end
84
84
 
85
- def put(body, timeout: READ_TIMEOUT + CONNECT_TIMEOUT)
85
+ def put(body, timeout: READ_TIMEOUT)
86
86
  base_url = "#{@uri.scheme}://#{@uri.host}:#{@uri.port}"
87
87
  session = Patron::Session.new(
88
88
  timeout: timeout,
@@ -109,7 +109,7 @@ module Zold
109
109
  end
110
110
 
111
111
  def to_s
112
- "#{code}: #{message}\n#{body}"
112
+ "#{status}: #{status_line}\n#{body}"
113
113
  end
114
114
 
115
115
  def body
@@ -51,6 +51,9 @@ module Zold
51
51
  end
52
52
  end
53
53
 
54
+ # Public key of the root wallet
55
+ ROOT = Key.new(file: File.expand_path(File.join(File.dirname(__FILE__), '../../resources/root.pub')))
56
+
54
57
  def ==(other)
55
58
  to_s == other.to_s
56
59
  end
@@ -20,10 +20,8 @@
20
20
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
21
  # SOFTWARE.
22
22
 
23
+ require 'logger'
23
24
  require 'rainbow'
24
- require 'monitor'
25
-
26
- STDOUT.sync = true
27
25
 
28
26
  # Zold module.
29
27
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
@@ -47,121 +45,64 @@ module Zold
47
45
  # messages. The user turns this mode by using --verbose command line argument.
48
46
  #
49
47
  module Log
50
- # Synchronized
51
- class Sync
52
- def initialize(log)
53
- @log = log
54
- @monitor = Monitor.new
55
- end
56
-
57
- def debug(msg)
58
- return unless debug?
59
- @monitor.synchronize do
60
- @log.debug(msg)
61
- end
62
- end
63
-
64
- def debug?
65
- @log.debug?
66
- end
67
-
68
- def info(msg)
69
- return unless info?
70
- @monitor.synchronize do
71
- @log.info(msg)
72
- end
73
- end
74
-
75
- def info?
76
- @log.info?
77
- end
78
-
79
- def error(msg)
80
- @monitor.synchronize do
81
- @log.error(msg)
82
- end
83
- end
48
+ def self.colored(text, severity)
49
+ case severity
50
+ when 'ERROR', 'FATAL'
51
+ return Rainbow(text).red
52
+ when 'DEBUG'
53
+ return Rainbow(text).yellow
54
+ end
55
+ text
84
56
  end
85
57
 
86
- # Extra verbose log
87
- class Verbose
88
- def debug(msg)
89
- print(msg)
90
- end
91
-
92
- def debug?
93
- true
94
- end
95
-
96
- def info(msg)
97
- print(msg)
98
- end
99
-
100
- def info?
101
- true
102
- end
103
-
104
- def error(msg)
105
- print("#{Rainbow('ERROR').red}: #{msg}")
106
- end
107
-
108
- private
109
-
110
- def print(text)
111
- puts(text)
58
+ # Compact formatter
59
+ COMPACT = proc do |severity, _time, _target, msg|
60
+ prefix = ''
61
+ case severity
62
+ when 'ERROR', 'FATAL'
63
+ prefix = 'E: '
64
+ when 'DEBUG'
65
+ prefix = 'D: '
112
66
  end
67
+ colored(prefix, severity) + msg.to_s.rstrip.gsub(/\n/, "\n" + (' ' * prefix.length)) + "\n"
113
68
  end
114
69
 
115
- # Regular log
116
- class Regular
117
- def debug(msg)
118
- # nothing
119
- end
120
-
121
- def debug?
122
- false
123
- end
124
-
125
- def info(msg)
126
- print(msg)
127
- end
128
-
129
- def info?
130
- true
131
- end
132
-
133
- def error(msg)
134
- print("#{Rainbow('ERROR').red}: #{msg}")
135
- end
136
-
137
- private
138
-
139
- def print(text)
140
- puts(text)
141
- end
70
+ # Short formatter
71
+ SHORT = proc do |_severity, _time, _target, msg|
72
+ msg.to_s.rstrip + "\n"
142
73
  end
143
74
 
144
- # Log that doesn't log anything
145
- class Quiet
146
- def debug(msg)
147
- # nothing to do here
148
- end
149
-
150
- def debug?
151
- false
152
- end
153
-
154
- def info(msg)
155
- # nothing to do here
156
- end
157
-
158
- def info?
159
- false
160
- end
161
-
162
- def error(msg)
163
- # nothing to do here
164
- end
75
+ # Full formatter
76
+ FULL = proc do |severity, time, _target, msg|
77
+ format(
78
+ "%<time>s %<severity>5s %<msg>s\n",
79
+ time: time.utc.iso8601,
80
+ severity: colored(severity, severity),
81
+ msg: msg.to_s.rstrip
82
+ )
165
83
  end
84
+
85
+ # No logging at all
86
+ NULL = Logger.new(STDOUT)
87
+ NULL.level = Logger::UNKNOWN
88
+ NULL.freeze
89
+
90
+ # Everything, including debug
91
+ VERBOSE = Logger.new(STDOUT)
92
+ VERBOSE.level = Logger::DEBUG
93
+ VERBOSE.formatter = COMPACT
94
+ VERBOSE.freeze
95
+
96
+ # Info and errors, no debug info
97
+ REGULAR = Logger.new(STDOUT)
98
+ REGULAR.level = Logger::INFO
99
+ REGULAR.formatter = COMPACT
100
+ REGULAR.freeze
101
+
102
+ # Errors only
103
+ ERRORS = Logger.new(STDOUT)
104
+ ERRORS.level = Logger::ERROR
105
+ ERRORS.formatter = COMPACT
106
+ ERRORS.freeze
166
107
  end
167
108
  end
@@ -32,7 +32,7 @@ require_relative 'verbose_thread'
32
32
  module Zold
33
33
  # Metronome
34
34
  class Metronome
35
- def initialize(log = Log::Quiet.new)
35
+ def initialize(log = Log::NULL)
36
36
  @log = log
37
37
  @routines = []
38
38
  @threads = []
@@ -86,16 +86,18 @@ module Zold
86
86
  begin
87
87
  yield(self)
88
88
  ensure
89
- alive = false
90
- @log.info("Stopping the metronome with #{@threads.count} threads: #{@threads.map(&:name).join(', ')}")
91
89
  start = Time.now
92
- @threads.each do |t|
93
- tstart = Time.now
94
- if t.join(60)
95
- @log.info("Thread #{t.name} finished in #{Age.new(tstart)}")
96
- else
97
- t.exit
98
- @log.info("Thread #{t.name} killed in #{Age.new(tstart)}")
90
+ unless @threads.empty?
91
+ alive = false
92
+ @log.info("Stopping the metronome with #{@threads.count} threads: #{@threads.map(&:name).join(', ')}")
93
+ @threads.each do |t|
94
+ tstart = Time.now
95
+ if t.join(60)
96
+ @log.info("Thread #{t.name} finished in #{Age.new(tstart)}")
97
+ else
98
+ t.exit
99
+ @log.info("Thread #{t.name} killed in #{Age.new(tstart)}")
100
+ end
99
101
  end
100
102
  end
101
103
  @log.info("Metronome stopped in #{Age.new(start)}, #{@failures.count} failures")