diff --git a/lib/github_import.rb b/lib/github_import.rb index 3689949..533b031 100644 --- a/lib/github_import.rb +++ b/lib/github_import.rb @@ -2,6 +2,7 @@ require_relative 'cargo_import' require_relative 'import_helpers' require_relative 'npm_import' require_relative 'requests' +require_relative 'ruby_gems_import' require 'base64' require 'json' @@ -38,14 +39,21 @@ class GithubImport data['last_tag'] = tag_info end - if ['JavaScript', 'TypeScript'].include?(repo_info['language']) + if project.language == :ruby + gems = get_rubygems_releases(user, repo, project) + last_update = gems.map { |gem| gem.last_release_time }.sort.last + + if last_update && (release.nil? || last_update > release['published_at']) + data['last_release'] = { 'published_at' => last_update } + end + elsif project.language == :js npm = get_npm_releases(user, repo, project) last_update = npm.map { |n| n.last_release_time }.sort.last if last_update && (release.nil? || last_update > release['published_at']) data['last_release'] = { 'published_at' => last_update } end - elsif repo_info['language'] == 'Rust' + elsif project.language == :rust crates = get_cargo_releases(user, repo, project) last_update = crates.map { |c| c.last_release_time }.sort.last @@ -222,4 +230,30 @@ class GithubImport releases end + + def get_rubygems_releases(user, repo, project) + response = get_response("https://api.github.com/repos/#{user}/#{repo}/contents") + raise FetchError.new(response) unless response.code.to_i == 200 + + gemspec_files = JSON.parse(response.body) + .select { |file| file['type'] == 'file' && file['name'].end_with?('.gemspec') } + .sort_by { |file| file['name'] } + + releases = [] + + gemspec_files.each do |gemspec_file| + response = get_response(gemspec_file['url']) + raise FetchError.new(response) unless response.code.to_i == 200 + + details = JSON.parse(response.body) + gemspec = RubyGemsImport::Gemspec.new(Base64.decode64(details['content'])) + next unless gemspec.name + + if gem = RubyGemsImport.new.get_gem_info(gemspec.name) + releases << gem + end + end + + releases + end end diff --git a/lib/ruby_gems_import.rb b/lib/ruby_gems_import.rb new file mode 100644 index 0000000..4b0dc32 --- /dev/null +++ b/lib/ruby_gems_import.rb @@ -0,0 +1,53 @@ +require_relative 'requests' + +require 'json' +require 'time' +require 'uri' + +class RubyGemsImport + include Requests + + class Gemspec + def initialize(contents) + @contents = contents + end + + def name + if @contents =~ /^\s*[a-zA-Z_][a-zA-Z0-9_]*\.name\s*=\s*('[^']+'|"[^"]+")/ + return $1[1..-2] + end + end + end + + class RemoteGem + def initialize(json) + @json = json + end + + def name + @json['name'] + end + + def last_release_time + Time.parse(@json['version_created_at']) + end + end + + def initialize + @@cache ||= {} + end + + def get_gem_info(name) + encoded_name = URI.encode_www_form_component(name) + response = @@cache[name] || get_response("https://rubygems.org/api/v1/gems/#{encoded_name}.json") + @@cache[name] = response + + if response.code.to_i == 200 + RemoteGem.new(JSON.parse(response.body)) + elsif response.code.to_i == 404 + nil + else + raise FetchError.new(response) + end + end +end diff --git a/lib/tangled_import.rb b/lib/tangled_import.rb index aaf0049..7724b28 100644 --- a/lib/tangled_import.rb +++ b/lib/tangled_import.rb @@ -2,6 +2,7 @@ require_relative 'cargo_import' require_relative 'import_helpers' require_relative 'npm_import' require_relative 'requests' +require_relative 'ruby_gems_import' require 'didkit' require 'fileutils' @@ -52,7 +53,15 @@ class TangledImport data['stars'] = get_stars(repo_record) - if project.language == :js + if project.language == :ruby + gems = get_rubygems_releases(repo_folder, project) + last_update = gems.map { |gem| gem.last_release_time }.sort.last + tag_date = tag_info && tag_info['committer_date'] + + if last_update && (tag_date.nil? || last_update > tag_date) + data['last_release'] = { 'published_at' => last_update } + end + elsif project.language == :js npm = get_npm_releases(repo_folder, project) last_update = npm.map { |n| n.last_release_time }.sort.last @@ -190,4 +199,19 @@ class TangledImport releases end end + + def get_rubygems_releases(repo_folder, project) + releases = [] + + Dir[File.join(repo_folder, '*.gemspec')].sort.each do |gemspec_file| + gemspec = RubyGemsImport::Gemspec.new(File.read(gemspec_file)) + next unless gemspec.name + + if gem = RubyGemsImport.new.get_gem_info(gemspec.name) + releases << gem + end + end + + releases + end end