zold 0.13.43 → 0.13.44

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
  SHA1:
3
- metadata.gz: 7c1b984c84978412b1cbbc753771396705f0d544
4
- data.tar.gz: 653f5e746fbae90ab0609915452eb646e49d86d9
3
+ metadata.gz: bf5190e58996ff52177172576009917026da5136
4
+ data.tar.gz: 7f0ce81b3a4ae8b21eb835cd6eb2d0e6aecd2aee
5
5
  SHA512:
6
- metadata.gz: 7aa48a078b7b037d165eae145f995ce886fb62f3bfe7d0f8b3e6fac984c80b02c6d4c0c5afc51f0c7411d9de28f6e0a607818043bd6c66f8fff4a38b82690784
7
- data.tar.gz: 31e5789f3c7bc710b3ee970376c40c140f0d73251ebd0a182e5acf7185ea4e9b0ed94f82b753722d8ca5824fd68274d997d26fe4e7d9038324181d6ffd65b65a
6
+ metadata.gz: a8e5c2b7ed530521fc5d3f8bda21b3f547a3a8757e3e4fa083be4b1cbf3cb59e793514d8ea85feb3f4a195e0e398312956bc7b7fa5b0c0f1587250d61a278bfd
7
+ data.tar.gz: a64b280273fcfae4bccf039b01419450065757cc8d3de53e88435864f3f026b6c2f49778c2d5b9dbe3565172681906a893fc4c3adfb04b3eee77675daef0a276
data/README.md CHANGED
@@ -18,7 +18,7 @@
18
18
  **NOTICE**: It's an experiment and a very early draft! Please, feel free to
19
19
  submit your ideas and/or pull requests.
20
20
 
