polisher 0.6.1 → 0.7.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 +1 -1
- data/bin/binary_gem_resolver.rb +1 -1
- data/bin/gem_dependency_checker.rb +4 -2
- data/bin/git_gem_updater.rb +3 -3
- data/bin/ruby_rpm_spec_updater.rb +2 -3
- data/lib/polisher.rb +1 -1
- data/lib/polisher/apt.rb +1 -1
- data/lib/polisher/bodhi.rb +8 -10
- data/lib/polisher/bugzilla.rb +3 -1
- data/lib/polisher/core.rb +9 -1
- data/lib/polisher/errata.rb +26 -14
- data/lib/polisher/fedora.rb +1 -1
- data/lib/polisher/formatter.rb +1 -0
- data/lib/polisher/gem.rb +124 -39
- data/lib/polisher/gem_cache.rb +34 -0
- data/lib/polisher/gemfile.rb +12 -3
- data/lib/polisher/gemspec.rb +1 -1
- data/lib/polisher/git.rb +166 -68
- data/lib/polisher/git_cache.rb +25 -0
- data/lib/polisher/koji.rb +1 -1
- data/lib/polisher/rhn.rb +1 -1
- data/lib/polisher/rpmspec.rb +263 -25
- data/lib/polisher/upstream.rb +1 -1
- data/lib/polisher/vendor.rb +1 -1
- data/lib/polisher/version.rb +2 -2
- data/lib/polisher/version_checker.rb +6 -1
- data/lib/polisher/yum.rb +1 -1
- data/spec/bodhi_spec.rb +1 -1
- data/spec/core_spec.rb +3 -3
- data/spec/errata_spec.rb +1 -1
- data/spec/fedora_spec.rb +1 -1
- data/spec/gem_spec.rb +159 -17
- data/spec/gemfile_spec.rb +2 -2
- data/spec/git_spec.rb +298 -94
- data/spec/koji_spec.rb +1 -1
- data/spec/rpmspec_spec.rb +435 -6
- data/spec/spec_helper.rb +41 -6
- data/spec/upstream_spec.rb +1 -1
- data/spec/yum_spec.rb +1 -1
- metadata +20 -3
@@ -0,0 +1,34 @@
|
|
1
|
+
# Mechanism to cache gems
|
2
|
+
#
|
3
|
+
# Licensed under the MIT license
|
4
|
+
# Copyright (C) 2013-2014 Red Hat, Inc.
|
5
|
+
|
6
|
+
require 'fileutils'
|
7
|
+
|
8
|
+
module Polisher
|
9
|
+
class GemCache
|
10
|
+
DIR = "#{ENV['HOME']}/.polisher/gems"
|
11
|
+
|
12
|
+
def self.create!
|
13
|
+
FileUtils.mkdir_p(DIR) unless File.directory?(DIR)
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.clear!
|
17
|
+
FileUtils.rm_rf(DIR)
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.path_for(name, version)
|
21
|
+
"#{DIR}/#{name}-#{version}.gem"
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.get(name, version)
|
25
|
+
path = path_for(name, version)
|
26
|
+
File.exists?(path) ? File.read(path) : nil
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.set(name, version, gem)
|
30
|
+
self.create!
|
31
|
+
File.write(path_for(name, version), gem)
|
32
|
+
end
|
33
|
+
end # class GemCache
|
34
|
+
end # module Polisher
|
data/lib/polisher/gemfile.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# Polisher Gemfile Represenation
|
2
2
|
#
|
3
3
|
# Licensed under the MIT license
|
4
|
-
# Copyright (C) 2013 Red Hat, Inc.
|
4
|
+
# Copyright (C) 2013-2014 Red Hat, Inc.
|
5
5
|
|
6
6
|
require 'bundler'
|
7
7
|
|
@@ -39,13 +39,13 @@ module Polisher
|
|
39
39
|
attr_accessor :dev_deps
|
40
40
|
|
41
41
|
# always empty array, for interface compatability
|
42
|
-
attr_accessor :
|
42
|
+
attr_accessor :file_paths
|
43
43
|
|
44
44
|
def initialize(args={})
|
45
45
|
@version = nil
|
46
46
|
@deps = args[:deps]
|
47
47
|
@dev_deps = args[:dev_deps]
|
48
|
-
@
|
48
|
+
@file_paths = []
|
49
49
|
end
|
50
50
|
|
51
51
|
# Parse the specified gemfile & return new Gemfile instance from metadata
|
@@ -68,5 +68,14 @@ module Polisher
|
|
68
68
|
|
69
69
|
self.new metadata
|
70
70
|
end
|
71
|
+
|
72
|
+
# TODO simply alias for gems in gemfile?
|
73
|
+
def vendored
|
74
|
+
end
|
75
|
+
|
76
|
+
# TODO retrieve gems which differ from
|
77
|
+
# rubygems.org/other upstream sources
|
78
|
+
def patched
|
79
|
+
end
|
71
80
|
end # class Gemfile
|
72
81
|
end # module Polisher
|
data/lib/polisher/gemspec.rb
CHANGED
data/lib/polisher/git.rb
CHANGED
@@ -1,112 +1,209 @@
|
|
1
|
-
# Polisher
|
1
|
+
# Polisher Git Entity Representations
|
2
2
|
#
|
3
3
|
# Licensed under the MIT license
|
4
|
-
# Copyright (C) 2013 Red Hat, Inc.
|
5
|
-
|
6
|
-
# TODO use ruby git api and others
|
4
|
+
# Copyright (C) 2013-2014 Red Hat, Inc.
|
7
5
|
|
8
6
|
require 'tmpdir'
|
9
7
|
require 'awesome_spawn'
|
10
8
|
require 'polisher/rpmspec'
|
9
|
+
require 'polisher/git_cache'
|
11
10
|
|
12
11
|
module Polisher
|
13
|
-
|
12
|
+
# Git Repository
|
13
|
+
class GitRepo
|
14
|
+
# TODO use ruby git api
|
15
|
+
GIT_CMD = '/usr/bin/git'
|
16
|
+
|
17
|
+
attr_accessor :url
|
18
|
+
|
19
|
+
def initialize(args={})
|
20
|
+
@url = args[:url]
|
21
|
+
end
|
22
|
+
|
23
|
+
def path
|
24
|
+
GitCache.path_for(@url)
|
25
|
+
end
|
26
|
+
|
27
|
+
def clone
|
28
|
+
AwesomeSpawn.run "#{GIT_CMD} clone #{url} #{path}"
|
29
|
+
end
|
30
|
+
|
31
|
+
def cloned?
|
32
|
+
File.directory?(path)
|
33
|
+
end
|
34
|
+
|
35
|
+
def in_repo
|
36
|
+
Dir.chdir path do
|
37
|
+
yield
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Note be careful when invoking:
|
42
|
+
def reset!
|
43
|
+
in_repo { AwesomeSpawn.run "#{GIT_CMD} reset HEAD~ --hard" }
|
44
|
+
self
|
45
|
+
end
|
46
|
+
|
47
|
+
def pull
|
48
|
+
in_repo { AwesomeSpawn.run "#{GIT_CMD} pull" }
|
49
|
+
self
|
50
|
+
end
|
51
|
+
|
52
|
+
def checkout(tgt)
|
53
|
+
in_repo { AwesomeSpawn.run "#{GIT_CMD} checkout #{tgt}" }
|
54
|
+
self
|
55
|
+
end
|
56
|
+
|
57
|
+
def commit(msg)
|
58
|
+
in_repo { AwesomeSpawn.run "#{GIT_CMD} commit -m '#{msg}'" }
|
59
|
+
self
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# DistGit Package Representation
|
64
|
+
class GitPackage < GitRepo
|
14
65
|
attr_accessor :name
|
15
66
|
attr_accessor :version
|
16
67
|
|
17
68
|
# TODO these should be to be configurable
|
69
|
+
RPM_PREFIX = 'rubygem-'
|
18
70
|
PKG_CMD = '/usr/bin/fedpkg'
|
19
|
-
GIT_CMD = '/usr/bin/git'
|
20
71
|
BUILD_CMD = '/usr/bin/koji'
|
21
72
|
BUILD_TGT = 'rawhide'
|
73
|
+
|
22
74
|
MD5SUM_CMD = '/usr/bin/md5sum'
|
23
75
|
SED_CMD = '/usr/bin/sed'
|
24
|
-
RPM_PREFIX = 'rubygem-'
|
25
76
|
DIST_GIT_URL = 'git://pkgs.fedoraproject.org/'
|
26
77
|
|
27
78
|
def initialize(args={})
|
28
79
|
@name = args[:name]
|
29
80
|
@version = args[:version]
|
81
|
+
super(args)
|
30
82
|
end
|
31
83
|
|
32
84
|
# Return full rpm name of package containing optional prefix
|
33
85
|
def rpm_name
|
34
|
-
"#{RPM_PREFIX}#{self.name}"
|
86
|
+
@rpm_name ||= "#{RPM_PREFIX}#{self.name}"
|
35
87
|
end
|
36
88
|
|
37
89
|
# Return full srpm file name of package
|
38
90
|
def srpm
|
39
|
-
"#{rpm_name}-#{self.version}-1.*.src.rpm"
|
91
|
+
@srpm ||= "#{rpm_name}-#{self.version}-1.*.src.rpm"
|
40
92
|
end
|
41
93
|
|
42
94
|
# Return full spec file name
|
95
|
+
def spec_file
|
96
|
+
@spec_path ||= "#{rpm_name}.spec"
|
97
|
+
end
|
98
|
+
|
99
|
+
# Return handle to instance of Polisher::RPMSpec corresponding to spec
|
43
100
|
def spec
|
44
|
-
|
101
|
+
@spec ||= in_repo { Polisher::RPMSpec.parse spec_file }
|
45
102
|
end
|
46
103
|
|
47
|
-
#
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
104
|
+
# Files representing pkg tracked by git
|
105
|
+
def pkg_files
|
106
|
+
@pkg_files ||= [spec_file, 'sources', '.gitignore']
|
107
|
+
end
|
108
|
+
|
109
|
+
# Override path to reference pkg name
|
110
|
+
# @override
|
111
|
+
def path
|
112
|
+
GitCache.path_for(rpm_name)
|
113
|
+
end
|
53
114
|
|
54
|
-
|
115
|
+
# Alias orig clone method to git_clone
|
116
|
+
alias :git_clone :clone
|
117
|
+
|
118
|
+
# Override clone to use PKG_PCMD
|
119
|
+
# @override
|
120
|
+
def clone
|
121
|
+
in_repo do
|
55
122
|
AwesomeSpawn.run "#{PKG_CMD} clone #{rpm_name}"
|
123
|
+
Dir.glob(rpm_name, '*').each { |f| File.move f, '.' }
|
124
|
+
FileUtils.rm_rf rpm_name
|
56
125
|
end
|
57
|
-
|
58
|
-
# cd into working directory
|
59
|
-
Dir.chdir rpm_name
|
60
126
|
|
61
|
-
|
62
|
-
|
127
|
+
self
|
128
|
+
end
|
129
|
+
|
130
|
+
def dead?
|
131
|
+
in_repo { File.exists?('dead.package') }
|
132
|
+
end
|
133
|
+
|
134
|
+
# Clone / init GitPkg
|
135
|
+
def fetch
|
136
|
+
clone unless cloned?
|
137
|
+
raise Exception, "Dead package detected" if dead?
|
138
|
+
checkout 'master'
|
139
|
+
reset!
|
140
|
+
pull
|
141
|
+
|
142
|
+
self
|
143
|
+
end
|
144
|
+
|
145
|
+
# Update the local spec to the specified gem version
|
146
|
+
#
|
147
|
+
# FIXME this should be removed and calls replaced with self.spec.update_to(gem)
|
148
|
+
def update_spec_to(gem)
|
149
|
+
in_repo do
|
150
|
+
replace_version = "s/Version.*/Version: #{gem.version}/"
|
151
|
+
replace_release = "s/Release:.*/Release: 1%{?dist}/"
|
152
|
+
[replace_version, replace_release].each do |replace|
|
153
|
+
AwesomeSpawn.run "#{SED_CMD} -i '#{replace}' #{spec_file}"
|
154
|
+
end
|
63
155
|
end
|
64
|
-
|
65
|
-
# checkout the latest rawhide
|
66
|
-
# TODO allow other branches to be specified
|
67
|
-
AwesomeSpawn.run "#{GIT_CMD} checkout master"
|
68
|
-
AwesomeSpawn.run "#{GIT_CMD} reset HEAD~ --hard"
|
69
|
-
AwesomeSpawn.run "#{GIT_CMD} pull"
|
156
|
+
end
|
70
157
|
|
71
|
-
|
158
|
+
# Generate new sources file
|
159
|
+
def gen_sources_for(gem)
|
160
|
+
in_repo do
|
161
|
+
AwesomeSpawn.run "#{MD5SUM_CMD} #{gem.name}-#{gem.version}.gem > sources"
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
# Update git ignore to ignore gem
|
166
|
+
def ignore(gem)
|
167
|
+
File.open(".gitignore", "w") { |f| f.write "#{gem.name}-#{gem.version}.gem" }
|
72
168
|
end
|
73
169
|
|
74
|
-
# Update the
|
170
|
+
# Update the local pkg to specified gem
|
75
171
|
#
|
76
172
|
# @param [Polisher::Gem] gem instance of gem containing metadata to update to
|
77
173
|
def update_to(gem)
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
File.open(".gitignore", "w") { |f| f.write "#{gem.name}-#{gem.version}.gem" }
|
174
|
+
update_spec_to gem
|
175
|
+
gen_sources_for gem
|
176
|
+
ignore gem
|
177
|
+
self
|
83
178
|
end
|
84
179
|
|
85
|
-
#
|
86
|
-
|
87
|
-
|
88
|
-
AwesomeSpawn.run "#{
|
89
|
-
|
90
|
-
|
91
|
-
AwesomeSpawn.run "#{BUILD_CMD} build --scratch #{BUILD_TGT} #{srpm}"
|
92
|
-
# TODO if build fails, spit out error, exit
|
180
|
+
# Override commit, generate a default msg, always add pkg files
|
181
|
+
# @override
|
182
|
+
def commit(msg=nil)
|
183
|
+
in_repo { AwesomeSpawn.run "#{GIT_CMD} add #{pkg_files.join(' ')}" }
|
184
|
+
super(msg.nil? ? "updated to #{version}" : msg)
|
185
|
+
self
|
93
186
|
end
|
94
187
|
|
95
|
-
#
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
File.open(spec, "r") do |spec|
|
100
|
-
spec.lines.any? { |line| line.include?("%check") }
|
101
|
-
end
|
188
|
+
# Build the srpm
|
189
|
+
def build_srpm
|
190
|
+
in_repo { AwesomeSpawn.run "#{PKG_CMD} srpm" }
|
191
|
+
self
|
102
192
|
end
|
103
193
|
|
104
|
-
#
|
105
|
-
def
|
106
|
-
#
|
107
|
-
|
108
|
-
|
109
|
-
|
194
|
+
# Run a scratch build
|
195
|
+
def scratch_build
|
196
|
+
# TODO if build fails, raise error, else return output
|
197
|
+
cmd = "#{BUILD_CMD} build --scratch #{BUILD_TGT} #{srpm}"
|
198
|
+
in_repo { AwesomeSpawn.run(cmd) }
|
199
|
+
self
|
200
|
+
end
|
201
|
+
|
202
|
+
# Build the pkg
|
203
|
+
def build
|
204
|
+
build_srpm
|
205
|
+
scratch_build
|
206
|
+
self
|
110
207
|
end
|
111
208
|
|
112
209
|
# Retrieve list of the version of the specified package in git
|
@@ -115,23 +212,24 @@ module Polisher
|
|
115
212
|
# @param [Callable] bl optional block to invoke with version retrieved
|
116
213
|
# @return [String] version retrieved, or nil if none found
|
117
214
|
def self.version_for(name, &bl)
|
118
|
-
rpm_name = "#{RPM_PREFIX}#{name}"
|
119
215
|
version = nil
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
spec = Polisher::RPMSpec.parse(File.read("#{rpm_name}.spec"))
|
127
|
-
version = spec.version
|
128
|
-
rescue => e
|
129
|
-
end
|
130
|
-
end
|
216
|
+
gitpkg = self.new :name => name
|
217
|
+
gitpkg.url = "#{DIST_GIT_URL}#{gitpkg.rpm_name}.git"
|
218
|
+
gitpkg.git_clone
|
219
|
+
begin
|
220
|
+
version = gitpkg.spec.version
|
221
|
+
rescue => e
|
131
222
|
end
|
132
223
|
|
133
224
|
bl.call(:git, name, [version]) unless(bl.nil?)
|
134
225
|
version
|
135
226
|
end
|
136
227
|
end # class GitPackage
|
228
|
+
|
229
|
+
# Upstream Git project representation
|
230
|
+
class GitProject < GitRepo
|
231
|
+
# TODO scan project for vendored components
|
232
|
+
def vendored
|
233
|
+
end
|
234
|
+
end
|
137
235
|
end # module Polisher
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# Mechanism to cache git repos
|
2
|
+
#
|
3
|
+
# Licensed under the MIT license
|
4
|
+
# Copyright (C) 2013-2014 Red Hat, Inc.
|
5
|
+
|
6
|
+
require 'fileutils'
|
7
|
+
|
8
|
+
module Polisher
|
9
|
+
class GitCache
|
10
|
+
DIR = "#{ENV['HOME']}/.polisher/git"
|
11
|
+
|
12
|
+
def self.create!
|
13
|
+
FileUtils.mkdir_p(DIR) unless File.directory?(DIR)
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.clear!
|
17
|
+
FileUtils.rm_rf(DIR)
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.path_for(id)
|
21
|
+
self.create!
|
22
|
+
"#{DIR}/#{id.gsub(/[:\/]/, '')}"
|
23
|
+
end
|
24
|
+
end # class GemCache
|
25
|
+
end # module Polisher
|
data/lib/polisher/koji.rb
CHANGED
data/lib/polisher/rhn.rb
CHANGED
data/lib/polisher/rpmspec.rb
CHANGED
@@ -1,15 +1,163 @@
|
|
1
1
|
# Polisher RPM Spec Represenation
|
2
2
|
#
|
3
3
|
# Licensed under the MIT license
|
4
|
-
# Copyright (C) 2013 Red Hat, Inc.
|
4
|
+
# Copyright (C) 2013-2014 Red Hat, Inc.
|
5
5
|
|
6
6
|
require 'gem2rpm'
|
7
|
+
require 'versionomy'
|
7
8
|
require 'active_support/core_ext'
|
8
9
|
|
9
10
|
require 'polisher/core'
|
11
|
+
require 'polisher/gem'
|
10
12
|
|
11
13
|
module Polisher
|
12
14
|
class RPMSpec
|
15
|
+
class Requirement
|
16
|
+
# Bool indiciating if req is a BR
|
17
|
+
attr_accessor :br
|
18
|
+
|
19
|
+
# Name of requirement
|
20
|
+
attr_accessor :name
|
21
|
+
|
22
|
+
# Condition, eg >=, =, etc
|
23
|
+
attr_accessor :condition
|
24
|
+
|
25
|
+
# Version number
|
26
|
+
attr_accessor :version
|
27
|
+
|
28
|
+
# Requirement string
|
29
|
+
def str
|
30
|
+
sp = self.specifier
|
31
|
+
sp.nil? ? "#{@name}" : "#{@name} #{sp}"
|
32
|
+
end
|
33
|
+
|
34
|
+
# Specified string
|
35
|
+
def specifier
|
36
|
+
@version.nil? ? nil : "#{@condition} #{@version}"
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.parse(str, opts={})
|
40
|
+
stra = str.split
|
41
|
+
br = str.include?('BuildRequires')
|
42
|
+
name = condition = version = nil
|
43
|
+
|
44
|
+
if str.include?('Requires')
|
45
|
+
name = stra[1]
|
46
|
+
condition = stra[2]
|
47
|
+
version = stra[3]
|
48
|
+
|
49
|
+
else
|
50
|
+
name = stra[0]
|
51
|
+
condition = stra[1]
|
52
|
+
version = stra[2]
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
req = self.new({:name => name,
|
57
|
+
:condition => condition,
|
58
|
+
:version => version,
|
59
|
+
:br => br}.merge(opts))
|
60
|
+
req
|
61
|
+
end
|
62
|
+
|
63
|
+
def initialize(args={})
|
64
|
+
@br = args[:br] || false
|
65
|
+
@name = args[:name]
|
66
|
+
@condition = args[:condition]
|
67
|
+
@version = args[:version]
|
68
|
+
|
69
|
+
@name.strip! unless @name.nil?
|
70
|
+
@condition.strip! unless @condition.nil?
|
71
|
+
@version.strip! unless @version.nil?
|
72
|
+
end
|
73
|
+
|
74
|
+
def ==(other)
|
75
|
+
@br == other.br &&
|
76
|
+
@name == other.name &&
|
77
|
+
@condition == other.condition &&
|
78
|
+
@version == other.version
|
79
|
+
end
|
80
|
+
|
81
|
+
# Greatest Common Denominator,
|
82
|
+
# Max version in list that is less than the local version
|
83
|
+
def gcd(versions)
|
84
|
+
lversion = Versionomy.parse(self.version)
|
85
|
+
versions.collect { |v| Versionomy.parse(v) }.
|
86
|
+
sort { |a,b| a <=> b }.reverse.
|
87
|
+
find { |v| v < lversion }.to_s
|
88
|
+
end
|
89
|
+
|
90
|
+
# Minimum gem version which satisfies this dependency
|
91
|
+
def min_satisfying_version
|
92
|
+
return "0.0" if self.version.nil? ||
|
93
|
+
self.condition == '<' ||
|
94
|
+
self.condition == '<='
|
95
|
+
return self.version if self.condition == '=' ||
|
96
|
+
self.condition == '>='
|
97
|
+
Versionomy.parse(self.version).bump(:tiny).to_s # self.condition == '>'
|
98
|
+
end
|
99
|
+
|
100
|
+
# Max gem version which satisfies this dependency
|
101
|
+
#
|
102
|
+
# Can't automatically deduce in '<' case, so if that is the conditional
|
103
|
+
# we require a version list, and will return the gcd from it
|
104
|
+
def max_satisfying_version(versions=nil)
|
105
|
+
return Float::INFINITY if self.version.nil? ||
|
106
|
+
self.condition == '>' ||
|
107
|
+
self.condition == '>='
|
108
|
+
return self.version if self.condition == '=' ||
|
109
|
+
self.condition == '<='
|
110
|
+
|
111
|
+
raise ArgumentError if versions.nil?
|
112
|
+
self.gcd(versions)
|
113
|
+
end
|
114
|
+
|
115
|
+
# Minimum gem version for which this dependency fails
|
116
|
+
def min_failing_version
|
117
|
+
raise ArgumentError if self.version.nil?
|
118
|
+
return "0.0" if self.condition == '>' ||
|
119
|
+
self.condition == '>='
|
120
|
+
return self.version if self.condition == '<'
|
121
|
+
Versionomy.parse(self.version).bump(:tiny).to_s # self.condition == '<=' and '='
|
122
|
+
end
|
123
|
+
|
124
|
+
# Max gem version for which this dependency fails
|
125
|
+
#
|
126
|
+
# Can't automatically deduce in '>=', and '=' cases, so if that is the
|
127
|
+
# conditional we require a version list, and will return the gcd from it
|
128
|
+
def max_failing_version(versions=nil)
|
129
|
+
raise ArgumentError if self.version.nil? ||
|
130
|
+
self.condition == '<=' ||
|
131
|
+
self.condition == '<'
|
132
|
+
return self.version if self.condition == '>'
|
133
|
+
|
134
|
+
raise ArgumentError if versions.nil?
|
135
|
+
self.gcd(versions)
|
136
|
+
end
|
137
|
+
|
138
|
+
def matches?(dep)
|
139
|
+
return self == dep if dep.is_a?(self.class)
|
140
|
+
raise ArgumentError unless dep.is_a?(::Gem::Dependency)
|
141
|
+
|
142
|
+
return false if !self.gem? || self.gem_name != dep.name
|
143
|
+
return true if self.version.nil?
|
144
|
+
|
145
|
+
Gem2Rpm::Helpers.expand_requirement([dep.requirement.to_s.split]).
|
146
|
+
any?{ |req|
|
147
|
+
req.first == self.condition && req.last.to_s == self.version
|
148
|
+
}
|
149
|
+
end
|
150
|
+
|
151
|
+
def gem?
|
152
|
+
!!(self.str =~ SPEC_GEM_REQ_MATCHER)
|
153
|
+
end
|
154
|
+
|
155
|
+
def gem_name
|
156
|
+
# XXX need to explicitly run regex here to get $1
|
157
|
+
!!(self.str =~ SPEC_GEM_REQ_MATCHER) ? $1 : nil
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
13
161
|
AUTHOR = "#{ENV['USER']} <#{ENV['USER']}@localhost.localdomain>"
|
14
162
|
|
15
163
|
COMMENT_MATCHER = /^\s*#.*/
|
@@ -24,18 +172,24 @@ module Polisher
|
|
24
172
|
SPEC_CHANGELOG_MATCHER = /^%changelog$/
|
25
173
|
SPEC_FILES_MATCHER = /^%files$/
|
26
174
|
SPEC_SUBPKG_FILES_MATCHER = /^%files\s*(.*)$/
|
175
|
+
SPEC_CHECK_MATCHER = /^%check$/
|
27
176
|
|
28
177
|
FILE_MACRO_MATCHERS =
|
29
178
|
[/^%doc\s/, /^%config\s/, /^%attr\s/,
|
30
179
|
/^%verify\s/, /^%docdir.*/, /^%dir\s/,
|
31
|
-
/^%defattr.*/, /^%exclude\s/, /^%{gem_instdir}
|
180
|
+
/^%defattr.*/, /^%exclude\s/, /^%{gem_instdir}\/+/]
|
32
181
|
|
33
182
|
FILE_MACRO_REPLACEMENTS =
|
34
|
-
{"%{_bindir}" => '
|
35
|
-
"%{gem_libdir}" => '
|
183
|
+
{"%{_bindir}" => 'bin',
|
184
|
+
"%{gem_libdir}" => 'lib'}
|
36
185
|
|
37
186
|
attr_accessor :metadata
|
38
187
|
|
188
|
+
# Return the currently configured author
|
189
|
+
def self.current_author
|
190
|
+
ENV['POLISHER_AUTHOR'] || AUTHOR
|
191
|
+
end
|
192
|
+
|
39
193
|
def initialize(metadata={})
|
40
194
|
@metadata = metadata
|
41
195
|
end
|
@@ -51,6 +205,32 @@ module Polisher
|
|
51
205
|
end
|
52
206
|
end
|
53
207
|
|
208
|
+
def has_check?
|
209
|
+
@metadata.has_key?(:has_check) && @metadata[:has_check]
|
210
|
+
end
|
211
|
+
|
212
|
+
# Return all the requirements for the specified gem
|
213
|
+
def requirements_for_gem(gem_name)
|
214
|
+
@metadata[:requires].nil? ? [] :
|
215
|
+
@metadata[:requires].select { |r| r.gem_name == gem_name }
|
216
|
+
end
|
217
|
+
|
218
|
+
# Return bool indicating if this spec specifies all the
|
219
|
+
# requirements in the specified gem dependency
|
220
|
+
def has_all_requirements_for?(gem_dep)
|
221
|
+
reqs = self.requirements_for_gem gem_dep.name
|
222
|
+
# create a spec requirement dependency for each expanded subrequirement,
|
223
|
+
# verify we can find a match for that
|
224
|
+
gem_dep.requirement.to_s.split(',').all? { |greq|
|
225
|
+
Gem2Rpm::Helpers.expand_requirement([greq.split]).all? { |ereq|
|
226
|
+
tereq = Requirement.new :name => "rubygem(#{gem_dep.name})",
|
227
|
+
:condition => ereq.first,
|
228
|
+
:version => ereq.last.to_s
|
229
|
+
reqs.any? { |req| req.matches?(tereq)}
|
230
|
+
}
|
231
|
+
}
|
232
|
+
end
|
233
|
+
|
54
234
|
# Parse the specified rpm spec and return new RPMSpec instance from metadata
|
55
235
|
#
|
56
236
|
# @param [String] string contents of spec to parse
|
@@ -87,12 +267,12 @@ module Polisher
|
|
87
267
|
elsif l =~ SPEC_REQUIRES_MATCHER &&
|
88
268
|
!in_subpackage
|
89
269
|
meta[:requires] ||= []
|
90
|
-
meta[:requires] << $1.strip
|
270
|
+
meta[:requires] << RPMSpec::Requirement.parse($1.strip)
|
91
271
|
|
92
272
|
elsif l =~ SPEC_BUILD_REQUIRES_MATCHER &&
|
93
273
|
!in_subpackage
|
94
274
|
meta[:build_requires] ||= []
|
95
|
-
meta[:build_requires] << $1.strip
|
275
|
+
meta[:build_requires] << RPMSpec::Requirement.parse($1.strip)
|
96
276
|
|
97
277
|
elsif l =~ SPEC_CHANGELOG_MATCHER
|
98
278
|
in_changelog = true
|
@@ -104,6 +284,9 @@ module Polisher
|
|
104
284
|
elsif l =~ SPEC_SUBPKG_FILES_MATCHER
|
105
285
|
subpkg_name = $1.strip
|
106
286
|
in_files = true
|
287
|
+
|
288
|
+
elsif l =~ SPEC_CHECK_MATCHER
|
289
|
+
meta[:has_check] = true
|
107
290
|
|
108
291
|
elsif in_changelog
|
109
292
|
meta[:changelog] ||= ""
|
@@ -128,6 +311,9 @@ module Polisher
|
|
128
311
|
|
129
312
|
# Update RPMSpec metadata to new gem
|
130
313
|
#
|
314
|
+
# TODO add option to enable/disable certain aspects
|
315
|
+
# from being updates
|
316
|
+
#
|
131
317
|
# @param [Polisher::Gem] new_source new gem to update rpmspec to
|
132
318
|
def update_to(new_source)
|
133
319
|
update_deps_from(new_source)
|
@@ -145,9 +331,9 @@ module Polisher
|
|
145
331
|
|
146
332
|
@metadata[:requires] ||= []
|
147
333
|
@metadata[:requires].each { |r|
|
148
|
-
if r
|
334
|
+
if !r.gem?
|
149
335
|
non_gem_requires << r
|
150
|
-
elsif !new_source.deps.any? { |d| d.name ==
|
336
|
+
elsif !new_source.deps.any? { |d| d.name == r.gem_name }
|
151
337
|
extra_gem_requires << r
|
152
338
|
#else
|
153
339
|
# spec_version = $2
|
@@ -156,9 +342,9 @@ module Polisher
|
|
156
342
|
|
157
343
|
@metadata[:build_requires] ||= []
|
158
344
|
@metadata[:build_requires].each { |r|
|
159
|
-
if r
|
345
|
+
if !r.gem?
|
160
346
|
non_gem_brequires << r
|
161
|
-
elsif !new_source.deps.any? { |d| d.name ==
|
347
|
+
elsif !new_source.deps.any? { |d| d.name == r.gem_name }
|
162
348
|
extra_gem_brequires << r
|
163
349
|
#else
|
164
350
|
# spec_version = $2
|
@@ -171,10 +357,13 @@ module Polisher
|
|
171
357
|
non_gem_requires + extra_gem_requires +
|
172
358
|
new_source.deps.collect { |r|
|
173
359
|
r.requirement.to_s.split(',').collect { |req|
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
360
|
+
expanded = Gem2Rpm::Helpers.expand_requirement [req.split]
|
361
|
+
expanded.collect { |e|
|
362
|
+
RPMSpec::Requirement.new :name => "rubygem(#{r.name})",
|
363
|
+
:condition => e.first.to_s,
|
364
|
+
:version => e.last.to_s,
|
365
|
+
:br => false
|
366
|
+
}
|
178
367
|
}
|
179
368
|
}.flatten
|
180
369
|
|
@@ -182,23 +371,30 @@ module Polisher
|
|
182
371
|
non_gem_brequires + extra_gem_brequires +
|
183
372
|
new_source.dev_deps.collect { |r|
|
184
373
|
r.requirement.to_s.split(',').collect { |req|
|
185
|
-
|
374
|
+
expanded = Gem2Rpm::Helpers.expand_requirement [req.split]
|
375
|
+
expanded.collect { |e|
|
376
|
+
RPMSpec::Requirement.new :name => "rubygem(#{r.name})",
|
377
|
+
:condition => e.first.to_s,
|
378
|
+
:version => e.last.to_s,
|
379
|
+
:br => true
|
380
|
+
}
|
186
381
|
}
|
187
382
|
}.flatten
|
188
383
|
end
|
189
384
|
|
190
385
|
def update_files_from(new_source)
|
191
|
-
to_add = new_source.
|
386
|
+
to_add = new_source.file_paths
|
192
387
|
@metadata[:files] ||= {}
|
193
388
|
@metadata[:files].each { |pkg,spec_files|
|
194
|
-
(new_source.
|
389
|
+
(new_source.file_paths & to_add).each { |gem_file|
|
195
390
|
# skip files already included in spec or in dir in spec
|
196
391
|
has_file = spec_files.any? { |sf|
|
197
392
|
gem_file.gsub(sf,'') != gem_file
|
198
393
|
}
|
199
394
|
|
200
395
|
to_add.delete(gem_file)
|
201
|
-
to_add << gem_file.rpmize if !has_file
|
396
|
+
to_add << gem_file.rpmize if !has_file &&
|
397
|
+
!Gem.ignorable_file?(gem_file)
|
202
398
|
}
|
203
399
|
}
|
204
400
|
|
@@ -208,14 +404,11 @@ module Polisher
|
|
208
404
|
def update_metadata_from(new_source)
|
209
405
|
# update to new version
|
210
406
|
@metadata[:version] = new_source.version
|
211
|
-
|
212
|
-
# better release updating ?
|
213
|
-
release = "1%{?dist}"
|
214
|
-
@metadata[:release] = release
|
407
|
+
@metadata[:release] = "1%{?dist}"
|
215
408
|
|
216
409
|
# add changelog entry
|
217
410
|
changelog_entry = <<EOS
|
218
|
-
* #{Time.now.strftime("%a %b %d %Y")} #{
|
411
|
+
* #{Time.now.strftime("%a %b %d %Y")} #{RPMSpec.current_author} - #{@metadata[:version]}-1
|
219
412
|
- Update to version #{new_source.version}
|
220
413
|
EOS
|
221
414
|
@metadata[:changelog_entries] ||= []
|
@@ -256,8 +449,8 @@ EOS
|
|
256
449
|
|
257
450
|
contents.slice!(tp...ltpn)
|
258
451
|
contents.insert tp,
|
259
|
-
(@metadata[:requires].collect { |r| "Requires: #{r}" } +
|
260
|
-
@metadata[:build_requires].collect { |r| "BuildRequires: #{r}" }).join("\n")
|
452
|
+
(@metadata[:requires].collect { |r| "Requires: #{r.str}" } +
|
453
|
+
@metadata[:build_requires].collect { |r| "BuildRequires: #{r.str}" }).join("\n")
|
261
454
|
|
262
455
|
# add new files
|
263
456
|
fp = contents.index SPEC_FILES_MATCHER
|
@@ -270,5 +463,50 @@ EOS
|
|
270
463
|
contents
|
271
464
|
end
|
272
465
|
|
466
|
+
def compare(upstream_source)
|
467
|
+
same = {}
|
468
|
+
diff = {}
|
469
|
+
upstream_source.deps.each do |d|
|
470
|
+
spec_reqs = self.requirements_for_gem(d.name)
|
471
|
+
spec_reqs_specifier = spec_reqs.empty? ? nil :
|
472
|
+
spec_reqs.collect { |req| req.specifier }
|
473
|
+
|
474
|
+
if spec_reqs.nil?
|
475
|
+
diff[d.name] = {:spec => nil,
|
476
|
+
:upstream => d.requirement.to_s}
|
477
|
+
|
478
|
+
elsif !spec_reqs.any? { |req| req.matches?(d) } ||
|
479
|
+
!self.has_all_requirements_for?(d)
|
480
|
+
diff[d.name] = {:spec => spec_reqs_specifier,
|
481
|
+
:upstream => d.requirement.to_s}
|
482
|
+
|
483
|
+
elsif !diff.has_key?(d.name)
|
484
|
+
same[d.name] = {:spec => spec_reqs_specifier,
|
485
|
+
:upstream => d.requirement.to_s }
|
486
|
+
end
|
487
|
+
end
|
488
|
+
|
489
|
+
@metadata[:requires].each do |req|
|
490
|
+
next unless req.gem?
|
491
|
+
|
492
|
+
upstream_dep = upstream_source.deps.find { |d| d.name == req.gem_name }
|
493
|
+
|
494
|
+
if upstream_dep.nil?
|
495
|
+
diff[req.gem_name] = {:spec => req.specifier,
|
496
|
+
:upstream => nil}
|
497
|
+
|
498
|
+
elsif !req.matches?(upstream_dep)
|
499
|
+
diff[req.gem_name] = {:spec => req.specifier,
|
500
|
+
:upstream => upstream_dep.requirement.to_s }
|
501
|
+
|
502
|
+
elsif !diff.has_key?(req.gem_name)
|
503
|
+
same[req.gem_name] = {:spec => req.specifier,
|
504
|
+
:upstream => upstream_dep.requirement.to_s }
|
505
|
+
end
|
506
|
+
end unless @metadata[:requires].nil?
|
507
|
+
|
508
|
+
{:same => same, :diff => diff}
|
509
|
+
end
|
510
|
+
|
273
511
|
end # class RPMSpec
|
274
512
|
end # module Polisher
|