summaryrefslogtreecommitdiff
path: root/config-list-mirrors-archlinux
blob: e59ea2c0e52429d8371545a324abb9c414719f49 (plain)
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
#!/usr/bin/env ruby
# 2013, 2016, 2018  Luke Shumaker

require 'json'
require 'net/http'
require 'optparse'
require 'set'
devnull = open("/dev/null")

requires = Set.new()
begin
	OptionParser.new do |parser|
	parser.on("--require=DIR", "Optional directory that the mirror needs ('archive', 'iso', 'other', or 'sources')") do |dir|
		requires.add(dir)
	end
	parser.on("-h", "--help", "Display this help") do
		puts parser
		exit
	end
	end.parse!
rescue OptionParser::ParseError => e
	STDERR.puts "#{$0}: #{e}"
	STDERR.puts "Try '#{$0} --help' for more information."
	exit 2
end
unless ARGV.empty?
	STDERR.puts "#{$0}: extra argument '#{ARGV[0]}'"
	STDERR.puts "Try '#{$0} --help' for more information."
	exit 2
end

data = JSON::parse(Net::HTTP.get(URI("https://www.archlinux.org/mirrors/status/tier/1/json/")))

if data["version"] != 3
	print "Data format version != 3"
	exit 1
end

# Filter out URLs with incomplete information
urls = data["urls"].select{|a| a.none?{|k,v|v.nil?}}

# Filter based on our criteria
rsync_urls = urls.select{|a| a["protocol"]=="rsync"}
if requires.include?("iso")
	rsync_urls = rsync_urls.select{|a| a["isos"]==true}
	requires.delete("iso")
end
unless requires.empty?
	listing_procs = {}
	rsync_urls.each do |a|
		# trailing slash is important; ensure we have one
		listing_procs[a["url"]] ||= IO.popen(["rsync", "--no-motd", "--list-only", "--", a["url"]+"/"], :err => devnull)
	end
	listings = {}
	listing_procs.map.each do |url,listing_proc|
		listings[url] = listing_proc.read.lines.map{|line|line.chomp.sub(/.*\s/,'')}
		listing_proc.close
	end
	rsync_urls = rsync_urls.select{|a|requires.all?{|dir|listings[a["url"]].include?(dir)}}
end
puts JSON.dump(rsync_urls)