-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- splits code into command classes - executes `do_it` as a default task - refactor status code handling - updates bundler/platform/nokogiri - handle encoding everywhere - adds test coverage (a few "online" tests)
- Loading branch information
Showing
16 changed files
with
286 additions
and
175 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,162 +1,29 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'thor' | ||
require 'colored' | ||
require 'fileutils' | ||
require 'apt/spy2/writer' | ||
require 'apt/spy2/country' | ||
require 'apt/spy2/downloader' | ||
require 'apt/spy2/ubuntu_mirrors' | ||
require 'apt/spy2/launchpad' | ||
require 'apt/spy2/request' | ||
require 'apt/spy2/url' | ||
require 'apt/spy2/command/fix' | ||
require 'apt/spy2/command/list' | ||
require 'apt/spy2/command/check' | ||
require 'apt/spy2/version' | ||
|
||
# apt-spy2 command interface | ||
class AptSpy2 < Thor | ||
package_name 'apt-spy2' | ||
class_option :country, default: 'mirrors' | ||
class_option :launchpad, type: :boolean, banner: "Use launchpad's mirror list" | ||
|
||
desc 'fix', 'Set the closest/fastest mirror' | ||
option :commit, type: :boolean | ||
option :strict, type: :boolean | ||
def fix | ||
mirrors = retrieve(options[:country], use_launchpad?(options)) | ||
working = filter(mirrors, options[:strict], false) | ||
print 'The closest mirror is: ' | ||
puts (working[0]).to_s.bold.magenta | ||
unless options[:commit] | ||
puts 'Run with --commit to adjust /etc/apt/sources.list'.yellow | ||
return | ||
end | ||
|
||
puts 'Updating /etc/apt/sources.list'.yellow | ||
update(working[0]) | ||
end | ||
class_option :launchpad, type: :boolean, banner: 'Use launchpad\'s mirror list' | ||
|
||
desc 'check', 'Evaluate mirrors' | ||
option :output, type: :boolean, default: true | ||
option :format, default: 'shell' | ||
option :strict, type: :boolean | ||
def check | ||
@writer = Apt::Spy2::Writer.new(options[:format]) | ||
subcommand 'check', Apt::Spy2::Command::Check | ||
|
||
mirrors = retrieve(options[:country], use_launchpad?(options)) | ||
filter(mirrors, options[:strict], options[:output]) | ||
|
||
puts @writer.to_json if @writer.json? | ||
end | ||
desc 'fix', 'Update sources' | ||
subcommand 'fix', Apt::Spy2::Command::Fix | ||
|
||
desc 'list', 'List the currently available mirrors' | ||
option :format, default: 'shell' | ||
def list | ||
mirrors = retrieve(options[:country], use_launchpad?(options)) | ||
|
||
@writer = Apt::Spy2::Writer.new(options[:format]) | ||
|
||
@writer.complete(mirrors) | ||
|
||
puts @writer.to_json if @writer.json? | ||
puts mirrors unless @writer.json? | ||
end | ||
subcommand 'list', Apt::Spy2::Command::List | ||
|
||
desc 'version', 'Show which version of apt-spy2 is installed' | ||
def version | ||
puts Apt::Spy2::VERSION | ||
exit | ||
end | ||
|
||
private | ||
|
||
def retrieve(country = 'mirrors', launchpad = false) | ||
downloader = Apt::Spy2::Downloader.new | ||
|
||
if launchpad | ||
csv_path = File.expand_path("#{File.dirname(__FILE__)}/../../var/country-names.txt") | ||
country = Apt::Spy2::Country.new(csv_path) | ||
name = country.to_country_name(options[:country]) | ||
|
||
launchpad = Apt::Spy2::Launchpad.new(downloader.do_download('https://launchpad.net/ubuntu/+archivemirrors')) | ||
return launchpad.mirrors(name) | ||
end | ||
|
||
country.upcase! if country.length == 2 | ||
|
||
ubuntu_mirrors = Apt::Spy2::UbuntuMirrors.new(downloader.do_download("http://mirrors.ubuntu.com/#{country}.txt")) | ||
ubuntu_mirrors.mirrors(country) | ||
end | ||
|
||
def filter(mirrors, strict = false, output = true) | ||
# f me :) | ||
|
||
working_mirrors = [] | ||
|
||
url = Apt::Spy2::Url.new(strict) | ||
|
||
mirrors.each do |mirror| | ||
data = { 'mirror' => mirror } | ||
|
||
check = url.adjust!(mirror) | ||
|
||
status = broken?(check) | ||
|
||
data['status'] = status | ||
|
||
working_mirrors << mirror if status == 'up' | ||
|
||
@writer.echo(data) if output | ||
end | ||
|
||
working_mirrors | ||
end | ||
|
||
def broken?(url) | ||
begin | ||
req = Apt::Spy2::Request.new(url) | ||
response = req.head | ||
return 'up' if response.code == '200' | ||
|
||
return 'broken' if response.code == '404' | ||
rescue StandardError | ||
# connection errors, ssl errors, etc. | ||
end | ||
|
||
'down' | ||
end | ||
|
||
def update(mirror) | ||
t = Time.now | ||
r = `lsb_release -c`.split(' ')[1] | ||
sources = "## Updated on #{t} by apt-spy2\n" | ||
sources += "deb #{mirror} #{r} main restricted universe multiverse\n" | ||
sources += "deb #{mirror} #{r}-updates main restricted universe multiverse\n" | ||
sources += "deb #{mirror} #{r}-backports main restricted universe multiverse\n" | ||
sources += "deb #{mirror} #{r}-security main restricted universe multiverse\n" | ||
|
||
apt_sources = '/etc/apt/sources.list' | ||
|
||
begin | ||
File.rename apt_sources, "#{apt_sources}.#{t.to_i}" | ||
File.open(apt_sources, 'w') do |f| | ||
f.write(sources) | ||
end | ||
rescue StandardError | ||
msg = "Failed updating #{apt_sources}!" | ||
msg += 'You probably need sudo!' | ||
raise msg | ||
end | ||
|
||
puts "Updated '#{apt_sources}' with #{mirror}".green | ||
puts 'Run `apt-get update` to update'.black_on_yellow | ||
end | ||
|
||
def use_launchpad?(options) | ||
return false unless options[:launchpad] | ||
|
||
if options[:country] && options[:country] == 'mirrors' | ||
raise 'Please supply a `--country=foo`. Launchpad cannot guess!' | ||
end | ||
|
||
true | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'apt/spy2/command/command' | ||
require 'apt/spy2/writer' | ||
|
||
module Apt | ||
module Spy2 | ||
module Command | ||
# runs `apt-spy2 check` | ||
class Check < BaseCommand | ||
option :output, type: :boolean, default: true | ||
option :format, default: 'shell' | ||
option :strict, type: :boolean | ||
|
||
desc 'do_it', '' | ||
def do_it | ||
@writer = Apt::Spy2::Writer.new(options[:format]) | ||
|
||
mirrors = retrieve(launchpad: use_launchpad?(options)) | ||
filter(mirrors, strict: options[:strict], output: options[:output]) | ||
|
||
puts @writer.to_json if @writer.json? | ||
end | ||
|
||
default_task :do_it | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'thor' | ||
require 'colored' | ||
require 'apt/spy2/country' | ||
require 'apt/spy2/downloader' | ||
require 'apt/spy2/launchpad' | ||
require 'apt/spy2/request' | ||
require 'apt/spy2/status' | ||
require 'apt/spy2/ubuntu_mirrors' | ||
require 'apt/spy2/url' | ||
require 'apt/spy2/writer' | ||
|
||
module Apt | ||
module Spy2 | ||
module Command | ||
# BaseCommmand for all others | ||
class BaseCommand < Thor | ||
# rubocop:disable Metrics/BlockLength | ||
no_commands do | ||
def use_launchpad?(options) | ||
return false unless options[:launchpad] | ||
|
||
if options[:country] && options[:country] == 'mirrors' | ||
raise 'Please supply a `--country=foo`. Launchpad cannot guess!' | ||
end | ||
|
||
true | ||
end | ||
|
||
def country_names | ||
File.expand_path("#{File.dirname(__FILE__)}/../../../../var/country-names.txt") | ||
end | ||
|
||
def retrieve(launchpad: false) | ||
downloader = Apt::Spy2::Downloader.new | ||
|
||
if launchpad | ||
name = Apt::Spy2::Country.new(country_names).to_country_name(options[:country]) | ||
launchpad = Apt::Spy2::Launchpad.new(downloader.do_download('https://launchpad.net/ubuntu/+archivemirrors')) | ||
return launchpad.mirrors(name) | ||
end | ||
|
||
country = options[:country] | ||
country.upcase! if country.length == 2 | ||
|
||
ubuntu_mirrors = Apt::Spy2::UbuntuMirrors.new(downloader.do_download("http://mirrors.ubuntu.com/#{country}.txt")) | ||
ubuntu_mirrors.mirrors(country) | ||
end | ||
|
||
def filter(mirrors, strict: false, output: true) | ||
# f me :) | ||
working_mirrors = [] | ||
url = Apt::Spy2::Url.new(strict) | ||
|
||
mirrors.each do |mirror| | ||
data = { 'mirror' => mirror } | ||
data['status'] = broken?(url.adjust!(mirror)) | ||
working_mirrors << mirror if data['status'] == Apt::Spy2::Status::UP | ||
@writer.echo(data) if output | ||
end | ||
|
||
working_mirrors | ||
end | ||
|
||
def broken?(url) | ||
begin | ||
req = Apt::Spy2::Request.new(url) | ||
return Apt::Spy2::Status.status?(req.head.code) | ||
rescue StandardError | ||
# connection errors, ssl errors, etc. | ||
end | ||
|
||
Apt::Spy2::Status::DOWN | ||
end | ||
end | ||
# rubocop:enable Metrics/BlockLength | ||
end | ||
end | ||
end | ||
end |
Oops, something went wrong.