bukin 0.6.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. data/.travis.yml +0 -1
  2. data/Gemfile +2 -0
  3. data/README.md +3 -3
  4. data/bukin.gemspec +2 -2
  5. data/docs/process.md +24 -0
  6. data/lib/bukin.rb +54 -2
  7. data/lib/bukin/bukfile.rb +46 -48
  8. data/lib/bukin/bukget.rb +63 -0
  9. data/lib/bukin/bukkit_dl.rb +45 -0
  10. data/lib/bukin/cli.rb +109 -83
  11. data/lib/bukin/download.rb +16 -0
  12. data/lib/bukin/file_match.rb +33 -0
  13. data/lib/bukin/installer.rb +65 -68
  14. data/lib/bukin/jenkins.rb +47 -0
  15. data/lib/bukin/lockfile.rb +23 -21
  16. data/lib/bukin/resource.rb +17 -0
  17. data/lib/bukin/version.rb +1 -1
  18. data/spec/bukfile_spec.rb +0 -16
  19. data/spec/bukget_spec.rb +56 -0
  20. data/spec/bukkit_dl_spec.rb +50 -0
  21. data/spec/cassettes/Bukin_Bukget/chooses_the_version_with_a_jar_file_when_there_are_multiple_versions.yml +61 -0
  22. data/spec/cassettes/Bukin_Bukget/installs_a_specific_version_of_a_resource.yml +61 -0
  23. data/spec/cassettes/Bukin_Bukget/installs_the_latest_version_of_a_resource.yml +49 -0
  24. data/spec/cassettes/Bukin_Bukget/returns_an_error_when_asked_for_a_file_that_does_not_exist.yml +61 -0
  25. data/spec/cassettes/Bukin_Bukget/returns_an_error_when_asked_for_a_resource_that_doese_not_exist.yml +43 -0
  26. data/spec/cassettes/Bukin_Bukget/returns_an_error_when_asked_for_a_version_that_doese_not_exist.yml +435 -0
  27. data/spec/cassettes/Bukin_BukkitDl/chooses_the_first_file_when_there_are_multiple_files.yml +59 -0
  28. data/spec/cassettes/Bukin_BukkitDl/installs_a_specific_version_of_a_resource.yml +59 -0
  29. data/spec/cassettes/Bukin_BukkitDl/installs_the_latest_version_of_a_resource.yml +59 -0
  30. data/spec/cassettes/Bukin_BukkitDl/returns_an_error_when_asked_for_a_file_that_does_not_exist.yml +59 -0
  31. data/spec/cassettes/Bukin_BukkitDl/returns_an_error_when_asked_for_a_resource_that_doese_not_exist.yml +128 -0
  32. data/spec/cassettes/Bukin_BukkitDl/returns_an_error_when_asked_for_a_version_that_doese_not_exist.yml +128 -0
  33. data/spec/cassettes/Bukin_Jenkins/chooses_the_first_file_when_there_are_multiple_files.yml +50 -0
  34. data/spec/cassettes/Bukin_Jenkins/installs_a_specific_version_of_a_resource.yml +50 -0
  35. data/spec/cassettes/Bukin_Jenkins/installs_the_latest_version_of_a_resource.yml +49 -0
  36. data/spec/cassettes/Bukin_Jenkins/returns_an_error_when_asked_for_a_file_that_does_not_exist.yml +50 -0
  37. data/spec/cassettes/Bukin_Jenkins/returns_an_error_when_asked_for_a_resource_that_doese_not_exist.yml +59 -0
  38. data/spec/cassettes/Bukin_Jenkins/returns_an_error_when_asked_for_a_version_that_does_not_exist.yml +59 -0
  39. data/spec/file_match_spec.rb +39 -0
  40. data/spec/installer_spec.rb +0 -1
  41. data/spec/jenkins_spec.rb +61 -0
  42. data/spec/lockfile_spec.rb +8 -8
  43. data/spec/spec_helper.rb +10 -0
  44. metadata +57 -26
  45. data/lib/bukin/exceptions.rb +0 -5
  46. data/lib/bukin/friendly_errors.rb +0 -22
  47. data/lib/bukin/providers/bukget.rb +0 -54
  48. data/lib/bukin/providers/bukkit_dl.rb +0 -29
  49. data/lib/bukin/providers/jenkins.rb +0 -40
