Skip to content

Commit

Permalink
Check update automatically (#13)
Browse files Browse the repository at this point in the history
* check update automatically
  • Loading branch information
david942j authored Oct 9, 2017
1 parent 4682e86 commit 24f1f9e
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 1 deletion.
3 changes: 3 additions & 0 deletions lib/one_gadget.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ def one_gadget(arg = nil, **options)
OneGadget.gadgets(**options)
end

require 'one_gadget/update'
OneGadget::Update.check!

require 'one_gadget/fetcher'
require 'one_gadget/helper'
require 'one_gadget/logger'
Expand Down
2 changes: 1 addition & 1 deletion lib/one_gadget/logger.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ module Logger
prep = ' ' * 12
message = msg.lines.map.with_index do |str, i|
next str if i.zero?
prep + str
str.strip.empty? ? str : prep + str
end
color = case severity
when 'WARN' then :warn
Expand Down
59 changes: 59 additions & 0 deletions lib/one_gadget/update.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
require 'fileutils'

require 'one_gadget/helper'
require 'one_gadget/logger'

module OneGadget
# For automatically check update.
module Update
# At least 7 days between check for new version.
FREQUENCY = 7 * 24 * 60 * 60
# Path to cache file.
CACHE_FILE = File.join(ENV['HOME'], '.cache', 'one_gadget', 'update').freeze

class << self
# Check if new releases have been drafted.
#
# @return [void]
def check!
return unless need_check?
OneGadget::Logger.info("Checking for new versions of OneGadget\n" \
"To disable this functionality, do\n$ echo never > #{CACHE_FILE}\n\n")
latest = Helper.latest_tag[1..-1] # remove 'v'
if Gem::Version.new(latest) <= Gem::Version.new(OneGadget::VERSION)
return OneGadget::Logger.info("You have the latest version of OneGadget (#{latest})!\n\n")
end

# show update message
msg = format("A newer version of OneGadget is available (%s --> %s).\n", OneGadget::VERSION, latest)
msg << "Update with: $ gem update one_gadget\n\n"
OneGadget::Logger.info(msg)
end

private

# check ~/.cache/one_gadget/update
def need_check?
cache = cache_file
return false if cache.nil? # cache file fails, no update check.
return false if IO.binread(cache).strip == 'never'
Time.now >= last_check + FREQUENCY
end

def last_check
cache = cache_file
return Time.now if cache.nil?
File.open(cache, &:mtime)
end

def cache_file
dir = File.dirname(CACHE_FILE)
FileUtils.mkdir_p(dir) unless File.directory?(dir)
IO.binwrite(CACHE_FILE, '') unless File.exist?(CACHE_FILE)
CACHE_FILE
rescue # prevent dir is not writable
return nil
end
end
end
end
70 changes: 70 additions & 0 deletions spec/update_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
require 'logger'

require 'one_gadget/update'
require 'one_gadget/version'

describe OneGadget::Update do
before(:all) do
# precent fail on CI
@hook_cache_file = lambda do |&block|
tmp = Dir::Tmpname.make_tmpname('/tmp/one_gadget/update', nil)
stub_const('OneGadget::Update::CACHE_FILE', tmp)
block.call(tmp)
end

@hook_logger = lambda do |&block|
# no method 'reopen' before ruby 2.3
org_logger = OneGadget::Logger.instance_variable_get(:@logger)
new_logger = ::Logger.new($stdout)
new_logger.formatter = org_logger.formatter
OneGadget::Logger.instance_variable_set(:@logger, new_logger)
block.call
OneGadget::Logger.instance_variable_set(:@logger, org_logger)
end
end

after(:all) do
FileUtils.rm_r('/tmp/one_gadget')
end

it 'cache_file' do
skip 'Windows so hard' unless RUBY_PLATFORM =~ /linux/
@hook_cache_file.call do |path|
expect(described_class.send(:cache_file)).to eq path
File.chmod(0o000, File.dirname(path))
expect(described_class.send(:cache_file)).to be nil
File.chmod(0o700, File.dirname(path))
end
end

it 'need_check?' do
@hook_cache_file.call do |path|
expect(described_class.send(:need_check?)).to be false
now = Time.now
allow(Time).to receive(:now).and_return(now + 7 * 24 * 3600)
expect(described_class.send(:need_check?)).to be true
IO.binwrite(path, 'never')
expect(described_class.send(:need_check?)).to be false
end
end

it 'check!' do
OneGadget::Helper.color_off!
@hook_cache_file.call do |path|
allow(described_class).to receive(:need_check?).and_return(true)
expect { @hook_logger.call { described_class.check! } }.to output(<<-EOS).to_stdout
[OneGadget] Checking for new versions of OneGadget
To disable this functionality, do
$ echo never > #{path}
[OneGadget] You have the latest version of OneGadget (#{OneGadget::VERSION})!
EOS
stub_const('OneGadget::VERSION', '0.0.0')
expect { @hook_logger.call { described_class.check! } }.to output(include(<<-EOS)).to_stdout
$ gem update one_gadget
EOS
end
OneGadget::Helper.color_on!
end
end

0 comments on commit 24f1f9e

Please sign in to comment.