redstruct 0.1.7 → 0.2.0

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.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +15 -11
  3. data/Rakefile +5 -5
  4. data/lib/redstruct/all.rb +14 -0
  5. data/lib/redstruct/configuration.rb +9 -6
  6. data/lib/redstruct/connection_proxy.rb +123 -0
  7. data/lib/redstruct/counter.rb +96 -0
  8. data/lib/redstruct/error.rb +2 -0
  9. data/lib/redstruct/factory/object.rb +31 -0
  10. data/lib/redstruct/factory.rb +94 -55
  11. data/lib/redstruct/hash.rb +123 -0
  12. data/lib/redstruct/list.rb +315 -0
  13. data/lib/redstruct/lock.rb +183 -0
  14. data/lib/redstruct/script.rb +104 -0
  15. data/lib/redstruct/set.rb +155 -0
  16. data/lib/redstruct/sorted_set/slice.rb +124 -0
  17. data/lib/redstruct/sorted_set.rb +153 -0
  18. data/lib/redstruct/string.rb +66 -0
  19. data/lib/redstruct/struct.rb +87 -0
  20. data/lib/redstruct/utils/coercion.rb +14 -8
  21. data/lib/redstruct/utils/inspectable.rb +8 -4
  22. data/lib/redstruct/utils/iterable.rb +52 -0
  23. data/lib/redstruct/utils/scriptable.rb +32 -6
  24. data/lib/redstruct/version.rb +4 -1
  25. data/lib/redstruct.rb +17 -51
  26. data/lib/yard/defscript_handler.rb +5 -3
  27. data/test/redstruct/configuration_test.rb +13 -0
  28. data/test/redstruct/connection_proxy_test.rb +85 -0
  29. data/test/redstruct/counter_test.rb +108 -0
  30. data/test/redstruct/factory/object_test.rb +21 -0
  31. data/test/redstruct/factory_test.rb +136 -0
  32. data/test/redstruct/hash_test.rb +138 -0
  33. data/test/redstruct/list_test.rb +244 -0
  34. data/test/redstruct/lock_test.rb +108 -0
  35. data/test/redstruct/script_test.rb +53 -0
  36. data/test/redstruct/set_test.rb +219 -0
  37. data/test/redstruct/sorted_set/slice_test.rb +10 -0
  38. data/test/redstruct/sorted_set_test.rb +219 -0
  39. data/test/redstruct/string_test.rb +8 -0
  40. data/test/redstruct/struct_test.rb +61 -0
  41. data/test/redstruct/utils/coercion_test.rb +33 -0
  42. data/test/redstruct/utils/inspectable_test.rb +31 -0
  43. data/test/redstruct/utils/iterable_test.rb +94 -0
  44. data/test/redstruct/utils/scriptable_test.rb +67 -0
  45. data/test/redstruct_test.rb +14 -0
  46. data/test/test_helper.rb +77 -1
  47. metadata +58 -26
  48. data/lib/redstruct/connection.rb +0 -47
  49. data/lib/redstruct/factory/creation.rb +0 -95
  50. data/lib/redstruct/factory/deserialization.rb +0 -7
  51. data/lib/redstruct/hls/lock.rb +0 -175
  52. data/lib/redstruct/hls/queue.rb +0 -29
  53. data/lib/redstruct/hls.rb +0 -2
  54. data/lib/redstruct/types/base.rb +0 -36
  55. data/lib/redstruct/types/counter.rb +0 -65
  56. data/lib/redstruct/types/hash.rb +0 -72
  57. data/lib/redstruct/types/list.rb +0 -76
  58. data/lib/redstruct/types/script.rb +0 -56
  59. data/lib/redstruct/types/set.rb +0 -96
  60. data/lib/redstruct/types/sorted_set.rb +0 -129
  61. data/lib/redstruct/types/string.rb +0 -64
  62. data/lib/redstruct/types/struct.rb +0 -58
  63. data/lib/releaser/logger.rb +0 -15
  64. data/lib/releaser/repository.rb +0 -32
  65. data/lib/tasks/release.rake +0 -49
  66. data/test/redstruct/restruct_test.rb +0 -4
