redis-copy 0.0.3 → 0.0.5

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.
data/README.md CHANGED
@@ -21,7 +21,7 @@ The current options can be grabbed using the `--help` flag.
21
21
 
22
22
  ```
23
23
  $ redis-copy --help
24
- redis-copy v0.0.2
24
+ redis-copy v0.0.5
25
25
  Usage: redis-copy [options] <source> <destination>
26
26
  <source> and <destination> must be redis connection uris
27
27
  like [redis://]<hostname>[:<port>][/<db>]
@@ -31,13 +31,14 @@ Specific options:
31
31
  auto: uses new if available, otherwise fallback
32
32
  new: use redis DUMP and RESTORE commands (faster)
33
33
  classic: migrates via multiple type-specific commands
34
+ --[no-]pipeline Use redis pipeline where available (default true)
35
+ -d, --[no-]debug Write debug output (default false)
36
+ -t, --[no-]trace Enable backtrace on failure (default false)
37
+ -f, --[no-]fail-fast Abort on first failure (default false)
38
+ --[no-]verify [PERCENT] Verify percentage of transfers -- VERY SLOW (default 0)
39
+ --[no-]prompt Prompt for confirmation (default true)
40
+ --[no-]allow-nonempty Allow non-empty destination (default false)
34
41
  --[no-]dry-run Output configuration and exit
35
- -d, --[no-]debug Write debug output
36
- -t, --[no-]trace Enable backtrace on failure
37
- -f, --[no-]fail-fast Abort on first failure
38
- -y, --yes Automatically accept any prompts
39
- --[no-]allow-nonempty Allow non-empty destination
40
-
41
42
  ```
42
43
 
43
44
  ## Example:
@@ -45,6 +45,17 @@ module RedisCopy
45
45
  ui.notify("FAIL: #{key.dump}")
46
46
  ui.abort if options[:fail_fast]
47
47
  end
48
+
49
+ probably(options[:verify]) do
50
+ if strategem.verify?(key)
51
+ stats[:verified] += 1
52
+ else
53
+ stats[:borked] += 1
54
+ ui.notify("BORK: #{key.dump}")
55
+ ui.abort if options[:fail_fast]
56
+ end
57
+ end
58
+
48
59
  ui.notify("PROGRESS: #{stats.inspect}") if (stats[:attempt] % 1000).zero?
49
60
  end.tap do |stats|
50
61
  ui.notify("DONE: #{stats.inspect}")
@@ -53,6 +64,17 @@ module RedisCopy
53
64
 
54
65
  private
55
66
 
67
+ # yields the block, probably.
68
+ # @param probability [Integer] 0-100
69
+ # @return [void]
70
+ # used by ::copy in determining whether to verify.
71
+ def probably(probability)
72
+ return if probability.zero?
73
+ if probability >= 100 || (Random::rand(100) % 100) < probability
74
+ yield
75
+ end
76
+ end
77
+
56
78
  def same_redis?(redis_a, redis_b)
57
79
  # Redis::Client#id returns the connection uri
58
80
  # e.g. 'redis://localhost:6379/0'
@@ -10,10 +10,12 @@ module RedisCopy
10
10
  ui: :command_line,
11
11
  key_emitter: :default,
12
12
  strategy: :auto,
13
+ verify: 0,
13
14
  pipeline: :true,
14
15
  fail_fast: false,
15
16
  prompt: true,
16
17
  trace: false,
18
+ debug: false,
17
19
  allow_nonempty: false,
18
20
  }.freeze unless defined?(DEFAULTS)
19
21
 
@@ -64,8 +66,21 @@ module RedisCopy
64
66
  options[:fail_fast] = ff
65
67
  end
66
68
 
67
- opts.on('--[no-]prompt', "Prompt for confirmation (default #{DEFAULTS[:prompt]})") do
68
- options[:prompt] = true
69
+ opts.on('--[no-]verify [PERCENT]',
70
+ "Verify percentage of transfers -- VERY SLOW (default #{DEFAULTS[:verify]})"
71
+ ) do |verify|
72
+ options[:verify] = case verify
73
+ when /\A1?[0-9]{2}\z/
74
+ verify.to_i
75
+ when false, 'false', 'none'
76
+ 0
77
+ else
78
+ 100
79
+ end
80
+ end
81
+
82
+ opts.on('--[no-]prompt', "Prompt for confirmation (default #{DEFAULTS[:prompt]})") do |prompt|
83
+ options[:prompt] = prompt
69
84
  end
