tirofinale 0.1.3 → 0.1.3.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.md +11 -9
- data/bin/experiment/list_all_alpine_linux_ruby_package_makedepends.rb +2 -1
- data/exe/tirofinale +3 -173
- data/lib/tirofinale.rb +172 -2
- data/lib/tirofinale/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5cf16d6f0fb4ba0811f0f98c38182c8468ebccf3
|
4
|
+
data.tar.gz: c5e85aae72bc747c88016871ed9b3b4081b977d3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f3e7813a117d0295115d88a311088c0eeeb56c235f5fbe6eb8c99bdd602432629fa450bc5894f6fb742f901171e422e3a7fe98349183e5977f2ca308cd3f9e62
|
7
|
+
data.tar.gz: f9363415589b540f581df6ee510b39c5e8f054591cf869c67b0143fbfc2209dae8a2cd44464f6c19cbff909864557d57b50bb650401aa7fc18bb9fd09ef71183
|
data/README.md
CHANGED
@@ -26,14 +26,15 @@ Usage: tirofinale [options]
|
|
26
26
|
--debug-local-aports PATH
|
27
27
|
~~~~
|
28
28
|
|
29
|
-
Default output format is optimized
|
30
|
-
You can install required packages to install `nokogiri` gem
|
29
|
+
Default output format is optimized for shell.
|
30
|
+
You can install required packages to install `nokogiri` gem following lines.
|
31
31
|
|
32
32
|
~~~~
|
33
33
|
# apk add `tirofinale --gem nokogiri`
|
34
|
+
# gem install nokogiri # successful!
|
34
35
|
~~~~
|
35
36
|
|
36
|
-
Human
|
37
|
+
Human friendry output format gettable by specifying `--pretty-print` option.
|
37
38
|
|
38
39
|
~~~~
|
39
40
|
$ tirofinale --gem nokogiri --pretty-print
|
@@ -43,18 +44,19 @@ This environment require following packages to install gem 'nokogiri'.
|
|
43
44
|
libxslt-dev
|
44
45
|
~~~~
|
45
46
|
|
46
|
-
|
47
|
-
If you specify version manually, you can use `--dist-version VERSION` option.
|
48
|
-
The following line show packages which are required to build `nokogiri` gem on Alpine Linux v3.4 on any environment.
|
47
|
+
Tirofinale read `/etc/alpine-release` file and detect Alpine Linux version automatically.
|
48
|
+
If you want to specify version manually, you can use `--dist-version VERSION` option.
|
49
49
|
|
50
50
|
~~~~
|
51
51
|
$ tirofinale --dist-version 3.4 --gem nokogiri
|
52
52
|
~~~~
|
53
53
|
|
54
|
-
|
54
|
+
Tirofinale resolve dependency of a gem to gems when specify `--dependency` option.
|
55
|
+
|
55
56
|
For example, `thin` gem depends on `daemons` gem, `eventmachine` gem and `rack` gem.
|
56
|
-
|
57
|
-
|
57
|
+
`openssl-dev` package is required to install `eventmachine` gem on Alpine Linux.
|
58
|
+
|
59
|
+
Folowing example, Tirofinale show distribution packages required by installing `thin` gem and `thin` gem depends to gems.
|
58
60
|
|
59
61
|
~~~~
|
60
62
|
$ tirofinale --gem thin --dependency --pretty-print
|
data/exe/tirofinale
CHANGED
@@ -1,175 +1,5 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
require '
|
3
|
-
|
4
|
-
require 'yaml'
|
5
|
-
require 'logger'
|
2
|
+
require 'tirofinale'
|
3
|
+
include Tirofinale
|
6
4
|
|
7
|
-
|
8
|
-
$logger = Logger.new(STDERR)
|
9
|
-
$logger.level = 4
|
10
|
-
if level = ENV['LOG_LEVEL']
|
11
|
-
$logger.level = level.to_i
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
def detect_version_alpine
|
16
|
-
content = open('/etc/alpine-release'){|f| f.read }
|
17
|
-
major_minor = content.match(/\A(\d\.\d)/)
|
18
|
-
major_minor ? major_minor[1] : nil
|
19
|
-
end
|
20
|
-
|
21
|
-
def search_apkbuild(gem_name, alpine_version, debug_local_aports = nil)
|
22
|
-
dir_list = ['community', 'main', 'non-free', 'testing', 'unmaintained']
|
23
|
-
dir_list.each{|dir_name|
|
24
|
-
apkbuild_url = "http://git.alpinelinux.org/cgit/aports/plain/#{dir_name}/ruby-#{gem_name}/APKBUILD?h=#{alpine_version + '-stable'}"
|
25
|
-
if debug_local_aports
|
26
|
-
apkbuild_url = "#{debug_local_aports}/#{dir_name}/ruby-#{gem_name}/APKBUILD"
|
27
|
-
end
|
28
|
-
|
29
|
-
begin
|
30
|
-
return open(apkbuild_url){|f| f.read}
|
31
|
-
rescue OpenURI::HTTPError => e
|
32
|
-
next
|
33
|
-
rescue Errno::ENOENT => e
|
34
|
-
next
|
35
|
-
end
|
36
|
-
}
|
37
|
-
false
|
38
|
-
end
|
39
|
-
|
40
|
-
def extract_makedepends(apkbuild)
|
41
|
-
variables = []
|
42
|
-
|
43
|
-
# extract quoted variable
|
44
|
-
apkbuild.scan(/^([a-z_]+)="(.*?)"/m){|m|
|
45
|
-
variables << ({:name => m[0], :value => m[1].gsub(/\s+/, ' ')})
|
46
|
-
}
|
47
|
-
|
48
|
-
# extract not quoted variable
|
49
|
-
apkbuild.scan(/^([a-z_]+)=([^"]*?)$/){|m|
|
50
|
-
variables << ({:name => m[0], :value => m[1].gsub(/\s+/, ' ')})
|
51
|
-
}
|
52
|
-
|
53
|
-
variables.sort_by!{|var| var[:name].length * -1}
|
54
|
-
|
55
|
-
variables.each{|var|
|
56
|
-
while var[:value].include?('$')
|
57
|
-
result = nil
|
58
|
-
variables.each{|var2|
|
59
|
-
result = result || var[:value].gsub!("$#{var2[:name]}", var2[:value])
|
60
|
-
}
|
61
|
-
break unless result
|
62
|
-
end
|
63
|
-
}
|
64
|
-
|
65
|
-
makedepends = variables.select{|var| var[:name] == 'makedepends'}.first
|
66
|
-
makedepends ? makedepends[:value] : ''
|
67
|
-
end
|
68
|
-
|
69
|
-
def fetch_dep_gems(gem_name, checked = [], level = 0)
|
70
|
-
$logger.debug("fetch_dep_gems(). Args:[#{[gem_name, checked, level].join(', ')}]")
|
71
|
-
|
72
|
-
if level > 10
|
73
|
-
return []
|
74
|
-
end
|
75
|
-
|
76
|
-
dep_gems = []
|
77
|
-
|
78
|
-
url = "https://rubygems.org/api/v1/gems/#{gem_name}.yaml"
|
79
|
-
runtime_dep = open(url){|f|
|
80
|
-
YAML.load(f.read)['dependencies']['runtime'].map{|dep| dep['name']}
|
81
|
-
}
|
82
|
-
|
83
|
-
dep_gems.push(*runtime_dep)
|
84
|
-
checked << gem_name
|
85
|
-
|
86
|
-
runtime_dep.each{|dep|
|
87
|
-
unless checked.include?(dep)
|
88
|
-
dep_gems.push(*fetch_dep_gems(dep, checked, level + 1))
|
89
|
-
end
|
90
|
-
}
|
91
|
-
|
92
|
-
dep_gems.uniq
|
93
|
-
|
94
|
-
$logger.info("Gem '#{gem_name}' depends on [#{dep_gems.join(', ')}].")
|
95
|
-
|
96
|
-
dep_gems
|
97
|
-
end
|
98
|
-
|
99
|
-
def fetch_build_dep_packages_alpine(gem_name, alpine_version, debug_local_aports)
|
100
|
-
$logger.info("Fetch Alpine Linux #{alpine_version} dependency packages to build '#{gem_name}'.")
|
101
|
-
apkbuild = search_apkbuild(gem_name, alpine_version, debug_local_aports)
|
102
|
-
unless apkbuild
|
103
|
-
$logger.warn("Alpine Linux does not have binary package for '#{gem_name}'.")
|
104
|
-
return []
|
105
|
-
end
|
106
|
-
makedepends = extract_makedepends(apkbuild)
|
107
|
-
packages = makedepends.strip.split(' ')
|
108
|
-
$logger.info("Alpine Linux build dependency packages [#{packages.join(', ')}] for '#{gem_name}'.")
|
109
|
-
packages
|
110
|
-
rescue => e
|
111
|
-
$logger.error(e.inspect)
|
112
|
-
$logger.error(e.backtrace)
|
113
|
-
raise e
|
114
|
-
end
|
115
|
-
|
116
|
-
def run
|
117
|
-
init_logger()
|
118
|
-
|
119
|
-
opts = {}
|
120
|
-
|
121
|
-
op = OptionParser.new
|
122
|
-
op.on('--dependency'){|val| opts[:dependency] = true}
|
123
|
-
op.on('--dist-version VERSION'){|val| opts[:alpine_version] = val}
|
124
|
-
op.on('--gem GEM_NAME'){|val| opts[:gem_name] = val}
|
125
|
-
op.on('--pretty-print'){|val| opts[:pretty_print] = true}
|
126
|
-
op.on('--debug-local-aports PATH'){|val| opts[:debug_local_aports] = val}
|
127
|
-
op.parse(ARGV)
|
128
|
-
|
129
|
-
$logger.info "Tirofinale start with #{opts}."
|
130
|
-
|
131
|
-
alpine_version = opts[:alpine_version]
|
132
|
-
gem_name = opts[:gem_name]
|
133
|
-
dependency = opts[:dependency]
|
134
|
-
debug_local_aports = opts[:debug_local_aports]
|
135
|
-
pretty_print = opts[:pretty_print]
|
136
|
-
|
137
|
-
unless alpine_version
|
138
|
-
$logger.info('Attempt to auto detect Alpine Linux version.')
|
139
|
-
alpine_version = detect_version_alpine()
|
140
|
-
$logger.info("Alpine Linux version '#{alpine_version}' was detected.")
|
141
|
-
end
|
142
|
-
|
143
|
-
packages = fetch_build_dep_packages_alpine(gem_name, alpine_version, debug_local_aports)
|
144
|
-
|
145
|
-
if dependency
|
146
|
-
dep_gem_list = fetch_dep_gems(gem_name)
|
147
|
-
|
148
|
-
dep_gem_list.each{|dep_gem_name|
|
149
|
-
dep_packages = fetch_build_dep_packages_alpine(dep_gem_name, alpine_version, debug_local_aports)
|
150
|
-
packages.push(*dep_packages) unless dep_packages.empty?
|
151
|
-
}
|
152
|
-
|
153
|
-
packages.uniq!
|
154
|
-
end
|
155
|
-
|
156
|
-
$logger.info("This environment require packages [#{packages.join(', ')}] to install gem '#{gem_name}'.")
|
157
|
-
|
158
|
-
if pretty_print
|
159
|
-
puts "This environment require following packages to install gem '#{gem_name}'."
|
160
|
-
packages.each{|package|
|
161
|
-
puts " #{package}"
|
162
|
-
}
|
163
|
-
else
|
164
|
-
print packages.join(' ')
|
165
|
-
end
|
166
|
-
|
167
|
-
$logger.info "Tirofinale done."
|
168
|
-
end
|
169
|
-
|
170
|
-
if $0 == __FILE__
|
171
|
-
# execute directory
|
172
|
-
run()
|
173
|
-
else
|
174
|
-
# not to do something by require/load this file
|
175
|
-
end
|
5
|
+
run()
|
data/lib/tirofinale.rb
CHANGED
@@ -1,5 +1,175 @@
|
|
1
|
-
require
|
1
|
+
require 'optparse'
|
2
|
+
require 'yaml'
|
3
|
+
require 'logger'
|
4
|
+
require 'open-uri'
|
5
|
+
|
6
|
+
require 'tirofinale/version'
|
2
7
|
|
3
8
|
module Tirofinale
|
4
|
-
|
9
|
+
def init_logger
|
10
|
+
$logger = Logger.new(STDERR)
|
11
|
+
$logger.level = 4
|
12
|
+
if level = ENV['LOG_LEVEL']
|
13
|
+
$logger.level = level.to_i
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def detect_version_alpine
|
18
|
+
content = open('/etc/alpine-release'){|f| f.read }
|
19
|
+
major_minor = content.match(/\A(\d\.\d)/)
|
20
|
+
major_minor ? major_minor[1] : nil
|
21
|
+
end
|
22
|
+
|
23
|
+
def search_apkbuild(gem_name, alpine_version, debug_local_aports = nil)
|
24
|
+
dir_list = ['community', 'main', 'non-free', 'testing', 'unmaintained']
|
25
|
+
dir_list.each{|dir_name|
|
26
|
+
apkbuild_url = "http://git.alpinelinux.org/cgit/aports/plain/#{dir_name}/ruby-#{gem_name}/APKBUILD?h=#{alpine_version + '-stable'}"
|
27
|
+
if debug_local_aports
|
28
|
+
apkbuild_url = "#{debug_local_aports}/#{dir_name}/ruby-#{gem_name}/APKBUILD"
|
29
|
+
end
|
30
|
+
|
31
|
+
begin
|
32
|
+
return open(apkbuild_url){|f| f.read}
|
33
|
+
rescue OpenURI::HTTPError => e
|
34
|
+
next
|
35
|
+
rescue Errno::ENOENT => e
|
36
|
+
next
|
37
|
+
end
|
38
|
+
}
|
39
|
+
false
|
40
|
+
end
|
41
|
+
|
42
|
+
def extract_makedepends(apkbuild)
|
43
|
+
variables = []
|
44
|
+
|
45
|
+
# extract quoted variable
|
46
|
+
apkbuild.scan(/^([a-z_]+)="(.*?)"/m){|m|
|
47
|
+
variables << ({:name => m[0], :value => m[1].gsub(/\s+/, ' ')})
|
48
|
+
}
|
49
|
+
|
50
|
+
# extract not quoted variable
|
51
|
+
apkbuild.scan(/^([a-z_]+)=([^"]*?)$/){|m|
|
52
|
+
variables << ({:name => m[0], :value => m[1].gsub(/\s+/, ' ')})
|
53
|
+
}
|
54
|
+
|
55
|
+
variables.sort_by!{|var| var[:name].length * -1}
|
56
|
+
|
57
|
+
variables.each{|var|
|
58
|
+
while var[:value].include?('$')
|
59
|
+
result = nil
|
60
|
+
variables.each{|var2|
|
61
|
+
result = result || var[:value].gsub!("$#{var2[:name]}", var2[:value])
|
62
|
+
}
|
63
|
+
break unless result
|
64
|
+
end
|
65
|
+
}
|
66
|
+
|
67
|
+
makedepends = variables.select{|var| var[:name] == 'makedepends'}.first
|
68
|
+
makedepends ? makedepends[:value] : ''
|
69
|
+
end
|
70
|
+
|
71
|
+
def fetch_dep_gems(gem_name, checked = [], level = 0)
|
72
|
+
$logger.debug("fetch_dep_gems(). Args:[#{[gem_name, checked, level].join(', ')}]")
|
73
|
+
|
74
|
+
if level > 10
|
75
|
+
return []
|
76
|
+
end
|
77
|
+
|
78
|
+
dep_gems = []
|
79
|
+
|
80
|
+
url = "https://rubygems.org/api/v1/gems/#{gem_name}.yaml"
|
81
|
+
runtime_dep = open(url){|f|
|
82
|
+
YAML.load(f.read)['dependencies']['runtime'].map{|dep| dep['name']}
|
83
|
+
}
|
84
|
+
|
85
|
+
dep_gems.push(*runtime_dep)
|
86
|
+
checked << gem_name
|
87
|
+
|
88
|
+
runtime_dep.each{|dep|
|
89
|
+
unless checked.include?(dep)
|
90
|
+
dep_gems.push(*fetch_dep_gems(dep, checked, level + 1))
|
91
|
+
end
|
92
|
+
}
|
93
|
+
|
94
|
+
dep_gems.uniq
|
95
|
+
|
96
|
+
$logger.info("Gem '#{gem_name}' depends on [#{dep_gems.join(', ')}].")
|
97
|
+
|
98
|
+
dep_gems
|
99
|
+
end
|
100
|
+
|
101
|
+
def fetch_build_dep_packages_alpine(gem_name, alpine_version, debug_local_aports)
|
102
|
+
$logger.info("Fetch Alpine Linux #{alpine_version} dependency packages to build '#{gem_name}'.")
|
103
|
+
apkbuild = search_apkbuild(gem_name, alpine_version, debug_local_aports)
|
104
|
+
unless apkbuild
|
105
|
+
$logger.warn("Alpine Linux does not have binary package for '#{gem_name}'.")
|
106
|
+
return []
|
107
|
+
end
|
108
|
+
makedepends = extract_makedepends(apkbuild)
|
109
|
+
packages = makedepends.strip.split(' ')
|
110
|
+
$logger.info("Alpine Linux build dependency packages [#{packages.join(', ')}] for '#{gem_name}'.")
|
111
|
+
packages
|
112
|
+
rescue => e
|
113
|
+
$logger.error(e.inspect)
|
114
|
+
$logger.error(e.backtrace)
|
115
|
+
raise e
|
116
|
+
end
|
117
|
+
|
118
|
+
def run
|
119
|
+
init_logger()
|
120
|
+
|
121
|
+
opts = {}
|
122
|
+
|
123
|
+
op = OptionParser.new
|
124
|
+
op.on('--dependency'){|val| opts[:dependency] = true}
|
125
|
+
op.on('--dist-version VERSION'){|val| opts[:alpine_version] = val}
|
126
|
+
op.on('--gem GEM_NAME'){|val| opts[:gem_name] = val}
|
127
|
+
op.on('--pretty-print'){|val| opts[:pretty_print] = true}
|
128
|
+
op.on('--debug-local-aports PATH'){|val| opts[:debug_local_aports] = val}
|
129
|
+
op.parse(ARGV)
|
130
|
+
|
131
|
+
$logger.info "Tirofinale start with #{opts}."
|
132
|
+
|
133
|
+
alpine_version = opts[:alpine_version]
|
134
|
+
gem_name = opts[:gem_name]
|
135
|
+
dependency = opts[:dependency]
|
136
|
+
debug_local_aports = opts[:debug_local_aports]
|
137
|
+
pretty_print = opts[:pretty_print]
|
138
|
+
|
139
|
+
unless gem_name
|
140
|
+
raise "Missing '--gem GEM_NAME' option."
|
141
|
+
end
|
142
|
+
|
143
|
+
unless alpine_version
|
144
|
+
$logger.info('Attempt to auto detect Alpine Linux version.')
|
145
|
+
alpine_version = detect_version_alpine()
|
146
|
+
$logger.info("Alpine Linux version '#{alpine_version}' was detected.")
|
147
|
+
end
|
148
|
+
|
149
|
+
packages = fetch_build_dep_packages_alpine(gem_name, alpine_version, debug_local_aports)
|
150
|
+
|
151
|
+
if dependency
|
152
|
+
dep_gem_list = fetch_dep_gems(gem_name)
|
153
|
+
|
154
|
+
dep_gem_list.each{|dep_gem_name|
|
155
|
+
dep_packages = fetch_build_dep_packages_alpine(dep_gem_name, alpine_version, debug_local_aports)
|
156
|
+
packages.push(*dep_packages) unless dep_packages.empty?
|
157
|
+
}
|
158
|
+
|
159
|
+
packages.uniq!
|
160
|
+
end
|
161
|
+
|
162
|
+
$logger.info("This environment require packages [#{packages.join(', ')}] to install gem '#{gem_name}'.")
|
163
|
+
|
164
|
+
if pretty_print
|
165
|
+
puts "This environment require following packages to install gem '#{gem_name}'."
|
166
|
+
packages.each{|package|
|
167
|
+
puts " #{package}"
|
168
|
+
}
|
169
|
+
else
|
170
|
+
print packages.join(' ')
|
171
|
+
end
|
172
|
+
|
173
|
+
$logger.info "Tirofinale done."
|
174
|
+
end
|
5
175
|
end
|
data/lib/tirofinale/version.rb
CHANGED