Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 44 additions & 12 deletions app/models/gem_dependent.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
class GemDependent
extend StatsD::Instrument
DepKey = Struct.new(:name, :number, :platform, :required_ruby_version, :required_rubygems_version, :sha256, :created_at)

attr_reader :gem_names

Expand Down Expand Up @@ -35,25 +36,56 @@ def fetch_dependencies
private

def fetch_dependency_from_db(gem_name)
gem_record = Rubygem.includes(:versions).find_by_name(gem_name)
return [] unless gem_record
gem_record.versions.includes(:dependencies).sort_by(&:number).reverse_each.map do |version|
version_deps = version.dependencies.select { |d| d.scope == 'runtime' }
sanitize_sql = ActiveRecord::Base.send(:sanitize_sql_array, sql_query(gem_name))
dataset = ActiveRecord::Base.connection.execute(sanitize_sql)
deps = {}

dataset.each do |row|
key = DepKey.new(
row['name'],
row['number'],
row['platform'],
row['required_ruby_version'],
row['required_rubygems_version'],
row['sha256'],
row['created_at']
)
deps[key] = [] unless deps[key]
deps[key] << [row['dep_name'], row['requirements']] if row['dep_name']
end

deps.map do |dep_key, gem_deps|
{
name: gem_name,
number: version.number,
platform: version.platform,
rubygems_version: version.required_rubygems_version,
ruby_version: version.required_ruby_version,
checksum: version.sha256,
created_at: version.created_at,
dependencies: version_deps.map { |d| [d.name, d.requirements] }
name: dep_key.name,
number: dep_key.number,
platform: dep_key.platform,
rubygems_version: dep_key.required_rubygems_version,
ruby_version: dep_key.required_ruby_version,
checksum: dep_key.sha256,
created_at: Time.zone.parse(dep_key.created_at).strftime('%Y-%m-%d %H:%M:%S %z'),
dependencies: gem_deps
}
end
end
statsd_measure :fetch_dependency_from_db, 'gem_dependent.fetch_dependency_from_db'

def sql_query(gem_name)
["SELECT rv.name, rv.number, rv.platform, rv.required_ruby_version, rv.sha256,
rv.required_rubygems_version, d.requirements, rv.created_at, for_dep_name.name dep_name
FROM
(SELECT r.name, v.number, v.platform,v.required_rubygems_version, v.sha256,
v.required_ruby_version, v.created_at, v.id AS version_id
FROM rubygems AS r, versions AS v
WHERE v.rubygem_id = r.id
AND v.indexed is true AND r.name = ?) AS rv
LEFT JOIN dependencies AS d ON
d.version_id = rv.version_id
LEFT JOIN rubygems AS for_dep_name ON
d.rubygem_id = for_dep_name.id
AND d.scope = 'runtime'
ORDER BY rv.created_at, rv.number, rv.platform, for_dep_name.name", gem_name]
end

# Returns a Hash of the gem's cache key, and its cached dependencies
def memcached_gem_info
@memcached_gem_info ||= Rails.cache.read_multi(*@gem_information.values)
Expand Down
14 changes: 7 additions & 7 deletions test/functional/api/v1/dependencies_controller_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ class Api::V1::DependenciesControllerTest < ActionController::TestCase
'rubygems_version' => '>= 2.6.3',
'ruby_version' => '>= 2.0.0',
'checksum' => 'tdQEXD9Gb6kf4sxqvnkjKhpXzfEE96JucW4KHieJ33g=',
'created_at' => '2016-05-24T00:00:00.000Z',
'created_at' => '2016-05-24 00:00:00 +0000',
'dependencies' => []
}]

Expand All @@ -78,23 +78,23 @@ class Api::V1::DependenciesControllerTest < ActionController::TestCase
result = [
{
'name' => 'myrails',
'number' => '3.0.0',
'number' => '1.0.0',
'platform' => 'ruby',
'rubygems_version' => '>= 2.6.3',
'ruby_version' => '>= 2.0.0',
'checksum' => 'tdQEXD9Gb6kf4sxqvnkjKhpXzfEE96JucW4KHieJ33g=',
'created_at' => '2016-05-24T00:00:00.000Z',
'created_at' => '2016-05-24 00:00:00 +0000',
'dependencies' => []
},

{
'name' => 'myrails',
'number' => '1.0.0',
'number' => '3.0.0',
'platform' => 'ruby',
'rubygems_version' => '>= 2.6.3',
'ruby_version' => '>= 2.0.0',
'checksum' => 'tdQEXD9Gb6kf4sxqvnkjKhpXzfEE96JucW4KHieJ33g=',
'created_at' => '2016-05-24T00:00:00.000Z',
'created_at' => '2016-05-24 00:00:00 +0000',
'dependencies' => []
},

Expand All @@ -105,7 +105,7 @@ class Api::V1::DependenciesControllerTest < ActionController::TestCase
'rubygems_version' => '>= 2.6.3',
'ruby_version' => '>= 2.0.0',
'checksum' => 'tdQEXD9Gb6kf4sxqvnkjKhpXzfEE96JucW4KHieJ33g=',
'created_at' => '2016-05-24T00:00:00.000Z',
'created_at' => '2016-05-24 00:00:00 +0000',
'dependencies' => []
}
]
Expand Down Expand Up @@ -173,7 +173,7 @@ class Api::V1::DependenciesControllerTest < ActionController::TestCase
rubygems_version: '>= 2.6.3',
ruby_version: '>= 2.0.0',
checksum: 'tdQEXD9Gb6kf4sxqvnkjKhpXzfEE96JucW4KHieJ33g=',
created_at: Date.new(2016, 05, 24),
created_at: "2016-05-24 00:00:00 +0000",
dependencies: []
}]