70
85
 
71
86
  opts.on('--[no-]allow-nonempty', "Allow non-empty destination (default #{DEFAULTS[:allow_nonempty]})") do |allow_nonempty|
@@ -28,6 +28,10 @@ module RedisCopy
28
28
  raise NotImplementedError
29
29
  end
30
30
 
31
+ def dbsize
32
+ @redis.dbsize
33
+ end
34
+
31
35
  def to_s
32
36
  self.class.name.demodulize.humanize
33
37
  end
@@ -36,10 +40,16 @@ module RedisCopy
36
40
  class Default
37
41
  include KeyEmitter
38
42
 
39
- def initialize(redis, ui, options = {})
40
- ui.abort unless ui.confirm? <<-EOWARNING.strip_heredoc
43
+ def keys
44
+ dbsize = self.dbsize
45
+
46
+ # HT: http://stackoverflow.com/a/11466770
47
+ dbsize_str = dbsize.to_s.reverse.gsub(/(\d{3})(?=\d)/, '\\1,').reverse
48
+
49
+ @ui.abort unless (dbsize < 10_000) || (@ui.confirm? <<-EOWARNING.strip_heredoc)
41
50
  WARNING: #{self} key emitter uses redis.keys('*') to
42
- get its list of keys.
51
+ get its list of keys, and you have #{dbsize_str} keys in
52
+ your source DB.
43
53
 
