hrk 1.0.7 → 1.0.8

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: 2a9d0caab344b968fe75fdf67544614eee7c8510
4
- data.tar.gz: f6bf197cf5943045989c0ff77f0cc5a7174cb88f
3
+ metadata.gz: 249a8378c38fae86402ccc5044724196514bb47c
4
+ data.tar.gz: cc1969e0eced0161a949b9f225c39d2878999ee7
5
5
  SHA512:
6
- metadata.gz: 8ad9226be51959e0d073fe622e86e817536e5b59658451576bbc28b2a717b6b23d3caace733612939cd928aab3c4f84f9705bbbedbf7d7d15af5e2ef58387662
7
- data.tar.gz: bd3fda9fe1058571c9b02f567c1440135bc0a2a54b2418d94979254c32703836af4268268b4407741c583d020fb2c6dfeea8261c86d700c35288cf95d0f5420a
6
+ metadata.gz: 5ec9446bb316c5a18cc6c9e21ab17754390ecae18533f8842b496f7615f310403bf2b3cf2d533498d39537068a6476f9a5d0e763fc13d70db27945eed1b78fe7
7
+ data.tar.gz: dd6513deeb046a20f65e9ef59571e00898c76ba7bd6d5d58cfeff94d968ff828d746768ca2f60fc0f03701d1241db77fa5e4bc41526b750a13dd09a0ec30f12f
@@ -73,11 +73,27 @@ module Hrk
73
73
  end
74
74
 
75
75
  def pid= value
76
- pid_path.write(value)
76
+ pid_path.write value
77
77
  end
78
78
 
79
79
  def pid_path
80
80
  tmp_path.join "#{tty_digest}.pid"
81
81
  end
82
+
83
+ def last_time
84
+ Time.at(last_time_path.read.to_i) if last_time?
85
+ end
86
+
87
+ def last_time?
88
+ last_time_path.exist?
89
+ end
90
+
91
+ def last_time= value
92
+ last_time_path.write value.to_i
93
+ end
94
+
95
+ def last_time_path
96
+ tmp_path.join "#{tty_digest}.time"
97
+ end
82
98
  end
83
99
  end
@@ -6,7 +6,7 @@ module Hrk
6
6
  end
7
7
 
8
8
  def call *args
9
- @next_callee.call *insure_remote(args)
9
+ @next_callee.call(*insure_remote(args))
10
10
  end
11
11
 
12
12
  private
@@ -11,8 +11,10 @@ module Hrk
11
11
 
12
12
  def call *args
13
13
  command, remote = command_and_remote args
14
- @env.remote = remote
15
- Hrk::Heroku.new(*remote).call(*command)
14
+ Hrk::Heroku.new(*remote).call(*command).tap do
15
+ @env.remote = remote
16
+ @env.last_time = Time.now
17
+ end
16
18
  end
17
19
 
18
20
  private
@@ -1,21 +1,43 @@
1
1
  module Hrk
2
2
  module Execute
3
3
  class Remember
4
+ class InvalidInputError < StandardError
5
+ def initialize input
6
+ super "Can't understand `#{input}` ; aborting"
7
+ end
8
+ end
9
+
4
10
  def initialize next_callee
5
11
  @next_callee = next_callee
6
12
  end
7
13
 
8
14
  def call *args
9
- env = Hrk::Env.new
10
- if remoteless?(args) && env.remote?
11
- @next_callee.call(*args, *env.remote)
12
- else
13
- @next_callee.call(*args)
14
- end
15
+ @next_callee.call(*remember_and_confirm!(args))
15
16
  end
16
17
 
17
18
  private
18
19
 
20
+ def remember_and_confirm! args
21
+ env = Hrk::Env.new
22
+ return args unless remoteless?(args) && env.remote? && reuse_or_confirm!(args, env)
23
+ args + env.remote
24
+ end
25
+
26
+ def reuse_or_confirm! args, env
27
+ !(env.last_time? && env.last_time + 5 < Time.now) || confirm!(args, env)
28
+ end
29
+
30
+ def confirm! args, env
31
+ puts "Please confirm that you want to run this command: `heroku #{(args + env.remote).join " "}` [Y]es [N]o:"
32
+ get_valid_input! =~ /\Ay(?:es)?\Z/i
33
+ end
34
+
35
+ def get_valid_input!
36
+ STDIN.gets.strip.tap do |input|
37
+ raise InvalidInputError.new(input) unless input =~ /\A(?:y(?:es)?)|(?:n(?:o)?)\Z/i
38
+ end
39
+ end
40
+
19
41
  def remoteless? args
20
42
  args.reverse.take(2).none? { |a| a =~ /\A-[ar]\Z/ }
21
43
  end
@@ -1,3 +1,3 @@
1
1
  module Hrk
2
- VERSION = '1.0.7'
2
+ VERSION = '1.0.8'
3
3
  end
@@ -19,6 +19,14 @@ RSpec.describe Hrk::Env do
19
19
  before { allow(env).to receive(:pid_path).and_return pid_path }
