-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathchannel.rb
105 lines (88 loc) · 3.04 KB
/
channel.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# frozen_string_literal: true
require "typhoeus"
require "json"
require "benchmark"
class Channel
ARCHES = %w[linux-32 linux-64 linux-aarch64 linux-armv6l linux-armv7l linux-ppc64le osx-64 win-64 win-32 noarch zos-z].freeze
attr_reader :timestamp
def initialize(channel, domain)
@channel_name = channel
@domain = domain
@timestamp = Time.now
@lock = Concurrent::ReadWriteLock.new
reload
end
def reload
new_packages = retrieve_packages
@lock.with_write_lock { @packages = new_packages }
@timestamp = Time.now
end
def packages
@lock.with_read_lock { @packages }
end
def package_version(name, version)
@lock.with_read_lock do
raise Sinatra::NotFound unless @packages.key?(name)
@packages[name][:versions].filter { |package| package[:number] == version }
end
end
def only_one_version_packages
@lock.with_read_lock { remove_duplicate_versions(@packages) }
end
private
def retrieve_packages
packages = {}
puts "Fetching packages for channel https://#{@domain}/#{@channel_name}..."
channel_resp = Typhoeus.get("https://#{@domain}/#{@channel_name}/channeldata.json")
channeldata = JSON.parse(channel_resp.body)["packages"]
benchmark = Benchmark.measure do
ARCHES.each do |arch|
url = "https://#{@domain}/#{@channel_name}/#{arch}/repodata.json"
puts "fetcing #{url}"
resp = Typhoeus.get(url)
blob = JSON.parse(resp.body)['packages']
blob.each_key do |key|
version = blob[key]
package_name = version["name"]
unless packages.key?(package_name)
package_data = channeldata[package_name]
packages[package_name] = base_package(package_data, package_name)
end
packages[package_name][:versions] << release_version(key, version)
end
rescue => e
puts "Failed to fetch for #{arch} https://#{@domain}/#{@channel_name}/#{arch}/repodata.json"
end
end
puts "Finished in #{benchmark.real.round(1)} sec: #{packages.to_json.bytesize / 1_000_000}mb of data."
packages
end
def base_package(package_data, package_name)
{
versions: [],
repository_url: package_data["dev_url"],
homepage: package_data["home"],
licenses: package_data["license"],
description: package_data["description"],
name: package_name,
}
end
def release_version(artifact, package_version)
{
artifact: artifact,
download_url: "https://#{@domain}/#{@channel_name}/#{package_version['subdir']}/#{artifact}",
number: package_version["version"],
original_license: package_version["license"],
published_at: package_version["timestamp"].nil? ? nil : Time.at(package_version["timestamp"] / 1000),
dependencies: package_version["depends"],
arch: package_version["subdir"],
channel: @channel_name,
}
end
def remove_duplicate_versions(packages)
packages.each_value do |value|
value[:versions] = value[:versions].uniq { |vers| vers[:number] }
end
packages
end
end