44
54
  The redis keys command [reference](http://redis.io/commands/keys)
45
55
  says this:
@@ -52,10 +62,7 @@ module RedisCopy
52
62
  > regular application code. If you're looking for a way to find
53
63
  > keys in a subset of your keyspace, consider using sets.
54
64
  EOWARNING
55
- super
56
- end
57
65
 
58
- def keys
59
66
  @ui.debug "REDIS: #{@redis.client.id} KEYS *"
60
67
  @redis.keys('*').to_enum
61
68
  end
@@ -21,6 +21,10 @@ module RedisCopy
21
21
  copierklass.new(source, destination, ui, options)
22
22
  end
23
23
 
24
+ def self.included(base)
25
+ base.send(:include, Verifier)
26
+ end
27
+
24
28
  # @param source [Redis]
25
29
  # @param destination [Redis]
26
30
  def initialize(source, destination, ui, options = {})
@@ -40,5 +44,46 @@ module RedisCopy
40
44
  return super if defined? super
41
45
  raise NotImplementedError
42
46
  end
47
+
48
+ def verify?(key)
49
+ @ui.debug("VERIFY: #{key.dump}")
50
+ type = @src.type(key)
51
+ proc = case type
52
+ when 'string' then proc { |r| r.get key }
53
+ when 'hash' then proc { |r| r.hgetall key }
54
+ when 'zset' then proc { |r| r.zrange(key, 0, -1, :with_scores => true) }
55
+ when 'set' then proc { |r| r.smembers(key).sort }
56
+ when 'list' then proc { |r| r.lrange(key, 0, -1) }
57
+ else
58
+ @ui.debug("BORK: #{key.dump} has unknown type #{type.dump}!")
59
+ return false
60
+ end
61
+
62
+ return false unless same_response?(&proc)
63
+ return false unless same_response? { |r| r.ttl key }
64
+
65
+ true
66
+ end
67
+
68
+ private
69
+
70
+ def same_response?(&blk)
71
+ responses = {
72
+ source: capture_result(@src, &blk),
73
+ destination: capture_result(@dst, &blk)
74
+ }
75
+ if (responses[:source] == responses[:destination])
76
+ return true
77
+ else
78
+ @ui.debug("MISMATCH: #{keys.dump} #{responses.inspect}")
79
+ return false
80
+ end
81
+ end
82
+
83
+ def capture_result(redis, &block)
84
+ return [:returned, block.call(redis)]
85
+ rescue Object => exception
86
+ return [:raised, exception]
87
+ end
43
88
  end
44
89
  end
@@ -6,6 +6,7 @@ module RedisCopy
6
6
  include Strategy
7
7
 
8
8
  def copy(key)
9
+ @ui.debug("COPY: #{key.dump}")
9
10
  vtype = @src.type(key)
10
11
  ttl = @src.ttl(key)
11
12
 
@@ -6,6 +6,8 @@ module RedisCopy
6
6
  include Strategy
7
7
 
8
8
  def copy(key)
9
+ @ui.debug("COPY: #{key.dump}")
10
+
9
11
  ttl = @src.ttl(key)
10
12
  # TTL returns seconds, -1 means none set
11
13
  # RESTORE ttl is in miliseconds, 0 means none set
@@ -1,5 +1,8 @@
1
1
  # encoding: utf-8
2
2
 
3
+ require_relative 'ui/auto_run'
4
+ require_relative 'ui/command_line'
5
+
3
6
  module RedisCopy
4
7
  module UI
5
8
  def self.load(options = {})
@@ -1,5 +1,5 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module RedisCopy
4
- VERSION = '0.0.3'
4
+ VERSION = '0.0.5'
5
5
  end
@@ -6,9 +6,11 @@ describe RedisCopy::KeyEmitter::Default do
6
6
  let(:ui) { double.as_null_object }
7
7
  let(:instance) { RedisCopy::KeyEmitter::Default.new(redis, ui)}
8
8
  let(:connection_uri) { 'redis://12.34.56.78:9000/15' }
9
+ let(:key_count) { 100_000 }
9
10
 
10
11
  before(:each) do
11
12
  redis.stub_chain('client.id').and_return(connection_uri)
13
+ redis.stub(:dbsize) { key_count }
12
14
  ui.stub(:debug).with(anything)
13
15
  end
14
16
 
@@ -28,6 +30,22 @@ describe RedisCopy::KeyEmitter::Default do
28
30
  exactly(:once)
29
31
  instance.keys
30
32
  end
33
+ context 'when source has > 10,000 keys' do
34
+ let(:key_count) { 100_000 }
35
+ it 'should ask for confirmation' do
36
+ ui.should_receive(:confirm?) do |confirmation|
37
+ confirmation.should match /\b100,000\b/
38
+ end
39
+ instance.keys
40
+ end
41
+ end
42
+ context 'when source has <= 10,000 keys' do
43
+ let(:key_count) { 1_000 }
44
+ it 'should not ask for confirmation' do
45
+ ui.should_not_receive(:confirm?)
46
+ instance.keys
47
+ end
48
+ end
31
49
  end
32
50
  end
33
51
  end
@@ -31,60 +31,76 @@ class RedisMultiplex < Struct.new(:source, :destination)
31
31
  end
32
32
  end
33
33
 
34
+ shared_examples_for(:no_ttl) do
35
+ # key, redis,
36
+ subject { redis.ttl(key) }
37
+ it { should eq -1 }
38
+ end
39
+
40
+ shared_examples_for(:ttl_set) do
41
+ # key, redis, ttl
42
+ subject { redis.ttl(key) }
43
+ it { should eq ttl }
44
+ end
45
+
46
+ shared_examples_for '#verify?' do
47
+ before(:each) do
48
+ ui.stub(:debug).and_call_original
49
+ ui.stub(:notify) do |message|
50
+ puts message
51
+ end
52
+ end
53
+ it 'should verify successfully' do
54
+ strategy.verify?(key).should be_true
55
+ end
56
+ end
57
+
34
58
  shared_examples_for(RedisCopy::Strategy) do
35
59
  let(:key) { rand(16**128).to_s(16) }
36
60
  after(:each) { multiplex.both { |redis| redis.del(key) } }
61
+ let(:ttl) { 100 }
37
62
 
38
63
  context '#copy' do
64
+ before(:each) { populate.call }
39
65
  context 'string' do
40
66
  let(:source_string) { rand(16**256).to_s(16) }
41
- before(:each) { source.set(key, source_string) }
67
+ let(:populate) { proc {source.set(key, source_string)} }
42
68
  [true,false].each do |with_expiry|
43
69
  context "with_expiry(#{with_expiry})" do
44
- before(:each) { source.expire(key, 100) } if with_expiry
70
+ before(:each) { source.expire(key, ttl) } if with_expiry
45
71
  context 'before' do
46
72
  context 'source' do
73
+ let(:redis) { source }
47
74
  subject { source.get(key) }
48
75
  it { should_not be_nil }
49
76
  it { should eq source_string }
50
- context 'ttl' do
51
- subject { source.ttl(key) }
52
- it { should eq 100 } if with_expiry
53
- it { should eq -1 } unless with_expiry
54
- end
77
+ it_should_behave_like (with_expiry ? :ttl_set : :no_ttl)
55
78
  end
56
79
  context 'destination' do
80
+ let(:redis) { destination }
57
81
  subject { destination.get(key) }
58
82
  it { should be_nil }
59
- context 'ttl' do
60
- subject { destination.ttl(key) }
61
- it { should eq -1 }
62
- end
83
+ it_should_behave_like :no_ttl
63
84
  end
64
85
  end
65
86
 
66
87
  context 'after' do
67
88
  before(:each) { strategy.copy(key) }
68
89
  context 'source' do
90
+ let(:redis) { source }
69
91
  subject { source.get(key) }
70
92
  it { should_not be_nil }
71
93
  it { should eq source_string }
72
- context 'ttl' do
73
- subject { source.ttl(key) }
74
- it { should eq 100 } if with_expiry
75
- it { should eq -1 } unless with_expiry
76
- end
94
+ it_should_behave_like (with_expiry ? :ttl_set : :no_ttl)
77
95
  end
78
96
  context 'destination' do
97
+ let(:redis) { destination }
79
98
  subject { destination.get(key) }
80
99
  it { should_not be_nil }
81
100
  it { should eq source_string }
82
- context 'ttl' do
83
- subject { destination.ttl(key) }
84
- it { should eq 100 } if with_expiry
85
- it { should eq -1 } unless with_expiry
86
- end
101
+ it_should_behave_like (with_expiry ? :ttl_set : :no_ttl)
87
102
  end
103
+ it_should_behave_like '#verify?'
88
104
  end
89
105
  end
90
106
  end
@@ -94,53 +110,43 @@ shared_examples_for(RedisCopy::Strategy) do
94
110
  let(:source_list) do
95
111
  %w(foo bar baz buz bingo jango)
96
112
  end
97
- before(:each) { source_list.each{|x| source.rpush(key, x)} }
113
+ let(:populate) { proc { source_list.each{|x| source.rpush(key, x)} } }
98
114
  [true,false].each do |with_expiry|
99
115
  context "with_expiry(#{with_expiry})" do
100
116
  before(:each) { source.expire(key, 100) } if with_expiry
101
117
  context 'before' do
102
118
  context 'source' do
119
+ let(:redis) { source }
103
120
  subject { source.lrange(key, 0, -1) }
104
121
  it { should_not be_empty }
105
122
  it { should eq source_list }
106
- context 'ttl' do
107
- subject { source.ttl(key) }
108
- it { should eq 100 } if with_expiry
109
- it { should eq -1 } unless with_expiry
110
- end
123
+ it_should_behave_like (with_expiry ? :ttl_set : :no_ttl)
111
124
  end
112
125
  context 'destination' do
126
+ let(:redis) { destination }
113
127
  subject { destination.lrange(key, 0, -1) }
114
128
  it { should be_empty }
115
- context 'ttl' do
116
- subject { destination.ttl(key) }
117
- it { should eq -1 }
118
- end
129
+ it_should_behave_like :no_ttl
119
130
  end
120
131
  end
121
132
 
122
133
  context 'after' do
123
134
  before(:each) { strategy.copy(key) }
124
135
  context 'source' do
136
+ let(:redis) { source }
125
137
  subject { source.lrange(key, 0, -1) }
126
138
  it { should_not be_empty }
127
139
  it { should eq source_list }
128
- context 'ttl' do
129
- subject { source.ttl(key) }
130
- it { should eq 100 } if with_expiry
131
- it { should eq -1 } unless with_expiry
132
- end
140
+ it_should_behave_like (with_expiry ? :ttl_set : :no_ttl)
133
141
  end
134
142
  context 'destination' do
143
+ let(:redis) { destination }
135
144
  subject { destination.lrange(key, 0, -1) }
136
145
  it { should_not be_empty }
137
146
  it { should eq source_list }
138
- context 'ttl' do
139
- subject { destination.ttl(key) }
140
- it { should eq 100 } if with_expiry
141
- it { should eq -1 } unless with_expiry
142
- end
147
+ it_should_behave_like (with_expiry ? :ttl_set : :no_ttl)
143
148
  end
149
+ it_should_behave_like '#verify?'
144
150
  end
145
151
  end
146
152
  end
@@ -150,52 +156,41 @@ shared_examples_for(RedisCopy::Strategy) do
150
156
  let(:source_list) do
151
157
  %w(foo bar baz buz bingo jango)
152
158
  end
153
- before(:each) { source_list.each{|x| source.sadd(key, x)} }
159
+ let(:populate) { proc { source_list.each{|x| source.sadd(key, x)} } }
154
160
  [true,false].each do |with_expiry|
155
161
  context "with_expiry(#{with_expiry})" do
156
162
  before(:each) { source.expire(key, 100) } if with_expiry
157
163
  context 'before' do
158
164
  context 'source' do
165
+ let(:redis) { source }
159
166
  subject { source.smembers(key) }
160
167
  it { should_not be_empty }
161
168
  it { should =~ source_list }
162
- context 'ttl' do
163
- subject { source.ttl(key) }
164
- it { should eq 100 } if with_expiry
165
- it { should eq -1 } unless with_expiry
166
- end
169
+ it_should_behave_like (with_expiry ? :ttl_set : :no_ttl)
167
170
  end
168
171
  context 'destination' do
172
+ let(:redis) { destination }
169
173
  subject { destination.smembers(key) }
170
174
  it { should be_empty }
171
- context 'ttl' do
172
- subject { destination.ttl(key) }
173
- it { should eq -1 }
174
- end
175
+ it_should_behave_like :no_ttl
175
176
  end
176
177
  end
177
178
 
178
179
  context 'after' do
179
180
  before(:each) { strategy.copy(key) }
180
181
  context 'source' do
182
+ let(:redis) { source }
181
183
  subject { source.smembers(key) }
182
184
  it { should_not be_empty }
183
185
  it { should =~ source_list }
184
- context 'ttl' do
185
- subject { source.ttl(key) }
186
- it { should eq 100 } if with_expiry
187
- it { should eq -1 } unless with_expiry
188
- end
186
+ it_should_behave_like (with_expiry ? :ttl_set : :no_ttl)
189
187
  end
190
188
  context 'destination' do
189
+ let(:redis) { destination }
191
190
  subject { destination.smembers(key) }
192
191
  it { should_not be_empty }
193
192
  it { should =~ source_list }
194
- context 'ttl' do
195
- subject { destination.ttl(key) }
196
- it { should eq 100 } if with_expiry
197
- it { should eq -1 } unless with_expiry
198
- end
193
+ it_should_behave_like (with_expiry ? :ttl_set : :no_ttl)
199
194
  end
200
195
  end
201
196
  end
@@ -209,53 +204,43 @@ shared_examples_for(RedisCopy::Strategy) do
209
204
  'baz' => 'buz'
210
205
  }