21
- Here is the [White Paper](https://github.com/zold-io/papers/raw/master/wp.pdf).
21
+ Here is the [White Paper](https://papers.zold.io/wp.pdf).
22
22
 
23
23
  Join our [Telegram group](https://t.me/zold_io) to discuss it all live.
24
24
 
@@ -0,0 +1,34 @@
1
+ # Copyright (c) 2018 Yegor Bugayenko
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the 'Software'), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all
11
+ # copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ # SOFTWARE.
20
+
21
+ require 'minitest'
22
+
23
+ # Test only module
24
+ module Assertions
25
+ extend Minitest::Assertions
26
+ class << self
27
+ attr_accessor :assertions
28
+ end
29
+ self.assertions = 0
30
+ end
31
+
32
+ def assert_equal(a, b)
33
+ Assertions.assert_equal(a, b)
34
+ end
@@ -0,0 +1,51 @@
1
+ -----BEGIN RSA PRIVATE KEY-----
2
+ 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
51
+ -----END RSA PRIVATE KEY-----
@@ -0,0 +1 @@
1
+ ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCemmeTOsKt6IpocXT1cpLps77bbvj7BIaj4Xwoe9Ws1up5qv97T2v08H8/psV0ugyHhdzun/v41IRkt67YSD90GRAsRvwz/OCRPiAEMbIRNb/O6xgcjOdf+WB/R/yqV4hAggH/djtCkPO2RqZZhMpaWeaWtxC8JUHS5FE+bhkxwwmi4pH2fsTYOkv16iUrI7Cv8ljTyIk64rce5bq1F28T7THsj7AOmszrk4f8+gCuV87mqcgZt5fCwQZFe3TDpr+5s+l5p0WM9ei0TtxPVIDhhIPW1ZMhWbVlamk4T3rtegMi6bq3O3kp/MM1F+z0ZsJ87QEvbfkfFs7wj2tOVUtMpw0CIR7QJaiVj0dHmkxqiw6Bno8HngickRkmzgvZvXRz4iVVRfVFKfB8ViDS/LmiqtjKq3uCeKmX/Tphbg8ohhztOWOiCwQd/0LP+SkQrOoO2wfYuuaMw2xtaKi6y80cz4w+By4yDxmfAsrAPL01Z0jhctOmDqFVEk0f16tl18A7m2D/e5vckt4lvI2jgF3l/8Gevlg3/1qFnzuRKkju/RCT3h1HiEM+Oy0RyCHJn1FVSg3nb6HWDzdx3dwiqSwl3SSJ8wKgGY5sPTXdFI9Co3Cv0YZTYlokSbblWrfl3LYMcCQ5ClRlVPwY2D0gzipQNXTJqBM3dtnK+4tYiC59vQ== yegor@be.Dlink
@@ -0,0 +1,6 @@
1
+ test
2
+ 1
3
+ 0000000000000000
4
+ MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnppnkzrCreiKaHF09XKS6bO+2274+wSGo+F8KHvVrNbqear/e09r9PB/P6bFdLoMh4Xc7p/7+NSEZLeu2Eg/dBkQLEb8M/zgkT4gBDGyETW/zusYHIznX/lgf0f8qleIQIIB/3Y7QpDztkamWYTKWlnmlrcQvCVB0uRRPm4ZMcMJouKR9n7E2DpL9eolKyOwr/JY08iJOuK3HuW6tRdvE+0x7I+wDprM65OH/PoArlfO5qnIGbeXwsEGRXt0w6a/ubPpeadFjPXotE7cT1SA4YSD1tWTIVm1ZWppOE967XoDIum6tzt5KfzDNRfs9GbCfO0BL235HxbO8I9rTlVLTKcNAiEe0CWolY9HR5pMaosOgZ6PB54InJEZJs4L2b10c+IlVUX1RSnwfFYg0vy5oqrYyqt7gnipl/06YW4PKIYc7TljogsEHf9Cz/kpEKzqDtsH2LrmjMNsbWiousvNHM+MPgcuMg8ZnwLKwDy9NWdI4XLTpg6hVRJNH9erZdfAO5tg/3ub3JLeJbyNo4Bd5f/Bnr5YN/9ahZ87kSpI7v0Qk94dR4hDPjstEcghyZ9RVUoN52+h1g83cd3cIqksJd0kifMCoBmObD013RSPQqNwr9GGU2JaJEm25Vq35dy2DHAkOQpUZVT8GNg9IM4qUDV0yagTN3bZyvuLWIgufb0CAwEAAQ==
5
+
6
+ 0001;2018-06-22T07:38:23Z;fffffe0000000000;g6hVRJNH;0123456789abcdef;To help you;IFQvo0PN3JkpkuZRjPyQ6BywuM9aSRFI6GdNOevSQxWJMwSesYp6b25KIi78TcIV9b84f0Qr96d8TgvkTjLqczvZZzyYIJ+e2w8qQhbxSiCgFxfThm6U8NnrXNprMBRHg4amV40dAjgW2lfVDDRk+RtCYEUEZDX5xPhiCHC8lhtoJm/atgJfgOIAfeLTy6ZWwC+teMtHUt6/uHH9z9giYnWHLBpYFyjYSSlrf4K/0e86Kzy/8Bwmk9Q/I6Yvo7IWL7TNN5vCGiz74R2wUTHVfmlY/YdXD15JnPmmZGjoR+BCjxbpjPqYWGm2bTxSuDHCFg0oTKAHIPqC57hKzGQUNzmoSqMHxTBDTvdLHjf0Uo9oaWhdT+BTpnGzFJxgz7d9oJOsIFqrLzPZ6VjOqKtl+ptbFkrjpq9ZdfpbzzBxHhLU8quxmBihodxBZAI6f2rpDGgnwS/D2v+Ncdcmqpdin1GkU0lAeAzWhenKBqu2t9C5UeZbjw6diiKyrGPHWLS9X9BGX9j6STMyI93f81Y6+j798gqv+XZtsohxL/sHDNJK0m81S6QWnAD//bZbNqW85y8ZMFwHmn3GXsSDupaQGpe6wpvFknWxho4vM8A/nAk20rWur5PF1S4RpFwpOr/4RmBA06yWnPxdB6x9lonPKmYC5Pck0fwxXDOEcjMTdWo=
@@ -0,0 +1,6 @@
1
+ test
2
+ 1
3
+ 0123456789abcdef
4
+ MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnppnkzrCreiKaHF09XKS6bO+2274+wSGo+F8KHvVrNbqear/e09r9PB/P6bFdLoMh4Xc7p/7+NSEZLeu2Eg/dBkQLEb8M/zgkT4gBDGyETW/zusYHIznX/lgf0f8qleIQIIB/3Y7QpDztkamWYTKWlnmlrcQvCVB0uRRPm4ZMcMJouKR9n7E2DpL9eolKyOwr/JY08iJOuK3HuW6tRdvE+0x7I+wDprM65OH/PoArlfO5qnIGbeXwsEGRXt0w6a/ubPpeadFjPXotE7cT1SA4YSD1tWTIVm1ZWppOE967XoDIum6tzt5KfzDNRfs9GbCfO0BL235HxbO8I9rTlVLTKcNAiEe0CWolY9HR5pMaosOgZ6PB54InJEZJs4L2b10c+IlVUX1RSnwfFYg0vy5oqrYyqt7gnipl/06YW4PKIYc7TljogsEHf9Cz/kpEKzqDtsH2LrmjMNsbWiousvNHM+MPgcuMg8ZnwLKwDy9NWdI4XLTpg6hVRJNH9erZdfAO5tg/3ub3JLeJbyNo4Bd5f/Bnr5YN/9ahZ87kSpI7v0Qk94dR4hDPjstEcghyZ9RVUoN52+h1g83cd3cIqksJd0kifMCoBmObD013RSPQqNwr9GGU2JaJEm25Vq35dy2DHAkOQpUZVT8GNg9IM4qUDV0yagTN3bZyvuLWIgufb0CAwEAAQ==
5
+
6
+ 0001;2018-06-22T07:38:23Z;0000020000000000;g6hVRJNH;0000000000000000;To help you;
@@ -0,0 +1,23 @@
1
+ # Copyright (c) 2018 Yegor Bugayenko
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the 'Software'), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all
11
+ # copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ # SOFTWARE.
20
+
21
+ require_relative 'asserts.rb'
22
+ wallet = Zold::Wallet.new(Zold::Id.new('0123456789abcdef'))
23
+ assert_equal(Zold::Amount.new(zld: 388.0), wallet.balance)
@@ -0,0 +1,7 @@
1
+ test
2
+ 1
3
+ 0123456789abcdef
4
+ MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnppnkzrCreiKaHF09XKS6bO+2274+wSGo+F8KHvVrNbqear/e09r9PB/P6bFdLoMh4Xc7p/7+NSEZLeu2Eg/dBkQLEb8M/zgkT4gBDGyETW/zusYHIznX/lgf0f8qleIQIIB/3Y7QpDztkamWYTKWlnmlrcQvCVB0uRRPm4ZMcMJouKR9n7E2DpL9eolKyOwr/JY08iJOuK3HuW6tRdvE+0x7I+wDprM65OH/PoArlfO5qnIGbeXwsEGRXt0w6a/ubPpeadFjPXotE7cT1SA4YSD1tWTIVm1ZWppOE967XoDIum6tzt5KfzDNRfs9GbCfO0BL235HxbO8I9rTlVLTKcNAiEe0CWolY9HR5pMaosOgZ6PB54InJEZJs4L2b10c+IlVUX1RSnwfFYg0vy5oqrYyqt7gnipl/06YW4PKIYc7TljogsEHf9Cz/kpEKzqDtsH2LrmjMNsbWiousvNHM+MPgcuMg8ZnwLKwDy9NWdI4XLTpg6hVRJNH9erZdfAO5tg/3ub3JLeJbyNo4Bd5f/Bnr5YN/9ahZ87kSpI7v0Qk94dR4hDPjstEcghyZ9RVUoN52+h1g83cd3cIqksJd0kifMCoBmObD013RSPQqNwr9GGU2JaJEm25Vq35dy2DHAkOQpUZVT8GNg9IM4qUDV0yagTN3bZyvuLWIgufb0CAwEAAQ==
5
+
6
+ 0001;2018-06-22T08:26:19Z;fffffff000000000;TESTPREFIX;ffffffffffffffff;For pizza;L1MFiKqM8O6Eg/v54TD7M48gI/oq7iYYmjM7cKgUpMUk7dx48K+9DRQ2as+d2SrMMH/TKdJ/It8v8DJN6RV3kVtpdZo7CsUrUisive5rpJduO68+nJFr3TB3vQrCPm8N3Cz9vfmM68WrmskPHOABETyIC9cSQrSIvaCWhchwru7sO0625y2aYiMVoW2jmKFTtflGr6M9n7rqTkaYG/EftrNMrJS7PaG19T1HOQupAcKQ4DzBujEnbm3KQQc9Rp5GR8cb49Y38IAr9lENkDB1zmMaVJeZNEyX0ne6S1ZB7Ys9L0jUIJA+SRzNHDEdWC6lcOifcCuanU4kBPFtOiuAjghJX09l8Ue1pyE478+Sy8BgApqKu1l4+p+qUSXOTx7yKwT9ahZaA9DgVHEinz6MqhiozDddw24fXRK956pQ+jUPzNJXVeH4UrDcUDAaCIX8jCaaqGQUqhJXH2KF0Z1PtWBfHYB7OxXEpiVVtScMQ+68iB40p71f7j4YrVW50G89NrCJbOamdai+3dmwiIZzSOsSahB8kXrkaF+lrDZiwNPfL2ixs3F2xW34aKHvA/UCCo7PVfUVDLC8VHiDtAKTSyoqhPP4ocomszfRaRGxSjDIh3ceCrPH9BIW2zfUzkU63+dJ5adS+XSXzO3L3gfwiLM6XPr2jlJbPy1OSMkDK7s=
7
+ 0001;2018-06-22T07:38:23Z;0000020000000000;g6hVRJNH;0000000000000000;To help you;
@@ -0,0 +1,7 @@
1
+ test
2
+ 1
3
+ 0123456789abcdef
4
+ MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnppnkzrCreiKaHF09XKS6bO+2274+wSGo+F8KHvVrNbqear/e09r9PB/P6bFdLoMh4Xc7p/7+NSEZLeu2Eg/dBkQLEb8M/zgkT4gBDGyETW/zusYHIznX/lgf0f8qleIQIIB/3Y7QpDztkamWYTKWlnmlrcQvCVB0uRRPm4ZMcMJouKR9n7E2DpL9eolKyOwr/JY08iJOuK3HuW6tRdvE+0x7I+wDprM65OH/PoArlfO5qnIGbeXwsEGRXt0w6a/ubPpeadFjPXotE7cT1SA4YSD1tWTIVm1ZWppOE967XoDIum6tzt5KfzDNRfs9GbCfO0BL235HxbO8I9rTlVLTKcNAiEe0CWolY9HR5pMaosOgZ6PB54InJEZJs4L2b10c+IlVUX1RSnwfFYg0vy5oqrYyqt7gnipl/06YW4PKIYc7TljogsEHf9Cz/kpEKzqDtsH2LrmjMNsbWiousvNHM+MPgcuMg8ZnwLKwDy9NWdI4XLTpg6hVRJNH9erZdfAO5tg/3ub3JLeJbyNo4Bd5f/Bnr5YN/9ahZ87kSpI7v0Qk94dR4hDPjstEcghyZ9RVUoN52+h1g83cd3cIqksJd0kifMCoBmObD013RSPQqNwr9GGU2JaJEm25Vq35dy2DHAkOQpUZVT8GNg9IM4qUDV0yagTN3bZyvuLWIgufb0CAwEAAQ==
5
+
6
+ 0002;2018-06-22T08:26:36Z;ffffffe000000000;TESTPREFIX;eeeeeeeeeeeeeeee;For coffee;ctLF7pKtNHLoaVmsSdPTjfilp0GIdP4EVCCnQs39j6AIAYJtr0342rfMmql8piCrPn/TbnrL835QwohFHolH44ygTRgcQ2ZCSVvK49M+FekPg25S38jZEGQvBiIEdw4y/DyOW7pQLCubIqZZdbuUHuR4S5InI+sFm+IlMaKPaJ3NoOo6dgX+XC+cxJqhM8e8L/Sy2s3smNvPKjy3FVh5vEeharoov6frQztLABwFIJIGMGI6xDCfZO0lh6X3FjCCwtrtMK0pY2cYHNZS3GzMtvpQE0sNPIAjujjI/Sz8bTOLqaRSD+8SjR24DRDq4nD90L74NbbxwFaypFyhVIryAzetZs+AIhkf7hDVnh3GtzfoqIQKOzQPFV6oV4ciFSR5oiT6yt89xxeKhHTKD/E1nw0xltZ+SiqVH9Ha/8NEn5wJEeko5h+fnDL+1yVziQy9gMC1Dh/pnZgMn8T7k2Ecif3knxZf+NAoCvFRyueFzZM7S7xDs9krxc56EnZaLo7/pJ6jVuXLQlXnMgzPrbx8mJSjUQY6X2yNe5qVFauSwH6JAa0ewZm5H8n0dsHT0bKHxV+eRcFFh/g3z6LEwxxCN6KrLnPr3x66NntCEom3B+y6WCPnpa9gKSHu1caLuSoSbJ1R8Rtx1iqQN3iHlVIbHpiy3xTbfXKiwS17KZV46yA=
7
+ 0001;2018-06-22T07:38:23Z;0000020000000000;g6hVRJNH;0000000000000000;To help you;
@@ -0,0 +1,7 @@
1
+ test
2
+ 1
3
+ 0123456789abcdef
4
+ MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnppnkzrCreiKaHF09XKS6bO+2274+wSGo+F8KHvVrNbqear/e09r9PB/P6bFdLoMh4Xc7p/7+NSEZLeu2Eg/dBkQLEb8M/zgkT4gBDGyETW/zusYHIznX/lgf0f8qleIQIIB/3Y7QpDztkamWYTKWlnmlrcQvCVB0uRRPm4ZMcMJouKR9n7E2DpL9eolKyOwr/JY08iJOuK3HuW6tRdvE+0x7I+wDprM65OH/PoArlfO5qnIGbeXwsEGRXt0w6a/ubPpeadFjPXotE7cT1SA4YSD1tWTIVm1ZWppOE967XoDIum6tzt5KfzDNRfs9GbCfO0BL235HxbO8I9rTlVLTKcNAiEe0CWolY9HR5pMaosOgZ6PB54InJEZJs4L2b10c+IlVUX1RSnwfFYg0vy5oqrYyqt7gnipl/06YW4PKIYc7TljogsEHf9Cz/kpEKzqDtsH2LrmjMNsbWiousvNHM+MPgcuMg8ZnwLKwDy9NWdI4XLTpg6hVRJNH9erZdfAO5tg/3ub3JLeJbyNo4Bd5f/Bnr5YN/9ahZ87kSpI7v0Qk94dR4hDPjstEcghyZ9RVUoN52+h1g83cd3cIqksJd0kifMCoBmObD013RSPQqNwr9GGU2JaJEm25Vq35dy2DHAkOQpUZVT8GNg9IM4qUDV0yagTN3bZyvuLWIgufb0CAwEAAQ==
5
+
6
+ 0003;2018-06-22T08:26:54Z;fffffff800000000;TESTPREFIX;eeeeeeeeeeeeeeee;For fun;TMrg2FZY8HJHTq7FM0VAMSTzMd3WFpUtI0naaR58pEpC/kSXM820bwIkErFW6Ymie03baRoB7BHnqrJjhCN57KkrK0LUr+FMQNbkPfbhqWnws0X/+HIcSTEdWozkc/t/I4xD2dGHUqbjJRPU87KfbmadVLwZx9TO5bL0ywBGZbV8di+GgQ7/NDdmyIWE/bkW/t3rErfNEYu0X3pyj41T02MwgETNyZTvfzhZWXFD2fooJ3qFIdw8kLoNY2RJkCwpxeJMAyeFvEWi9D5LoSO2VWw7okZylkA4TiwfDByPip9ABu4ekR7lq1MIL1RxswwwwQLiBi0VrvV3tN4VXTpaBYQTjuEh7mC3IwuK84Q29o1QX8sVcihnrwYDuUohx7D3HdSTxoV8EFsWmAaSHMwQn9xhb4hAkbS5Zv9qUvsjjBcdf9jhFTo/ecT17pdav5fZ+lxx7+fYVklJK/J9z7ZXKphOfbQ3Jg5oeOO4kuAcpSRjd2SAHySzsf06xfa5L32ZDcLorqVZC5GUdikHHVc889HeZbWNkPbGbCleK2ICwGh5b+eW1KAygtXrehhJiJVJfCPlxpFk172DdZf9Rxfs5QKdH4QTIt3xztAdU6BwZ7nwpejyz7hbgou1XqqCcaZEkMD3vMOBGurBfKFpCgX+YYsxMphmw9QSNi1D/WnSkvE=
7
+ 0001;2018-06-22T07:38:23Z;0000020000000000;g6hVRJNH;0000000000000000;To help you;
@@ -0,0 +1,7 @@
1
+ test
2
+ 1
3
+ 0123456789abcdef
4
+ MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnppnkzrCreiKaHF09XKS6bO+2274+wSGo+F8KHvVrNbqear/e09r9PB/P6bFdLoMh4Xc7p/7+NSEZLeu2Eg/dBkQLEb8M/zgkT4gBDGyETW/zusYHIznX/lgf0f8qleIQIIB/3Y7QpDztkamWYTKWlnmlrcQvCVB0uRRPm4ZMcMJouKR9n7E2DpL9eolKyOwr/JY08iJOuK3HuW6tRdvE+0x7I+wDprM65OH/PoArlfO5qnIGbeXwsEGRXt0w6a/ubPpeadFjPXotE7cT1SA4YSD1tWTIVm1ZWppOE967XoDIum6tzt5KfzDNRfs9GbCfO0BL235HxbO8I9rTlVLTKcNAiEe0CWolY9HR5pMaosOgZ6PB54InJEZJs4L2b10c+IlVUX1RSnwfFYg0vy5oqrYyqt7gnipl/06YW4PKIYc7TljogsEHf9Cz/kpEKzqDtsH2LrmjMNsbWiousvNHM+MPgcuMg8ZnwLKwDy9NWdI4XLTpg6hVRJNH9erZdfAO5tg/3ub3JLeJbyNo4Bd5f/Bnr5YN/9ahZ87kSpI7v0Qk94dR4hDPjstEcghyZ9RVUoN52+h1g83cd3cIqksJd0kifMCoBmObD013RSPQqNwr9GGU2JaJEm25Vq35dy2DHAkOQpUZVT8GNg9IM4qUDV0yagTN3bZyvuLWIgufb0CAwEAAQ==
5
+
6
+ 0004;2018-06-22T08:27:06Z;ffffffc000000000;TESTPREFIX;eeeeeeeeeeeeeeee;For something else;K0V9Hfv9vAhe2QlCq69RI55bAI0RFHTaDrZFaY9pGiQT6vQV5cri19XhI6BC2i9qWUqIhEL2ikaPGZ5ODqu4rt6BBQcb/OOwZU21lPEcdm/n8HCsitPzGDX/hGjWg/ab88mFw5qLB6pasadtvjDoTG/5dBoB5rk9Ujy2c5JPpiXGR8OqF2bUsMVmUXSEKFmAK3u/EgrcApz4kFezcCriZ4lwqjgyT7grbyZXyGu8AA+AhX3zq/tyiuNJbHCrsnuWedxa9DtlTQy0/qg3JT2xPcruxoBe6ijjPbalMwWI41jt5Bp+wNUaFm94kc2cB+gyxQPf7vtHgVv5C9ikMO4XMF9b3PBVCB4i7J6b+U+PCHG4m/EA9c+PZvJSVc2cV+Ya8YTL+yTXiXOGpzvjateDwatyKjE5yA5G8yfxrtPDwuWslhT//kSHFuwpUGwZnTL4q769Wy/lEQM2uLWlD0GJ+mb/PZ6n5YhbGsgUAFiV2h93x1g3u0JKykP8/E758ZGWPMoivdxKm+dhRjNjh8jQ89Kt8UkGsD3vhi4pkSkm6vXQ8q/tq9ul6R3Is8FVAU2V9vThI/GZmT+BMUHsrMnpXEQEoBMQSMMcaSpK4hwRfpYmpC7NKBDUoSQhIcMumsXvDQaJKybKqC1BO1y3t9L7OX0Ev/fJawcDY4sJgptq7JQ=
7
+ 0001;2018-06-22T07:38:23Z;0000020000000000;g6hVRJNH;0000000000000000;To help you;
@@ -0,0 +1,7 @@
1
+ test
2
+ 1
3
+ 0123456789abcdef
4
+ MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnppnkzrCreiKaHF09XKS6bO+2274+wSGo+F8KHvVrNbqear/e09r9PB/P6bFdLoMh4Xc7p/7+NSEZLeu2Eg/dBkQLEb8M/zgkT4gBDGyETW/zusYHIznX/lgf0f8qleIQIIB/3Y7QpDztkamWYTKWlnmlrcQvCVB0uRRPm4ZMcMJouKR9n7E2DpL9eolKyOwr/JY08iJOuK3HuW6tRdvE+0x7I+wDprM65OH/PoArlfO5qnIGbeXwsEGRXt0w6a/ubPpeadFjPXotE7cT1SA4YSD1tWTIVm1ZWppOE967XoDIum6tzt5KfzDNRfs9GbCfO0BL235HxbO8I9rTlVLTKcNAiEe0CWolY9HR5pMaosOgZ6PB54InJEZJs4L2b10c+IlVUX1RSnwfFYg0vy5oqrYyqt7gnipl/06YW4PKIYc7TljogsEHf9Cz/kpEKzqDtsH2LrmjMNsbWiousvNHM+MPgcuMg8ZnwLKwDy9NWdI4XLTpg6hVRJNH9erZdfAO5tg/3ub3JLeJbyNo4Bd5f/Bnr5YN/9ahZ87kSpI7v0Qk94dR4hDPjstEcghyZ9RVUoN52+h1g83cd3cIqksJd0kifMCoBmObD013RSPQqNwr9GGU2JaJEm25Vq35dy2DHAkOQpUZVT8GNg9IM4qUDV0yagTN3bZyvuLWIgufb0CAwEAAQ==
5
+
6
+ 0005;2018-06-22T08:27:22Z;fffffffc00000000;TESTPREFIX;eeeeeeeeeeeeeeee;For my friend;WF/xCNKtRpzm2DPlFAOsxHKCw6hg5Nrn3M78cNSpoaEQRPDCaPeLrQiOkLaseqPB3xk//F74qJv4EcKsjlWsgH+eQ9PQ7pp1+4pnEqff1fXcb6M5vxIa8BMMYfbcPyWIIDtAyHSn/8t35r/Zanua0tcH0FfGLzfUfGK4jK9s49rLPkEDVGjKGJPS0zaJP4a3DWclohGvU1+t2EGNk09niDKhtZKjv6YRk9t11kK76zsWj8Zc9NVxthpGavRgsrGSP7jPsMsLdPYnEGXberO1Iexl5FHG/Gc8+kj/qUcGZv3f06vfkbGbAgknibufv8uAD1OVcptjp+M55HcWyFXJhvI2OIDoyQv1RIUiL26X0b3qAOEqKEXnnAA5FbD7RlanJ3Jl+IzDKYrocE5mWvrK36w31meTReJH8I1bX8XK4TIHJNXh8xi2LK1fUZ8Crxg8pPxLgvrgfk8AR9sOS+vC5tmbWsuP1EDSwD6wB9TYGbacgpSd3Yzz8DEOvNykJoEpEUku4MLeJzYQPC7n1GWoO7ysFDr+BXiFd7d+xdfUnDK8UiiT2AecUpnnNr4fjuWfa5OTbcYmKQ34Ys3ddNc47Vc9+Eax8Q1qnEZs5lMiyA7r7gkPQSKMP17L9NyYPMOwzLvspmUzgK8vDylTHW3uGNb86dzyqKkXeA+fs7AmjTs=
7
+ 0001;2018-06-22T07:38:23Z;0000020000000000;g6hVRJNH;0000000000000000;To help you;
@@ -0,0 +1,5 @@
1
+ 1,0.0.0.0,4096,10,2018-06-21T03:41:21Z
2
+ 2,0.0.0.0,4096,20,2018-06-21T03:41:21Z
3
+ 3,0.0.0.0,4096,30,2018-06-21T03:41:21Z
4
+ 4,0.0.0.0,4096,40,2018-06-21T03:41:21Z
5
+ 5,0.0.0.0,4096,50,2018-06-21T03:41:21Z
@@ -0,0 +1,6 @@
1
+ test
2
+ 1
3
+ 0000000000000000
4
+ MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnppnkzrCreiKaHF09XKS6bO+2274+wSGo+F8KHvVrNbqear/e09r9PB/P6bFdLoMh4Xc7p/7+NSEZLeu2Eg/dBkQLEb8M/zgkT4gBDGyETW/zusYHIznX/lgf0f8qleIQIIB/3Y7QpDztkamWYTKWlnmlrcQvCVB0uRRPm4ZMcMJouKR9n7E2DpL9eolKyOwr/JY08iJOuK3HuW6tRdvE+0x7I+wDprM65OH/PoArlfO5qnIGbeXwsEGRXt0w6a/ubPpeadFjPXotE7cT1SA4YSD1tWTIVm1ZWppOE967XoDIum6tzt5KfzDNRfs9GbCfO0BL235HxbO8I9rTlVLTKcNAiEe0CWolY9HR5pMaosOgZ6PB54InJEZJs4L2b10c+IlVUX1RSnwfFYg0vy5oqrYyqt7gnipl/06YW4PKIYc7TljogsEHf9Cz/kpEKzqDtsH2LrmjMNsbWiousvNHM+MPgcuMg8ZnwLKwDy9NWdI4XLTpg6hVRJNH9erZdfAO5tg/3ub3JLeJbyNo4Bd5f/Bnr5YN/9ahZ87kSpI7v0Qk94dR4hDPjstEcghyZ9RVUoN52+h1g83cd3cIqksJd0kifMCoBmObD013RSPQqNwr9GGU2JaJEm25Vq35dy2DHAkOQpUZVT8GNg9IM4qUDV0yagTN3bZyvuLWIgufb0CAwEAAQ==
5
+
6
+ 0001;2018-06-22T07:38:23Z;fffffe0000000000;g6hVRJNH;0123456789abcdef;To help you;IFQvo0PN3JkpkuZRjPyQ6BywuM9aSRFI6GdNOevSQxWJMwSesYp6b25KIi78TcIV9b84f0Qr96d8TgvkTjLqczvZZzyYIJ+e2w8qQhbxSiCgFxfThm6U8NnrXNprMBRHg4amV40dAjgW2lfVDDRk+RtCYEUEZDX5xPhiCHC8lhtoJm/atgJfgOIAfeLTy6ZWwC+teMtHUt6/uHH9z9giYnWHLBpYFyjYSSlrf4K/0e86Kzy/8Bwmk9Q/I6Yvo7IWL7TNN5vCGiz74R2wUTHVfmlY/YdXD15JnPmmZGjoR+BCjxbpjPqYWGm2bTxSuDHCFg0oTKAHIPqC57hKzGQUNzmoSqMHxTBDTvdLHjf0Uo9oaWhdT+BTpnGzFJxgz7d9oJOsIFqrLzPZ6VjOqKtl+ptbFkrjpq9ZdfpbzzBxHhLU8quxmBihodxBZAI6f2rpDGgnwS/D2v+Ncdcmqpdin1GkU0lAeAzWhenKBqu2t9C5UeZbjw6diiKyrGPHWLS9X9BGX9j6STMyI93f81Y6+j798gqv+XZtsohxL/sHDNJK0m81S6QWnAD//bZbNqW85y8ZMFwHmn3GXsSDupaQGpe6wpvFknWxho4vM8A/nAk20rWur5PF1S4RpFwpOr/4RmBA06yWnPxdB6x9lonPKmYC5Pck0fwxXDOEcjMTdWo=
@@ -0,0 +1,5 @@
1
+ test
2
+ 1
3
+ 0123456789abcdef
4
+ MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnppnkzrCreiKaHF09XKS6bO+2274+wSGo+F8KHvVrNbqear/e09r9PB/P6bFdLoMh4Xc7p/7+NSEZLeu2Eg/dBkQLEb8M/zgkT4gBDGyETW/zusYHIznX/lgf0f8qleIQIIB/3Y7QpDztkamWYTKWlnmlrcQvCVB0uRRPm4ZMcMJouKR9n7E2DpL9eolKyOwr/JY08iJOuK3HuW6tRdvE+0x7I+wDprM65OH/PoArlfO5qnIGbeXwsEGRXt0w6a/ubPpeadFjPXotE7cT1SA4YSD1tWTIVm1ZWppOE967XoDIum6tzt5KfzDNRfs9GbCfO0BL235HxbO8I9rTlVLTKcNAiEe0CWolY9HR5pMaosOgZ6PB54InJEZJs4L2b10c+IlVUX1RSnwfFYg0vy5oqrYyqt7gnipl/06YW4PKIYc7TljogsEHf9Cz/kpEKzqDtsH2LrmjMNsbWiousvNHM+MPgcuMg8ZnwLKwDy9NWdI4XLTpg6hVRJNH9erZdfAO5tg/3ub3JLeJbyNo4Bd5f/Bnr5YN/9ahZ87kSpI7v0Qk94dR4hDPjstEcghyZ9RVUoN52+h1g83cd3cIqksJd0kifMCoBmObD013RSPQqNwr9GGU2JaJEm25Vq35dy2DHAkOQpUZVT8GNg9IM4qUDV0yagTN3bZyvuLWIgufb0CAwEAAQ==
5
+
@@ -0,0 +1,23 @@
1
+ # Copyright (c) 2018 Yegor Bugayenko
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the 'Software'), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all
11
+ # copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ # SOFTWARE.
20
+
21
+ require_relative 'asserts'
22
+ wallet = Zold::Wallet.new(Zold::Id.new('0123456789abcdef'))
23
+ assert_equal(Zold::Amount.new(zld: 512.0), wallet.balance)
@@ -0,0 +1,6 @@
1
+ test
2
+ 1
3
+ 0123456789abcdef
4
+ MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnppnkzrCreiKaHF09XKS6bO+2274+wSGo+F8KHvVrNbqear/e09r9PB/P6bFdLoMh4Xc7p/7+NSEZLeu2Eg/dBkQLEb8M/zgkT4gBDGyETW/zusYHIznX/lgf0f8qleIQIIB/3Y7QpDztkamWYTKWlnmlrcQvCVB0uRRPm4ZMcMJouKR9n7E2DpL9eolKyOwr/JY08iJOuK3HuW6tRdvE+0x7I+wDprM65OH/PoArlfO5qnIGbeXwsEGRXt0w6a/ubPpeadFjPXotE7cT1SA4YSD1tWTIVm1ZWppOE967XoDIum6tzt5KfzDNRfs9GbCfO0BL235HxbO8I9rTlVLTKcNAiEe0CWolY9HR5pMaosOgZ6PB54InJEZJs4L2b10c+IlVUX1RSnwfFYg0vy5oqrYyqt7gnipl/06YW4PKIYc7TljogsEHf9Cz/kpEKzqDtsH2LrmjMNsbWiousvNHM+MPgcuMg8ZnwLKwDy9NWdI4XLTpg6hVRJNH9erZdfAO5tg/3ub3JLeJbyNo4Bd5f/Bnr5YN/9ahZ87kSpI7v0Qk94dR4hDPjstEcghyZ9RVUoN52+h1g83cd3cIqksJd0kifMCoBmObD013RSPQqNwr9GGU2JaJEm25Vq35dy2DHAkOQpUZVT8GNg9IM4qUDV0yagTN3bZyvuLWIgufb0CAwEAAQ==
5
+
6
+ 0001;2018-06-22T07:38:23Z;0000020000000000;g6hVRJNH;0000000000000000;To help you;
@@ -0,0 +1 @@
1
+ 1,0.0.0.0,4096,50,2018-06-21T03:41:21Z
@@ -51,13 +51,13 @@ Available options:"
51
51
  mine = Args.new(opts, @log).take || return