20
20
  end
21
21
 
22
+ shared_context 'fake last_time_path' do
23
+ let(:last_time_path) { double(Pathname) }
24
+
25
+ before { allow(last_time_path).to receive(:write) }
26
+ before { allow(last_time_path).to receive(:delete) }
27
+ before { allow(env).to receive(:last_time_path).and_return last_time_path }
28
+ end
29
+
22
30
  shared_context 'fake tty' do
23
31
  let(:tty) { "/dev/pts/#{rand(1..9)}" }
24
32
 
@@ -276,8 +284,66 @@ RSpec.describe Hrk::Env do
276
284
 
277
285
  let(:some_dir) { Pathname.new "/and#{rand(1..9)}/another_/dir" }
278
286
 
279
- before { allow(env).to receive(:tmp_path).and_return(Pathname.new(some_dir)) }
287
+ before { allow(env).to receive(:tmp_path).and_return(some_dir) }
280
288
 
281
289
  it { expect(env.pid_path).to eq Pathname.new("#{some_dir}/#{Digest::MD5.hexdigest(tty)}.pid") }
282
290
  end
291
+
292
+ describe '#last_time' do
293
+ include_context 'fake last_time_path'
294
+
295
+ before { allow(last_time_path).to receive(:exist?).and_return it_pre_exist }
296
+ before { allow(last_time_path).to receive(:read).and_return last_time.to_i.to_s }
297
+
298
+ context 'no last_time file exists' do
299
+ let(:it_pre_exist) { false }
300
+ let(:last_time) { nil }
301
+
302
+ it { expect(env.last_time).to eq nil }
303
+ end
304
+
305
+ context 'the last_time file exists' do
306
+ let(:it_pre_exist) { true }
307
+ let(:last_time) { Time.at(rand(Time.new(2015, 1, 1, 0, 0, 0).to_i..Time.new(2020, 1, 1, 0, 0, 0).to_i)) }
308
+
309
+ it { expect(env.last_time).to eq last_time }
310
+ end
311
+ end
312
+
313
+ describe '#last_time?' do
314
+ include_context 'fake last_time_path'
315
+
316
+ before { allow(last_time_path).to receive(:exist?).and_return it_pre_exist }
317
+
318
+ context 'the last_time file exists' do
319
+ let(:it_pre_exist) { true }
320
+
321
+ it { expect(env.last_time?).to eq true }
322
+ end
323
+
324
+ context 'the last_time file does not exist' do
325
+ let(:it_pre_exist) { false }
326
+
327
+ it { expect(env.last_time?).to eq false }
328
+ end
329
+ end
330
+
331
+ describe '#last_time=' do
332
+ let(:last_time) { Time.at(rand(Time.new(2015, 1, 1, 0, 0, 0).to_i..Time.new(2020, 1, 1, 0, 0, 0).to_i)) }
333
+ include_context 'fake last_time_path'
334
+
335
+ before { env.last_time = last_time }
336
+
337
+ it { expect(last_time_path).to have_received(:write).with(last_time.to_i) }
338
+ end
339
+
340
+ describe '#last_time_path' do
341
+ include_context "fake tty"
342
+
343
+ let(:some_dir) { Pathname.new "/stairway/#{rand(1..9)}/heavens" }
344
+
345
+ before { allow(env).to receive(:tmp_path).and_return(some_dir) }
346
+
347
+ it { expect(env.last_time_path).to eq Pathname.new("#{some_dir}/#{Digest::MD5.hexdigest(tty)}.time") }
348
+ end
283
349
  end
@@ -9,6 +9,7 @@ RSpec.describe Hrk::Execute::Command do
9
9
  before { allow(Hrk::Heroku).to receive(:new).and_return(heroku) }
10
10
 
11
11
  before { allow(command.env).to receive(:remote=) }
12
+ before { allow(command.env).to receive(:last_time=) }
12
13
 
13
14
  context "no remote was previously memorized" do
14
15
  before { allow(command.env).to receive(:remote?).and_return(nil) }
@@ -28,11 +29,13 @@ RSpec.describe Hrk::Execute::Command do
28
29
  end
29
30
 
30
31
  describe "interactions" do
32
+ around { |b| Timecop.freeze Time.now, &b }
31
33
  before { command.call(*args, opt, remote) }
32
34
 
33
35
  it { expect(Hrk::Heroku).to have_received(:new).with(opt, remote) }
34
36
  it { expect(heroku).to have_received(:call).with(*%w{whatever that:may -b}) }
35
37
  it { expect(command.env).to have_received(:remote=).with([opt, remote]) }
38
+ it { expect(command.env).to have_received(:last_time=).with(Time.now) }
36
39
  end
37
40
  end
38
41
  end
@@ -53,11 +56,13 @@ RSpec.describe Hrk::Execute::Command do
53
56
  end
54
57
 
55
58
  describe "interactions" do
59
+ around { |b| Timecop.freeze Time.now, &b }
56
60
  before { command.call(opt, remote) }