211
206
  end
212
- before(:each) { source.mapped_hmset(key, source_hash) }
207
+ let(:populate) { proc { source.mapped_hmset(key, source_hash) } }
213
208
  [true,false].each do |with_expiry|
214
209
  context "with_expiry(#{with_expiry})" do
215
210
  before(:each) { source.expire(key, 100) } if with_expiry
216
211
  context 'before' do
217
212
  context 'source' do
213
+ let(:redis) { source }
218
214
  subject { source.hgetall(key) }
219
215
  it { should_not be_empty }
220
216
  it { should eq source_hash }
221
- context 'ttl' do
222
- subject { source.ttl(key) }
223
- it { should eq 100 } if with_expiry
224
- it { should eq -1 } unless with_expiry
225
- end
217
+ it_should_behave_like (with_expiry ? :ttl_set : :no_ttl)
226
218
  end
227
219
  context 'destination' do
220
+ let(:redis) { destination }
228
221
  subject { destination.hgetall(key) }
229
222
  it { should be_empty }
230
- context 'ttl' do
231
- subject { destination.ttl(key) }
232
- it { should eq -1 }
233
- end
223
+ it_should_behave_like :no_ttl
234
224
  end
235
225
  end
236
226
 
237
227
  context 'after' do
238
228
  before(:each) { strategy.copy(key) }