Expand Down
79 changes: 68 additions & 11 deletions test/unit/gem_dependent_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,8 @@ class GemDependentTest < ActiveSupport::TestCase

context "with gem_names" do
setup do
@gem = create(:rubygem, name: "rack")
create(:version, number: "0.0.1", rubygem_id: @gem.id)
create(:version, number: "0.0.2", rubygem_id: @gem.id)

@gem2 = create(:rubygem, name: "rack2")
create(:version, number: "0.0.1", created_at: Date.new(2016, 05, 24), rubygem_id: @gem2.id)
rack2 = create(:rubygem, name: "rack2")
create(:version, number: "0.0.1", created_at: Date.new(2016, 05, 24), rubygem: rack2)
end

should "return rack2" do
Expand All @@ -38,7 +34,7 @@ class GemDependentTest < ActiveSupport::TestCase
rubygems_version: ">= 2.6.3",
ruby_version: ">= 2.0.0",
checksum: "tdQEXD9Gb6kf4sxqvnkjKhpXzfEE96JucW4KHieJ33g=",
created_at: Date.new(2016, 05, 24),
created_at: "2016-05-24 00:00:00 +0000",
dependencies: []
}

Expand All @@ -48,11 +44,72 @@ class GemDependentTest < ActiveSupport::TestCase
end
end

should "return all versions for a gem" do
result = %w(0.0.2 0.0.1)
context "multiple versions" do
setup do
rack = create(:rubygem, name: "rack")
create(:version, number: "0.2.2", created_at: Date.new(2016, 05, 24), rubygem: rack)
create(:version, number: "0.1.2", created_at: Date.new(2016, 05, 24), rubygem: rack)
create(:version, number: "0.1.2", created_at: Date.new(2016, 05, 24), platform: 'jruby', rubygem: rack)
create(:version, number: "0.1.3", created_at: Date.new(2016, 05, 25), rubygem: rack)
end

should "orders versions by created_at, versions and platform" do
result = [["0.1.2", "jruby"], ["0.1.2", "ruby"], ["0.2.2", "ruby"], ["0.1.3", "ruby"]]

deps = GemDependent.new(["rack"]).to_a
assert_equal result, deps.map { |x| [x[:number], x[:platform]] }
end
end

context "has dependencies" do
setup do
devise = create(:rubygem, name: "devise")
version = create(:version, number: "1.0.0", rubygem: devise)

%w(foo bar).map do |gem_name|
create(:rubygem, name: gem_name).tap do |rubygem|
gem_dependency = Gem::Dependency.new(rubygem.name, ['>= 0.0.0'])
create(:dependency, rubygem: rubygem, version: version, gem_dependency: gem_dependency)
end
end
end

deps = GemDependent.new(["rack"]).to_a
assert_equal result, deps.map { |x| x[:number] }
should "return dependencies ordered by name" do
result = {
name: 'devise',
number: '1.0.0',
dependencies: [['bar', '>= 0.0.0'], ['foo', '>= 0.0.0']]
}

dep = GemDependent.new(["devise"]).to_a.first
result.each_pair do |k, v|
assert_equal v, dep[k]
end
end
end

context "non indexed versions" do
setup do
nokogiri = create(:rubygem, name: "nokogiri")
create(:version, number: "0.0.1", created_at: Date.new(2016, 05, 24), rubygem: nokogiri)
create(:version, number: "0.1.1", rubygem: nokogiri, indexed: false)
end

should "filter non indexed version" do
result = {
name: "nokogiri",
number: "0.0.1",
platform: "ruby",
rubygems_version: ">= 2.6.3",
ruby_version: ">= 2.0.0",
checksum: "tdQEXD9Gb6kf4sxqvnkjKhpXzfEE96JucW4KHieJ33g=",
created_at: "2016-05-24 00:00:00 +0000",
dependencies: []
}

deps = GemDependent.new(["nokogiri"]).to_a
assert_equal [result], deps
end
end
end

Expand Down