apt-spy2 0.7.2 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 91d09bec4d6918e39405d38ee164b8215c6e04d778887c0e570bdab6cc39592e
4
- data.tar.gz: d2f69bf166ca8bf79fff732e30184270dfbc0422a41dbe616afc9ddd56b21641
3
+ metadata.gz: 456003f4c6ac4e210a1cd7ebe44888b8a58d3b9fac87d1b68f03e9b3d8c45bdf
4
+ data.tar.gz: 907656e6cf49fe081152826de58348ff75d3f2ff1014f5af854dfb24f86e421d
5
5
  SHA512:
6
- metadata.gz: 931ef089f949e870538b77887a7825a42647bcc8a4ef577118a12b51112bcba1b1a63c235d2bbe0e1fed348608d84954c6a44c7f16a578e42c29e198a4403619
7
- data.tar.gz: 956aa4b5d89409a4366549b84846a42b95c46f7013197182fdfd22956ba07e60fddccf5f210a5eb85d0c09f3e8ff15cc730642ea1afb66b9fee81703cb172da3
6
+ metadata.gz: 5a2c12f506751914dc44243f88ecef036e7a5ca41cab0f6595c70e4c61d7d68e3da6cc304f9879a8b4f8b36fd2daa96b664a8fd91cf5a5a9cf64a06c2723cd10
7
+ data.tar.gz: '0815dfcb1e3b857aac1a30a8d0cee549e3c4a8a95ee0213e227b6747bb88939813118fbbaffc3d44ed1de663963c2ab22d7a7f03f552d4cbcd2e744183461fcb'
@@ -0,0 +1,70 @@
1
+ # For most projects, this workflow file will not need changing; you simply need
2
+ # to commit it to your repository.
3
+ #
4
+ # You may wish to alter this file to override the set of languages analyzed,
5
+ # or to provide custom queries or build logic.
6
+ #
7
+ # ******** NOTE ********
8
+ # We have attempted to detect the languages in your repository. Please check
9
+ # the `language` matrix defined below to confirm you have the correct set of
10
+ # supported CodeQL languages.
11
+ #
12
+ name: "CodeQL"
13
+
14
+ on:
15
+ push:
16
+ branches: [ master ]
17
+ pull_request:
18
+ # The branches below must be a subset of the branches above
19
+ branches: [ master ]
20
+ schedule:
21
+ - cron: '43 11 * * 5'
22
+
23
+ jobs:
24
+ analyze:
25
+ name: Analyze
26
+ runs-on: ubuntu-latest
27
+ permissions:
28
+ actions: read
29
+ contents: read
30
+ security-events: write
31
+
32
+ strategy:
33
+ fail-fast: false
34
+ matrix:
35
+ language: [ 'ruby' ]
36
+ # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
37
+ # Learn more about CodeQL language support at https://git.io/codeql-language-support
38
+
39
+ steps:
40
+ - name: Checkout repository
41
+ uses: actions/checkout@v2
42
+
43
+ # Initializes the CodeQL tools for scanning.
44
+ - name: Initialize CodeQL
45
+ uses: github/codeql-action/init@v1
46
+ with:
47
+ languages: ${{ matrix.language }}
48
+ # If you wish to specify custom queries, you can do so here or in a config file.
49
+ # By default, queries listed here will override any specified in a config file.
50
+ # Prefix the list here with "+" to use these queries and those in the config file.
51
+ # queries: ./path/to/local/query, your-org/your-repo/queries@main
52
+
53
+ # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
54
+ # If this step fails, then you should remove it and run the build manually (see below)
55
+ - name: Autobuild
56
+ uses: github/codeql-action/autobuild@v1
57
+
58
+ # ℹ️ Command-line programs to run using the OS shell.
59
+ # 📚 https://git.io/JvXDl
60
+
61
+ # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
62
+ # and modify them (or add more) to build your code if your project
63
+ # uses a compiled language
64
+
65
+ #- run: |
66
+ # make bootstrap
67
+ # make release
68
+
69
+ - name: Perform CodeQL Analysis
70
+ uses: github/codeql-action/analyze@v1
@@ -11,11 +11,12 @@ jobs:
11
11
  strategy:
12
12
  matrix:
13
13
  ruby-version:
14
+ - '3.2'
15
+ - '3.1'
14
16
  - '3.0'
15
- - 2.7
16
- - 2.6
17
+ - '2.7'
17
18
  steps:
18
- - uses: actions/checkout@v2
19
+ - uses: actions/checkout@v3
19
20
  - uses: ruby/setup-ruby@v1
20
21
  with:
21
22
  ruby-version: ${{ matrix.ruby-version }}
@@ -24,9 +25,23 @@ jobs:
24
25
  - run: bundle exec rake build
25
26
  - run: ls -lah ./pkg/apt-spy2*
26
27
  - run: gem install pkg/apt-spy2*
27
- - run: apt-spy2
28
+ - run: apt-spy2 check
28
29
  - uses: coverallsapp/github-action@master
29
30
  with:
30
31
  github-token: ${{ secrets.GITHUB_TOKEN }}
31
32
 
33
+ test_strict:
34
+ runs-on: ubuntu-latest
35
+ steps:
36
+ - uses: actions/checkout@v3
37
+ - uses: ruby/setup-ruby@v1
38
+ with:
39
+ ruby-version: 3.2
40
+ - run: bundle install
41
+ - run: bundle exec rake test
42
+ - run: bundle exec rake build
43
+ - run: ls -lah ./pkg/apt-spy2*
44
+ - run: gem install pkg/apt-spy2*
45
+ - run: apt-spy2 check --strict
46
+
32
47
 
