Skip to content

Commit

Permalink
Add rubocop and coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
vitalie committed Mar 28, 2023
1 parent 2cbc1c2 commit 91b4a28
Show file tree
Hide file tree
Showing 34 changed files with 507 additions and 326 deletions.
87 changes: 87 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
require:
- rubocop-performance
- rubocop-rspec

AllCops:
TargetRubyVersion: 2.4
NewCops: enable
Exclude:
- bin/**/*

Bundler/OrderedGems:
Enabled: false

Gemspec/RequireMFA:
Enabled: false

Gemspec/OrderedDependencies:
Enabled: false

Naming/VariableNumber:
Enabled: false

Metrics/ClassLength:
Max: 150

Metrics/MethodLength:
Max: 30

Metrics/CyclomaticComplexity:
Max: 20

Metrics/PerceivedComplexity:
Max: 20

Metrics/AbcSize:
Max: 40

Style/FrozenStringLiteralComment:
Enabled: false

Style/Documentation:
Enabled: false

Style/ClassAndModuleChildren:
Enabled: false

Style/StructInheritance:
Enabled: false

Style/RescueStandardError:
Enabled: false

Style/HashSyntax:
EnforcedShorthandSyntax: never

Style/FetchEnvVar:
Enabled: false

Style/FormatString:
Enabled: false

Style/FormatStringToken:
Enabled: false

Style/OptionalBooleanParameter:
Enabled: false

Lint/BooleanSymbol:
Enabled: false

Naming/MethodParameterName:
Enabled: false

RSpec/FilePath:
Enabled: false

RSpec/MultipleDescribes:
Enabled: false

RSpec/DescribeMethod:
Enabled: false

RSpec/ExampleLength:
Max: 20

RSpec/MultipleExpectations:
Enabled: false
6 changes: 6 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,10 @@ gemspec
group :test do
gem 'rspec'
gem 'webmock'

gem 'rubocop', require: false
gem 'rubocop-performance', require: false
gem 'rubocop-rspec', require: false
gem 'simplecov', require: false
gem 'simplecov-console', require: false
end
15 changes: 11 additions & 4 deletions lib/gh.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,16 @@ module GH
autoload :Wrapper, 'gh/wrapper'

def self.with(backend)
if Hash === backend
if backend.is_a?(Hash)
@options ||= {}
@options, options = @options.merge(backend), @options
options = @options
@options = @options.merge(backend)
backend = DefaultStack.build(@options)
end

if block_given?
was, self.current = current, backend
was = current
self.current = backend
yield
else
backend
Expand All @@ -54,12 +56,17 @@ def self.current=(backend)
end

extend SingleForwardable
def_delegators :current, :api_host, :[], :reset, :load, :post, :delete, :patch, :put, :in_parallel, :in_parallel?, :options, :head
def_delegators :current, :api_host, :[], :reset, :load, :post, :delete, :patch, :put, :in_parallel, :in_parallel?,
:options, :head

def self.method_missing(*args, &block)
current.public_send(*args, &block)
end

def self.respond_to_missing?(method, *)
super
end

DefaultStack = Stack.new do
use Instrumentation
use Parallel
Expand Down
23 changes: 18 additions & 5 deletions lib/gh/cache.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
require 'gh'
require 'thread'

module GH
# Public: This class caches responses.
Expand All @@ -13,19 +12,32 @@ class SimpleCache
#
# size - Number of objects to hold in cache.
def initialize(size = 2048)
@old, @new, @size, @mutex = {}, {}, size / 2, Mutex.new
@old = {}
@new = {}
@size = size / 2
@mutex = Mutex.new
end

# Internal: Tries to fetch a value from the cache and if it doesn't exist, generates it from the
# block given.
def fetch(key)
@mutex.synchronize { @old, @new = @new, {} if @new.size > @size } if @new.size > @size
if @new.size > @size
@mutex.synchronize do
if @new.size > @size
@old = @new
@new = {}
end
end
end
@new[key] ||= @old[key] || yield
end

# Internal: ...
def clear
@mutex.synchronize { @old, @new = {}, {} }
@mutex.synchronize do
@old = {}
@new = {}
end
end
end

Expand All @@ -51,7 +63,8 @@ def fetch_resource(key)

def clear_partial
return false unless cache.respond_to? :delete_matched
pattern = "^" << Regexp.escape(prefixed(""))

pattern = '^' << Regexp.escape(prefixed(''))
cache.delete_matched Regexp.new(pattern)
true
rescue NotImplementedError
Expand Down
51 changes: 28 additions & 23 deletions lib/gh/error.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,28 @@ class Error < StandardError
attr_reader :info