52
52
  mine = @wallets.all if mine.empty?
53
53
  mine.map { |i| Id.new(i) }.each do |id|
54
- clean(Copies.new(File.join(@copies, id)), opts)
54
+ clean(Copies.new(File.join(@copies, id), log: @log), opts)
55
55
  end
56
56
  end
57
57
 
58
58
  def clean(cps, _)
59
- cps.clean
60
- @log.debug("Expired local copies removed for #{cps}, \
59
+ deleted = cps.clean
60
+ @log.debug("#{deleted} expired local copies removed for #{cps}, \
61
61
  #{cps.all.count} left")
62
62
  end
63
63
  end
@@ -72,8 +72,8 @@ Available options:"
72
72
  cps = cps.all.sort_by { |c| c[:score] }.reverse
73
73
  patch = Patch.new(@wallets, log: @log)
74
74
  cps.each do |c|
75
- merge_one(opts, patch, Wallet.new(c[:path]), "#{c[:host]}:#{c[:port]}")
76
- @log.debug("#{c[:host]}:#{c[:port]} merged: #{patch}")
75
+ merge_one(opts, patch, Wallet.new(c[:path]), c[:name])
76
+ @log.debug("Copy ##{c[:name]} merged: #{patch}")
77
77
  end
78
78
  wallet = @wallets.find(id)
79
79
  if wallet.exists?
@@ -84,7 +84,7 @@ Available options:"
84
84
  end
85
85
  modified = patch.save(wallet.path, overwrite: true)
86
86
  if modified
87
- @log.debug("#{cps.count} copies merged successfully into #{wallet.path}")
87
+ @log.debug("#{cps.count} copies merged successfully into #{wallet.id}, balance is #{wallet.balance}")
88
88
  else
89
89
  @log.debug("Nothing changed in #{wallet.id} after merge of #{cps.count} copies")
90
90
  end
@@ -94,7 +94,7 @@ Available options:"
94
94
  def merge_one(opts, patch, wallet, name)
95
95
  patch.join(wallet, !opts['no-baseline'])
96
96
  rescue StandardError => e
97
- @log.error("Can't merge a copy coming from #{name}: #{e.message}")
97
+ @log.error("Can't merge copy ##{name}: #{e.message}")
98
98
  @log.debug(Backtrace.new(e).to_s)
99
99
  end
100
100
  end
@@ -38,9 +38,9 @@ module Zold
38
38
  end
39
39
 
40
40
  def run(args = [])
41
+ Zold::Clean.new(wallets: @wallets, copies: @copies, log: @log).run(args)
41
42
  Zold::Fetch.new(wallets: @wallets, remotes: @remotes, copies: @copies, log: @log).run(args)
42
43
  Zold::Merge.new(wallets: @wallets, copies: @copies, log: @log).run(args)
43
- Zold::Clean.new(wallets: @wallets, copies: @copies, log: @log).run(args)
44
44
  end
45
45
  end
46
46
  end
data/lib/zold/copies.rb CHANGED
@@ -21,6 +21,7 @@
21
21
  require 'time'
22
22
  require 'csv'
23
23
  require_relative 'atomic_file'
24
+ require_relative 'log'
24
25
 
25
26
  # The list of copies.
26
27
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
@@ -29,8 +30,12 @@ require_relative 'atomic_file'
29
30
  module Zold
30
31
  # All copies
31
32
  class Copies
32
- def initialize(dir)
33
+ def initialize(dir, log: Log::Quiet.new)
34
+ raise 'Dir can\'t be nil' if dir.nil?
33
35
  @dir = dir
36
+ raise 'Log can\'t be nil' if log.nil?
37
+ @log = log
38
+ @mutex = Mutex.new
34
39
  end
35
40
 
36
41
  def root
@@ -42,16 +47,27 @@ module Zold
42
47
  end
43
48
 
44
49
  def clean
45
- list = load
46
- list.reject! { |s| s[:time] < Time.now - 24 * 60 * 60 }
47
- save(list)
48
- Dir.new(@dir).select { |f| f =~ /^[0-9]+$/ }.each do |f|
49
- File.delete(File.join(@dir, f)) if list.find { |s| s[:name] == f }.nil?
50
+ @mutex.synchronize do
51
+ list = load
52
+ list.reject! { |s| s[:time] < Time.now - 24 * 60 * 60 }
53
+ save(list)
54
+ deleted = 0
55
+ Dir.new(@dir).select { |f| f =~ /^[0-9]+$/ }.each do |f|
56
+ next unless list.find { |s| s[:name] == f }.nil?
57
+ file = File.join(@dir, f)
58
+ size = File.size(file)
59
+ File.delete(file)
60
+ @log.debug("Copy ##{f} deleted: #{size}b")
61
+ deleted += 1
62
+ end
63
+ deleted
50
64
  end
51
65
  end
52
66
 
53
67
  def remove(host, port)
54
- save(load.reject { |s| s[:host] == host && s[:port] == port })
68
+ @mutex.synchronize do
69
+ save(load.reject { |s| s[:host] == host && s[:port] == port })
70
+ end
55
71
  end
56
72
 
57
73
  # Returns the name of the copy
@@ -63,47 +79,49 @@ module Zold
63
79
  raise "Time must be in the past: #{time}" if time > Time.now
64
80
  raise 'Score must be Integer' unless score.is_a?(Integer)
65
81
  raise "Score can't be negative: #{score}" if score < 0
66
- FileUtils.mkdir_p(@dir)
67
- list = load
68
- target = list.find do |s|
69
- f = File.join(@dir, s[:name])
70
- File.exist?(f) && AtomicFile.new(f).read == content
71
- end
72
- if target.nil?
73
- max = Dir.new(@dir)
74
- .select { |f| f =~ /^[0-9]+$/ }
75
- .map(&:to_i)
76
- .max
77
- max = 0 if max.nil?
78
- name = (max + 1).to_s
79
- AtomicFile.new(File.join(@dir, name)).write(content)
80
- else
81
- name = target[:name]
82
+ @mutex.synchronize do
83
+ FileUtils.mkdir_p(@dir)
84
+ list = load
85
+ target = list.find do |s|
86
+ f = File.join(@dir, s[:name])
87
+ File.exist?(f) && AtomicFile.new(f).read == content
88
+ end
89
+ if target.nil?
90
+ max = Dir.new(@dir)
91
+ .select { |f| f =~ /^[0-9]+$/ }
92
+ .map(&:to_i)
93
+ .max
94
+ max = 0 if max.nil?
95
+ name = (max + 1).to_s
96
+ AtomicFile.new(File.join(@dir, name)).write(content)
97
+ else
98
+ name = target[:name]
99
+ end
100
+ list.reject! { |s| s[:host] == host && s[:port] == port }
101
+ list << {
102
+ name: name,
103
+ host: host,
104
+ port: port,
105
+ score: score,
106
+ time: time
107
+ }
108
+ save(list)
109
+ name
82
110
  end
83
- list.reject! { |s| s[:host] == host && s[:port] == port }
84
- list << {
85
- name: name,
86
- host: host,
87
- port: port,
88
- score: score,
89
- time: time
90
- }
91
- save(list)
92
- name
93
111
  end
94
112
 
95
113
  def all
96
- load.group_by { |s| s[:name] }.map do |name, scores|
97
- {
98
- name: name,
99
- host: scores[0][:host],
100
- port: scores[0][:port],
101
- path: File.join(@dir, name),
102
- score: scores.select { |s| s[:time] > Time.now - 24 * 60 * 60 }
103
- .map { |s| s[:score] }
104
- .inject(&:+) || 0
105
- }
106
- end.select { |c| File.exist?(c[:path]) }
114
+ @mutex.synchronize do
115
+ load.group_by { |s| s[:name] }.map do |name, scores|
116
+ {
117
+ name: name,
118
+ path: File.join(@dir, name),
119
+ score: scores.select { |s| s[:time] > Time.now - 24 * 60 * 60 }
120
+ .map { |s| s[:score] }
121
+ .inject(&:+) || 0
122
+ }
123
+ end.select { |c| File.exist?(c[:path]) }
124
+ end
107
125
  end
108
126
 
109
127
  private
@@ -48,6 +48,8 @@ module Zold
48
48
  @address = address
49
49
  raise 'Log can\'t be nil' if log.nil?
50
50
  @log = log
51
+ @history = []
52
+ @mutex = Mutex.new
51
53
  end
52
54
 
53
55
  def start
@@ -55,7 +57,9 @@ module Zold
55
57
  end
56
58
 
57
59
  def to_json
58
- {}
60
+ {
61
+ history: @history.join(', ')
62
+ }
59
63
  end
60
64
 
61
65
  # Returns a list of modifed wallets (as Zold::Id)
@@ -77,9 +81,15 @@ module Zold
77
81
  ).run(['merge', id.to_s, '--no-baseline'])
78
82
  Clean.new(wallets: @wallets, copies: copies.root, log: @log).run(['clean', id.to_s])
79
83
  copies.remove(localhost, Remotes::PORT)
80
- unless modified.empty?
81
- @log.info("Accepted #{id} in #{(Time.now - start).round(2)}s \
82
- and modified #{modified.join(', ')}")
84
+ sec = (Time.now - start).round(2)
85
+ if modified.empty?
86
+ @log.info("Accepted #{id} in #{sec}s and not modified anything")
87
+ else
88
+ @log.info("Accepted #{id} in #{sec}s and modified #{modified.join(', ')}")
89
+ end
90
+ @mutex.synchronize do
91
+ @history.shift if @history.length > 16
92
+ @history << "#{id}/#{sec}/#{modified.count}"
83
93
  end
84
94
  modified
85
95
  end
data/lib/zold/patch.rb CHANGED
@@ -40,7 +40,7 @@ module Zold
40
40
  end
41
41
 
42
42
  def to_s
43
- return 'empty' if @txns.empty?
43
+ return 'empty patch' if @txns.empty?
44
44
  "#{@txns.count} txns"
45
45
  end
46
46
 
@@ -61,14 +61,9 @@ module Zold
61
61
  end
62
62
  raise 'Public key mismatch' if wallet.key != @key
63
63
  raise "Wallet ID mismatch: #{@id} != #{wallet.id}" if wallet.id != @id
64
- max = @txns.select { |t| t.amount.negative? }.map(&:id).max.to_i
65
64
  wallet.txns.each do |txn|
66
65
  next if @txns.find { |t| t == txn }
67
66
  if txn.amount.negative?
68
- if txn.id <= max
69
- @log.error("Transaction ID is not greater than max ID #{max}: #{txn.to_text}")
70
- next
71
- end
72
67
  dup = @txns.find { |t| t.id == txn.id && t.amount.negative? }
73
68
  if dup
74
69
  @log.error("An attempt to overwrite #{dup.to_text} with this: #{txn.to_text}")
@@ -100,8 +95,8 @@ among #{payer.txns.count} transactions: #{txn.to_text}")
100
95
  next
101
96
  end
102
97
  end
103
- @log.debug("Merged on top: #{txn.to_text}")
104
98
  @txns << txn
99
+ @log.debug("Merged on top, balance is #{@txns.map(&:amount).inject(&:+)}: #{txn.to_text}")
105
100
  end
106
101
  end
107
102
 
data/lib/zold/version.rb CHANGED
@@ -23,5 +23,5 @@
23
23
  # Copyright:: Copyright (c) 2018 Yegor Bugayenko
24
24
  # License:: MIT
25
25
  module Zold
26
- VERSION = '0.13.43'.freeze
26
+ VERSION = '0.13.44'.freeze
27
27
  end
@@ -19,6 +19,7 @@
19
19
  # SOFTWARE.
20
20
 
21
21
  require 'minitest/autorun'
22
+ require 'tmpdir'
22
23
  require 'time'
23
24
  require 'webmock/minitest'
24
25
  require_relative '../test__helper'
@@ -121,4 +122,22 @@ class TestMerge < Minitest::Test
121
122
  assert_equal(Zold::Amount::ZERO, main.balance)
122
123
  end
123
124
  end
125
+
126
+ def test_merges_scenarios
127
+ base = 'fixtures/merge'
128
+ Dir.new(base).select { |f| File.directory?(File.join(base, f)) && !f.start_with?('.') }.each do |f|
129
+ Dir.mktmpdir 'test' do |dir|
130
+ FileUtils.cp_r(File.join('fixtures/merge', "#{f}/."), dir)
131
+ FileUtils.cp('fixtures/merge/asserts.rb', dir)
132
+ wallets = Zold::Wallets.new(dir)
133
+ copies = File.join(dir, 'copies')
134
+ Zold::Merge.new(wallets: wallets, copies: copies, log: test_log).run(
135
+ %w[merge 0123456789abcdef]
136
+ )
137
+ Dir.chdir(dir) do
138
+ require File.join(dir, 'assert.rb')
139
+ end
140
+ end
141
+ end
142
+ end
124
143
  end
@@ -51,10 +51,18 @@ class TestEntrance < Minitest::Test
51
51
  FakeHome.new.run do |home|
52
52
  source = home.create_wallet(sid)
53
53
  home.create_wallet(tid)
54
- modified = Zold::Entrance.new(home.wallets, home.remotes, home.copies(source).root, 'x', log: test_log).push(
55
- source.id, body
56
- )
54
+ e = Zold::Entrance.new(home.wallets, home.remotes, home.copies(source).root, 'x', log: test_log)
55
+ modified = e.push(source.id, body)
57
56
  assert_equal(2, modified.count)
58
57
  end
59
58
  end
59
+
60
+ def test_renders_json
61
+ FakeHome.new.run do |home|
62
+ wallet = home.create_wallet
63
+ e = Zold::Entrance.new(home.wallets, home.remotes, home.copies.root, 'x', log: test_log)
64
+ e.push(wallet.id, File.read(wallet.path))
65
+ assert(e.to_json[:history].include?(wallet.id.to_s))
66
+ end
67
+ end
60
68
  end
@@ -147,7 +147,7 @@ class FrontTest < Minitest::Test
147
147
  "Expected HTTP 200 OK: Found #{response.code}"
148
148
  )
149
149
  assert_operator(
150
- 700, :>, response['content-length'].to_i,
150
+ 750, :>, response['content-length'].to_i,
151
151
  'Expected the content to be smaller than 600 bytes for gzip'
152
152
  )
153
153
  end
data/test/test_amount.rb CHANGED
@@ -19,7 +19,6 @@
19
19
  # SOFTWARE.
20
20
 
21
21
  require 'minitest/autorun'
22
- require 'tmpdir'
23
22
  require_relative '../lib/zold/amount'
24
23
 
25
24
  # Amount test.
data/test/test_zold.rb CHANGED
@@ -31,8 +31,7 @@ require_relative '../lib/zold/version'
31
31
  # License:: MIT
32
32
  class TestZold < Minitest::Test
33
33
  def test_all_scripts
34
- Dir.new('fixtures/scripts').each.select { |f| f =~ /\.sh$/ && !f.start_with?('_') }.each do |f|
35
- next unless f == 'redeploy-on-upgrade.sh'
34
+ Dir.new('fixtures/scripts').select { |f| f =~ /\.sh$/ && !f.start_with?('_') }.each do |f|
36
35
  Dir.mktmpdir 'test' do |dir|
37
36
  FileUtils.cp('fixtures/id_rsa.pub', dir)
38
37
  FileUtils.cp('fixtures/id_rsa', dir)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zold
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.13.43
4
+ version: 0.13.44
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yegor Bugayenko
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-06-21 00:00:00.000000000 Z
11
+ date: 2018-06-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -327,6 +327,23 @@ files:
327
327
  - fixtures/keys/1.pub
328
328
  - fixtures/keys/2
329
329
  - fixtures/keys/2.pub
330
+ - fixtures/merge/asserts.rb
331
+ - fixtures/merge/id_rsa
332
+ - fixtures/merge/id_rsa.pub
333
+ - fixtures/merge/random-expenses/0000000000000000
334
+ - fixtures/merge/random-expenses/0123456789abcdef
335
+ - fixtures/merge/random-expenses/assert.rb
336
+ - fixtures/merge/random-expenses/copies/0123456789abcdef/1
337
+ - fixtures/merge/random-expenses/copies/0123456789abcdef/2
338
+ - fixtures/merge/random-expenses/copies/0123456789abcdef/3
339
+ - fixtures/merge/random-expenses/copies/0123456789abcdef/4
340
+ - fixtures/merge/random-expenses/copies/0123456789abcdef/5
341
+ - fixtures/merge/random-expenses/copies/0123456789abcdef/scores
342
+ - fixtures/merge/simple-case/0000000000000000
343
+ - fixtures/merge/simple-case/0123456789abcdef
344
+ - fixtures/merge/simple-case/assert.rb
345
+ - fixtures/merge/simple-case/copies/0123456789abcdef/1
346
+ - fixtures/merge/simple-case/copies/0123456789abcdef/scores
330
347
  - fixtures/scripts/_head.sh
331
348
  - fixtures/scripts/calculate-scores.sh
332
349
  - fixtures/scripts/print-helps.sh