239
229
  context 'source' do
230
+ let(:redis) { source }
240
231
  subject { source.hgetall(key) }
241
232
  it { should_not be_empty }
242
233
  it { should eq source_hash }
243
- context 'ttl' do
244
- subject { source.ttl(key) }
245
- it { should eq 100 } if with_expiry
246
- it { should eq -1 } unless with_expiry
247
- end
234
+ it_should_behave_like (with_expiry ? :ttl_set : :no_ttl)
248
235
  end
249
236
  context 'destination' do
237
+ let(:redis) { destination }
250
238
  subject { destination.hgetall(key) }
251
239
  it { should_not be_empty }
252
240
  it { should eq source_hash }
253
- context 'ttl' do
254
- subject { destination.ttl(key) }
255
- it { should eq 100 } if with_expiry
256
- it { should eq -1 } unless with_expiry
257
- end
241
+ it_should_behave_like (with_expiry ? :ttl_set : :no_ttl)
258
242
  end
243
+ it_should_behave_like '#verify?'
259
244
  end
260
245
  end
261
246
  end
@@ -272,53 +257,43 @@ shared_examples_for(RedisCopy::Strategy) do
272
257
  end
273
258
  let(:vs_source_zset) { source_zset.to_a }
274
259
  let(:sv_source_zset) { vs_source_zset.map(&:reverse) }
