From 21ae099b5df065ef8718eb3792f81ce869b20066 Mon Sep 17 00:00:00 2001 From: david942j Date: Mon, 9 Oct 2017 20:31:00 +0800 Subject: [PATCH 1/6] check update automatically --- lib/one_gadget.rb | 3 ++ lib/one_gadget/logger.rb | 2 +- lib/one_gadget/update.rb | 59 +++++++++++++++++++++++++++++++++++++ spec/update_spec.rb | 63 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 lib/one_gadget/update.rb create mode 100644 spec/update_spec.rb diff --git a/lib/one_gadget.rb b/lib/one_gadget.rb index abb5f728..4b1ebf83 100644 --- a/lib/one_gadget.rb +++ b/lib/one_gadget.rb @@ -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' diff --git a/lib/one_gadget/logger.rb b/lib/one_gadget/logger.rb index d6964c19..2b3abb6d 100644 --- a/lib/one_gadget/logger.rb +++ b/lib/one_gadget/logger.rb @@ -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 diff --git a/lib/one_gadget/update.rb b/lib/one_gadget/update.rb new file mode 100644 index 00000000..33fa6c17 --- /dev/null +++ b/lib/one_gadget/update.rb @@ -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 diff --git a/spec/update_spec.rb b/spec/update_spec.rb new file mode 100644 index 00000000..23f5f5bf --- /dev/null +++ b/spec/update_spec.rb @@ -0,0 +1,63 @@ +require 'tempfile' + +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 = Tempfile.new + stub_const('OneGadget::Update::CACHE_FILE', tmp.path) + block.call(tmp.path) + tmp.close + end + + @hook_logger = lambda do |&block| + logdev = OneGadget::Logger.instance_variable_get(:@logger).instance_variable_get(:@logdev) + dev = logdev.dev + logdev.reopen($stdout) + block.call + logdev.instance_variable_set(:@dev, dev) + end + end + + it 'cache_file' do + stub_const('OneGadget::Update::CACHE_FILE', '/bin/pusheeeeeen') + expect(described_class.send(:cache_file)).to be nil + @hook_cache_file.call do |path| + expect(described_class.send(:cache_file)).to eq 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 From bc89255aeb31da642967ebbb3b23ae19658eeb51 Mon Sep 17 00:00:00 2001 From: david942j Date: Mon, 9 Oct 2017 20:42:02 +0800 Subject: [PATCH 2/6] Tempfile.new before 2.2 need a argument --- spec/update_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/update_spec.rb b/spec/update_spec.rb index 23f5f5bf..c6caad6d 100644 --- a/spec/update_spec.rb +++ b/spec/update_spec.rb @@ -7,7 +7,7 @@ before(:all) do # precent fail on CI @hook_cache_file = lambda do |&block| - tmp = Tempfile.new + tmp = Tempfile.new('update') stub_const('OneGadget::Update::CACHE_FILE', tmp.path) block.call(tmp.path) tmp.close From b3b62bf245385300bdd8d77ca43ce42172f6ddce Mon Sep 17 00:00:00 2001 From: david942j Date: Mon, 9 Oct 2017 20:56:20 +0800 Subject: [PATCH 3/6] fix ruby 2.2 --- spec/update_spec.rb | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/spec/update_spec.rb b/spec/update_spec.rb index c6caad6d..80b5a586 100644 --- a/spec/update_spec.rb +++ b/spec/update_spec.rb @@ -1,3 +1,4 @@ +require 'logger' require 'tempfile' require 'one_gadget/update' @@ -14,11 +15,13 @@ end @hook_logger = lambda do |&block| - logdev = OneGadget::Logger.instance_variable_get(:@logger).instance_variable_get(:@logdev) - dev = logdev.dev - logdev.reopen($stdout) + # 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 - logdev.instance_variable_set(:@dev, dev) + OneGadget::Logger.instance_variable_set(:@logger, org_logger) end end From 38814699a12c549be9510a9a400b573a1ab793e8 Mon Sep 17 00:00:00 2001 From: david942j Date: Mon, 9 Oct 2017 21:48:43 +0800 Subject: [PATCH 4/6] fix tmp --- lib/one_gadget/update.rb | 2 +- spec/update_spec.rb | 17 ++++++++++------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/lib/one_gadget/update.rb b/lib/one_gadget/update.rb index 33fa6c17..adfa649b 100644 --- a/lib/one_gadget/update.rb +++ b/lib/one_gadget/update.rb @@ -43,7 +43,7 @@ def need_check? def last_check cache = cache_file return Time.now if cache.nil? - File.open(cache).mtime + File.open(cache, &:mtime) end def cache_file diff --git a/spec/update_spec.rb b/spec/update_spec.rb index 80b5a586..7af96e64 100644 --- a/spec/update_spec.rb +++ b/spec/update_spec.rb @@ -1,5 +1,4 @@ require 'logger' -require 'tempfile' require 'one_gadget/update' require 'one_gadget/version' @@ -8,10 +7,9 @@ before(:all) do # precent fail on CI @hook_cache_file = lambda do |&block| - tmp = Tempfile.new('update') - stub_const('OneGadget::Update::CACHE_FILE', tmp.path) - block.call(tmp.path) - tmp.close + 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| @@ -25,11 +23,16 @@ end end + after(:all) do + FileUtils.rm_r('/tmp/one_gadget') + end + it 'cache_file' do - stub_const('OneGadget::Update::CACHE_FILE', '/bin/pusheeeeeen') - expect(described_class.send(:cache_file)).to be nil @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 From 64fe5c611acc64d36e00337580642edf85e9ac85 Mon Sep 17 00:00:00 2001 From: david942j Date: Mon, 9 Oct 2017 21:52:41 +0800 Subject: [PATCH 5/6] Fix windows? --- spec/update_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/update_spec.rb b/spec/update_spec.rb index 7af96e64..09445d1f 100644 --- a/spec/update_spec.rb +++ b/spec/update_spec.rb @@ -30,9 +30,9 @@ it 'cache_file' do @hook_cache_file.call do |path| expect(described_class.send(:cache_file)).to eq path - File.chmod(0o000, File.dirname(path)) + FileUtils.chmod(0o000, File.dirname(path)) expect(described_class.send(:cache_file)).to be nil - File.chmod(0o700, File.dirname(path)) + FileUtils.chmod(0o700, File.dirname(path)) end end From 440b11f8c724dc4dc5417e7ae495f67b1a5682e2 Mon Sep 17 00:00:00 2001 From: david942j Date: Mon, 9 Oct 2017 21:56:21 +0800 Subject: [PATCH 6/6] forget windows --- spec/update_spec.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/spec/update_spec.rb b/spec/update_spec.rb index 09445d1f..d46658a9 100644 --- a/spec/update_spec.rb +++ b/spec/update_spec.rb @@ -28,11 +28,12 @@ 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 - FileUtils.chmod(0o000, File.dirname(path)) + File.chmod(0o000, File.dirname(path)) expect(described_class.send(:cache_file)).to be nil - FileUtils.chmod(0o700, File.dirname(path)) + File.chmod(0o700, File.dirname(path)) end end