timers 4.1.2 → 4.3.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- checksums.yaml.gz.sig +0 -0
- data/lib/timers/events.rb +105 -105
- data/lib/timers/group.rb +125 -119
- data/lib/timers/interval.rb +41 -0
- data/lib/timers/priority_heap.rb +146 -0
- data/lib/timers/timer.rb +135 -125
- data/lib/timers/version.rb +6 -1
- data/lib/timers/wait.rb +48 -42
- data/lib/timers.rb +18 -3
- data/license.md +48 -0
- data/{README.md → readme.md} +29 -32
- data.tar.gz.sig +0 -0
- metadata +119 -46
- metadata.gz.sig +0 -0
- data/.coveralls.yml +0 -1
- data/.gitignore +0 -17
- data/.rspec +0 -6
- data/.rubocop.yml +0 -28
- data/.ruby-version +0 -1
- data/.travis.yml +0 -21
- data/AUTHORS.md +0 -15
- data/CHANGES.md +0 -62
- data/Gemfile +0 -19
- data/LICENSE +0 -23
- data/Rakefile +0 -10
- data/spec/spec_helper.rb +0 -21
- data/spec/timers/cancel_spec.rb +0 -45
- data/spec/timers/events_spec.rb +0 -56
- data/spec/timers/every_spec.rb +0 -33
- data/spec/timers/group_spec.rb +0 -255
- data/spec/timers/performance_spec.rb +0 -96
- data/spec/timers/strict_spec.rb +0 -36
- data/spec/timers/wait_spec.rb +0 -30
- data/timers.gemspec +0 -26
data/lib/timers/timer.rb
CHANGED
@@ -1,129 +1,139 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
class Timer
|
10
|
-
include Comparable
|
11
|
-
attr_reader :interval, :offset, :recurring
|
12
|
-
|
13
|
-
def initialize(group, interval, recurring = false, offset = nil, &block)
|
14
|
-
@group = group
|
15
|
-
|
16
|
-
@interval = interval
|
17
|
-
@recurring = recurring
|
18
|
-
@block = block
|
19
|
-
@offset = offset
|
20
|
-
|
21
|
-
@handle = nil
|
22
|
-
|
23
|
-
# If a start offset was supplied, use that, otherwise use the current timers offset.
|
24
|
-
reset(@offset || @group.current_offset)
|
25
|
-
end
|
26
|
-
|
27
|
-
def paused?
|
28
|
-
@group.paused_timers.include? self
|
29
|
-
end
|
30
|
-
|
31
|
-
def pause
|
32
|
-
return if paused?
|
33
|
-
|
34
|
-
@group.timers.delete self
|
35
|
-
@group.paused_timers.add self
|
36
|
-
|
37
|
-
@handle.cancel! if @handle
|
38
|
-
@handle = nil
|
39
|
-
end
|
40
|
-
|
41
|
-
def resume
|
42
|
-
return unless paused?
|
43
|
-
|
44
|
-
@group.paused_timers.delete self
|
45
|
-
|
46
|
-
# This will add us back to the group:
|
47
|
-
reset
|
48
|
-
end
|
49
|
-
|
50
|
-
alias continue resume
|
51
|
-
|
52
|
-
# Extend this timer
|
53
|
-
def delay(seconds)
|
54
|
-
@handle.cancel! if @handle
|
55
|
-
|
56
|
-
@offset += seconds
|
57
|
-
|
58
|
-
@handle = @group.events.schedule(@offset, self)
|
59
|
-
end
|
3
|
+
# Released under the MIT License.
|
4
|
+
# Copyright, 2014-2022, by Samuel Williams.
|
5
|
+
# Copyright, 2014-2017, by Tony Arcieri.
|
6
|
+
# Copyright, 2014, by Utenmiki.
|
7
|
+
# Copyright, 2014, by Lin Jen-Shin.
|
8
|
+
# Copyright, 2017, by Vít Ondruch.
|
60
9
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
10
|
+
module Timers
|
11
|
+
# An individual timer set to fire a given proc at a given time. A timer is
|
12
|
+
# always connected to a Timer::Group but it would ONLY be in @group.timers
|
13
|
+
# if it also has a @handle specified. Otherwise it is either PAUSED or has
|
14
|
+
# been FIRED and is not recurring. You can manually enter this state by
|
15
|
+
# calling #cancel and resume normal operation by calling #reset.
|
16
|
+
class Timer
|
17
|
+
include Comparable
|
18
|
+
attr_reader :interval, :offset, :recurring
|
19
|
+
|
20
|
+
def initialize(group, interval, recurring = false, offset = nil, &block)
|
21
|
+
@group = group
|
22
|
+
|
23
|
+
@interval = interval
|
24
|
+
@recurring = recurring
|
25
|
+
@block = block
|
26
|
+
@offset = offset
|
27
|
+
|
28
|
+
@handle = nil
|
29
|
+
|
30
|
+
# If a start offset was supplied, use that, otherwise use the current timers offset.
|
31
|
+
reset(@offset || @group.current_offset)
|
32
|
+
end
|
33
|
+
|
34
|
+
def paused?
|
35
|
+
@group.paused_timers.include? self
|
36
|
+
end
|
37
|
+
|
38
|
+
def pause
|
39
|
+
return if paused?
|
40
|
+
|
41
|
+
@group.timers.delete self
|
42
|
+
@group.paused_timers.add self
|
43
|
+
|
44
|
+
@handle.cancel! if @handle
|
45
|
+
@handle = nil
|
46
|
+
end
|
47
|
+
|
48
|
+
def resume
|
49
|
+
return unless paused?
|
50
|
+
|
51
|
+
@group.paused_timers.delete self
|
52
|
+
|
53
|
+
# This will add us back to the group:
|
54
|
+
reset
|
55
|
+
end
|
56
|
+
|
57
|
+
alias continue resume
|
58
|
+
|
59
|
+
# Extend this timer
|
60
|
+
def delay(seconds)
|
61
|
+
@handle.cancel! if @handle
|
62
|
+
|
63
|
+
@offset += seconds
|
64
|
+
|
65
|
+
@handle = @group.events.schedule(@offset, self)
|
66
|
+
end
|
67
|
+
|
68
|
+
# Cancel this timer. Do not call while paused.
|
69
|
+
def cancel
|
70
|
+
return unless @handle
|
71
|
+
|
72
|
+
@handle.cancel! if @handle
|
73
|
+
@handle = nil
|
74
|
+
|
75
|
+
# This timer is no longer valid:
|
76
|
+
@group.timers.delete self if @group
|
77
|
+
end
|
78
|
+
|
79
|
+
# Reset this timer. Do not call while paused.
|
80
|
+
# @param offset [Numeric] the duration to add to the timer.
|
81
|
+
def reset(offset = @group.current_offset)
|
82
|
+
# This logic allows us to minimise the interaction with @group.timers.
|
83
|
+
# A timer with a handle is always registered with the group.
|
84
|
+
if @handle
|
85
|
+
@handle.cancel!
|
86
|
+
else
|
87
|
+
@group.timers << self
|
88
|
+
end
|
89
|
+
|
90
|
+
@offset = Float(offset) + @interval
|
91
|
+
|
92
|
+
@handle = @group.events.schedule(@offset, self)
|
93
|
+
end
|
94
|
+
|
95
|
+
# Fire the block.
|
96
|
+
def fire(offset = @group.current_offset)
|
97
|
+
if recurring == :strict
|
98
|
+
# ... make the next interval strictly the last offset + the interval:
|
99
|
+
reset(@offset)
|
100
|
+
elsif recurring
|
101
|
+
reset(offset)
|
102
|
+
else
|
103
|
+
@offset = offset
|
104
|
+
end
|
105
|
+
|
106
|
+
@block.call(offset, self)
|
107
|
+
|
108
|
+
cancel unless recurring
|
109
|
+
end
|
110
|
+
|
111
|
+
alias call fire
|
112
|
+
|
113
|
+
# Number of seconds until next fire / since last fire
|
114
|
+
def fires_in
|
115
|
+
@offset - @group.current_offset if @offset
|
116
|
+
end
|
117
|
+
|
118
|
+
# Inspect a timer
|
119
|
+
def inspect
|
120
|
+
buffer = "#{to_s[0..-2]} ".dup
|
121
|
+
|
122
|
+
if @offset
|
123
|
+
if fires_in >= 0
|
124
|
+
buffer << "fires in #{fires_in} seconds"
|
125
|
+
else
|
126
|
+
buffer << "fired #{fires_in.abs} seconds ago"
|
127
|
+
end
|
128
|
+
|
129
|
+
buffer << ", recurs every #{interval}" if recurring
|
130
|
+
else
|
131
|
+
buffer << "dead"
|
132
|
+
end
|
133
|
+
|
134
|
+
buffer << ">"
|
135
|
+
|
136
|
+
return buffer
|
137
|
+
end
|
138
|
+
end
|
129
139
|
end
|
data/lib/timers/version.rb
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# Released under the MIT License.
|
4
|
+
# Copyright, 2012-2016, by Tony Arcieri.
|
5
|
+
# Copyright, 2014-2022, by Samuel Williams.
|
6
|
+
# Copyright, 2015, by Donovan Keme.
|
7
|
+
|
3
8
|
module Timers
|
4
|
-
|
9
|
+
VERSION = "4.3.5"
|
5
10
|
end
|
data/lib/timers/wait.rb
CHANGED
@@ -1,47 +1,53 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
# Released under the MIT License.
|
4
|
+
# Copyright, 2014-2022, by Samuel Williams.
|
5
|
+
# Copyright, 2014-2016, by Tony Arcieri.
|
6
|
+
# Copyright, 2015, by Utenmiki.
|
7
|
+
# Copyright, 2015, by Donovan Keme.
|
4
8
|
|
5
|
-
|
6
|
-
# An exclusive, monotonic timeout class.
|
7
|
-
class Wait
|
8
|
-
def self.for(duration, &block)
|
9
|
-
if duration
|
10
|
-
timeout = new(duration)
|
11
|
-
|
12
|
-
timeout.while_time_remaining(&block)
|
13
|
-
else
|
14
|
-
loop do
|
15
|
-
yield(nil)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
def initialize(duration)
|
21
|
-
@duration = duration
|
22
|
-
@remaining = true
|
23
|
-
end
|
24
|
-
|
25
|
-
attr_reader :duration
|
26
|
-
attr_reader :remaining
|
27
|
-
|
28
|
-
# Yields while time remains for work to be done:
|
29
|
-
def while_time_remaining
|
30
|
-
@interval = Hitimes::Interval.new
|
31
|
-
@interval.start
|
9
|
+
require_relative "interval"
|
32
10
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
11
|
+
module Timers
|
12
|
+
# An exclusive, monotonic timeout class.
|
13
|
+
class Wait
|
14
|
+
def self.for(duration, &block)
|
15
|
+
if duration
|
16
|
+
timeout = new(duration)
|
17
|
+
|
18
|
+
timeout.while_time_remaining(&block)
|
19
|
+
else
|
20
|
+
loop do
|
21
|
+
yield(nil)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def initialize(duration)
|
27
|
+
@duration = duration
|
28
|
+
@remaining = true
|
29
|
+
end
|
30
|
+
|
31
|
+
attr_reader :duration
|
32
|
+
attr_reader :remaining
|
33
|
+
|
34
|
+
# Yields while time remains for work to be done:
|
35
|
+
def while_time_remaining
|
36
|
+
@interval = Interval.new
|
37
|
+
@interval.start
|
38
|
+
|
39
|
+
yield @remaining while time_remaining?
|
40
|
+
ensure
|
41
|
+
@interval.stop
|
42
|
+
@interval = nil
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def time_remaining?
|
48
|
+
@remaining = (@duration - @interval.to_f)
|
49
|
+
|
50
|
+
@remaining > 0
|
51
|
+
end
|
52
|
+
end
|
47
53
|
end
|
data/lib/timers.rb
CHANGED
@@ -1,6 +1,21 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
# Released under the MIT License.
|
4
|
+
# Copyright, 2012-2016, by Tony Arcieri.
|
5
|
+
# Copyright, 2012, by Ryan LeCompte.
|
6
|
+
# Copyright, 2012, by Nicholas Evans.
|
7
|
+
# Copyright, 2012, by Dimitrij Denissenko.
|
8
|
+
# Copyright, 2013, by Chuck Remes.
|
9
|
+
# Copyright, 2013, by Ron Evans.
|
10
|
+
# Copyright, 2013, by Sean Gregory.
|
11
|
+
# Copyright, 2013, by Utenmiki.
|
12
|
+
# Copyright, 2013, by Jeremy Hinegardner.
|
13
|
+
# Copyright, 2014, by Larry Lv.
|
14
|
+
# Copyright, 2014, by Bruno Enten.
|
15
|
+
# Copyright, 2014-2022, by Samuel Williams.
|
16
|
+
# Copyright, 2014, by Mike Bourgeous.
|
4
17
|
|
5
|
-
|
6
|
-
|
18
|
+
require_relative "timers/version"
|
19
|
+
|
20
|
+
require_relative "timers/group"
|
21
|
+
require_relative "timers/wait"
|
data/license.md
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
# MIT License
|
2
|
+
|
3
|
+
Copyright, 2012-2017, by Tony Arcieri.
|
4
|
+
Copyright, 2012, by Ryan LeCompte.
|
5
|
+
Copyright, 2012, by Jesse Cooke.
|
6
|
+
Copyright, 2012, by Nicholas Evans.
|
7
|
+
Copyright, 2012, by Dimitrij Denissenko.
|
8
|
+
Copyright, 2013, by Chuck Remes.
|
9
|
+
Copyright, 2013, by Ron Evans.
|
10
|
+
Copyright, 2013, by Sean Gregory.
|
11
|
+
Copyright, 2013-2015, by Utenmiki.
|
12
|
+
Copyright, 2013, by Jeremy Hinegardner.
|
13
|
+
Copyright, 2014, by Larry Lv.
|
14
|
+
Copyright, 2014, by Bruno Enten.
|
15
|
+
Copyright, 2014-2022, by Samuel Williams.
|
16
|
+
Copyright, 2014, by Mike Bourgeous.
|
17
|
+
Copyright, 2014, by Klaus Trainer.
|
18
|
+
Copyright, 2014, by Lin Jen-Shin.
|
19
|
+
Copyright, 2014, by Lavir the Whiolet.
|
20
|
+
Copyright, 2015-2016, by Donovan Keme.
|
21
|
+
Copyright, 2015, by Tommy Ong Gia Phu.
|
22
|
+
Copyright, 2015, by Will Jessop.
|
23
|
+
Copyright, 2016, by Ryunosuke SATO.
|
24
|
+
Copyright, 2016, by Atul Bhosale.
|
25
|
+
Copyright, 2016, by Feram.
|
26
|
+
Copyright, 2017, by Vít Ondruch.
|
27
|
+
Copyright, 2017-2020, by Olle Jonsson.
|
28
|
+
Copyright, 2020, by Tim Smith.
|
29
|
+
Copyright, 2021, by Wander Hillen.
|
30
|
+
Copyright, 2022, by Yoshiki Takagi.
|
31
|
+
|
32
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
33
|
+
of this software and associated documentation files (the "Software"), to deal
|
34
|
+
in the Software without restriction, including without limitation the rights
|
35
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
36
|
+
copies of the Software, and to permit persons to whom the Software is
|
37
|
+
furnished to do so, subject to the following conditions:
|
38
|
+
|
39
|
+
The above copyright notice and this permission notice shall be included in all
|
40
|
+
copies or substantial portions of the Software.
|
41
|
+
|
42
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
43
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
44
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
45
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
46
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
47
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
48
|
+
SOFTWARE.
|
data/{README.md → readme.md}
RENAMED
@@ -1,35 +1,30 @@
|
|
1
|
-
# Timers
|
1
|
+
# Timers
|
2
2
|
|
3
|
-
[
|
4
|
-
[gem-link]: http://rubygems.org/gems/timers
|
5
|
-
[build-image]: https://secure.travis-ci.org/celluloid/timers.svg?branch=master
|
6
|
-
[build-link]: https://travis-ci.org/celluloid/timers
|
7
|
-
[codeclimate-image]: https://codeclimate.com/github/celluloid/timers.svg
|
8
|
-
[codeclimate-link]: https://codeclimate.com/github/celluloid/timers
|
9
|
-
[coverage-image]: https://coveralls.io/repos/celluloid/timers/badge.svg?branch=master
|
10
|
-
[coverage-link]: https://coveralls.io/r/celluloid/timers
|
11
|
-
[license-image]: https://img.shields.io/badge/license-MIT-blue.svg
|
12
|
-
[license-link]: https://github.com/celluloid/timers/master/LICENSE.txt
|
3
|
+
Collections of one-shot and periodic timers, intended for use with event loops such as [async](https://github.com/socketry/async).
|
13
4
|
|
14
|
-
|
5
|
+
[![Development Status](https://github.com/socketry/timers/workflows/Test/badge.svg)](https://github.com/socketry/timers/actions?workflow=Test)
|
15
6
|
|
16
|
-
|
17
|
-
to provide the timer subsystem for [Celluloid], it can be used independently
|
18
|
-
in any sort of event loop context, or can provide a purely timer-based event
|
19
|
-
loop itself.
|
7
|
+
## Installation
|
20
8
|
|
21
|
-
|
9
|
+
Add this line to your application's Gemfile:
|
22
10
|
|
23
|
-
|
11
|
+
``` ruby
|
12
|
+
gem 'timers'
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle
|
24
18
|
|
25
|
-
|
26
|
-
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install timers
|
27
22
|
|
28
23
|
## Usage
|
29
24
|
|
30
25
|
Create a new timer group with `Timers::Group.new`:
|
31
26
|
|
32
|
-
```ruby
|
27
|
+
``` ruby
|
33
28
|
require 'timers'
|
34
29
|
|
35
30
|
timers = Timers::Group.new
|
@@ -37,7 +32,7 @@ timers = Timers::Group.new
|
|
37
32
|
|
38
33
|
Schedule a proc to run after 5 seconds with `Timers::Group#after`:
|
39
34
|
|
40
|
-
```ruby
|
35
|
+
``` ruby
|
41
36
|
five_second_timer = timers.after(5) { puts "Take five" }
|
42
37
|
```
|
43
38
|
|
@@ -46,7 +41,7 @@ cancel a timer, use `Timers::Timer#cancel`
|
|
46
41
|
|
47
42
|
Once you've scheduled a timer, you can wait until the next timer fires with `Timers::Group#wait`:
|
48
43
|
|
49
|
-
```ruby
|
44
|
+
``` ruby
|
50
45
|
# Waits 5 seconds
|
51
46
|
timers.wait
|
52
47
|
|
@@ -55,14 +50,15 @@ timers.wait
|
|
55
50
|
|
56
51
|
You can schedule a block to run periodically with `Timers::Group#every`:
|
57
52
|
|
58
|
-
```ruby
|
53
|
+
``` ruby
|
59
54
|
every_five_seconds = timers.every(5) { puts "Another 5 seconds" }
|
60
55
|
|
61
56
|
loop { timers.wait }
|
62
57
|
```
|
63
58
|
|
64
59
|
You can also schedule a block to run immediately and periodically with `Timers::Group#now_and_every`:
|
65
|
-
|
60
|
+
|
61
|
+
``` ruby
|
66
62
|
now_and_every_five_seconds = timers.now_and_every(5) { puts "Now and in another 5 seconds" }
|
67
63
|
|
68
64
|
loop { timers.wait }
|
@@ -72,7 +68,7 @@ If you'd like another method to do the waiting for you, e.g. `Kernel.select`,
|
|
72
68
|
you can use `Timers::Group#wait_interval` to obtain the amount of time to wait. When
|
73
69
|
a timeout is encountered, you can fire all pending timers with `Timers::Group#fire`:
|
74
70
|
|
75
|
-
```ruby
|
71
|
+
``` ruby
|
76
72
|
loop do
|
77
73
|
interval = timers.wait_interval
|
78
74
|
ready_readers, ready_writers = select readers, writers, nil, interval
|
@@ -89,7 +85,7 @@ end
|
|
89
85
|
|
90
86
|
You can also pause and continue individual timers, or all timers:
|
91
87
|
|
92
|
-
```ruby
|
88
|
+
``` ruby
|
93
89
|
paused_timer = timers.every(5) { puts "I was paused" }
|
94
90
|
|
95
91
|
paused_timer.pause
|
@@ -105,9 +101,10 @@ timers.resume
|
|
105
101
|
10.times { timers.wait } # will fire all timers
|
106
102
|
```
|
107
103
|
|
108
|
-
##
|
109
|
-
|
110
|
-
Copyright (c) 2012-2016 Celluloid timers project developers (given in the file
|
111
|
-
AUTHORS.md).
|
104
|
+
## Contributing
|
112
105
|
|
113
|
-
|
106
|
+
1. Fork it
|
107
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
108
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
109
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
110
|
+
5. Create new Pull Request
|
data.tar.gz.sig
ADDED
Binary file
|