275
- before(:each) { source.zadd(key, sv_source_zset) }
260
+ let(:populate) { proc { source.zadd(key, sv_source_zset) } }
276
261
  [true,false].each do |with_expiry|
277
262
  context "with_expiry(#{with_expiry})" do
278
263
  before(:each) { source.expire(key, 100) } if with_expiry
279
264
  context 'before' do
280
265
  context 'source' do
266
+ let(:redis) { source }
281
267
  subject { source.zrange(key, 0, -1, :with_scores => true) }
282
268
  it { should_not be_empty }
283
269
  it { should =~ vs_source_zset }
284
- context 'ttl' do
285
- subject { source.ttl(key) }
286
- it { should eq 100 } if with_expiry
287
- it { should eq -1 } unless with_expiry
288
- end
270
+ it_should_behave_like (with_expiry ? :ttl_set : :no_ttl)
289
271
  end
290
272
  context 'destination' do
273
+ let(:redis) { destination }
291
274
  subject { destination.zrange(key, 0, -1, :with_scores => true) }
292
275
  it { should be_empty }
293
- context 'ttl' do
294
- subject { destination.ttl(key) }
295
- it { should eq -1 }
296
- end
276
+ it_should_behave_like :no_ttl
297
277
  end
298
278
  end
299
279
 
300
280
  context 'after' do
301
281
  before(:each) { strategy.copy(key) }
302
282
  context 'source' do
283
+ let(:redis) { source }
303
284
  subject { source.zrange(key, 0, -1, :with_scores => true) }
304
285
  it { should_not be_empty }
305
286
  it { should =~ vs_source_zset }
306
- context 'ttl' do
307
- subject { source.ttl(key) }
308
- it { should eq 100 } if with_expiry
309
- it { should eq -1 } unless with_expiry
310
- end
287
+ it_should_behave_like (with_expiry ? :ttl_set : :no_ttl)
311
288
  end
312
289
  context 'destination' do
290
+ let(:redis) { destination }
313
291
  subject { destination.zrange(key, 0, -1, :with_scores => true) }
314
292
  it { should_not be_empty }
315
293
  it { should =~ vs_source_zset }
316
- context 'ttl' do
317
- subject { destination.ttl(key) }
318
- it { should eq 100 } if with_expiry
319
- it { should eq -1 } unless with_expiry
320
- end
294
+ it_should_behave_like (with_expiry ? :ttl_set : :no_ttl)
321
295
  end
296
+ it_should_behave_like '#verify?'
322
297
  end
323
298
  end
324
299
  end
@@ -328,7 +303,8 @@ end
328
303
 
329
304
  describe RedisCopy::Strategy do
330
305
  let(:options) { Hash.new } # append using before(:each) { options.update(foo: true) }
331
- let(:ui) { double.as_null_object }
306
+ # let(:ui) { double.as_null_object }
307
+ let(:ui) { RedisCopy::UI::CommandLine.new(options) }
332
308
  let(:strategy) { strategy_class.new(source, destination, ui, options)}
333
309
  let(:multiplex) { RedisMultiplex.new(source, destination) }
334
310
  let(:source) { Redis.new(db: 14) }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redis-copy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.5
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-10-11 00:00:00.000000000 Z
12
+ date: 2013-11-01 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler