polisher 0.9.1 → 0.10.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/bin/gem_dependency_checker.rb +55 -25
- data/bin/git_gem_updater.rb +18 -7
- data/lib/polisher/bodhi.rb +11 -10
- data/lib/polisher/component.rb +43 -0
- data/lib/polisher/config.rb +32 -0
- data/lib/polisher/core.rb +59 -34
- data/lib/polisher/errata.rb +56 -56
- data/lib/polisher/fedora.rb +33 -33
- data/lib/polisher/gem.rb +316 -281
- data/lib/polisher/gem_state.rb +86 -0
- data/lib/polisher/gemfile.rb +85 -87
- data/lib/polisher/git/pkg.rb +232 -175
- data/lib/polisher/git/repo.rb +74 -61
- data/lib/polisher/koji.rb +136 -83
- data/lib/polisher/logger.rb +23 -0
- data/lib/polisher/rhn.rb +6 -5
- data/lib/polisher/rpm/requirement.rb +186 -177
- data/lib/polisher/rpm/spec.rb +420 -356
- data/lib/polisher/tag_mapper.rb +27 -0
- data/lib/polisher/version.rb +1 -1
- data/lib/polisher/version_checker.rb +86 -17
- data/lib/polisher/yum.rb +26 -19
- data/spec/component_spec.rb +53 -0
- data/spec/core_spec.rb +6 -0
- data/spec/gem_spec.rb +230 -47
- data/spec/git_spec.rb +63 -27
- data/spec/koji_spec.rb +60 -3
- data/spec/rpm/spec_spec.rb +7 -3
- data/spec/spec_helper.rb +2 -1
- data/spec/version_checker_spec.rb +97 -0
- data/spec/yum_spec.rb +5 -0
- metadata +34 -28
- data/lib/polisher/missing.rb +0 -12
data/lib/polisher/errata.rb
CHANGED
@@ -3,73 +3,73 @@
|
|
3
3
|
# Licensed under the MIT license
|
4
4
|
# Copyright (C) 2013-2014 Red Hat, Inc.
|
5
5
|
|
6
|
-
require 'json'
|
7
|
-
require 'curb'
|
8
|
-
|
9
6
|
require 'polisher/core'
|
7
|
+
require 'polisher/component'
|
10
8
|
|
11
9
|
module Polisher
|
12
|
-
|
13
|
-
|
10
|
+
Component.verify("Errata", 'json', 'curb') do
|
11
|
+
class Errata
|
12
|
+
include ConfHelpers
|
13
|
+
|
14
|
+
conf_attr :advisory_url, ''
|
15
|
+
conf_attr :package_prefix, 'rubygem-'
|
14
16
|
|
15
|
-
|
16
|
-
|
17
|
+
# Initialize/return singleton curl handle to query errata
|
18
|
+
def self.client
|
19
|
+
@curl ||= begin
|
20
|
+
curl = Curl::Easy.new
|
21
|
+
curl.ssl_verify_peer = false
|
22
|
+
curl.ssl_verify_host = false
|
23
|
+
curl.http_auth_types = :negotiate
|
24
|
+
curl.userpwd = ':'
|
25
|
+
curl
|
26
|
+
end
|
27
|
+
end
|
17
28
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
curl.ssl_verify_peer = false
|
23
|
-
curl.ssl_verify_host = false
|
24
|
-
curl.http_auth_types = :negotiate
|
25
|
-
curl.userpwd = ':'
|
26
|
-
curl
|
29
|
+
def self.clear!
|
30
|
+
@cached_url = nil
|
31
|
+
@cached_builds = nil
|
32
|
+
self
|
27
33
|
end
|
28
|
-
end
|
29
34
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
self
|
34
|
-
end
|
35
|
+
def self.builds
|
36
|
+
@cached_url ||= advisory_url
|
37
|
+
@cached_builds ||= nil
|
35
38
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
+
if @cached_url != advisory_url || @cached_builds.nil?
|
40
|
+
client.url = "#{advisory_url}/builds"
|
41
|
+
@cached_builds = client.get
|
42
|
+
@cached_builds = JSON.parse(client.body_str)
|
43
|
+
end
|
39
44
|
|
40
|
-
|
41
|
-
client.url = "#{advisory_url}/builds"
|
42
|
-
@cached_builds = client.get
|
43
|
-
@cached_builds = JSON.parse(client.body_str)
|
45
|
+
@cached_builds
|
44
46
|
end
|
45
47
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
end
|
53
|
-
|
54
|
-
versions
|
55
|
-
end
|
56
|
-
end
|
48
|
+
def self.versions_for(name, &bl)
|
49
|
+
versions = builds.collect do |tag, builds|
|
50
|
+
ErrataBuild.builds_matching(builds, name)
|
51
|
+
end.flatten
|
52
|
+
bl.call(:errata, name, versions) unless(bl.nil?)
|
53
|
+
versions
|
54
|
+
end
|
55
|
+
end # class Errata
|
57
56
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
57
|
+
class ErrataBuild
|
58
|
+
def self.builds_matching(builds, name)
|
59
|
+
builds.collect { |build|
|
60
|
+
self.build_matches?(build, name) ? self.build_version(build, name) : nil
|
61
|
+
}.compact
|
62
|
+
end
|
64
63
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
64
|
+
def self.build_matches?(build, name)
|
65
|
+
pkg,meta = *build.flatten
|
66
|
+
pkg =~ /^#{Errata.package_prefix}#{name}-([^-]*)-.*$/
|
67
|
+
end
|
69
68
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
end
|
69
|
+
def self.build_version(build, name)
|
70
|
+
pkg,meta = *build.flatten
|
71
|
+
pkg.gsub(Errata.package_prefix, '').split('-')[1]
|
72
|
+
end
|
73
|
+
end # class ErrataBuild
|
74
|
+
end # Component.verify(Errata)
|
75
|
+
end # module Polisher
|
data/lib/polisher/fedora.rb
CHANGED
@@ -3,44 +3,44 @@
|
|
3
3
|
# Licensed under the MIT license
|
4
4
|
# Copyright (C) 2013-2014 Red Hat, Inc.
|
5
5
|
|
6
|
-
require 'curb'
|
7
|
-
require 'pkgwat'
|
8
|
-
|
9
6
|
require 'polisher/bodhi'
|
7
|
+
require 'polisher/component'
|
10
8
|
|
11
9
|
module Polisher
|
12
|
-
|
13
|
-
|
10
|
+
Component.verify("Fedora", "curb", "pkgwat", "nokogiri") do
|
11
|
+
class Fedora
|
12
|
+
PACKAGE_LIST = 'https://admin.fedoraproject.org/pkgdb/users/packages/'
|
14
13
|
|
15
|
-
|
16
|
-
|
17
|
-
|
14
|
+
def self.client
|
15
|
+
@client ||= Curl::Easy.new
|
16
|
+
end
|
18
17
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
18
|
+
# Retrieve list of gems owned by the specified user
|
19
|
+
#
|
20
|
+
# @param [String] user Fedora username to lookup
|
21
|
+
# @return [Array<String>] list of gems which the user owns/has access to
|
22
|
+
def self.gems_owned_by(user)
|
23
|
+
client.url = "#{PACKAGE_LIST}#{user}"
|
24
|
+
client.http_get
|
25
|
+
packages = client.body_str
|
26
|
+
# TODO: instantiate Polisher::Gem instances & return
|
27
|
+
Nokogiri::HTML(packages).xpath("//a[@class='PackageName']")
|
28
|
+
.select { |i| i.text =~ /rubygem-.*/ }
|
29
|
+
.collect { |i| i.text.gsub(/rubygem-/, '') }
|
30
|
+
end
|
32
31
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
32
|
+
# Retrieve list of the versions of the specified package in the various
|
33
|
+
# Fedora releases.
|
34
|
+
#
|
35
|
+
# @param [String] name name of the package to lookup
|
36
|
+
# @param [Callable] bl optional callback to invoke with versions retrieved
|
37
|
+
# @return [Array<String>] list of versions in Fedora
|
38
|
+
def self.versions_for(name, &bl)
|
39
|
+
# simply dispatch to bodhi to get latest updates
|
40
|
+
Polisher::Bodhi.versions_for name do |_target, pkg_name, versions|
|
41
|
+
bl.call(:fedora, pkg_name, versions) unless bl.nil?
|
42
|
+
end
|
43
43
|
end
|
44
|
-
end
|
45
|
-
end #
|
44
|
+
end # class Fedora
|
45
|
+
end # Component.verify("Fedora")
|
46
46
|
end # module Polisher
|
data/lib/polisher/gem.rb
CHANGED
@@ -3,310 +3,345 @@
|
|
3
3
|
# Licensed under the MIT license
|
4
4
|
# Copyright (C) 2013-2014 Red Hat, Inc.
|
5
5
|
|
6
|
-
require '
|
7
|
-
require 'json'
|
8
|
-
require 'yaml'
|
9
|
-
require 'tempfile'
|
10
|
-
require 'pathname'
|
11
|
-
require 'fileutils'
|
12
|
-
require 'awesome_spawn'
|
13
|
-
require 'rubygems/installer'
|
14
|
-
require 'active_support/core_ext'
|
15
|
-
|
16
|
-
require 'polisher/version_checker'
|
17
|
-
require 'polisher/gem_cache'
|
6
|
+
require 'polisher/core'
|
18
7
|
require 'polisher/vendor'
|
8
|
+
require 'polisher/component'
|
9
|
+
require 'polisher/gem_cache'
|
10
|
+
require 'polisher/version_checker'
|
11
|
+
require 'polisher/gem_state'
|
19
12
|
|
20
13
|
module Polisher
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
end
|
50
|
-
|
51
|
-
# Return bool indiicating if the specified file is on the IGNORE_FILES list
|
52
|
-
def self.ignorable_file?(file)
|
53
|
-
IGNORE_FILES.any? do |ignore|
|
54
|
-
ignore.is_a?(Regexp) ? ignore.match(file) : ignore == file
|
14
|
+
deps = ['curb', 'json', 'yaml', 'tempfile', 'pathname', 'fileutils',
|
15
|
+
'awesome_spawn', 'rubygems/installer', 'active_support', 'active_support/core_ext']
|
16
|
+
Component.verify("Gem", *deps) do
|
17
|
+
class Gem
|
18
|
+
include ConfHelpers
|
19
|
+
include HasState
|
20
|
+
include HasVendoredDeps
|
21
|
+
|
22
|
+
conf_attr :diff_cmd, '/usr/bin/diff'
|
23
|
+
|
24
|
+
# Common files shipped in gems that we should ignore
|
25
|
+
IGNORE_FILES = ['.gemtest', '.gitignore', '.travis.yml',
|
26
|
+
/.*.gemspec/, /Gemfile.*/, 'Rakefile',
|
27
|
+
/rspec.*/, '.yardopts', '.rvmrc']
|
28
|
+
|
29
|
+
# Common files shipped in gems that we should mark as doc
|
30
|
+
DOC_FILES = [/\/?CHANGELOG.*/, /\/?CONTRIBUTING.*/, /\/?README.*/, /\/?.*LICENSE/]
|
31
|
+
|
32
|
+
attr_accessor :spec
|
33
|
+
attr_accessor :name
|
34
|
+
attr_accessor :version
|
35
|
+
attr_accessor :deps
|
36
|
+
attr_accessor :dev_deps
|
37
|
+
|
38
|
+
attr_accessor :path
|
39
|
+
|
40
|
+
def file_name
|
41
|
+
"#{name}-#{version}.gem"
|
55
42
|
end
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
silence_warnings do
|
65
|
-
@local_db ||= ::Gem::Specification.all
|
43
|
+
|
44
|
+
def initialize(args = {})
|
45
|
+
@spec = args[:spec]
|
46
|
+
@name = args[:name]
|
47
|
+
@version = args[:version]
|
48
|
+
@path = args[:path]
|
49
|
+
@deps = args[:deps] || []
|
50
|
+
@dev_deps = args[:dev_deps] || []
|
66
51
|
end
|
67
|
-
versions = @local_db.select { |s| s.name == name }.collect { |s| s.version }
|
68
|
-
bl.call(:local_gem, name, versions) unless(bl.nil?)
|
69
|
-
versions
|
70
|
-
end
|
71
|
-
|
72
|
-
# Return new instance of Gem from JSON Specification
|
73
|
-
def self.from_json(json)
|
74
|
-
specj = JSON.parse(json)
|
75
|
-
metadata = {}
|
76
|
-
metadata[:spec] = specj
|
77
|
-
metadata[:name] = specj['name']
|
78
|
-
metadata[:version] = specj['version']
|
79
|
-
|
80
|
-
metadata[:deps] =
|
81
|
-
specj['dependencies']['runtime'].collect { |d|
|
82
|
-
::Gem::Dependency.new d['name'], *d['requirements'].split(',')
|
83
|
-
}
|
84
|
-
|
85
|
-
metadata[:dev_deps] =
|
86
|
-
specj['dependencies']['development'].collect { |d|
|
87
|
-
::Gem::Dependency.new d['name'], d['requirements'].split(',')
|
88
|
-
}
|
89
|
-
|
90
|
-
self.new metadata
|
91
|
-
end
|
92
|
-
|
93
|
-
# Return new instance of Gem from Gemspec
|
94
|
-
def self.from_gemspec(gemspec)
|
95
|
-
gemspec =
|
96
|
-
::Gem::Specification.load(gemspec) if !gemspec.is_a?(::Gem::Specification) &&
|
97
|
-
File.exists?(gemspec)
|
98
|
-
|
99
|
-
metadata = {}
|
100
|
-
metadata[:spec] = gemspec
|
101
|
-
metadata[:name] = gemspec.name
|
102
|
-
metadata[:version] = gemspec.version.to_s
|
103
|
-
|
104
|
-
metadata[:deps] =
|
105
|
-
gemspec.dependencies.select { |dep|
|
106
|
-
dep.type == :runtime
|
107
|
-
}.collect { |dep| dep }
|
108
|
-
|
109
|
-
metadata[:dev_deps] =
|
110
|
-
gemspec.dependencies.select { |dep|
|
111
|
-
dep.type == :development
|
112
|
-
}.collect { |dep| dep }
|
113
|
-
|
114
|
-
self.new metadata
|
115
|
-
end
|
116
|
-
|
117
|
-
# Return new instance of Gem from rubygem
|
118
|
-
def self.from_gem(gem_path)
|
119
|
-
gem = self.parse :gemspec => ::Gem::Package.new(gem_path).spec
|
120
|
-
gem.path = gem_path
|
121
|
-
gem
|
122
|
-
end
|
123
|
-
|
124
|
-
# Parse the specified gemspec & return new Gem instance from metadata
|
125
|
-
#
|
126
|
-
# @param [String,Hash] args contents of actual gemspec of option hash
|
127
|
-
# specifying location of gemspec to parse
|
128
|
-
# @option args [String] :gemspec path to gemspec to load / parse
|
129
|
-
# @return [Polisher::Gem] gem instantiated from gemspec metadata
|
130
|
-
def self.parse(args={})
|
131
|
-
if args.is_a?(String)
|
132
|
-
return self.from_json args
|
133
|
-
|
134
|
-
elsif args.has_key?(:gemspec)
|
135
|
-
return self.from_gemspec args[:gemspec]
|
136
|
-
|
137
|
-
elsif args.has_key?(:gem)
|
138
|
-
return self.from_gem args[:gem]
|
139
52
|
|
53
|
+
# Return bool indicating if the specified file is on the IGNORE_FILES list
|
54
|
+
def self.ignorable_file?(file)
|
55
|
+
IGNORE_FILES.any? do |ignore|
|
56
|
+
ignore.is_a?(Regexp) ? ignore.match(file) : ignore == file
|
57
|
+
end
|
140
58
|
end
|
141
59
|
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
@client ||= Curl::Easy.new
|
148
|
-
end
|
149
|
-
|
150
|
-
# Download the specified gem and return the binary file contents as a string
|
151
|
-
#
|
152
|
-
# @return [String] binary gem contents
|
153
|
-
def self.download_gem(name, version)
|
154
|
-
cached = GemCache.get(name, version)
|
155
|
-
return cached unless cached.nil?
|
156
|
-
|
157
|
-
client.url = "https://rubygems.org/gems/#{name}-#{version}.gem"
|
158
|
-
client.follow_location = true
|
159
|
-
client.http_get
|
160
|
-
gemf = client.body_str
|
161
|
-
|
162
|
-
GemCache.set(name, version, gemf)
|
163
|
-
gemf
|
164
|
-
end
|
165
|
-
|
166
|
-
# Download the local gem and return it as a string
|
167
|
-
def download_gem
|
168
|
-
self.class.download_gem @name, @version
|
169
|
-
end
|
170
|
-
|
171
|
-
# Download the specified gem / version from rubygems and
|
172
|
-
# return instance of Polisher::Gem class corresponding to it
|
173
|
-
def self.from_rubygems(name, version)
|
174
|
-
download_gem name, version
|
175
|
-
self.from_gem downloaded_gem_path(name, version)
|
176
|
-
end
|
177
|
-
|
178
|
-
# Returns path to downloaded gem
|
179
|
-
#
|
180
|
-
# @return [String] path to downloaded gem
|
181
|
-
def self.downloaded_gem_path(name, version)
|
182
|
-
# ensure gem is downloaded
|
183
|
-
self.download_gem(name, version)
|
184
|
-
GemCache.path_for(name, version)
|
185
|
-
end
|
186
|
-
|
187
|
-
# Return path to downloaded gem
|
188
|
-
def downloaded_gem_path
|
189
|
-
self.class.downloaded_gem_path @name, @version
|
190
|
-
end
|
191
|
-
|
192
|
-
# Returns path to gem, either specified one of downloaded one
|
193
|
-
def gem_path
|
194
|
-
@path || downloaded_gem_path
|
195
|
-
end
|
196
|
-
|
197
|
-
# Unpack files & return unpacked directory
|
198
|
-
#
|
199
|
-
# If block is specified, it will be invoked
|
200
|
-
# with directory after which directory will be removed
|
201
|
-
def unpack(&bl)
|
202
|
-
dir = nil
|
203
|
-
pkg = ::Gem::Installer.new gem_path, :unpack => true
|
204
|
-
|
205
|
-
if bl
|
206
|
-
Dir.mktmpdir { |dir|
|
207
|
-
pkg.unpack dir
|
208
|
-
bl.call dir
|
209
|
-
}
|
210
|
-
else
|
211
|
-
dir = Dir.mktmpdir
|
212
|
-
pkg.unpack dir
|
60
|
+
# Return bool indicating if the specified file is on the DOC_FILES list
|
61
|
+
def self.doc_file?(file)
|
62
|
+
DOC_FILES.any? do |doc|
|
63
|
+
doc.is_a?(Regexp) ? doc.match(file) : doc == file
|
64
|
+
end
|
213
65
|
end
|
214
66
|
|
215
|
-
|
216
|
-
|
67
|
+
# Retrieve list of the versions of the specified gem installed locally
|
68
|
+
#
|
69
|
+
# @param [String] name name of the gem to lookup
|
70
|
+
# @param [Callable] bl optional block to invoke with versions retrieved
|
71
|
+
# @return [Array<String>] list of versions of gem installed locally
|
72
|
+
def self.local_versions_for(name, &bl)
|
73
|
+
silence_warnings do
|
74
|
+
@local_db ||= ::Gem::Specification.all
|
75
|
+
end
|
76
|
+
versions = @local_db.select { |s| s.name == name }.collect { |s| s.version }
|
77
|
+
bl.call(:local_gem, name, versions) unless(bl.nil?)
|
78
|
+
versions
|
79
|
+
end
|
80
|
+
|
81
|
+
# Return new instance of Gem from JSON Specification
|
82
|
+
def self.from_json(json)
|
83
|
+
specj = JSON.parse(json)
|
84
|
+
metadata = {}
|
85
|
+
metadata[:spec] = specj
|
86
|
+
metadata[:name] = specj['name']
|
87
|
+
metadata[:version] = specj['version']
|
88
|
+
|
89
|
+
metadata[:deps] =
|
90
|
+
specj['dependencies']['runtime'].collect do |d|
|
91
|
+
::Gem::Dependency.new d['name'], *d['requirements'].split(',')
|
92
|
+
end
|
93
|
+
|
94
|
+
metadata[:dev_deps] =
|
95
|
+
specj['dependencies']['development'].collect do |d|
|
96
|
+
::Gem::Dependency.new d['name'], d['requirements'].split(',')
|
97
|
+
end
|
98
|
+
|
99
|
+
new metadata
|
100
|
+
end
|
101
|
+
|
102
|
+
# Retrieve all versions of gem available on rubygems
|
103
|
+
def self.remote_versions_for(name)
|
104
|
+
client.url = "https://rubygems.org/api/v1/versions/#{name}.json"
|
105
|
+
client.follow_location = true
|
106
|
+
client.http_get
|
107
|
+
json = JSON.parse(client.body_str)
|
108
|
+
json.collect { |version| version['number'] }
|
109
|
+
end
|
110
|
+
|
111
|
+
# Retieve latest version of gem available on rubygems
|
112
|
+
def self.latest_version_of(name)
|
113
|
+
remote_versions_for(name).first
|
114
|
+
end
|
115
|
+
|
116
|
+
# Return new instance of Gem from Gemspec
|
117
|
+
def self.from_gemspec(gemspec)
|
118
|
+
gemspec =
|
119
|
+
::Gem::Specification.load(gemspec) if !gemspec.is_a?(::Gem::Specification) &&
|
120
|
+
File.exist?(gemspec)
|
121
|
+
|
122
|
+
metadata = {}
|
123
|
+
metadata[:spec] = gemspec
|
124
|
+
metadata[:name] = gemspec.name
|
125
|
+
metadata[:version] = gemspec.version.to_s
|
126
|
+
|
127
|
+
metadata[:deps] =
|
128
|
+
gemspec.dependencies.select { |dep|
|
129
|
+
dep.type == :runtime
|
130
|
+
}.collect { |dep| dep }
|
131
|
+
|
132
|
+
metadata[:dev_deps] =
|
133
|
+
gemspec.dependencies.select { |dep|
|
134
|
+
dep.type == :development
|
135
|
+
}.collect { |dep| dep }
|
136
|
+
|
137
|
+
new metadata
|
138
|
+
end
|
139
|
+
|
140
|
+
# Return new instance of Gem from rubygem
|
141
|
+
def self.from_gem(gem_path)
|
142
|
+
gem = parse :gemspec => ::Gem::Package.new(gem_path).spec
|
143
|
+
gem.path = gem_path
|
144
|
+
gem
|
145
|
+
end
|
146
|
+
|
147
|
+
# Parse the specified gemspec & return new Gem instance from metadata
|
148
|
+
#
|
149
|
+
# @param [String,Hash] args contents of actual gemspec of option hash
|
150
|
+
# specifying location of gemspec to parse
|
151
|
+
# @option args [String] :gemspec path to gemspec to load / parse
|
152
|
+
# @return [Polisher::Gem] gem instantiated from gemspec metadata
|
153
|
+
def self.parse(args={})
|
154
|
+
if args.is_a?(String)
|
155
|
+
return from_json args
|
156
|
+
|
157
|
+
elsif args.key?(:gemspec)
|
158
|
+
return from_gemspec args[:gemspec]
|
159
|
+
|
160
|
+
elsif args.key?(:gem)
|
161
|
+
return from_gem args[:gem]
|
217
162
|
|
218
|
-
# Iterate over each file in gem invoking block with path
|
219
|
-
def each_file(&bl)
|
220
|
-
self.unpack do |dir|
|
221
|
-
Pathname(dir).find do |path|
|
222
|
-
next if path.to_s == dir.to_s
|
223
|
-
pathstr = path.to_s.gsub("#{dir}/", '')
|
224
|
-
bl.call pathstr unless pathstr.blank?
|
225
163
|
end
|
164
|
+
|
165
|
+
new
|
226
166
|
end
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
167
|
+
|
168
|
+
# Return handler to internal curl helper
|
169
|
+
def self.client
|
170
|
+
@client ||= Curl::Easy.new
|
171
|
+
end
|
172
|
+
|
173
|
+
# Download the specified gem and return the binary file contents as a string
|
174
|
+
#
|
175
|
+
# @return [String] binary gem contents
|
176
|
+
def self.download_gem(name, version)
|
177
|
+
cached = GemCache.get(name, version)
|
178
|
+
return cached unless cached.nil?
|
179
|
+
|
180
|
+
client.url = "https://rubygems.org/gems/#{name}-#{version}.gem"
|
181
|
+
client.follow_location = true
|
182
|
+
client.http_get
|
183
|
+
gemf = client.body_str
|
184
|
+
|
185
|
+
GemCache.set(name, version, gemf)
|
186
|
+
gemf
|
187
|
+
end
|
188
|
+
|
189
|
+
# Download the local gem and return it as a string
|
190
|
+
def download_gem
|
191
|
+
self.class.download_gem @name, @version
|
192
|
+
end
|
193
|
+
|
194
|
+
# Download the specified gem / version from rubygems and
|
195
|
+
# return instance of Polisher::Gem class corresponding to it
|
196
|
+
def self.from_rubygems(name, version)
|
197
|
+
download_gem name, version
|
198
|
+
from_gem downloaded_gem_path(name, version)
|
199
|
+
end
|
200
|
+
|
201
|
+
# Returns path to downloaded gem
|
202
|
+
#
|
203
|
+
# @return [String] path to downloaded gem
|
204
|
+
def self.downloaded_gem_path(name, version)
|
205
|
+
# ensure gem is downloaded
|
206
|
+
download_gem name, version
|
207
|
+
GemCache.path_for(name, version)
|
208
|
+
end
|
209
|
+
|
210
|
+
# Return path to downloaded gem
|
211
|
+
def downloaded_gem_path
|
212
|
+
self.class.downloaded_gem_path @name, @version
|
213
|
+
end
|
214
|
+
|
215
|
+
# Returns path to gem, either specified one of downloaded one
|
216
|
+
def gem_path
|
217
|
+
@path || downloaded_gem_path
|
218
|
+
end
|
219
|
+
|
220
|
+
# Unpack files & return unpacked directory
|
221
|
+
#
|
222
|
+
# If block is specified, it will be invoked
|
223
|
+
# with directory after which directory will be removed
|
224
|
+
def unpack(&bl)
|
225
|
+
dir = nil
|
226
|
+
pkg = ::Gem::Installer.new gem_path, :unpack => true
|
227
|
+
|
228
|
+
if bl
|
229
|
+
Dir.mktmpdir do |tmpdir|
|
230
|
+
pkg.unpack tmpdir
|
231
|
+
bl.call tmpdir
|
232
|
+
end
|
233
|
+
else
|
234
|
+
dir = Dir.mktmpdir
|
235
|
+
pkg.unpack dir
|
236
|
+
end
|
237
|
+
|
238
|
+
dir
|
239
|
+
end
|
240
|
+
|
241
|
+
# Iterate over each file in gem invoking block with path
|
242
|
+
def each_file(&bl)
|
243
|
+
unpack do |dir|
|
244
|
+
Pathname(dir).detect do |path|
|
245
|
+
next if path.to_s == dir.to_s
|
246
|
+
pathstr = path.to_s.gsub("#{dir}/", '')
|
247
|
+
bl.call pathstr unless pathstr.blank?
|
248
|
+
end
|
237
249
|
end
|
238
|
-
files
|
239
250
|
end
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
gem = self.parse spec
|
250
|
-
gem
|
251
|
-
end
|
252
|
-
|
253
|
-
# Retreive versions of gem available in all configured targets (optionally recursively)
|
254
|
-
#
|
255
|
-
# @param [Hash] args hash of options to configure retrieval
|
256
|
-
# @option args [Boolean] :recursive indicates if versions of dependencies
|
257
|
-
# should also be retrieved
|
258
|
-
# @option args [Boolean] :dev_deps indicates if versions of development
|
259
|
-
# dependencies should also be retrieved
|
260
|
-
# @return [Hash<name,versions>] hash of name to list of versions for gem
|
261
|
-
# (and dependencies if specified)
|
262
|
-
def versions(args={}, &bl)
|
263
|
-
recursive = args[:recursive]
|
264
|
-
dev_deps = args[:dev_deps]
|
265
|
-
versions = args[:versions] || {}
|
266
|
-
|
267
|
-
gem_versions = Polisher::VersionChecker.versions_for(self.name, &bl)
|
268
|
-
versions.merge!({ self.name => gem_versions })
|
269
|
-
args[:versions] = versions
|
270
|
-
|
271
|
-
if recursive
|
272
|
-
self.deps.each { |dep|
|
273
|
-
unless versions.has_key?(dep.name)
|
274
|
-
gem = Polisher::Gem.retrieve(dep.name)
|
275
|
-
versions.merge! gem.versions(args, &bl)
|
251
|
+
|
252
|
+
# Retrieve the list of paths to files in the gem
|
253
|
+
#
|
254
|
+
# @return [Array<String>] list of files in the gem
|
255
|
+
def file_paths
|
256
|
+
@file_paths ||= begin
|
257
|
+
files = []
|
258
|
+
each_file do |path|
|
259
|
+
files << path
|
276
260
|
end
|
277
|
-
|
261
|
+
files
|
262
|
+
end
|
263
|
+
end
|
278
264
|
|
279
|
-
|
280
|
-
|
281
|
-
|
265
|
+
# Retrieve gem metadata and contents from rubygems.org
|
266
|
+
#
|
267
|
+
# @param [String] name string name of gem to retrieve
|
268
|
+
# @return [Polisher::Gem] representation of gem
|
269
|
+
def self.retrieve(name)
|
270
|
+
gem_json_path = "https://rubygems.org/api/v1/gems/#{name}.json"
|
271
|
+
spec = Curl::Easy.http_get(gem_json_path).body_str
|
272
|
+
gem = parse spec
|
273
|
+
gem
|
274
|
+
end
|
275
|
+
|
276
|
+
# Retreive versions of gem available in all configured targets (optionally recursively)
|
277
|
+
#
|
278
|
+
# @param [Hash] args hash of options to configure retrieval
|
279
|
+
# @option args [Boolean] :recursive indicates if versions of dependencies
|
280
|
+
# should also be retrieved
|
281
|
+
# @option args [Boolean] :dev_deps indicates if versions of development
|
282
|
+
# dependencies should also be retrieved
|
283
|
+
# @retrieve versions of all gem dependencies available in configured targets
|
284
|
+
def dependency_versions(args = {}, &bl)
|
285
|
+
versions = args[:versions] || {}
|
286
|
+
check_deps = args[:dev] ? dev_deps : deps
|
287
|
+
|
288
|
+
check_deps.each do |dep|
|
289
|
+
unless versions.key?(dep.name)
|
290
|
+
begin
|
282
291
|
gem = Polisher::Gem.retrieve(dep.name)
|
283
292
|
versions.merge! gem.versions(args, &bl)
|
293
|
+
rescue
|
294
|
+
unknown = Polisher::VersionChecker.unknown_version(:all, dep.name, &bl)
|
295
|
+
versions.merge! dep.name => unknown
|
284
296
|
end
|
285
|
-
|
297
|
+
end
|
298
|
+
|
299
|
+
args[:versions] = versions
|
286
300
|
end
|
301
|
+
|
302
|
+
versions
|
287
303
|
end
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
304
|
+
|
305
|
+
# (and dependencies if specified)
|
306
|
+
def versions(args = {}, &bl)
|
307
|
+
local_args = Hash[args]
|
308
|
+
recursive = local_args[:recursive]
|
309
|
+
dev_deps = local_args[:dev_deps]
|
310
|
+
versions = local_args[:versions] || {}
|
311
|
+
|
312
|
+
gem_versions = Polisher::VersionChecker.versions_for(name, &bl)
|
313
|
+
versions.merge! name => gem_versions
|
314
|
+
local_args[:versions] = versions
|
315
|
+
|
316
|
+
if recursive
|
317
|
+
dependency_versions local_args
|
318
|
+
dependency_versions local_args.merge(:dev => true) if dev_deps
|
319
|
+
end
|
320
|
+
|
321
|
+
versions
|
306
322
|
end
|
307
323
|
|
308
|
-
out
|
309
|
-
end
|
310
324
|
|
311
|
-
|
325
|
+
# Return diff of content in this gem against other
|
326
|
+
def diff(other)
|
327
|
+
require_cmd! diff_cmd
|
328
|
+
out = nil
|
329
|
+
|
330
|
+
begin
|
331
|
+
this_dir = unpack
|
332
|
+
other_dir = other.is_a?(Polisher::Gem) ? other.unpack :
|
333
|
+
(other.is_a?(Polisher::Git::Repo) ? other.path : other)
|
334
|
+
result = AwesomeSpawn.run("#{diff_cmd} -r #{this_dir} #{other_dir}")
|
335
|
+
out = result.output.gsub("#{this_dir}", 'a').gsub("#{other_dir}", 'b')
|
336
|
+
rescue
|
337
|
+
ensure
|
338
|
+
FileUtils.rm_rf this_dir unless this_dir.nil?
|
339
|
+
FileUtils.rm_rf other_dir unless other_dir.nil? ||
|
340
|
+
!other.is_a?(Polisher::Gem)
|
341
|
+
end
|
342
|
+
|
343
|
+
out
|
344
|
+
end
|
345
|
+
end # class Gem
|
346
|
+
end # Component.verify("Gem")
|
312
347
|
end # module Polisher
|