def initialize(error = nil, payload = nil, info = {})
info = info.merge(error.info) if error.respond_to? :info and Hash === error.info
super(error)

info = info.merge(error.info) if error.respond_to?(:info) && error.info.is_a?(Hash)
error = error.error while error.respond_to? :error
@info = info.merge(:error => error, :payload => payload)
@info = info.merge(error: error, payload: payload)

return unless error

if error
set_backtrace error.backtrace if error.respond_to? :backtrace
if error.respond_to? :response and error.response
case response = error.response
when Hash
@info[:response_status] = response[:status]
@info[:response_headers] = response[:headers]
@info[:response_body] = response[:body]
when Faraday::Response
@info[:response_status] = response.status
@info[:response_headers] = response.headers
@info[:response_body] = response.body
else
@info[:response] = response
end
end
set_backtrace error.backtrace if error.respond_to? :backtrace
return unless error.respond_to?(:response) && error.response

case response = error.response
when Hash
@info[:response_status] = response[:status]
@info[:response_headers] = response[:headers]
@info[:response_body] = response[:body]
when Faraday::Response
@info[:response_status] = response.status
@info[:response_headers] = response.headers
@info[:response_body] = response.body
else
@info[:response] = response
end
end

Expand All @@ -37,16 +39,16 @@ def error
end

def message
"GH request failed\n" + info.map { |k, v| entry(k, v) }.join("\n")
(['GH request failed'] + info.map { |k, v| entry(k, v) }).join("\n")
end

private

def entry(key, value)
value = "#{value.class}: #{value.message}" if Exception === value
value = value.inspect unless String === value
value = "#{value.class}: #{value.message}" if value.is_a?(Exception)
value = value.inspect unless value.is_a?(String)
value.gsub!(/"Basic .+"|(client_(?:id|secret)=)[^&\s]+/, '\1[removed]')
(key.to_s + ": ").ljust(20) + value
"#{key}: ".ljust(20) + value
end
end

Expand All @@ -56,8 +58,11 @@ class TokenInvalid < Error
def self.Error(conditions)
Module.new do
define_singleton_method(:===) do |exception|
return false unless Error === exception and not exception.info.nil?
return false unless exception.is_a?(Error) && !exception.info.nil?

# rubocop:disable Style/CaseEquality
conditions.all? { |k, v| v === exception.info[k] }
# rubocop:enable Style/CaseEquality
end
end
end
Expand Down
11 changes: 6 additions & 5 deletions lib/gh/instrumentation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,25 @@ def setup(backend, options)
end

def http(verb, url, *)
instrument(:http, :verb => verb, :url => url) { super }
instrument(:http, verb: verb, url: url) { super }
end

def load(data)
instrument(:load, :data => data) { super }
instrument(:load, data: data) { super }
end

def [](key)
instrument(:access, :key => key) { super }
instrument(:access, key: key) { super }
end

private

def instrument(type, payload = {})
return yield unless instrumenter

result = nil
instrumenter.call("#{type}.gh", payload.merge(:gh => frontend)) { result = yield }
return result
instrumenter.call("#{type}.gh", payload.merge(gh: frontend)) { result = yield }
result
end
end
end
12 changes: 6 additions & 6 deletions lib/gh/lazy_loader.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,19 @@ class LazyLoader < Wrapper

def modify_hash(hash, loaded = false)
hash = super(hash)
link = hash['_links']['self'] unless loaded or hash['_links'].nil?
link = hash['_links']['self'] unless loaded || hash['_links'].nil?
setup_lazy_loading(hash, link['href']) if link
hash
rescue Exception => error
raise Error.new(error, hash)
rescue => e
raise Error.new(e, hash)
end

private

def lazy_load(hash, key, link)
def lazy_load(hash, _key, link)
modify_hash(backend[link].data, true)
rescue Exception => error
raise Error.new(error, hash)
rescue => e
raise Error.new(e, hash)
end
end
end
12 changes: 6 additions & 6 deletions lib/gh/link_follower.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,20 @@ class LinkFollower < Wrapper
double_dispatch

def modify_hash(hash)
hash = super
hash = super(hash)
setup_lazy_loading(hash) if hash['_links']
hash
rescue Exception => error
raise Error.new(error, hash)
rescue => e
raise Error.new(e, hash)
end

private

def lazy_load(hash, key)
link = hash['_links'][key]
{ key => self[link['href']] } if link
rescue Exception => error
raise Error.new(error, hash)
rescue => e
raise Error.new(e, hash)
end
end
end
end
Loading

0 comments on commit 91b4a28

Please sign in to comment.