class RuboCop::Schema::Repo

Constants

TAGS_PER_PAGE

GitHub public APIs have a rate limit of 60/hour when making unauthenticated requests. 100 items per page is the maximum allowed, which we'll use to keep the number of requests to a minimum.

TAGS_URL_TEMPLATE

Public Class Methods

new(dir, loader, &event_handler) click to toggle source
# File lib/rubocop/schema/repo.rb, line 18
def initialize(dir, loader, &event_handler)
  @dir           = Pathname(dir)
  @loader        = loader
  @event_handler = event_handler
  @dir.mkpath
end

Public Instance Methods

build() click to toggle source
# File lib/rubocop/schema/repo.rb, line 25
def build
  ExtensionSpec::KNOWN_GEMS.each &method(:build_for_gem)
  Event.dispatch message: "Repo updated: #{@dir}", &@event_handler
end

Private Instance Methods

build_for_gem(name) click to toggle source
# File lib/rubocop/schema/repo.rb, line 32
def build_for_gem(name)
  existing = read(name).map { |h| [h['version'], h['diff']] }.to_h
  previous = nil
  body     = versions_of(name).map do |version|
    previous, diff = fetch_for_spec(Spec.new(name: name, version: version), existing, previous)
    {
      'version' => version,
      'diff'    => diff
    }
  end
  write name, body.compact
end
build_for_spec(spec) click to toggle source
# File lib/rubocop/schema/repo.rb, line 56
def build_for_spec(spec)
  Event.dispatch message: "Generating: #{spec}", &@event_handler
  Generator.new([spec], @loader).schema
end
fetch_for_spec(spec, existing, previous) click to toggle source
# File lib/rubocop/schema/repo.rb, line 45
def fetch_for_spec(spec, existing, previous)
  if existing.key? spec.version
    diff   = existing[spec.version]
    schema = Diff.apply(previous, diff)
  else
    schema = build_for_spec(spec)
    diff   = Diff.diff(previous, schema)
  end
  [schema, diff]
end
path_for(name) click to toggle source
# File lib/rubocop/schema/repo.rb, line 72
def path_for(name)
  @dir.join("#{name}.json")
end
read(name) click to toggle source
# File lib/rubocop/schema/repo.rb, line 65
def read(name)
  path = path_for(name)
  return [] unless path.exist?

  JSON.parse path.read
end
versions_of(name) click to toggle source
# File lib/rubocop/schema/repo.rb, line 76
def versions_of(name)
  tags = []
  loop do
    json = http_get(format(TAGS_URL_TEMPLATE, name, (tags.length / TAGS_PER_PAGE) + 1))
    raise "No tags available for #{name}" if json == ''

    parsed = JSON.parse(json)
    tags += parsed
    break unless parsed.length == TAGS_PER_PAGE
  end

  tags.reverse.map { |obj| obj['name'].to_s[/(?<=\Av)\d.+/] }.compact
end
write(name, body) click to toggle source
# File lib/rubocop/schema/repo.rb, line 61
def write(name, body)
  path_for(name).binwrite JSON.pretty_generate body
end