57
61
 
58
62
  it { expect(Hrk::Heroku).to have_received(:new).with(opt, remote) }
59
63
  it { expect(heroku).to have_received(:call).with no_args }
60
64
  it { expect(command.env).to have_received(:remote=).with([opt, remote]) }
65
+ it { expect(command.env).to have_received(:last_time=).with(Time.now) }
61
66
  end
62
67
  end
63
68
  end
@@ -68,6 +73,7 @@ RSpec.describe Hrk::Execute::Command do
68
73
 
69
74
  before { expect(heroku).not_to receive(:call) }
70
75
  before { expect(command.env).not_to receive(:remote=) }
76
+ before { expect(command.env).not_to receive(:last_time=) }
71
77
 
72
78
  it { expect { command.call }.to raise_error ArgumentError }
73
79
  it { expect { command.call(*other_args) }.to raise_error ArgumentError }
@@ -50,15 +50,52 @@ RSpec.describe Hrk::Execute::Remember do
50
50
  before { allow(env).to receive(:remote?).and_return(true) }
51
51
  before { allow(env).to receive(:remote).and_return(remote) }
52
52
 
53
+ context "no remote in the args" do
54
+ before { allow(env).to receive(:last_time?).and_return true }
55
+ before { allow(env).to receive(:last_time).and_return(the_last_time) }
56
+
57
+ context "last command ended less than 5 seconds ago" do
58
+ let(:the_last_time) { Time.now - 4 }
59
+
60
+ receiving %w(restart), it_should_pass_on: -> { %w(restart) + remote }
61
+ end
62
+
63
+ context "last command ended more than 5 seconds ago" do
64
+ let(:the_last_time) { Time.now - 6 }
65
+ before { allow(remember).to receive(:puts) }
66
+ before { allow(STDIN).to receive(:gets).and_return(the_users_input) }
67
+
68
+ ["y", "Y", "yes", "YES", "Yes"].each do |confirmation|
69
+ context "and the user confirms with #{confirmation}" do
70
+ let(:the_users_input) { "#{confirmation}\n" }
71
+
72
+ receiving %w(restart), it_should_pass_on: -> { %w(restart) + remote }
73
+ end
74
+ end
75
+
76
+ ["n", "N", "no", "NO", "No"].each do |abortion|
77
+ context "and the user aborts with #{abortion}" do
78
+ let(:the_users_input) { abortion }
79
+
80
+ receiving %w(run rake db:migrate), it_should_pass_on: -> { %w(run rake db:migrate) }
81
+ end
82
+ end
83
+
84
+ ["o", "whatever", "dude", "-r demo"].each do |gibbrish|
85
+ context "and the user answers with #{gibbrish}" do
86
+ let(:the_users_input) { gibbrish }
87
+
88
+ it { expect { remember.call %w(run rails console) }.to raise_error Hrk::Execute::Remember::InvalidInputError }
89
+ end
90
+ end
91
+ end
92
+ end
93
+
53
94
  context "a remote in the args" do
54
95
  receiving %w(run rake some:task -r a-remote), it_should_pass_on: %w(run rake some:task -r a-remote)
55
96
  receiving %w(maintenance:on -a another-app), it_should_pass_on: %w(maintenance:on -a another-app)
56
97
  end
57
98
 
58
- context "no remote in the args" do
59
- receiving %w(restart), it_should_pass_on: -> { %w(restart) + remote }
60
- end
61
-
62
99
  context "part of a remote in the args" do
63
100
  receiving %w(run console -r), it_should_pass_on: %w(run console -r)
64
101
  receiving %w(maintenance:on -a), it_should_pass_on: %w(maintenance:on -a)
@@ -1,5 +1,6 @@
1
1
  require 'simplecov'
2
2
  require 'coveralls'
3
+ require 'timecop'
3
4
 
4
5
  SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
5
6
  SimpleCov::Formatter::HTMLFormatter,
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hrk
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.7
4
+ version: 1.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michel Belleville
@@ -150,6 +150,26 @@ dependencies:
150
150
  - - ">="
151
151
  - !ruby/object:Gem::Version
152
152
  version: 0.7.1
153
+ - !ruby/object:Gem::Dependency
154
+ name: timecop
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - "~>"
158
+ - !ruby/object:Gem::Version
159
+ version: '0.7'
160
+ - - ">="
161
+ - !ruby/object:Gem::Version
162
+ version: 0.7.3
163
+ type: :development
164
+ prerelease: false
165
+ version_requirements: !ruby/object:Gem::Requirement
166
+ requirements:
167
+ - - "~>"
168
+ - !ruby/object:Gem::Version
169
+ version: '0.7'
170
+ - - ">="
171
+ - !ruby/object:Gem::Version
172
+ version: 0.7.3
153
173
  description: |
154
174
  Hrk gives you the hrk command that proxies commands to heroku, keeping track of
155
175
  the latest remote you used so you don't have to keep on typing it on every