@@ -1,36 +0,0 @@
1
- module Redstruct
2
- module Types
3
- # Base class for all objects a factory can produce
4
- class Base
5
- include Redstruct::Utils::Inspectable
6
- extend Forwardable
7
-
8
- def_delegators :@factory, :connection, :connection
9
-
10
- # @return [String] The key used to identify the struct on redis
11
- attr_reader :key
12
-
13
- def initialize(key:, factory:)
14
- @factory = factory
15
- @key = key
16
- end
17
-
18
- def to_h
19
- return { key: @key }
20
- end
21
-
22
- def create
23
- return unless block_given?
24
- subfactory = @factory.factory(@key)
25
- yield(subfactory)
26
- end
27
- protected :create
28
-
29
- # :nocov:
30
- def inspectable_attributes
31
- { key: @key, factory: @factory }
32
- end
33
- # :nocov:
34
- end
35
- end
36
- end
@@ -1,65 +0,0 @@
1
- module Redstruct
2
- module Types
3
- class Counter < Redstruct::Types::String
4
- include Redstruct::Utils::Scriptable
5
-
6
- def initialize(increment: 1, max: nil, **options)
7
- super(**options)
8
- @increment = increment
9
- @max = max
10
- end
11
-
12
- def get
13
- super.to_i
14
- end
15
-
16
- def set(value, **options)
17
- super(value.to_i, **options)
18
- end
19
-
20
- def increment(by: nil, max: nil)
21
- by ||= @increment
22
- max ||= @max
23
-
24
- value = if max.nil?
25
- self.connection.incrby(@key, by.to_i).to_i
26
- else
27
- ring_increment_script(keys: @key, argv: [by.to_i, max.to_i]).to_i
28
- end
29
-
30
- return value
31
- end
32
-
33
- def decrement(by: nil, max: nil)
34
- by ||= @increment
35
- by = -by.to_i
36
- return increment(by: by, max: max)
37
- end
38
-
39
- def getset(value)
40
- return super(value.to_i).to_i
41
- end
42
-
43
- # @!group Lua Scripts
44
-
45
- defscript :ring_increment_script, <<~LUA
46
- local by = tonumber(ARGV[1])
47
- local max = tonumber(ARGV[2])
48
- local current = redis.call('get', KEYS[1])
49
- local value = current and tonumber(current) or 0
50
-
51
- value = (value + by) % max
52
- redis.call('set', KEYS[1], value)
53
-
54
- return value
55
- LUA
56
-
57
- # @!endgroup
58
-
59
- # Helper method for easy inspection
60
- def inspectable_attributes
61
- super.merge(max: @max, increment: @increment)
62
- end
63
- end
64
- end
65
- end
@@ -1,72 +0,0 @@
1
- module Redstruct
2
- module Types
3
- class Hash < Redstruct::Types::Struct
4
- include Redstruct::Utils::Coercion
5
-
6
- def [](key)
7
- return self.connection.hget(@key, key)
8
- end
9
-
10
- def []=(key, value)
11
- self.connection.hset(@key, key, value)
12
- end
13
-
14
- def set(key, value, overwrite: true)
15
- if overwrite
16
- self[key] = value
17
- else
18
- self.connection.hsetnx(@key, key, value)
19
- end
20
- end
21
-
22
- def get(*keys)
23
- return self[keys.first] if keys.size == 1
24
- return self.connection.mapped_hmget(@key, *keys)
25
- end
26
-
27
- def update(hash)
28
- self.connection.mapped_hmset(@key, hash)
29
- end
30
-
31
- def remove(*keys)
32
- return self.connection.hdel(@key, keys)
33
- end
34
-
35
- def key?(key)
36
- return coerce_bool(self.connection.hexists(@key, key))
37
- end
38
-
39
- def incr(key, increment: 1)
40
- if increment.is_a?(Float)
41
- self.connection.hincrbyfloat(@key, key, increment.to_f)
42
- else
43
- self.connection.hincrby(@key, key, increment)
44
- end
45
- end
46
-
47
- def decr(key, increment: 1)
48
- return incr(key, -increment)
49
- end
50
-
51
- def to_h
52
- return self.connection.hgetall(@key)
53
- end
54
-
55
- def keys
56
- return self.connection.hkeys(@key)
57
- end
58
-
59
- def values
60
- return self.connection.hvals(@key)
61
- end
62
-
63
- def size
64
- return self.connection.hlen(@key)
65
- end
66
-
67
- def each(options = {}, &block)
68
- return self.connection.hscan_each(@key, options, &block)
69
- end
70
- end
71
- end
72
- end
@@ -1,76 +0,0 @@
1
- module Redstruct
2
- module Types
3
- class List < Redstruct::Types::Struct
4
- include Redstruct::Utils::Scriptable
5
-
6
- def clear
7
- delete
8
- end
9
-
10
- def empty?
11
- return !exists?
12
- end
13
-
14
- def [](index)
15
- return self.connection.lindex(@key, index.to_i)
16
- end
17
-
18
- def []=(index, value)
19
- return self.connection.lset(@key, index.to_i, value)
20
- end
21
-
22
- def append(*elements, max: 0)
23
- max = max.to_i
24
- return self.connection.rpush(@key, elements) if max <= 0
25
- return push_and_trim_script(keys: @key, argv: [max - 1, 0] + elements)
26
- end
27
-
28
- def prepend(*elements, max: nil)
29
- max = max.to_i
30
- return self.connection.lpush(@key, elements) if max <= 0
31
- return push_and_trim_script(keys: @key, argv: [max - 1, 1] + elements)
32
- end
33
-
34
- def pop(timeout: nil)
35
- return timeout.nil? ? self.connection.lpop(@key) : self.connection.blpop(@key, timeout: timeout)&.last
36
- end
37
-
38
- def remove(value, count: 1)
39
- count = [1, count.to_i].max
40
- self.connection.lrem(@key, count, value)
41
- end
42
-
43
- def size
44
- return self.connection.llen(@key)
45
- end
46
-
47
- def slice(start = 0, length = -1)
48
- return self.connection.lrange(@key, start.to_i, length.to_i)
49
- end
50
-
51
- def to_a
52
- return slice(0, -1)
53
- end
54
-
55
- # Appends or prepends (argv[1]) a number of items (argv[2]) to a list (keys[1]),
56
- # then trims it out to size (argv[3])
57
- # @param [Array<(::String)>] keys First key should be the key to the list to prepend to and resize
58
- # @param [Array<(Fixnum, Fixnum, Array<::String>)>] argv The maximum size of the list; if 1, will lpush, otherwise rpush; the list of items to prepend
59
- # @return [Fixnum] The length of the list after the operation
60
- defscript :push_and_trim_script, <<~LUA
61
- local max = tonumber(table.remove(ARGV, 1))
62
- local prepend = tonumber(table.remove(ARGV, 1)) == 1
63
- local push = prepend and 'lpush' or 'rpush'
64
-
65
- local size = redis.call(push, KEYS[1], unpack(ARGV))
66
- if size > max then
67
- redis.call('ltrim', KEYS[1], 0, max)
68
- size = max + 1
69
- end
70
-
71
- return size
72
- LUA
73
- protected :push_and_trim_script
74
- end
75
- end
76
- end
@@ -1,56 +0,0 @@
1
- require 'digest'
2
-
3
- module Redstruct
4
- module Types
5
- # It is recommended you flush your script cache on the redis server every once in a while
6
- class Script < Redstruct::Types::Base
7
- ERROR_MESSAGE_PREFIX = 'NOSCRIPT'.freeze
8
-
9
- # @return [::String] The Lua script to evaluate
10
- attr_reader :script
11
-
12
- def initialize(script:, **options)
13
- script = script&.strip
14
- raise(Redstruct::Error, 'No source script given') if script.empty?
15
-
16
- super(**options)
17
- self.script = script
18
- end
19
-
20
- def script=(script)
21
- @sha1 = nil
22
- @script = script.dup.freeze
23
- end
24
-
25
- def sha1
26
- return @sha1 ||= begin
27
- Digest::SHA1.hexdigest(@script)
28
- end
29
- end
30
-
31
- def exists?
32
- return self.connection.script(:exists, self.sha1)
33
- end
34
-
35
- def load
36
- @sha1 = self.connection.script(:load, @script)
37
- return @sha1
38
- end
39
-
40
- def eval(keys:, argv:)
41
- keys = [keys] unless keys.is_a?(Array)
42
- argv = [argv] unless argv.is_a?(Array)
43
- self.connection.evalsha(self.sha1, keys, argv)
44
- rescue Redis::CommandError => err
45
- raise unless err.message.start_with?(ERROR_MESSAGE_PREFIX)
46
- self.connection.eval(@script, keys, argv)
47
- end
48
-
49
- # :nocov:
50
- def inspectable_attributes
51
- return super.merge(sha1: self.sha1, script: @script.slice(0, 20))
52
- end
53
- # :nocov:
54
- end
55
- end
56
- end
@@ -1,96 +0,0 @@
1
- # frozen_string_literal: true
2
- module Redstruct
3
- module Types
4
- # Note: keep in mind Redis converts everything to a string on the DB side
5
- class Set < Redstruct::Types::Struct
6
- def clear
7
- delete
8
- end
9
-
10
- def random(count: 1)
11
- list = self.connection.srandmember(@key, count)
12
- return count == 1 ? list[0] : Set.new(list)
13
- end
14
-
15
- def empty?
16
- return !exists?
17
- end
18
-
19
- def contain?(member)
20
- return self.connection.sismember(@key, member)
21
- end
22
- alias_method :include?, :contain?
23
-
24
- def to_a
25
- return self.connection.smembers(@key)
26
- end
27
-
28
- def add(*members)
29
- return self.connection.sadd(@key, members)
30
- end
31
- alias_method :<<, :add
32
-
33
- def size
34
- return self.connection.scard(@key).to_i
35
- end
36
-
37
- def -(other)
38
- return ::Set.new(self.connection.sdiff(@key, other.key))
39
- end
40
-
41
- def +(other)
42
- return ::Set.new(self.connection.sunion(@key, other.key))
43
- end
44
-
45
- def |(other)
46
- return ::Set.new(self.connection.sinter(@key, other.key))
47
- end
48
-
49
- def difference(other, dest: nil)
50
- destination = coerce_destination(dest)
51
- return self - other if destination.nil?
52
-
53
- self.connection.sdiffstore(destination.key, @key, other.key)
54
- return destination
55
- end
56
-
57
- def intersection(other, dest: nil)
58
- destination = coerce_destination(dest)
59
- return self - other if destination.nil?
60
-
61
- self.connection.sinterstore(destination.key, @key, other.key)
62
- return destination
63
- end
64
-
65
- def union(other, dest: nil)
66
- destination = coerce_destination(dest)
67
- return self - other if destination.nil?
68
-
69
- self.connection.sunionstore(destination.key, @key, other.key)
70
- return destination
71
- end
72
-
73
- def pop
74
- return self.connection.spop(@key)
75
- end
76
-
77
- def remove(*members)
78
- return self.connection.srem(@key, *members)
79
- end
80
-
81
- def each(options = {}, &block)
82
- return self.connection.sscan_each(@key, options, &block)
83
- end
84
-
85
- def coerce_destination(dest)
86
- return case dest
87
- when ::String
88
- @factory.set(dest)
89
- when self.class
90
- dest
91
- end
92
- end
93
- private :coerce_destination
94
- end
95
- end
96
- end
@@ -1,129 +0,0 @@
1
- # frozen_string_literal: true
2
- module Redstruct
3
- module Types
4
- class SortedSet < Redstruct::Types::Struct
5
- # @param [Array<Array<#to_f, #to_s>>] pairs a list of pairs, where the first element is the score, and second the value
6
- # @return [Integer] returns the amount of pairs inserted
7
- def add(*pairs)
8
- return self.connection.zadd(@key, pairs)
9
- end
10
-
11
- # @param [Array<#to_s>] values list of member values to remove from the set
12
- # @return [Integer] the amount of elements removed
13
- def remove(*values)
14
- return self.connection.zrem(@key, values)
15
- end
16
-
17
- # Removes all items from the set. Does this by simply deleting the key
18
- # @see Redstruct::Struct#delete
19
- def clear
20
- delete
21
- end
22
-
23
- # Returns the cardinality of the set
24
- # @return [Integer] how many items are in the set
25
- def size
26
- return self.connection.zcard(@key)
27
- end
28
-
29
- # Returns the number of items between lower and upper bounds.
30
- # By default lower and upper are inclusive. If you want to make them exclusive, prepend the value with "("
31
- # @param [#to_s, #to_f] lower lower bound for the count range
32
- # @param [#to_s, #to_f] upper upper bound for the count range
33
- # @return [Integer] the number of items in the given range
34
- def count(lower: nil, upper: nil)
35
- return slice(lower: lower, upper: upper).size
36
- end
37
-
38
- # Returns a slice or partial selection of the set.
39
- # @param [#to_s, #to_f] lower lower bound for the slice operation; it should be a simple float
40
- # @param [#to_s, #to_f] upper upper bound for the slice operation; it should be a simple float
41
- # @return [Redstruct::Types::SortedSet::Slice] sorted slice by given bounds, as list of pairs: (score, value)
42
- def slice(lower: nil, upper: nil)
43
- return self.class::Slice.new(self, lower: lower, upper: upper)
44
- end
45
-
46
- # Checks if the set contains any items.
47
- # @return [Boolean] true if the key exists (meaning it contains at least 1 item), false otherwise
48
- def empty?
49
- return !self.connection.exists?
50
- end
51
-
52
- # @param [#to_s] item the item to check for
53
- # @return [Boolean] true if the item is in the set, false otherwise
54
- def contain?(item)
55
- return !index(item).nil?
56
- end
57
- alias include? contain?
58
-
59
- # Returns the index of the item in the set, sorted ascending by score
60
- # @param [#to_s] item the item to check for
61
- # @return [Integer, nil] the index of the item, or nil if not found
62
- # @see Redis#zrank
63
- def index(item)
64
- return self.connection.zrank(@key, item)
65
- end
66
-
67
- # Returns the index of the item in the set, sorted descending by score
68
- # @param [#to_s] item the item to check for
69
- # @return [Integer, nil] the index of the item, or nil if not found
70
- # @see Redis#zrevrank
71
- def rindex(item)
72
- return self.connection.zrevrank(@key, item)
73
- end
74
-
75
- # Returns an array representation of the set, sorted by score ascending
76
- # NOTE: It pulls the whole set into memory, so use each if that's a concern
77
- # @return [Array<Redstruct::Utils::ScoredValue>] all the items in the set, sorted by score ascending
78
- # @see Redis#zrange
79
- def to_a
80
- return slice.to_a
81
- end
82
-
83
- # Utility class to allow operations on portions of the set only
84
- class Slice
85
- include Redstruct::Utils::Inspectable
86
-
87
- # @param [String, Float] lower lower bound for the slice operation
88
- # @param [String, Float] upper upper bound for the slice operation
89
- def initialize(set, lower: nil, upper: nil)
90
- @set = set
91
- @lower = parse_bound(lower || '-inf')
92
- @upper = parse_bound(upper || '+inf')
93
- end
94
-
95
- # @return [Array<String>] returns an array of values for the given scores
96
- def to_a
97
- @set.connection.zrangebyscore(@set.key, @lower, @upper)
98
- end
99
-
100
- # @return [Integer] the number of elements removed
101
- def remove
102
- @set.connection.zremrangebyscore(@set.key, @lower, @upper)
103
- end
104
-
105
- # @return [Integer] number of elements in the slice
106
- def size
107
- @set.connection.zcount(@set.key, @lower, @upper)
108
- end
109
-
110
- def inspectable_attributes
111
- { lower: @lower, upper: @upper, set: @set }
112
- end
113
-
114
- private
115
-
116
- def parse_bound(bound)
117
- case bound
118
- when -Float::INFINITY
119
- '-inf'
120
- when Float::INFINITY
121
- '+inf'
122
- else
123
- bound
124
- end
125
- end
126
- end
127
- end
128
- end
129
- end
@@ -1,64 +0,0 @@
1
- module Redstruct
2
- module Types
3
- class String < Redstruct::Types::Struct
4
- include Redstruct::Utils::Scriptable, Redstruct::Utils::Coercion
5
-
6
- # @return [::String] The string value stored in the database
7
- def get
8
- return self.connection.get(@key)
9
- end
10
-
11
- # @param [Object] value The object to store; note, it will be stored using a string representation
12
- # @param [Integer] expiry The expiry time in seconds; if nil, will never expire
13
- # @param [Boolean] nx Not Exists: if true, will not set the key if it already existed
14
- # @param [Boolean] xx Already Exists: if true, will set the key only if it already existed
15
- # @return [Boolean] True if set, false otherwise
16
- def set(value, expiry: nil, nx: nil, xx: nil)
17
- options = {}
18
- options[:ex] = expiry.to_i unless expiry.nil?
19
- options[:nx] = nx unless nx.nil?
20
- options[:xx] = xx unless xx.nil?
21
-
22
- self.connection.set(@key, value, options) == 'OK'
23
- end
24
-
25
- # @param [::String] value The value to compare with
26
- # @return [Boolean] True if deleted, false otherwise
27
- def delete_if_equals(value)
28
- coerce_bool(delete_if_equals_script(keys: @key, argv: value))
29
- end
30
-
31
- # @param [Object] value The object to store; note, it will be stored using a string representation
32
- # @return [::String] The old value before setting it
33
- def getset(value)
34
- self.connection.getset(@key, value)
35
- end
36
-
37
- # @return [Fixnum] The length of the string
38
- def length
39
- self.connection.strlen(@key)
40
- end
41
-
42
- # @param [Fixnum] start Starting index of the slice
43
- # @param [Fixnum] length Length of the slice; negative numbers start counting from the right (-1 = end)
44
- # @return [Array<::String>] The requested slice from <start> with length <length>
45
- def slice(start = 0, length = -1)
46
- length = start + length if length >= 0
47
- return self.connection.getrange(@key, start, length)
48
- end
49
-
50
- # Deletes the key (keys[1]) iff the value is equal to argv[1].
51
- # @param [Array<(::String)>] keys The key to delete
52
- # @param [Array<(::String)>] argv The value to compare with
53
- # @return [Fixnum] 1 if deleted, 0 otherwise
54
- defscript :delete_if_equals_script, <<~LUA
55
- local deleted = false
56
- if redis.call("get", KEYS[1]) == ARGV[1] then
57
- deleted = redis.call("del", KEYS[1])
58
- end
59
-
60
- return deleted
61
- LUA
62
- end
63
- end
64
- end
@@ -1,58 +0,0 @@
1
- require 'forwardable'
2
-
3
- module Redstruct
4
- module Types
5
- class Struct < Redstruct::Types::Base
6
- include Redstruct::Utils::Inspectable
7
-
8
- # @return [Boolean] Returns true if it exists in redis, false otherwise
9
- def exists?
10
- return self.connection.exists(@key)
11
- end
12
-
13
- # @return [Fixnum] 0 if nothing was deleted in the DB, 1 if it was
14
- def delete
15
- self.connection.del(@key)
16
- end
17
-
18
- # Sets the key to expire after ttl seconds
19
- # @param [Integer, #to_i] ttl the time to live in seconds (or milliseconds if ms is true)
20
- # @param [Boolean] ms if true, assumes ttl is in milliseconds
21
- def expire(ttl, ms: false)
22
- if ms
23
- self.connection.pexpire(@key, ttl.to_i)
24
- else
25
- self.connection.expire(@key, ttl.to_i)
26
- end
27
- end
28
-
29
- # Sets the key to expire at the given timestamp.
30
- # @param [Time, Integer, #to_i] time time or unix timestamp at which the key should expire
31
- # @param [Boolean] ms if true, assumes the timestamp is in milliseconds
32
- def expire_at(time, ms: false)
33
- if ms
34
- time = (time.to_f * 1000) if time.is_a?(Time)
35
- self.connection.pexpireat(@key, time.to_i)
36
- else
37
- self.connection.expireat(@key, time.to_i)
38
- end
39
- end
40
-
41
- # Removes the expiry time from a key
42
- def persist
43
- self.connection.persist(@key)
44
- end
45
-
46
- # @return [String] the underlying redis type
47
- def type
48
- self.connection.type(@key)
49
- end
50
-
51
- # :nocov:
52
- def inspectable_attributes
53
- super.merge(key: @key)
54
- end
55
- # :nocov:
56
- end
57
- end
58
- end
@@ -1,15 +0,0 @@
1
- require 'logger'
2
-
3
- module Releaser
4
- class Logger < ::Logger
5
- TAG = '[RELEASER]'.freeze
6
-
7
- def info(message)
8
- super(TAG) { message }
9
- end
10
-
11
- def error(message)
12
- super(TAG) { message }
13
- end
14
- end
15
- end
@@ -1,32 +0,0 @@
1
- require 'english'
2
-
3
- module Releaser
4
- class Repository
5
- attr_reader :path
6
-
7
- def initialize(path = '.')
8
- @path = File.expand_path(path)
9
- raise(Error, 'Unreadable path given') unless File.readable?(@path)
10
- raise(Error, 'Repository is not a directory') unless File.directory?(@path)
11
- raise(Error, 'Repository is not a github repository') unless git?
12
- end
13
-
14
- def git?
15
- File.directory?("#{@path}/.git")
16
- end
17
-
18
- def clean?
19
- committed = `git status -s`.chomp.strip.empty?
20
- pushed = `git log origin/master..HEAD`.chomp.strip.empty?
21
-
22
- return committed && pushed
23
- end
24
-
25
- def fetch_remote_tags
26
- `git fetch --tags`
27
- return $CHILD_STATUS.success?
28
- end
29
-
30
- class Error < StandardError; end
31
- end
32
- end