@@ -0,0 +1,22 @@
1
+ ---
2
+ name: release
3
+
4
+ on:
5
+ push:
6
+ tags:
7
+ - 'v*'
8
+
9
+ jobs:
10
+ publish:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@v2
14
+ - uses: ruby/setup-ruby@v1
15
+ with:
16
+ ruby-version: 3.0
17
+ - run: bundle install
18
+ - uses: cadwallion/publish-rubygems-action@master
19
+ env:
20
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
21
+ RUBYGEMS_API_KEY: ${{ secrets.RUBYGEMS_API_KEY }}
22
+ RELEASE_COMMAND: bundle exec rake release
data/Dockerfile CHANGED
@@ -1,9 +1,13 @@
1
- FROM ubuntu:18.04
1
+ FROM ubuntu:22.10
2
2
 
3
- RUN apt-get update -y \
4
- && apt-get install -y ruby ruby-dev git gcc g++ make zlib1g-dev lsb-release \
5
- && gem install bundler \
6
- && mkdir -p /work
3
+ RUN apt update -y \
4
+ && apt install -y \
5
+ ruby3.0 \
6
+ ruby-dev \
7
+ ruby-bundler \
8
+ git \
9
+ lsb-release \
10
+ build-essential
7
11
 
8
12
  WORKDIR /work
9
13
  COPY . /work
data/Gemfile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source 'https://rubygems.org'
2
4
 
3
5
  gemspec
data/Gemfile.lock CHANGED
@@ -1,23 +1,45 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- apt-spy2 (0.7.2)
4
+ apt-spy2 (0.8.0)
5
5
  colored (>= 1.2)
6
6
  json
7
- nokogiri (>= 1.6, < 1.13)
7
+ nokogiri (~> 1.14.1)
8
8
  thor (>= 0.18.1)
9
9
 
10
10
  GEM
11
11
  remote: https://rubygems.org/
12
12
  specs:
13
+ ast (2.4.2)
13
14
  colored (1.2)
14
15
  docile (1.4.0)
15
- json (2.6.1)
16
+ json (2.6.3)
17
+ mini_portile2 (2.8.1)
16
18
  minitest (5.15.0)
17
- nokogiri (1.12.5-x86_64-darwin)
19
+ nokogiri (1.14.1)
20
+ mini_portile2 (~> 2.8.0)
18
21
  racc (~> 1.4)
19
- racc (1.5.2)
22
+ parallel (1.22.1)
23
+ parser (3.2.1.0)
24
+ ast (~> 2.4.1)
25
+ racc (1.6.2)
26
+ rainbow (3.1.1)
20
27
  rake (13.0.6)
28
+ regexp_parser (2.7.0)
29
+ rexml (3.2.5)
30
+ rubocop (1.45.1)
31
+ json (~> 2.3)
32
+ parallel (~> 1.10)
33
+ parser (>= 3.2.0.0)
34
+ rainbow (>= 2.2.2, < 4.0)
35
+ regexp_parser (>= 1.8, < 3.0)
36
+ rexml (>= 3.2.5, < 4.0)
37
+ rubocop-ast (>= 1.24.1, < 2.0)
38
+ ruby-progressbar (~> 1.7)
39
+ unicode-display_width (>= 2.4.0, < 3.0)
40
+ rubocop-ast (1.24.1)
41
+ parser (>= 3.1.1.0)
42
+ ruby-progressbar (1.11.0)
21
43
  simplecov (0.21.2)
22
44
  docile (~> 1.1)
23
45
  simplecov-html (~> 0.11)
@@ -25,7 +47,8 @@ GEM
25
47
  simplecov-html (0.12.3)
26
48
  simplecov-lcov (0.8.0)
27
49
  simplecov_json_formatter (0.1.3)
28
- thor (1.1.0)
50
+ thor (1.2.1)
51
+ unicode-display_width (2.4.2)
29
52
 
30
53
  PLATFORMS
31
54
  ruby
@@ -35,6 +58,7 @@ DEPENDENCIES
35
58
  bundler (~> 2.0)
36
59
  minitest (~> 5.15.0)
37
60
  rake
61
+ rubocop
38
62
  simplecov (~> 0.18)
39
63
  simplecov-lcov (~> 0.8.0)
40
64
 
data/Makefile CHANGED
@@ -1,11 +1,29 @@
1
+ .PHONY: clean install release docker-build docker-run
2
+
3
+ IMAGE?=lagged/apt-spy2:dev
4
+
5
+ container:=apt-spy2
6
+
7
+ clean:
8
+ docker rm -f $(container) || true
9
+
1
10
  install:
2
11
  bundle install --path ./vendor/bundle
3
12
 
4
13
  release:
5
14
  bundle exec rake release
6
15
 
16
+ lint:
17
+ bundle exec rubocop .
18
+
19
+ test: install
20
+ bundle exec rake test
21
+
7
22
  docker-build:
8
- docker build -t lagged/apt-spy2:dev .
23
+ docker build -t $(IMAGE) .
9
24
 
10
- docker-run: docker-build
11
- docker run -it lagged/apt-spy2:dev bash
25
+ docker-run: clean docker-build
26
+ docker run --rm -it \
27
+ --name $(container) \
28
+ -v $(CURDIR):/work \
29
+ $(IMAGE) bash
data/README.md CHANGED
@@ -44,13 +44,14 @@ $ apt-spy2 list --launchpad --country=Germany
44
44
 
45
45
  ### check command
46
46
 
47
- `check` works like `list`, but also determines if the servers returned are working. It supports Launchpad as well.
47
+ `check` works like `list`, but also determines if the servers returned are working. It supports the flag `--launchpad` as well and additionally a flag `--strict` which checks if a mirror carries a certain release and distribution.
48
48
 
49
49
  ```
50
50
  $ apt-spy2 check
51
51
  ...
52
- $ apt-spy2 list --launchpad --country=US
52
+ $ apt-spy2 check --launchpad --country=US
53
53
  ...
54
+ $ apt-spy2 check --strict
54
55
  ```
55
56
 
56
57
  ### fix command
@@ -81,3 +82,9 @@ Generally, `apt-spy2` plays especially nice in a non-interactive environment and
81
82
  ## License
82
83
 
83
84
  [New BSD License](http://opensource.org/licenses/BSD-2-Clause)
85
+
86
+ ### Release (procedure)
87
+
88
+ - update version in `lib/apt/spy2/version.rb`
89
+ - `bundle install`
90
+ - `git commit -a -m 'New release' && git tag -a vVERSION && git push --tags`
data/Rakefile CHANGED
@@ -1,24 +1,17 @@
1
- require "bundler/gem_tasks"
2
- require "minitest/autorun"
3
- require "simplecov"
4
- require "simplecov-lcov"
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rake/testtask'
5
5
 
6
6
  Encoding.default_external = Encoding::UTF_8
7
7
  Encoding.default_internal = Encoding::UTF_8
8
8
 
9
- task :test do
9
+ Rake::TestTask.new do |t|
10
10
  ENV['COVERAGE'] = 'true'
11
+ t.pattern = 'tests/*_test.rb'
11
12
 
12
- SimpleCov.formatter = SimpleCov::Formatter::LcovFormatter
13
- SimpleCov::Formatter::LcovFormatter.config do |c|
14
- c.output_directory = './coverage'
15
- c.report_with_single_file = true
16
- c.single_report_path = './coverage/lcov.info'
17
- end
18
- SimpleCov.start
19
-
20
- $LOAD_PATH.unshift('lib', 'tests')
21
- Dir.glob('./tests/*_test.rb') do |f|
22
- require f
23
- end
13
+ # $LOAD_PATH.unshift('lib', 'tests')
14
+ # Dir.glob('./tests/*_test.rb').sort.each do |f|
15
+ # require f
16
+ # end
24
17
  end
data/apt-spy2.gemspec CHANGED
@@ -1,31 +1,36 @@
1
- # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
1
+ # frozen_string_literal: true
2
+
3
+ # require 'English'
4
+ lib = File.expand_path('lib', __dir__)
3
5
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
6
  require 'apt/spy2/version'
5
7
 
6
8
  Gem::Specification.new do |spec|
7
- spec.name = "apt-spy2"
9
+ spec.name = 'apt-spy2'
8
10
  spec.version = Apt::Spy2::VERSION
9
- spec.authors = ["till"]
10
- spec.email = ["till@php.net"]
11
- spec.description = "Keep your /etc/apt/sources.list up to date"
12
- spec.summary = "apt-spy2, or apt-spy for ubuntu"
13
- spec.homepage = "https://github.com/lagged/apt-spy2"
11
+ spec.authors = ['till']
12
+ spec.email = ['till@php.net']
13
+ spec.description = 'Keep your /etc/apt/sources.list up to date'
14
+ spec.summary = 'apt-spy2, or apt-spy for ubuntu'
15
+ spec.homepage = 'https://github.com/lagged/apt-spy2'
14
16
  spec.license = 'BSD-2-Clause'
15
17
 
16
- spec.files = `git ls-files`.split($/)
18
+ spec.required_ruby_version = '>= 2.7', '< 3.3'
19
+
20
+ spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
17
21
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
22
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
- spec.require_paths = ["lib"]
23
+ spec.require_paths = ['lib']
20
24
 
21
- spec.add_dependency 'thor', '>= 0.18.1'
22
25
  spec.add_dependency 'colored', '>= 1.2'
23
26
  spec.add_dependency 'json'
24
- spec.add_dependency 'nokogiri', '>= 1.6', '< 1.13'
27
+ spec.add_dependency 'nokogiri', '~> 1.14.1'
28
+ spec.add_dependency 'thor', '>= 0.18.1'
25
29
 
26
- spec.add_development_dependency "bundler", "~> 2.0"
27
- spec.add_development_dependency "rake"
28
- spec.add_development_dependency "minitest", "~> 5.15.0"
29
- spec.add_development_dependency "simplecov", "~> 0.18"
30
- spec.add_development_dependency "simplecov-lcov", "~> 0.8.0"
30
+ spec.add_development_dependency 'bundler', '~> 2.0'
31
+ spec.add_development_dependency 'minitest', '~> 5.15.0'
32
+ spec.add_development_dependency 'rake'
33
+ spec.add_development_dependency 'rubocop'
34
+ spec.add_development_dependency 'simplecov', '~> 0.18'
35
+ spec.add_development_dependency 'simplecov-lcov', '~> 0.8.0'
31
36
  end
data/bin/apt-spy2 CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'apt/spy2'
4
5
  require 'colored'
@@ -8,7 +9,7 @@ Encoding.default_internal = Encoding::UTF_8
8
9
 
9
10
  begin
10
11
  AptSpy2.start
11
- rescue => the_error
12
- puts the_error.to_s.white_on_red
12
+ rescue StandardError => e
13
+ puts e.to_s.white_on_red
13
14
  exit 1
14
15
  end
@@ -1,33 +1,32 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Apt
2
4
  module Spy2
5
+ # lookup a country based on code
3
6
  class Country
4
-
5
7
  def initialize(country_database)
6
8
  @database = country_database
7
9
  end
8
10
 
9
11
  def to_country_name(code)
10
12
  code = code.upcase
11
- return capitalize(code) unless code.length == 2
13
+ return capitalize!(code) unless code.length == 2
12
14
 
13
15
  File.open(@database).each do |line|
14
16
  country, tld = line.split(';', 2)
15
17
  tld.gsub!(/\n/, '')
16
18
 
17
- if code == tld
18
- return capitalize(country)
19
- end
20
-
19
+ return capitalize!(country) if code == tld
21
20
  end
22
21
 
23
22
  raise "Could not look up: #{code}"
24
23
  end
25
24
 
26
25
  private
27
- def capitalize(str)
28
- return str.split(" ").map(&:capitalize).join(" ")
29
- end
30
26
 
27
+ def capitalize!(str)
28
+ str.split(' ').map(&:capitalize).join(' ')
29
+ end
31
30
  end
32
31
  end
33
32
  end
@@ -1,30 +1,27 @@
1
- require 'open-uri'
1
+ # frozen_string_literal: true
2
+
3
+ require 'apt/spy2/request'
2
4
 
3
5
  module Apt
4
6
  module Spy2
7
+ # download url (e.g. mirror list or launchpad page)
5
8
  class Downloader
6
-
7
- def initialize(url = nil)
8
- @url = url if !url.nil?
9
- end
10
-
11
9
  def do_download(url = nil)
12
- @url = url if !url.nil?
10
+ raise 'Please supply a url.' if url.nil?
13
11
 
14
- raise "Please supply a url." if url.nil?
12
+ req = Apt::Spy2::Request.new(url)
15
13
 
16
14
  begin
17
- return open(@url).read
18
- rescue OpenURI::HTTPError => the_error
19
- case the_error.io.status[0]
20
- when "404"
21
- raise "The URL #{@url} does not exist."
22
- else
23
- raise "Status: #{the_error.io.status[0]}"
24
- end
15
+ response = req.get
16
+ return response.body if response.code == '200'
17
+
18
+ raise "The URL #{@url} does not exist." if response.code == '404'
19
+
20
+ raise "Status code: #{response.code}"
21
+ rescue StandardError => e
22
+ raise e
25
23
  end
26
24
  end
27
-
28
25
  end
29
26
  end
30
27
  end
@@ -1,15 +1,16 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'nokogiri'
2
4
 
3
5
  module Apt
4
6
  module Spy2
7
+ # parse launchpad output
5
8
  class Launchpad
6
-
7
9
  def initialize(download)
8
10
  @launchpad = download
9
11
  end
10
12
 
11
- def get_mirrors(country)
12
-
13
+ def mirrors(country)
13
14
  mirrors = []
14
15
 
15
16
  document = Nokogiri::HTML(@launchpad)
@@ -27,10 +28,8 @@ module Apt
27
28
  end
28
29
  end
29
30
 
30
- return mirrors
31
-
31
+ mirrors
32
32
  end
33
-
34
33
  end
35
34
  end
36
35
  end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'net/http'
4
+ require 'net/https'
5
+ require 'uri'
6
+
7
+ module Apt
8
+ module Spy2
9
+ # make requests
10
+ class Request
11
+ def initialize(url)
12
+ uri = URI(url)
13
+
14
+ http = Net::HTTP.new(uri.host, uri.port)
15
+ http.use_ssl = true if uri.scheme == 'https'
16
+
17
+ @http = http
18
+ @request_uri = uri.request_uri
19
+ end
20
+
21
+ def get
22
+ @http.request(Net::HTTP::Get.new(@request_uri))
23
+ end
24
+
25
+ def head
26
+ @http.request(Net::HTTP::Head.new(@request_uri))
27
+ end
28
+ end
29
+ end
30
+ end
@@ -1,19 +1,17 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Apt
2
4
  module Spy2
5
+ # wraps around the \n delimited list of mirrors
3
6
  class UbuntuMirrors
4
-
5
7
  def initialize(download)
6
8
  @ubuntu_mirrors = download
7
9
  end
8
10
 
9
- def get_mirrors(country)
10
-
11
+ def mirrors(_country)
11
12
  mirrors = @ubuntu_mirrors
12
- mirrors = mirrors.split(/\n/)
13
- return mirrors
14
-
13
+ mirrors.split(/\n/)
15
14
  end
16
-
17
15
  end
18
16
  end
19
17
  end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Apt
4
+ module Spy2
5
+ # build mirror url
6
+ class Url
7
+ def initialize(strict)
8
+ @strict = strict
9
+ end
10
+
11
+ def adjust!(mirror)
12
+ return mirror unless @strict
13
+
14
+ "#{mirror}dists/#{release}/Contents-#{arch}.gz"
15
+ end
16
+
17
+ private
18
+
19
+ def arch
20
+ `dpkg --print-architecture`.strip
21
+ end
22
+
23
+ def release
24
+ `lsb_release -c`.split(' ')[1].strip
25
+ end
26
+ end
27
+ end
28
+ end
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Apt
2
4
  module Spy2
3
- VERSION = "0.7.2"
5
+ VERSION = '0.8.0'
4
6
  end
5
7
  end
@@ -1,20 +1,20 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'colored'
2
4
  require 'json'
3
5
 
4
6
  module Apt
5
7
  module Spy2
8
+ # abstracted puts or json
6
9
  class Writer
7
10
  def initialize(format)
8
-
9
- if !["json", "shell"].include?(format)
10
- raise "Unknown format: #{format}"
11
- end
11
+ raise "Unknown format: #{format}" unless %w[json shell].include?(format)
12
12
 
13
13
  @format = format
14
14
  @complete = []
15
15
  end
16
16
 
17
- def set_complete(complete)
17
+ def complete(complete)
18
18
  @complete = complete
19
19
  end
20
20
 
@@ -24,32 +24,29 @@ module Apt
24
24
  return
25
25
  end
26
26
 
27
- print "Mirror: #{data["mirror"]} - "
27
+ print "Mirror: #{data['mirror']} - "
28
28
 
29
- case data["status"]
30
- when "up"
31
- puts data["status"].upcase.green
32
- when "down"
33
- puts data["status"].upcase.red
34
- when "broken"
35
- puts data["status"].upcase.yellow
29
+ case data['status']
30
+ when 'up'
31
+ puts data['status'].upcase.green
32
+ when 'down'
33
+ puts data['status'].upcase.red
34
+ when 'broken'
35
+ puts data['status'].upcase.yellow
36
36
  else
37
- puts "Unknown status: #{data["status"]}".white_on_red
37
+ puts "Unknown status: #{data['status']}".white_on_red
38
38
  end
39
39
  end
40
40
 
41
41
  def json?
42
- if @format == 'json'
43
- return true
44
- end
42
+ return true if @format == 'json'
45
43
 
46
- return false
44
+ false
47
45
  end
48
46
 
49
- def to_json
47
+ def to_json(*_args)
50
48
  JSON.generate(@complete)
51
49
  end
52
-
53
50
  end
54
51
  end
55
52
  end
data/lib/apt/spy2.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'thor'
2
4
  require 'open-uri'
3
5
  require 'colored'
@@ -7,116 +9,126 @@ require 'apt/spy2/country'
7
9
  require 'apt/spy2/downloader'
8
10
  require 'apt/spy2/ubuntu_mirrors'
9
11
  require 'apt/spy2/launchpad'
12
+ require 'apt/spy2/request'
13
+ require 'apt/spy2/url'
10
14
 
15
+ # apt-spy2 command interface
11
16
  class AptSpy2 < Thor
12
- package_name "apt-spy2"
17
+ package_name 'apt-spy2'
18
+ class_option :country, default: 'mirrors'
19
+ class_option :launchpad, type: :boolean, banner: "Use launchpad's mirror list"
13
20
 
14
- desc "fix", "Set the closest/fastest mirror"
15
- option :country, :default => "mirrors"
16
- option :commit, :type => :boolean
17
- option :launchpad, :type => :boolean, :banner => "Use launchpad's mirror list"
21
+ desc 'fix', 'Set the closest/fastest mirror'
22
+ option :commit, type: :boolean
23
+ option :strict, type: :boolean
18
24
  def fix
19
- working = filter(retrieve(options[:country], use_launchpad?(options)), false)
20
- print "The closest mirror is: "
21
- puts "#{working[0]}".bold.magenta
22
- if !options[:commit]
23
- puts "Run with --commit to adjust /etc/apt/sources.list".yellow
24
- else
25
- puts "Updating /etc/apt/sources.list".yellow
26
- update(working[0])
25
+ mirrors = retrieve(options[:country], use_launchpad?(options))
26
+ working = filter(mirrors, options[:strict], false)
27
+ print 'The closest mirror is: '
28
+ puts (working[0]).to_s.bold.magenta
29
+ unless options[:commit]
30
+ puts 'Run with --commit to adjust /etc/apt/sources.list'.yellow
31
+ return
27
32
  end
33
+
34
+ puts 'Updating /etc/apt/sources.list'.yellow
35
+ update(working[0])
28
36
  end
29
37
 
30
- desc "check", "Evaluate mirrors"
31
- option :country, :default => "mirrors"
32
- option :output, :type => :boolean, :default => true
33
- option :format, :default => "shell"
34
- option :launchpad, :type => :boolean, :banner => "Use launchpad's mirror list"
38
+ desc 'check', 'Evaluate mirrors'
39
+ option :output, type: :boolean, default: true
40
+ option :format, default: 'shell'
41
+ option :strict, type: :boolean
35
42
  def check
36
-
37
43
  @writer = Apt::Spy2::Writer.new(options[:format])
38
44
 
39
45
  mirrors = retrieve(options[:country], use_launchpad?(options))
40
- filter(mirrors, options[:output])
46
+ filter(mirrors, options[:strict], options[:output])
41
47
 
42
48
  puts @writer.to_json if @writer.json?
43
49
  end
44
50
 
45
- desc "list", "List the currently available mirrors"
46
- option :country, :default => "mirrors"
47
- option :format, :default => "shell"
48
- option :launchpad, :type => :boolean, :banner => "Use launchpad's mirror list"
51
+ desc 'list', 'List the currently available mirrors'
52
+ option :format, default: 'shell'
49
53
  def list
50
54
  mirrors = retrieve(options[:country], use_launchpad?(options))
51
55
 
52
56
  @writer = Apt::Spy2::Writer.new(options[:format])
53
57
 
54
- @writer.set_complete(mirrors)
58
+ @writer.complete(mirrors)
55
59
 
56
60
  puts @writer.to_json if @writer.json?
57
- puts mirrors if !@writer.json?
61
+ puts mirrors unless @writer.json?
58
62
  end
59
63
 
60
- desc "version", "Show which version of apt-spy2 is installed"
64
+ desc 'version', 'Show which version of apt-spy2 is installed'
61
65
  def version
62
66
  puts Apt::Spy2::VERSION
63
67
  exit
64
68
  end
65
69
 
66
70
  private
67
- def retrieve(country = "mirrors", launchpad = false)
68
71
 
72
+ def retrieve(country = 'mirrors', launchpad = false)
69
73
  downloader = Apt::Spy2::Downloader.new
70
74
 
71
- if launchpad === true
72
- csv_path = File.expand_path(File.dirname(__FILE__) + "/../../var/country-names.txt")
75
+ if launchpad
76
+ csv_path = File.expand_path("#{File.dirname(__FILE__)}/../../var/country-names.txt")
73
77
  country = Apt::Spy2::Country.new(csv_path)
74
78
  name = country.to_country_name(options[:country])
75
79
 
76
80
  launchpad = Apt::Spy2::Launchpad.new(downloader.do_download('https://launchpad.net/ubuntu/+archivemirrors'))
77
- return launchpad.get_mirrors(name)
81
+ return launchpad.mirrors(name)
78
82
  end
79
83
 
80
84
  country.upcase! if country.length == 2
81
85
 
82
86
  ubuntu_mirrors = Apt::Spy2::UbuntuMirrors.new(downloader.do_download("http://mirrors.ubuntu.com/#{country}.txt"))
83
- mirrors = ubuntu_mirrors.get_mirrors(country)
84
- return mirrors
85
-
87
+ ubuntu_mirrors.mirrors(country)
86
88
  end
87
89
 
88
- private
89
- def filter(mirrors, output = true)
90
+ def filter(mirrors, strict = false, output = true)
90
91
  # f me :)
91
92
 
92
93
  working_mirrors = []
93
94
 
95
+ url = Apt::Spy2::Url.new(strict)
96
+
94
97
  mirrors.each do |mirror|
95
- data = {"mirror" => mirror }
96
- begin
97
- open(mirror)
98
- data["status"] = "up"
99
- working_mirrors << mirror
100
- rescue OpenURI::HTTPError
101
- data["status"] = "broken"
102
- rescue
103
- # this is a catch-all for everything else
104
- data["status"] = "down"
105
- end
98
+ data = { 'mirror' => mirror }
99
+
100
+ check = url.adjust!(mirror)
101
+
102
+ status = broken?(check)
103
+
104
+ data['status'] = status
105
+
106
+ working_mirrors << mirror if status == 'up'
106
107
 
107
108
  @writer.echo(data) if output
108
109
  end
109
110
 
110
- return working_mirrors
111
+ working_mirrors
112
+ end
113
+
114
+ def broken?(url)
115
+ begin
116
+ req = Apt::Spy2::Request.new(url)
117
+ response = req.head
118
+ return 'up' if response.code == '200'
119
+
120
+ return 'broken' if response.code == '404'
121
+ rescue StandardError
122
+ # connection errors, ssl errors, etc.
123
+ end
111
124
 
125
+ 'down'
112
126
  end
113
127
 
114
- private
115
128
  def update(mirror)
116
-
117
129
  t = Time.now
118
- r = `lsb_release -c`.split(" ")[1]
119
- sources = "## Updated on #{t.to_s} by apt-spy2\n"
130
+ r = `lsb_release -c`.split(' ')[1]
131
+ sources = "## Updated on #{t} by apt-spy2\n"
120
132
  sources << "deb #{mirror} #{r} main restricted universe multiverse\n"
121
133
  sources << "deb #{mirror} #{r}-updates main restricted universe multiverse\n"
122
134
  sources << "deb #{mirror} #{r}-backports main restricted universe multiverse\n"
@@ -129,26 +141,23 @@ class AptSpy2 < Thor
129
141
  File.open(apt_sources, 'w') do |f|
130
142
  f.write(sources)
131
143
  end
132
- rescue
144
+ rescue StandardError
133
145
  msg = "Failed updating #{apt_sources}!"
134
- msg << "You probably need sudo!"
146
+ msg << 'You probably need sudo!'
135
147
  raise msg
136
148
  end
137
149
 
138
150
  puts "Updated '#{apt_sources}' with #{mirror}".green
139
- puts "Run `apt-get update` to update".black_on_yellow
151
+ puts 'Run `apt-get update` to update'.black_on_yellow
140
152
  end
141
153
 
142
- private
143
154
  def use_launchpad?(options)
144
- if !options[:launchpad]
145
- return false
146
- end
155
+ return false unless options[:launchpad]
147
156
 
148
157
  if options[:country] && options[:country] == 'mirrors'
149
- raise "Please supply a `--country=foo`. Launchpad cannot guess!"
158
+ raise 'Please supply a `--country=foo`. Launchpad cannot guess!'
150
159
  end
151
160
 
152
- return true
161
+ true
153
162
  end
154
163
  end
data/test_helper.rb ADDED
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'simplecov'
4
+ require 'simplecov-lcov'
5
+
6
+ if ENV['CI']
7
+ SimpleCov.formatter = SimpleCov::Formatter::LcovFormatter
8
+ SimpleCov::Formatter::LcovFormatter.config do |c|
9
+ c.output_directory = './coverage'
10
+ c.report_with_single_file = true
11
+ c.single_report_path = './coverage/lcov.info'
12
+ end
13
+ else
14
+ SimpleCov.formatter SimpleCov::Formatter::MultiFormatter.new([
15
+ SimpleCov::Formatter::SimpleFormatter,
16
+ SimpleCov::Formatter::HTMLFormatter
17
+ ])
18
+ end
19
+
20
+ SimpleCov.profiles.define 'apt-spy2' do
21
+ add_filter '/tests/'
22
+ add_filter '/pkg/'
23
+ add_filter '/vendor/'
24
+ add_filter '/var'
25
+
26
+ add_group 'lib', 'lib/apt'
27
+ add_group 'bin', 'bin'
28
+ end
29
+ SimpleCov.start 'apt-spy2'
30
+ require 'minitest/autorun'
@@ -1,12 +1,15 @@
1
- require 'apt/spy2/country'
1
+ # frozen_string_literal: true
2
2
 
3
+ require_relative '../test_helper'
4
+ require_relative '../lib/apt/spy2/country'
5
+
6
+ # test the name resolution
3
7
  class CountryTest < Minitest::Test
4
8
  def setup
5
- @country_list = File.expand_path(File.dirname(__FILE__) + "/../var/country-names.txt")
9
+ @country_list = File.expand_path("#{File.dirname(__FILE__)}/../var/country-names.txt")
6
10
  end
7
11
 
8
- def test_tld_to_name()
9
-
12
+ def test_tld_to_name
10
13
  # fixtures for people who don't want to read about rails
11
14
  data = {
12
15
  'de' => 'Germany',
@@ -22,6 +25,5 @@ class CountryTest < Minitest::Test
22
25
  data.each_pair do |code, expected|
23
26
  assert_equal(expected, c.to_country_name(code))
24
27
  end
25
-
26
28
  end
27
29
  end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../test_helper'
4
+ require_relative '../lib/apt/spy2/downloader'
5
+
6
+ # this is an integration test (needs interwebs)
7
+ class DownloaderTest < Minitest::Test
8
+ def test_do
9
+ downloader = Apt::Spy2::Downloader.new
10
+ data = downloader.do_download('http://mirrors.ubuntu.com/DE.txt')
11
+ assert(!data.empty?, 'There should have been a response, unless the mirrors are down.')
12
+ end
13
+
14
+ def test_do_wrong_countrys
15
+ downloader = Apt::Spy2::Downloader.new
16
+ assert_raises(RuntimeError) { downloader.do_download('http://mirrors.ubuntu.com/de.txt') }
17
+ end
18
+ end
@@ -1,13 +1,17 @@
1
- require 'apt/spy2/launchpad'
1
+ # frozen_string_literal: true
2
2
 
3
+ require_relative '../test_helper'
4
+ require_relative '../lib/apt/spy2/launchpad'
5
+
6
+ # test to confirm launchpad format (HTML) is parsed
3
7
  class LaunchpadTest < Minitest::Test
4
8
  def setup
5
- @download_fixture = File.read(File.expand_path(File.dirname(__FILE__) + "/fixtures/launchpad.html"))
9
+ @download_fixture = File.read(File.expand_path("#{File.dirname(__FILE__)}/fixtures/launchpad.html"))
6
10
  end
7
11
 
8
12
  def test_german_mirrors
9
13
  lp = Apt::Spy2::Launchpad.new(@download_fixture)
10
- mirrors = lp.get_mirrors('Germany')
14
+ mirrors = lp.mirrors('Germany')
11
15
  assert_equal(false, mirrors.empty?)
12
16
  end
13
17
  end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../test_helper'
4
+ require_relative '../lib/apt/spy2/ubuntu_mirrors'
5
+
6
+ # test to confirm launchpad format (HTML) is parsed
7
+ class UbuntuMirrorsTest < Minitest::Test
8
+ def test_mirrors
9
+ expected = ['http://example.org', 'http://example.de']
10
+ fixture = expected.join("\n")
11
+
12
+ m = Apt::Spy2::UbuntuMirrors.new(fixture)
13
+ assert_equal(expected, m.mirrors('country'))
14
+ end
15
+ end
data/tests/url_test.rb ADDED
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../test_helper'
4
+ require_relative '../lib/apt/spy2/url'
5
+
6
+ # test to check request lib
7
+ class UrlTest < Minitest::Test
8
+ def test_non_strict
9
+ expected = 'http://example.org'
10
+
11
+ url = Apt::Spy2::Url.new(false)
12
+ assert_equal(expected, url.adjust!(expected))
13
+ end
14
+
15
+ # def strict
16
+ # skip "Test only runs on ubuntu" if OS.unix? and not OS.mac?
17
+
18
+ # expected = 'http://example.org'
19
+
20
+ # url = Apt::Spy2::Url.new(true)
21
+ # assert_not_equal(expected, url.mirror)
22
+ # end
23
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../test_helper'
4
+ require_relative '../lib/apt/spy2/writer'
5
+ require 'json'
6
+
7
+ # test to check request lib
8
+ class WriterTest < Minitest::Test
9
+ def test_json
10
+ fixture = { 'mirror': 'http://example.org', 'status': 'up' }
11
+
12
+ w = Apt::Spy2::Writer.new('json')
13
+ w.echo(fixture)
14
+
15
+ # json string
16
+ j = w.to_json
17
+
18
+ assert_equal(true, w.json?)
19
+ assert_equal(true, j.is_a?(String))
20
+ assert_equal(true, JSON.parse(j).is_a?(Array))
21
+ end
22
+
23
+ def test_no_json
24
+ w = Apt::Spy2::Writer.new('shell')
25
+ assert_equal(false, w.json?)
26
+ end
27
+ end
metadata CHANGED
@@ -1,77 +1,71 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: apt-spy2
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.2
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - till
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-12-22 00:00:00.000000000 Z
11
+ date: 2023-02-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: thor
14
+ name: colored
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 0.18.1
19
+ version: '1.2'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: 0.18.1
26
+ version: '1.2'
27
27
  - !ruby/object:Gem::Dependency
28
- name: colored
28
+ name: json
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '1.2'
33
+ version: '0'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '1.2'
40
+ version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: json
42
+ name: nokogiri
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ">="
45
+ - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '0'
47
+ version: 1.14.1
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ">="
52
+ - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '0'
54
+ version: 1.14.1
55
55
  - !ruby/object:Gem::Dependency
56
- name: nokogiri
56
+ name: thor
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - ">="
60
60
  - !ruby/object:Gem::Version
61
- version: '1.6'
62
- - - "<"
63
- - !ruby/object:Gem::Version
64
- version: '1.13'
61
+ version: 0.18.1
65
62
  type: :runtime
66
63
  prerelease: false
67
64
  version_requirements: !ruby/object:Gem::Requirement
68
65
  requirements:
69
66
  - - ">="
70
67
  - !ruby/object:Gem::Version
71
- version: '1.6'
72
- - - "<"
73
- - !ruby/object:Gem::Version
74
- version: '1.13'
68
+ version: 0.18.1
75
69
  - !ruby/object:Gem::Dependency
76
70
  name: bundler
77
71
  requirement: !ruby/object:Gem::Requirement
@@ -86,6 +80,20 @@ dependencies:
86
80
  - - "~>"
87
81
  - !ruby/object:Gem::Version
88
82
  version: '2.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: minitest
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 5.15.0
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 5.15.0
89
97
  - !ruby/object:Gem::Dependency
90
98
  name: rake
91
99
  requirement: !ruby/object:Gem::Requirement
@@ -101,19 +109,19 @@ dependencies:
101
109
  - !ruby/object:Gem::Version
102
110
  version: '0'
103
111
  - !ruby/object:Gem::Dependency
104
- name: minitest
112
+ name: rubocop
105
113
  requirement: !ruby/object:Gem::Requirement
106
114
  requirements:
107
- - - "~>"
115
+ - - ">="
108
116
  - !ruby/object:Gem::Version
109
- version: 5.15.0
117
+ version: '0'
110
118
  type: :development
111
119
  prerelease: false
112
120
  version_requirements: !ruby/object:Gem::Requirement
113
121
  requirements:
114
- - - "~>"
122
+ - - ">="
115
123
  - !ruby/object:Gem::Version
116
- version: 5.15.0
124
+ version: '0'
117
125
  - !ruby/object:Gem::Dependency
118
126
  name: simplecov
119
127
  requirement: !ruby/object:Gem::Requirement
@@ -152,7 +160,9 @@ extra_rdoc_files: []
152
160
  files:
153
161
  - ".dockerignore"
154
162
  - ".github/dependabot.yml"
163
+ - ".github/workflows/codeql-analysis.yml"
155
164
  - ".github/workflows/pr.yml"
165
+ - ".github/workflows/release.yml"
156
166
  - ".gitignore"
157
167
  - ".ruby_version"
158
168
  - CONTRIBUTING.md
@@ -169,12 +179,19 @@ files:
169
179
  - lib/apt/spy2/country.rb
170
180
  - lib/apt/spy2/downloader.rb
171
181
  - lib/apt/spy2/launchpad.rb
182
+ - lib/apt/spy2/request.rb
172
183
  - lib/apt/spy2/ubuntu_mirrors.rb
184
+ - lib/apt/spy2/url.rb
173
185
  - lib/apt/spy2/version.rb
174
186
  - lib/apt/spy2/writer.rb
187
+ - test_helper.rb
175
188
  - tests/country_test.rb
189
+ - tests/downloader_test.rb
176
190
  - tests/fixtures/launchpad.html
177
191
  - tests/launchpad_test.rb
192
+ - tests/ubuntu_mirrors_test.rb
193
+ - tests/url_test.rb
194
+ - tests/writer_test.rb
178
195
  - var/country-names.txt
179
196
  homepage: https://github.com/lagged/apt-spy2
180
197
  licenses:
@@ -188,14 +205,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
188
205
  requirements:
189
206
  - - ">="
190
207
  - !ruby/object:Gem::Version
191
- version: '0'
208
+ version: '2.7'
209
+ - - "<"
210
+ - !ruby/object:Gem::Version
211
+ version: '3.3'
192
212
  required_rubygems_version: !ruby/object:Gem::Requirement
193
213
  requirements:
194
214
  - - ">="
195
215
  - !ruby/object:Gem::Version
196
216
  version: '0'
197
217
  requirements: []
198
- rubygems_version: 3.2.32
218
+ rubygems_version: 3.4.2
199
219
  signing_key:
200
220
  specification_version: 4
201
221
  summary: apt-spy2, or apt-spy for ubuntu