mmi 0.1.3 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.adoc +57 -19
- data/exe/mmi +13 -13
- data/lib/mmi/assets_processor.rb +29 -16
- data/lib/mmi/cached_download.rb +59 -0
- data/lib/mmi/github_api.rb +11 -0
- data/lib/mmi/interactive/assets.rb +208 -0
- data/lib/mmi/interactive/modloader.rb +139 -0
- data/lib/mmi/interactive/updater.rb +25 -138
- data/lib/mmi/interactive.rb +1 -2
- data/lib/mmi/mod_file_processor.rb +39 -26
- data/lib/mmi/modloader/fabric.rb +65 -36
- data/lib/mmi/modloader/none.rb +3 -1
- data/lib/mmi/modrinth_api.rb +14 -0
- data/lib/mmi/option_attributes.rb +38 -0
- data/lib/mmi/semver.rb +4 -4
- data/lib/mmi/source/github.rb +28 -28
- data/lib/mmi/source/modrinth.rb +79 -0
- data/lib/mmi/source/url.rb +59 -0
- data/lib/mmi/version.rb +1 -1
- data/lib/mmi.rb +2 -7
- metadata +82 -17
@@ -1,6 +1,14 @@
|
|
1
|
+
require 'cli/ui'
|
2
|
+
|
3
|
+
require 'mmi/interactive/modloader'
|
4
|
+
require 'mmi/interactive/assets'
|
5
|
+
|
1
6
|
module Mmi
|
2
7
|
module Interactive
|
3
8
|
class Updater
|
9
|
+
include Modloader
|
10
|
+
include Assets
|
11
|
+
|
4
12
|
attr_accessor :processor
|
5
13
|
attr_accessor :file_path
|
6
14
|
|
@@ -10,157 +18,36 @@ module Mmi
|
|
10
18
|
end
|
11
19
|
|
12
20
|
def run!
|
13
|
-
|
21
|
+
loop do
|
14
22
|
to_update = CLI::UI::Prompt.ask('What do you want to update?') do |handler|
|
15
23
|
[
|
16
|
-
['
|
17
|
-
['
|
24
|
+
['modloader', :modloader ],
|
25
|
+
['assets', :assets ],
|
26
|
+
['quit & save changes', :quit_save ],
|
18
27
|
['quit & discard changes', :quit_discard],
|
19
28
|
].each do |name, result|
|
20
|
-
handler.option(name) do
|
29
|
+
handler.option(name) do
|
21
30
|
result
|
22
31
|
end
|
23
32
|
end
|
24
33
|
end
|
25
34
|
|
26
35
|
case to_update
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
break
|
35
|
-
when :quit_discard
|
36
|
-
break
|
37
|
-
else
|
38
|
-
raise 'Consider yourself lucky, you found a bug.'
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
def update_assets
|
44
|
-
while true
|
45
|
-
assets = processor.assets.assets
|
46
|
-
|
47
|
-
choice = CLI::UI::Prompt.ask('Which asset do you want to change?') do |handler|
|
48
|
-
assets.each do |asset|
|
49
|
-
handler.option(asset.display_name) do |s|
|
50
|
-
asset
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
handler.option('add' , &:to_sym)
|
55
|
-
handler.option('quit', &:to_sym)
|
56
|
-
end
|
57
|
-
|
58
|
-
case choice
|
59
|
-
when :quit
|
60
|
-
break
|
61
|
-
when :add
|
62
|
-
add_asset
|
63
|
-
else
|
64
|
-
update_asset(choice)
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
def add_asset
|
70
|
-
source_type = CLI::UI::Prompt.ask('Choose a source type.') do |handler|
|
71
|
-
[
|
72
|
-
'github',
|
73
|
-
].each do |type|
|
74
|
-
handler.option(type, &:to_sym)
|
75
|
-
end
|
76
|
-
|
77
|
-
handler.option('quit', &:to_sym)
|
78
|
-
end
|
79
|
-
|
80
|
-
case source_type
|
81
|
-
when :quit
|
82
|
-
false
|
83
|
-
when :github
|
84
|
-
options = {
|
85
|
-
'source' => {
|
86
|
-
'type' => 'github',
|
87
|
-
'asset_id' => 0,
|
88
|
-
}
|
89
|
-
}
|
90
|
-
|
91
|
-
options['source']['owner' ] = CLI::UI::Prompt.ask('Who is the owner of the source repository?').strip
|
92
|
-
options['source']['repo' ] = CLI::UI::Prompt.ask('What is the name of the source repository?').strip
|
93
|
-
options['source']['install_dir'] = CLI::UI::Prompt.ask('In which directory should the asset be placed?', default: 'mods').strip
|
94
|
-
options['source']['filename' ] = CLI::UI::Prompt.ask('Under which filename should the asset be saved? (leave empty for release asset name)', allow_empty: true).strip.then do |filename|
|
95
|
-
filename == '' ? nil : filename
|
96
|
-
end
|
97
|
-
|
98
|
-
options['source'].compact!
|
99
|
-
|
100
|
-
source = Mmi::Source::Github.new(options['source'])
|
101
|
-
|
102
|
-
if update_asset(source)
|
103
|
-
self.processor.content['assets'] ||= []
|
104
|
-
|
105
|
-
self.processor.content['assets'].push(options)
|
106
|
-
self.processor.assets.assets.push(source)
|
107
|
-
|
108
|
-
true
|
109
|
-
else
|
110
|
-
CLI::UI.puts('Aborting asset addition. No change will be made.', color: CLI::UI::Color::RED)
|
111
|
-
|
112
|
-
false
|
113
|
-
end
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
def update_asset(asset)
|
118
|
-
case asset
|
119
|
-
when Mmi::Source::Github
|
120
|
-
releases = ::Github::Client::Repos::Releases.new.list(owner: asset.owner, repo: asset.repo, per_page: 100)
|
121
|
-
|
122
|
-
release = CLI::UI::Prompt.ask('Choose a release.') do |handler|
|
123
|
-
releases.select do |release|
|
124
|
-
release.assets.any?
|
125
|
-
end.each do |release|
|
126
|
-
handler.option(release.name) do |s|
|
127
|
-
release
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
handler.option('quit', &:to_sym)
|
132
|
-
end
|
133
|
-
|
134
|
-
case release
|
135
|
-
when :quit
|
136
|
-
false
|
137
|
-
else
|
138
|
-
release_asset = CLI::UI::Prompt.ask('Choose an asset.') do |handler|
|
139
|
-
release.assets.each do |a|
|
140
|
-
handler.option(a.name) do |s|
|
141
|
-
a
|
142
|
-
end
|
143
|
-
end
|
36
|
+
when :modloader
|
37
|
+
update_modloader
|
38
|
+
when :assets
|
39
|
+
update_assets
|
40
|
+
when :quit_save
|
41
|
+
file_path = CLI::UI::Prompt.ask('Filename', default: self.file_path, is_file: true)
|
42
|
+
yaml = self.processor.options.to_yaml
|
144
43
|
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
when :quit
|
150
|
-
false
|
44
|
+
File.write(File.expand_path(file_path, Dir.pwd), yaml)
|
45
|
+
break
|
46
|
+
when :quit_discard
|
47
|
+
break
|
151
48
|
else
|
152
|
-
|
153
|
-
asset.options.delete('file' )
|
154
|
-
|
155
|
-
asset.options['asset_id'] = release_asset.id
|
156
|
-
|
157
|
-
true
|
158
|
-
end
|
49
|
+
raise 'Consider yourself lucky, you found a bug.'
|
159
50
|
end
|
160
|
-
else
|
161
|
-
CLI::UI.puts('This asset cannot be updated.', color: CLI::UI::Color::RED)
|
162
|
-
|
163
|
-
false
|
164
51
|
end
|
165
52
|
end
|
166
53
|
end
|
data/lib/mmi/interactive.rb
CHANGED
@@ -1,50 +1,63 @@
|
|
1
|
+
require 'mmi/assets_processor'
|
1
2
|
require 'mmi/modloader/none'
|
2
3
|
require 'mmi/modloader/fabric'
|
3
|
-
require 'mmi/
|
4
|
+
require 'mmi/option_attributes'
|
4
5
|
require 'mmi/semver'
|
5
6
|
|
6
7
|
module Mmi
|
7
8
|
class ModFileProcessor
|
8
|
-
|
9
|
+
include OptionAttributes
|
9
10
|
|
10
|
-
|
11
|
-
|
11
|
+
opt_accessor :version
|
12
|
+
opt_accessor :modloader
|
13
|
+
opt_accessor :assets
|
12
14
|
|
13
|
-
attr_reader :
|
14
|
-
attr_reader :
|
15
|
+
attr_reader :parsed_modloader
|
16
|
+
attr_reader :parsed_assets
|
15
17
|
|
16
|
-
def initialize(
|
17
|
-
@
|
18
|
-
|
19
|
-
@version = content['version' ]
|
20
|
-
@profile_dir = content['profile_dir'] || Mmi.minecraft_dir
|
18
|
+
def initialize(options)
|
19
|
+
@options = options
|
21
20
|
|
21
|
+
parse!
|
22
|
+
end
|
23
|
+
|
24
|
+
def parse!
|
22
25
|
version = Semver.parse(self.version)
|
23
26
|
lib_version = Semver.parse(Mmi::VERSION)
|
24
27
|
|
25
28
|
if self.version
|
26
29
|
if version.major <= lib_version.major
|
27
30
|
if version.minor > lib_version.minor
|
28
|
-
Mmi.warn %Q
|
31
|
+
Mmi.warn %Q(Config file specified "version" #{version}, but MMI is at #{lib_version}. Some features might not be supported.)
|
29
32
|
end
|
30
33
|
|
31
|
-
ml
|
32
|
-
@
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
34
|
+
ml = self.modloader
|
35
|
+
@parsed_modloader =
|
36
|
+
if ml
|
37
|
+
case ml['name']
|
38
|
+
when 'none'
|
39
|
+
Modloader::None.new(ml)
|
40
|
+
when 'fabric'
|
41
|
+
Modloader::Fabric.new(ml)
|
42
|
+
else
|
43
|
+
raise Mmi::InvalidAttributeError, "Unkown modloader #{ml['name'].inspect}."
|
44
|
+
end
|
38
45
|
else
|
39
|
-
|
46
|
+
Modloader::None.new
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
if self.assets
|
51
|
+
if self.assets.is_a?(Hash)
|
52
|
+
@parsed_assets = AssetsProcessor.new(self.assets)
|
53
|
+
else
|
54
|
+
raise Mmi::InvalidAttributeError, %Q(Invalid "assets": expected Hash but received #{self.assets.inspect})
|
40
55
|
end
|
41
56
|
else
|
42
|
-
|
57
|
+
raise Mmi::MissingAttributeError, 'Missing "assets".'
|
43
58
|
end
|
44
|
-
|
45
|
-
@assets = AssetsProcessor.new(self.profile_dir, content['assets'])
|
46
59
|
else
|
47
|
-
raise Mmi::InvalidAttributeError, %Q
|
60
|
+
raise Mmi::InvalidAttributeError, %Q(Config file specified "version" #{version}, but MMI is at #{lib_version}.)
|
48
61
|
end
|
49
62
|
else
|
50
63
|
raise Mmi::MissingAttributeError, 'Missing "version".'
|
@@ -52,8 +65,8 @@ module Mmi
|
|
52
65
|
end
|
53
66
|
|
54
67
|
def install
|
55
|
-
self.
|
56
|
-
self.
|
68
|
+
self.parsed_modloader.install
|
69
|
+
self.parsed_assets.install
|
57
70
|
end
|
58
71
|
end
|
59
72
|
end
|
data/lib/mmi/modloader/fabric.rb
CHANGED
@@ -1,31 +1,41 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'nokogiri'
|
3
|
+
|
4
|
+
require 'mmi/cached_download'
|
5
|
+
require 'mmi/option_attributes'
|
6
|
+
|
1
7
|
module Mmi
|
2
8
|
module Modloader
|
3
9
|
class Fabric
|
4
|
-
|
10
|
+
include Mmi::OptionAttributes
|
5
11
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
12
|
+
opt_accessor :version
|
13
|
+
opt_accessor :install_type
|
14
|
+
opt_accessor :mcversion, 'minecraft_version'
|
15
|
+
opt_accessor(:install_dir ) { Mmi.minecraft_dir }
|
16
|
+
opt_accessor(:download_mc, 'download_minecraft') { false }
|
10
17
|
|
11
18
|
def initialize(options)
|
12
19
|
@options = options
|
13
20
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
21
|
+
parse!
|
22
|
+
end
|
23
|
+
|
24
|
+
def parse!
|
19
25
|
if self.version
|
20
26
|
if self.install_type
|
21
|
-
if
|
27
|
+
if allowed_install_types.include?(self.install_type)
|
22
28
|
if self.mcversion
|
23
|
-
|
29
|
+
if [true, false].include?(self.download_mc)
|
30
|
+
# Pass.
|
31
|
+
else
|
32
|
+
raise Mmi::InvalidAttributeError, %Q(Invalid "modloader.download_minecraft". Expecting true or false, got #{self.download_mc.inspect}.)
|
33
|
+
end
|
24
34
|
else
|
25
35
|
raise Mmi::MissingAttributeError, 'Missing "modloader.minecraft_version".'
|
26
36
|
end
|
27
37
|
else
|
28
|
-
raise Mmi::InvalidAttributeError, %Q
|
38
|
+
raise Mmi::InvalidAttributeError, %Q(Invalid "modloader.install_type". Expecting "client" or "server", got #{self.install_type.inspect}.)
|
29
39
|
end
|
30
40
|
else
|
31
41
|
raise Mmi::MissingAttributeError, 'Missing "modloader.install_type".'
|
@@ -35,8 +45,31 @@ module Mmi
|
|
35
45
|
end
|
36
46
|
end
|
37
47
|
|
48
|
+
def allowed_install_types
|
49
|
+
%w[
|
50
|
+
client
|
51
|
+
server
|
52
|
+
]
|
53
|
+
end
|
54
|
+
|
55
|
+
def base_uri
|
56
|
+
'https://maven.fabricmc.net/net/fabricmc/fabric-installer'
|
57
|
+
end
|
58
|
+
|
59
|
+
def metadata_uri
|
60
|
+
File.join(base_uri, 'maven-metadata.xml')
|
61
|
+
end
|
62
|
+
|
63
|
+
def metadata_sha512sum_uri
|
64
|
+
"#{metadata_uri}.sha512"
|
65
|
+
end
|
66
|
+
|
67
|
+
def metadata_path
|
68
|
+
File.join(Mmi.cache_dir, 'fabric_maven_metadata.xml')
|
69
|
+
end
|
70
|
+
|
38
71
|
def installer_uri
|
39
|
-
|
72
|
+
File.join(base_uri, self.version, "fabric-installer-#{self.version}.jar")
|
40
73
|
end
|
41
74
|
|
42
75
|
def installer_sha512sum_uri
|
@@ -55,34 +88,16 @@ module Mmi
|
|
55
88
|
Mmi.info "Downloading fabric-installer version #{self.version.inspect}."
|
56
89
|
|
57
90
|
begin
|
58
|
-
|
59
|
-
|
60
|
-
expected_hexdigest = URI.open(installer_sha512sum_uri).read
|
61
|
-
|
62
|
-
if !File.exists?(installer_path) || expected_hexdigest != Digest::SHA512.hexdigest(File.read(installer_path))
|
63
|
-
stream = URI.open(installer_uri)
|
64
|
-
|
65
|
-
IO.copy_stream(stream, installer_path)
|
66
|
-
|
67
|
-
actual_hexdigest = Digest::SHA512.hexdigest(File.read(installer_path))
|
68
|
-
|
69
|
-
if expected_hexdigest == actual_hexdigest
|
70
|
-
# Pass.
|
71
|
-
else
|
72
|
-
Mmi.fail! "Expected fabric installer to have SHA512 sum #{expected_hexdigest.inspect} but received #{actual_hexdigest.inspect}."
|
73
|
-
end
|
74
|
-
else
|
75
|
-
Mmi.info 'Using cached fabric-installer.'
|
76
|
-
end
|
91
|
+
Mmi::CachedDownload.download_cached(installer_uri, installer_path, sha512_uri: installer_sha512sum_uri)
|
77
92
|
rescue OpenURI::HTTPError => e
|
78
|
-
Mmi.fail! %Q
|
93
|
+
Mmi.fail! %Q(Error when requesting fabric installer. Maybe "modloader.version" == #{version.inspect} is invalid.\n#{e.inspect})
|
79
94
|
end
|
80
95
|
end
|
81
96
|
|
82
97
|
def run_installer
|
83
98
|
FileUtils.mkdir_p(absolute_install_dir)
|
84
99
|
|
85
|
-
if system('java', '-jar', installer_path, self.install_type, '-dir', absolute_install_dir, '-noprofile', '-mcversion', self.mcversion)
|
100
|
+
if system('java', '-jar', installer_path, self.install_type, '-dir', absolute_install_dir, '-noprofile', '-mcversion', self.mcversion, self.download_mc ? '-downloadMinecraft' : '')
|
86
101
|
# Pass.
|
87
102
|
else
|
88
103
|
Mmi.fail! 'Failed to install Fabric modloader.'
|
@@ -93,6 +108,20 @@ module Mmi
|
|
93
108
|
download_installer
|
94
109
|
run_installer
|
95
110
|
end
|
111
|
+
|
112
|
+
def available_versions
|
113
|
+
begin
|
114
|
+
Mmi::CachedDownload.download_cached(metadata_uri, metadata_path, sha512_uri: metadata_sha512sum_uri)
|
115
|
+
rescue OpenURI::HTTPError => e
|
116
|
+
Mmi.fail! "Error when requesting available fabric installer versions.\n#{e.inspect}"
|
117
|
+
end
|
118
|
+
|
119
|
+
xml = File.open(metadata_path) do |f|
|
120
|
+
Nokogiri::XML(f)
|
121
|
+
end
|
122
|
+
|
123
|
+
xml.xpath('/metadata/versioning/versions/version').map(&:inner_html)
|
124
|
+
end
|
96
125
|
end
|
97
126
|
end
|
98
|
-
end
|
127
|
+
end
|
data/lib/mmi/modloader/none.rb
CHANGED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'open-uri'
|
3
|
+
|
4
|
+
module Mmi
|
5
|
+
module ModrinthApi
|
6
|
+
BASE_URL = URI('https://api.modrinth.com/v2/')
|
7
|
+
|
8
|
+
class << self
|
9
|
+
def project_versions(mod_slug)
|
10
|
+
JSON.parse((BASE_URL + "project/#{mod_slug}/version").open.read)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Mmi
|
2
|
+
module OptionAttributes
|
3
|
+
attr_reader :options
|
4
|
+
|
5
|
+
def self.included(klass)
|
6
|
+
klass.extend(ClassMethods)
|
7
|
+
end
|
8
|
+
|
9
|
+
module ClassMethods
|
10
|
+
def opt_reader(attr, name=attr.to_s, &block)
|
11
|
+
define_method(:"#{attr.to_sym}") do
|
12
|
+
result = self.options[name]
|
13
|
+
|
14
|
+
if result.nil? && block_given?
|
15
|
+
block.call
|
16
|
+
else
|
17
|
+
result
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def opt_writer(attr, name=attr.to_s)
|
23
|
+
define_method(:"#{attr.to_sym}=") do |value|
|
24
|
+
if value.nil?
|
25
|
+
self.options.delete(name)
|
26
|
+
else
|
27
|
+
self.options[name] = value
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def opt_accessor(attr, name=attr.to_s, &block)
|
33
|
+
opt_reader(attr, name, &block)
|
34
|
+
opt_writer(attr, name )
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/lib/mmi/semver.rb
CHANGED
@@ -10,11 +10,11 @@ module Mmi
|
|
10
10
|
self.patch = patch
|
11
11
|
end
|
12
12
|
|
13
|
-
def self.parse(
|
14
|
-
if m = /\A(?<major>\d+)
|
15
|
-
new(m[:major], m[:minor], m[:patch])
|
13
|
+
def self.parse(version)
|
14
|
+
if (m = /\A(?<major>\d+)\.(?<minor>\d+)\.(?<patch>\d+)\z/.match(version.strip))
|
15
|
+
new(m[:major].to_i, m[:minor].to_i, m[:patch].to_i)
|
16
16
|
else
|
17
|
-
raise "Version string not in valid format: #{
|
17
|
+
raise "Version string not in valid format: #{version.inspect}"
|
18
18
|
end
|
19
19
|
end
|
20
20
|
end
|
data/lib/mmi/source/github.rb
CHANGED
@@ -1,43 +1,43 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'open-uri'
|
3
|
+
|
4
|
+
require 'mmi/github_api'
|
5
|
+
require 'mmi/option_attributes'
|
6
|
+
|
1
7
|
module Mmi
|
2
8
|
module Source
|
3
9
|
class Github
|
4
|
-
|
10
|
+
include Mmi::OptionAttributes
|
5
11
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
12
|
+
opt_accessor :owner
|
13
|
+
opt_accessor :repo
|
14
|
+
opt_accessor :install_dir
|
15
|
+
opt_accessor :filename
|
10
16
|
|
11
|
-
|
12
|
-
|
13
|
-
|
17
|
+
opt_accessor :asset_id
|
18
|
+
opt_accessor :release
|
19
|
+
opt_accessor :file
|
14
20
|
|
15
21
|
def initialize(options)
|
16
22
|
@options = options
|
17
23
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
@file = options['file' ]
|
23
|
-
@install_dir = options['install_dir']
|
24
|
-
@filename = options['filename' ]
|
25
|
-
|
24
|
+
parse!
|
25
|
+
end
|
26
|
+
|
27
|
+
def parse!
|
26
28
|
if self.owner
|
27
29
|
if self.repo
|
28
30
|
if self.install_dir
|
29
31
|
if self.asset_id
|
30
32
|
# Pass.
|
31
|
-
|
32
|
-
if self.
|
33
|
-
|
34
|
-
# Pass.
|
35
|
-
else
|
36
|
-
raise Mmi::MissingAttributeError, 'Missing "source.file" from asset because "source.asset_id" is not provided.'
|
37
|
-
end
|
33
|
+
elsif self.release
|
34
|
+
if self.file
|
35
|
+
# Pass.
|
38
36
|
else
|
39
|
-
raise Mmi::MissingAttributeError, 'Missing "source.
|
37
|
+
raise Mmi::MissingAttributeError, 'Missing "source.file" from asset because "source.asset_id" is not provided.'
|
40
38
|
end
|
39
|
+
else
|
40
|
+
raise Mmi::MissingAttributeError, 'Missing "source.release" from asset because "source.asset_id" is not provided.'
|
41
41
|
end
|
42
42
|
else
|
43
43
|
raise Mmi::MissingAttributeError, 'Missing "source.install_dir" from asset.'
|
@@ -55,7 +55,7 @@ module Mmi
|
|
55
55
|
end
|
56
56
|
|
57
57
|
def cached_asset_response
|
58
|
-
@
|
58
|
+
@cached_asset_response ||= Mmi::GithubApi.client.release_asset("/repos/#{self.owner}/#{self.repo}/releases/assets/#{self.asset_id}")
|
59
59
|
end
|
60
60
|
|
61
61
|
def download_url
|
@@ -75,11 +75,11 @@ module Mmi
|
|
75
75
|
FileUtils.mkdir_p(install_dir)
|
76
76
|
|
77
77
|
begin
|
78
|
-
stream = URI.
|
78
|
+
stream = URI.parse(download_url).open
|
79
79
|
|
80
80
|
IO.copy_stream(stream, filepath)
|
81
81
|
rescue OpenURI::HTTPError => e
|
82
|
-
Mmi.fail!
|
82
|
+
Mmi.fail! "Error when requesting asset.\n#{e.inspect}"
|
83
83
|
end
|
84
84
|
end
|
85
85
|
|
@@ -88,4 +88,4 @@ module Mmi
|
|
88
88
|
end
|
89
89
|
end
|
90
90
|
end
|
91
|
-
end
|
91
|
+
end
|