data/.travis.yml CHANGED
@@ -2,5 +2,4 @@ language: ruby
2
2
  rvm:
3
3
  - 2.0.0
4
4
  - 1.9.3
5
- - 1.8.7
6
5
 
data/Gemfile CHANGED
@@ -8,4 +8,6 @@ group :development, :test do
8
8
  gem 'rake', '~> 10.1.0'
9
9
  gem 'coveralls', :require => false
10
10
  gem 'fakefs', '~> 0.4.2', :require => 'fakefs/safe'
11
+ gem 'webmock', '~> 1.15.2'
12
+ gem 'vcr', '~> 2.7.0'
11
13
  end
data/README.md CHANGED
@@ -38,13 +38,13 @@ You can specify specific versions of a plugin or server to install. Craftbukkit
38
38
 
39
39
  By default, bukin will try to download jar files from bukkit dev. If only zip files are available, it will automatically extract all jar files from it. If you want to specify what files are extracted from a zip file, use the `extract` option. It takes a string or [ruby regular expression](http://ruby-doc.org/core-1.9.3/Regexp.html) used to match file names in the zip file.
40
40
 
41
- plugin 'permissionsex', '1.19.5', :extract => /PermissionsEx.*\.jar/
41
+ plugin 'permissionsex', '1.19.5', extract: /PermissionsEx.*\.jar/
42
42
 
43
43
  Plugins or servers can also be downloaded from Jenkins. Just specify the base url for Jenkins and a [ruby regular expression](http://ruby-doc.org/core-1.9.3/Regexp.html) matching the file you want to download. If no file is specified, bukin will download the first one listed.
44
44
 
45
- server 'spigot', 'build-844', :jenkins => 'http://ci.md-5.net', :file => /spigot\.jar/
45
+ server 'spigot', 'build-844', jenkins: 'http://ci.md-5.net', file: /spigot\.jar/
46
46
 
47
47
  Need something custom? Use the `download` option. Version is optional but will display when the plugin is downloading.
48
48
 
49
- plugin 'mycustomplugin', '2.4', :download => 'http://example.com/My-Custom-Plugin.jar'
49
+ plugin 'mycustomplugin', '2.4', download: 'http://example.com/My-Custom-Plugin.jar'
50
50
 
data/bukin.gemspec CHANGED
@@ -17,7 +17,7 @@ Gem::Specification.new do |gem|
17
17
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
18
  gem.require_paths = ['lib']
19
19
 
20
+ gem.required_ruby_version = '>= 1.9.1'
20
21
  gem.add_dependency('thor', '~> 0.18.1')
21
- gem.add_dependency('json', '~> 1.8.0')
22
- gem.add_dependency('rubyzip', '~> 0.9.9')
22
+ gem.add_dependency('rubyzip', '~> 1.1.0')
23
23
  end
data/docs/process.md ADDED
@@ -0,0 +1,24 @@
1
+ Bukin Process
2
+ =============
3
+
4
+ Getting from a fresh Bukfile to having all plugins installed is a rather complex process. This file tries to document it as much as possible.
5
+
6
+ Parse Bukfile
7
+ -------------
8
+
9
+ The Bukfile is evaluated and any errors are presented to the user. Each resource present is constructed into a list of `Resource` objects that will be passed to future steps.
10
+
11
+ Resolve Dependencies
12
+ --------------------
13
+
14
+ All resources are checked for any dependancies that will also need to be installed. At this point, the final version for each `Resource` is recoreded. Any conflicts are reported to the user. During this time, many webservice calls are made to the various sites to confirm information. If the correct version of a resource is already installed, it's excluded from installation.
15
+
16
+ Download Resources
17
+ ------------------
18
+
19
+ All required files from the previous step are downloaded to a temporary folder. If installation is cancelled at this point, no changes will be made to the system. Any compressed files are also extracted.
20
+
21
+ Install Resources
22
+ -----------------
23
+
24
+ All previously downloaded files are copied to the locations specified for installation. All information about installed version is updated in Bukfile.lock and the locations of installed files is stored.
data/lib/bukin.rb CHANGED
@@ -1,7 +1,59 @@
1
1
  require 'bukin/version'
2
2
  require 'bukin/cli'
3
- require 'bukin/friendly_errors'
4
- require 'bukin/exceptions'
3
+ require 'socket'
5
4
 
6
5
  module Bukin
6
+ class BukinError < StandardError; end
7
+ class BukfileError < BukinError; end
8
+ class InstallError < BukinError; end
9
+
10
+ class VersionError < BukinError
11
+ def initialize(name, bad_version, good_version)
12
+ super("The resource #{name} (#{bad_version}) has an improper version. "\
13
+ "It should be in the form of #{good_version}")
14
+ end
15
+ end
16
+
17
+ class NoDownloadError < BukinError
18
+ def initialize(name, version)
19
+ super("The resource '#{name}' has no available downloads listed with "\
20
+ "the version '#{version}'")
21
+ end
22
+ end
23
+
24
+ class MissingProviderError < BukinError
25
+ def initialize(resource)
26
+ super("The #{resource[:type].to_s} '#{resource[:name]}' "\
27
+ "is missing a provider")
28
+ end
29
+ end
30
+
31
+ def self.get_json(url)
32
+ JSON.parse(open(url).read)
33
+ end
34
+
35
+ def self.try_get_json(url)
36
+ get_json(url)
37
+ rescue OpenURI::HTTPError
38
+ nil
39
+ end
40
+
41
+ def self.with_friendly_errors
42
+ yield
43
+ rescue Bukin::BukinError => error
44
+ abort error.message
45
+ rescue SocketError => error
46
+ abort "#{error.message}\nCheck that you have a stable connection and the service is online"
47
+ rescue Errno::ENOENT => error
48
+ abort error.message
49
+ rescue Interrupt
50
+ abort ''
51
+ rescue Exception => error
52
+ puts %Q(
53
+ Oops, Bukin just crashed. Please report this at http://bit.ly/bukin-issues
54
+ Be sure to include as much information as possible such as your Bukfile,
55
+ Bukfile.lock and the stack trace below.
56
+ )
57
+ raise error
58
+ end
7
59
  end
data/lib/bukin/bukfile.rb CHANGED
@@ -1,60 +1,58 @@
1
- class Bukin::Bukfile
2
- FILE_NAME = 'Bukfile'
3
- PROVIDERS = [:download, :jenkins, :bukkit_dl, :bukget]
4
-
5
- attr_reader :path, :resources
6
-
7
- def initialize(path = nil, &block)
8
- @resources = []
9
- @path = path || File.join(Dir.pwd, FILE_NAME)
10
- if block
11
- instance_eval(&block)
12
- else
13
- instance_eval(File.read(@path))
1
+ module Bukin
2
+ class Bukfile
3
+ FILE_NAME = 'Bukfile'
4
+ attr_reader :path, :resources
5
+
6
+ def initialize(path = nil, &block)
7
+ @resources = []
8
+ @path = path || File.join(Dir.pwd, FILE_NAME)
9
+ if block
10
+ instance_eval(&block)
11
+ else
12
+ instance_eval(File.read(@path))
13
+ end
14
14
  end
15
- end
16
15
 
17
- def server(name, *args)
18
- add_resource name, :server, args do |resource|
19
- resource[:bukkit_dl] = Bukin::BukkitDl::DEFAULT_URL
16
+ def server(name, *args)
17
+ add_resource name, :server, args
20
18
  end
21
- end
22
19
 
23
- def plugin(name, *args)
24
- add_resource name, :plugin, args do |resource|
25
- resource[:bukget] = Bukin::Bukget::DEFAULT_URL
20
+ def plugin(name, *args)
21
+ add_resource name, :plugin, args
26
22
  end
23
+
24
+ def to_s
25
+ @reources.map do |resource|
26
+ result = "#{resource[:name]}"
27
+ result << " (#{resource[:version]})" if resource[:version]
28
+ result
29
+ end.join('\n')
27
30
  end
28
31
 
29
- private
30
- def add_resource(name, type, args)
31
- raise(
32
- Bukin::BukinError,
33
- "Error: The #{type} '#{name}' is declared "\
34
- "more than once in your #{FILE_NAME}"
35
- ) if resource_exists?(name, type)
36
-
37
- options = args.last.is_a?(Hash) ? args.pop : {}
38
- version = args.pop || nil
39
-
40
- resource = {
41
- :name => name,
42
- :type => type,
43
- :version => version
44
- }.merge(options)
45
-
46
- # Already have a specific provider assigned?
47
- # If not, yield so that one can be set.
48
- unless PROVIDERS.any? {|key| resource.key?(key)}
49
- yield resource
50
- end
32
+ private
33
+ def add_resource(name, type, args)
34
+ raise(
35
+ Bukin::BukinError,
36
+ "Error: The #{type} '#{name}' is declared "\
37
+ "more than once in your #{FILE_NAME}"
38
+ ) if resource_exists?(name, type)
51
39
 
52
- @resources << resource
53
- end
40
+ options = args.last.is_a?(Hash) ? args.pop : {}
41
+ version = args.pop || nil
42
+
43
+ resource = {
44
+ :name => name,
45
+ :type => type,
46
+ :version => version
47
+ }.merge(options)
48
+
49
+ @resources << resource
50
+ end
54
51
 
55
- def resource_exists?(name, type)
56
- @resources.any? do |resource|
57
- resource[:name] == name && resource[:type] == type
52
+ def resource_exists?(name, type)
53
+ @resources.any? do |resource|
54
+ resource[:name] == name && resource[:type] == type
55
+ end
58
56
  end
59
57
  end
60
58
  end
@@ -0,0 +1,63 @@
1
+ require 'json'
2
+ require 'cgi'
3
+ require 'bukin/file_match'
4
+ require 'bukin/resource'
5
+
6
+ module Bukin
7
+ # BukGet api
8
+ # Docs: http://bukget.org/pages/docs/API3.html
9
+ class Bukget
10
+ attr_reader :url, :server
11
+
12
+ VERSION = 'release'
13
+ URL = 'http://api.bukget.org'
14
+ SERVER = 'bukkit'
15
+
16
+ def initialize(url = URL, server = SERVER)
17
+ @url = url
18
+ @server = server
19
+ end
20
+
21
+ def find(data)
22
+ name = data[:name]
23
+ version = data[:version] || VERSION
24
+ match = data[:file] ? FileMatch.new(data[:file]) : FileMatch.any
25
+
26
+ info = Bukin.try_get_json("#{@url}/3/plugins/#{CGI.escape(@server)}/"\
27
+ "#{CGI.escape(name)}/#{CGI.escape(version)}")
28
+
29
+ raise NoDownloadError.new(name, version) unless info
30
+
31
+ versions = info['versions']
32
+
33
+ if versions.nil? || versions.empty?
34
+ # A couple of plugins don't update the 'version' field correctly but
35
+ # do update the 'dbo_version' field. This attempts to find a
36
+ # downloadable version with the correct 'dbo_version' field
37
+ info = Bukin.get_json("#{@url}/3/plugins/#{CGI.escape(@server)}/"\
38
+ "#{CGI.escape(name)}")
39
+ versions = info['versions'].select do |data|
40
+ data['dbo_version'] == version
41
+ end
42
+
43
+ raise NoDownloadError.new(name, version) if versions.empty?
44
+ end
45
+
46
+ # Filter out any plugins that don't match our file name
47
+ versions = versions.select{|data| match =~ data['filename']}
48
+
49
+ # Some people release two of the same version on bukkit dev,
50
+ # one as a zip package and one with the jar only.
51
+ # This downloads the jar only version by default.
52
+ version_data = versions.find {|data| jar_filename(data)} || versions.first
53
+ raise NoDownloadError.new(name, version) unless version_data
54
+
55
+ return version_data['version'], version_data['download']
56
+ end
57
+
58
+ private
59
+ def jar_filename(data)
60
+ File.extname(data['filename']) == '.jar'
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,45 @@
1
+ require 'json'
2
+ require 'cgi'
3
+
4
+ module Bukin
5
+ # Bukkit download api
6
+ # Docs: http://dl.bukkit.org/about/
7
+ class BukkitDl
8
+ attr_reader :url
9
+
10
+ VERSION = 'latest-rb'
11
+ URL = 'http://dl.bukkit.org'
12
+ GOOD_VERSIONS = "'latest', 'latest-rb', 'latest-beta', 'latest-dev', "\
13
+ "'git-0fd25c4' or 'build-2912'"
14
+
15
+ def initialize(url = URL)
16
+ @url = url
17
+ end
18
+
19
+ def find(data)
20
+ name = data[:name]
21
+ version = data[:version] || VERSION
22
+
23
+ unless correct_version_format?(version)
24
+ raise VersionError.new(name, version, GOOD_VERSIONS)
25
+ end
26
+
27
+ info = Bukin.try_get_json(
28
+ "#{@url}/api/1.0/downloads/projects/"\
29
+ "#{CGI.escape(name)}/view/#{CGI.escape(version)}/")
30
+
31
+ raise NoDownloadError.new(name, version) unless info
32
+
33
+ download = @url + info['file']['url']
34
+
35
+ return "build-#{info['build_number']}", download
36
+ end
37
+
38
+ def correct_version_format?(version)
39
+ 'latest' == version ||
40
+ /^latest-(rb|beta|dev)$/ =~ version ||
41
+ /^git-[0-9a-f]{7,40}$/ =~ version ||
42
+ /^build-[0-9]+$/ =~ version
43
+ end
44
+ end
45
+ end
data/lib/bukin/cli.rb CHANGED
@@ -1,71 +1,85 @@
1
1
  require 'thor'
2
2
  require 'open-uri'
3
+ require 'bukin'
3
4
  require 'bukin/installer'
4
5
  require 'bukin/bukfile'
5
- require 'bukin/providers/bukget'
6
- require 'bukin/providers/bukkit_dl'
7
- require 'bukin/providers/jenkins'
8
-
9
- class Bukin::CLI < Thor
10
- PROVIDERS = {
11
- :bukkit_dl => Bukin::BukkitDl,
12
- :bukget => Bukin::Bukget,
13
- :jenkins => Bukin::Jenkins
14
- }
15
-
16
- desc 'install [NAMES]', "Download and install the resources specified in a "\
17
- "Bukfile.\nOptionally specify the names of specific "\
18
- "plugins to install."
19
- def install(*names)
20
- # Parse in the Bukfile
21
- raw_resources = parse_resources(names)
22
-
23
- # Get all the informatin needed to install
24
- resources = prepare_resources(raw_resources)
25
-
26
- # Download and install all resources
27
- install_resources(resources)
28
- end
6
+ require 'bukin/bukget'
7
+ require 'bukin/bukkit_dl'
8
+ require 'bukin/jenkins'
9
+ require 'bukin/download'
10
+
11
+ module Bukin
12
+ class CLI < Thor
13
+ desc 'install [NAMES]', "Download and install the resources specified in a "\
14
+ "Bukfile.\nOptionally specify the names of specific "\
15
+ "plugins to install."
16
+ def install(*names) # Parse in the Bukfile
17
+ raw_resources = parse_resources(names)
18
+
19
+ # Get all the informatin needed to install
20
+ resources = prepare_resources(raw_resources)
21
+
22
+ # Download and install all resources
23
+ install_resources(resources)
24
+ end
29
25
 
30
- def help(*)
31
- shell.say "Bukin is a plugin and server package manager for Minecraft.\n"
32
- super
33
- end
26
+ def help(*)
27
+ shell.say "Bukin is a plugin and server package manager for Minecraft.\n"
28
+ super
29
+ end
34
30
 
35
- private
36
- def parse_resources(names)
37
- resources = section('Parsing Bukfile') {Bukin::Bukfile.new.resources}
31
+ private
32
+ def parse_resources(names)
33
+ resources = section('Parsing Bukfile') {Bukin::Bukfile.new.resources}
38
34
 
39
- # If name are specified, only install resources with those names
40
- resources.select! {|resource| names.include?(resource[:name])} if names.any?
41
- raise Bukin::BukinError, "Nothing to install" if resources.empty?
35
+ # If name are specified, only install resources with those names
36
+ resources.select! {|resource| names.include?(resource[:name])} if names.any?
37
+ raise Bukin::BukinError, "Nothing to install" if resources.empty?
42
38
 
43
- resources
44
- end
39
+ resources
40
+ end
45
41
 
46
- def prepare_resources(raw_resources)
47
- downloads = {}
48
- final_resources = []
42
+ def prepare_resources(raw_resources)
43
+ downloads = {}
44
+ final_resources = []
49
45
 
50
- raw_resources.each do |resource|
51
- name, provider = PROVIDERS.find {|name, p| resource[name]}
52
- next unless name
46
+ raw_resources.group_by {|data| get_provider(data)}.each do |name, datas|
47
+ datas.group_by {|data| data[name]}.each do |url, data|
48
+ downloads[PROVIDERS[name].new(url)] = data
49
+ end
50
+ end
51
+
52
+ downloads.each do |provider, datas|
53
+ fetching provider do
54
+ datas.each do |data|
55
+ begin
56
+ version, download = provider.find(data)
57
+ final_resources << Resource.new(data, version, download)
58
+ rescue OpenURI::HTTPError => ex
59
+ raise Bukin::BukinError,
60
+ "There was an error fetching information about "\
61
+ "'#{data[:name]} (#{data[:version]})'.\n"\
62
+ "#{ex.message}"
63
+ end
64
+ end
65
+ end
66
+ end
53
67
 
54
- url = resource[name]
55
- downloads[url] ||= []
56
- downloads[url] << provider.new(resource)
68
+ final_resources
57
69
  end
58
70
 
59
- downloads.each do |url, resources|
60
- section "Fetching information from #{url}" do
61
- resources.each do |resource|
71
+ def install_resources(resources)
72
+ installer = Bukin::Installer.new(Dir.pwd, true)
73
+
74
+ resources.each do |resource|
75
+ downloading resource.name, resource.version do
62
76
  begin
63
- final_resources << resource.resolve_info
77
+ installer.install(resource)
64
78
  rescue OpenURI::HTTPError => ex
65
79
  raise(
66
80
  Bukin::BukinError,
67
- "There was an error fetching information about "\
68
- "'#{resource.data[:name]} (#{resource.data[:version]})'.\n"\
81
+ "There was an error installing "\
82
+ "'#{resource[:name]} (#{resource[:version]})'.\n"\
69
83
  "#{ex.message}"
70
84
  )
71
85
  end
@@ -73,41 +87,53 @@ private
73
87
  end
74
88
  end
75
89
 
76
- final_resources
77
- end
78
-
79
- def install_resources(resources)
80
- installer = Bukin::Installer.new(Dir.pwd, true)
81
-
82
- resources.each do |resource|
83
- downloading resource[:name], resource[:version] do
84
- begin
85
- installer.install(resource)
86
- rescue OpenURI::HTTPError => ex
87
- raise(
88
- Bukin::BukinError,
89
- "There was an error installing "\
90
- "'#{resource[:name]} (#{resource[:version]})'.\n"\
91
- "#{ex.message}"
92
- )
93
- end
90
+ PROVIDERS = {
91
+ download: Download,
92
+ jenkins: Jenkins,
93
+ bukget: Bukget,
94
+ bukkit_dl: BukkitDl
95
+ }
96
+
97
+ DEFAULTS = {
98
+ server: :bukkit_dl,
99
+ plugin: :bukget
100
+ }
101
+
102
+ def get_provider(data)
103
+ name = PROVIDERS.keys.find {|n| data[n]}
104
+
105
+ # If this resource doesn't have a provider, we assign a default
106
+ unless name
107
+ name = DEFAULTS[data[:type]]
108
+ raise MissingProviderError.new(data) unless name
109
+ data[name] = PROVIDERS[name]::URL
94
110
  end
111
+
112
+ name
95
113
  end
96
- end
97
114
 
98
- def section(message)
99
- say "#{message}... "
100
- value = yield
101
- say 'Done', :green
102
- value
103
- rescue => ex
104
- say 'Error', :red
105
- raise ex
106
- end
115
+ def section(message)
116
+ say "#{message}... "
117
+ value = yield
118
+ say 'Done', :green
119
+ value
120
+ rescue => ex
121
+ say 'Error', :red
122
+ raise ex
123
+ end
124
+
125
+ def downloading(name, version, &block)
126
+ msg = "Downloading #{name}"
127
+ msg << " (#{version})" if version
128
+ section(msg, &block)
129
+ end
107
130
 
108
- def downloading(name, version, &block)
109
- msg = "Downloading #{name}"
110
- msg << " (#{version})" if version
111
- section(msg, &block)
131
+ def fetching(provider, &block)
132
+ if provider.is_a?(Download)
133
+ yield
134
+ else
135
+ section("Fetching information from #{provider.url}", &block)
136
+ end
137
+ end
112
138
  end
113
139
  end