polisher 0.9.1 → 0.10.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -3,379 +3,443 @@
3
3
  # Licensed under the MIT license
4
4
  # Copyright (C) 2013-2014 Red Hat, Inc.
5
5
 
6
- require 'gem2rpm'
7
- require 'versionomy'
8
- require 'active_support/core_ext'
9
-
10
6
  require 'polisher/core'
11
7
  require 'polisher/gem'
12
8
  require 'polisher/rpm/requirement'
9
+ require 'polisher/component'
13
10
 
14
11
  module Polisher
15
- module RPM
16
- class Spec
17
- AUTHOR = "#{ENV['USER']} <#{ENV['USER']}@localhost.localdomain>"
18
-
19
- COMMENT_MATCHER = /^\s*#.*/
20
- GEM_NAME_MATCHER = /^%global\s*gem_name\s(.*)$/
21
- SPEC_NAME_MATCHER = /^Name:\s*rubygem-(.*)$/
22
- SPEC_VERSION_MATCHER = /^Version:\s*(.*)$/
23
- SPEC_RELEASE_MATCHER = /^Release:\s*(.*)$/
24
- SPEC_REQUIRES_MATCHER = /^Requires:\s*(.*)$/
25
- SPEC_BUILD_REQUIRES_MATCHER = /^BuildRequires:\s*(.*)$/
26
- SPEC_GEM_REQ_MATCHER = /^.*\s*rubygem\((.*)\)(\s*(.*))?$/
27
- SPEC_SUBPACKAGE_MATCHER = /^%package\s(.*)$/
28
- SPEC_CHANGELOG_MATCHER = /^%changelog$/
29
- SPEC_FILES_MATCHER = /^%files$/
30
- SPEC_SUBPKG_FILES_MATCHER = /^%files\s*(.*)$/
31
- SPEC_CHECK_MATCHER = /^%check$/
32
-
33
- FILE_MACRO_MATCHERS =
34
- [/^%doc\s/, /^%config\s/, /^%attr\s/,
35
- /^%verify\s/, /^%docdir.*/, /^%dir\s/,
36
- /^%defattr.*/, /^%exclude\s/, /^%{gem_instdir}\/+/]
37
-
38
- FILE_MACRO_REPLACEMENTS =
39
- {"%{_bindir}" => 'bin',
40
- "%{gem_libdir}" => 'lib'}
41
-
42
- attr_accessor :metadata
43
-
44
- # Return the currently configured author
45
- def self.current_author
46
- ENV['POLISHER_AUTHOR'] || AUTHOR
47
- end
48
-
49
- def initialize(metadata={})
50
- @metadata = metadata
51
- end
52
-
53
- # Dispatch all missing methods to lookup calls in rpm spec metadata
54
- def method_missing(method, *args, &block)
55
- # proxy to metadata
56
- if @metadata.has_key?(method)
57
- @metadata[method]
58
-
59
- else
60
- super(method, *args, &block)
12
+ deps = ['gem2rpm', 'versionomy', 'active_support', 'active_support/core_ext']
13
+ Component.verify("RPM::Spec", *deps) do
14
+ module RPM
15
+ class Spec
16
+ # RPM Spec Requirement Prefix
17
+ def self.requirement_prefix
18
+ Requirement.prefix
61
19
  end
62
- end
63
-
64
- # Return boolean indicating if spec has a %check section
65
- def has_check?
66
- @metadata.has_key?(:has_check) && @metadata[:has_check]
67
- end
68
-
69
- # Return all the Requires for the specified gem
70
- def requirements_for_gem(gem_name)
71
- @metadata[:requires].nil? ? [] :
72
- @metadata[:requires].select { |r| r.gem_name == gem_name }
73
- end
74
-
75
- # Return all the BuildRequires for the specified gem
76
- def build_requirements_for_gem(gem_name)
77
- @metadata[:build_requires].nil? ? [] :
78
- @metadata[:build_requires].select { |r| r.gem_name == gem_name }
79
- end
80
-
81
- # Return bool indicating if this spec specifies all the
82
- # requirements in the specified gem dependency
83
- #
84
- # @param [Gem::Dependency] gem_dep dependency which to retreive / compare
85
- # requirements
86
- def has_all_requirements_for?(gem_dep)
87
- reqs = self.requirements_for_gem gem_dep.name
88
- # create a spec requirement dependency for each expanded subrequirement,
89
- # verify we can find a match for that
90
- gem_dep.requirement.to_s.split(',').all? { |greq|
91
- Gem2Rpm::Helpers.expand_requirement([greq.split]).all? { |ereq|
92
- tereq = Requirement.new :name => "rubygem(#{gem_dep.name})",
93
- :condition => ereq.first,
94
- :version => ereq.last.to_s
95
- reqs.any? { |req| req.matches?(tereq)}
96
- }
97
- }
98
- end
99
-
100
- # Return all gem Requires
101
- def gem_requirements
102
- @metadata[:requires].nil? ? [] :
103
- @metadata[:requires].select { |r| r.gem? }
104
- end
105
-
106
- # Return all gem BuildRequires
107
- def gem_build_requirements
108
- @metadata[:build_requires].nil? ? [] :
109
- @metadata[:build_requires].select { |r| r.gem? }
110
- end
111
-
112
- # Return all non gem Requires
113
- def non_gem_requirements
114
- @metadata[:requires].nil? ? [] :
115
- @metadata[:requires].select { |r| !r.gem? }
116
- end
117
-
118
- # Return all non gem BuildRequires
119
- def non_gem_build_requirements
120
- @metadata[:build_requires].nil? ? [] :
121
- @metadata[:build_requires].select { |r| !r.gem? }
122
- end
123
-
124
- # Return all gem requirements _not_ in the specified gem
125
- def extra_gem_requirements(gem)
126
- gem_reqs = gem.deps.collect { |d| requirements_for_gem(d.name) }.flatten
127
- gem_requirements - gem_reqs
128
- end
129
-
130
- # Return all gem build requirements _not_ in the specified gem
131
- def extra_gem_build_requirements(gem)
132
- gem_reqs = gem.deps.collect { |d| requirements_for_gem(d.name) }.flatten
133
- gem_build_requirements - gem_reqs
134
- end
135
-
136
- # Parse the specified rpm spec and return new RPM::Spec instance from metadata
137
- #
138
- # @param [String] string contents of spec to parse
139
- # @return [Polisher::RPM::Spec] spec instantiated from rpmspec metadata
140
- def self.parse(spec)
141
- in_subpackage = false
142
- in_changelog = false
143
- in_files = false
144
- subpkg_name = nil
145
- meta = {:contents => spec}
146
- spec.each_line { |l|
147
- if l =~ COMMENT_MATCHER
148
- ;
149
-
150
- # TODO support optional gem prefix
151
- elsif l =~ GEM_NAME_MATCHER
152
- meta[:gem_name] = $1.strip
153
- meta[:gem_name] = $1.strip
154
-
155
- elsif l =~ SPEC_NAME_MATCHER &&
156
- $1.strip != "%{gem_name}"
157
- meta[:gem_name] = $1.strip
158
-
159
- elsif l =~ SPEC_VERSION_MATCHER
160
- meta[:version] = $1.strip
161
-
162
- elsif l =~ SPEC_RELEASE_MATCHER
163
- meta[:release] = $1.strip
164
-
165
- elsif l =~ SPEC_SUBPACKAGE_MATCHER
166
- subpkg_name = $1.strip
167
- in_subpackage = true
168
-
169
- elsif l =~ SPEC_REQUIRES_MATCHER &&
170
- !in_subpackage
171
- meta[:requires] ||= []
172
- meta[:requires] << RPM::Requirement.parse($1.strip)
173
-
174
- elsif l =~ SPEC_BUILD_REQUIRES_MATCHER &&
175
- !in_subpackage
176
- meta[:build_requires] ||= []
177
- meta[:build_requires] << RPM::Requirement.parse($1.strip)
178
-
179
- elsif l =~ SPEC_CHANGELOG_MATCHER
180
- in_changelog = true
181
-
182
- elsif l =~ SPEC_FILES_MATCHER
183
- subpkg_name = nil
184
- in_files = true
185
-
186
- elsif l =~ SPEC_SUBPKG_FILES_MATCHER
187
- subpkg_name = $1.strip
188
- in_files = true
189
-
190
- elsif l =~ SPEC_CHECK_MATCHER
191
- meta[:has_check] = true
192
-
193
- elsif in_changelog
194
- meta[:changelog] ||= ""
195
- meta[:changelog] << l
196
-
197
- elsif in_files
198
- tgt = subpkg_name.nil? ? meta[:gem_name] : subpkg_name
199
- meta[:files] ||= {}
200
- meta[:files][tgt] ||= []
201
-
202
- sl = l.strip.unrpmize
203
- meta[:files][tgt] << sl unless sl.blank?
20
+
21
+ def requirement_prefix
22
+ self.class.requirement_prefix
23
+ end
24
+
25
+ def self.package_prefix
26
+ requirement_prefix
27
+ end
28
+
29
+ AUTHOR = "#{ENV['USER']} <#{ENV['USER']}@localhost.localdomain>"
30
+
31
+ COMMENT_MATCHER = /^\s*#.*/
32
+ GEM_NAME_MATCHER = /^%global\s*gem_name\s(.*)$/
33
+ SPEC_NAME_MATCHER = /^Name:\s*#{package_prefix}-(.*)$/
34
+ SPEC_VERSION_MATCHER = /^Version:\s*(.*)$/
35
+ SPEC_RELEASE_MATCHER = /^Release:\s*(.*)$/
36
+ SPEC_REQUIRES_MATCHER = /^Requires:\s*(.*)$/
37
+ SPEC_BUILD_REQUIRES_MATCHER = /^BuildRequires:\s*(.*)$/
38
+ SPEC_GEM_REQ_MATCHER = /^.*\s*#{requirement_prefix}\((.*)\)(\s*(.*))?$/
39
+ SPEC_SUBPACKAGE_MATCHER = /^%package\s(.*)$/
40
+ SPEC_CHANGELOG_MATCHER = /^%changelog$/
41
+ SPEC_FILES_MATCHER = /^%files$/
42
+ SPEC_SUBPKG_FILES_MATCHER = /^%files\s*(.*)$/
43
+ SPEC_DOC_FILES_MATCHER = /^%files doc$/
44
+ SPEC_CHECK_MATCHER = /^%check$/
45
+
46
+ FILE_MACRO_MATCHERS =
47
+ [/^%doc\s/, /^%config\s/, /^%attr\s/,
48
+ /^%verify\s/, /^%docdir.*/, /^%dir\s/,
49
+ /^%defattr.*/, /^%exclude\s/, /^%{gem_instdir}\/+/]
50
+
51
+ FILE_MACRO_REPLACEMENTS =
52
+ {"%{_bindir}" => 'bin',
53
+ "%{gem_libdir}" => 'lib'}
54
+
55
+ attr_accessor :metadata
56
+
57
+ # Return the currently configured author
58
+ def self.current_author
59
+ ENV['POLISHER_AUTHOR'] || AUTHOR
60
+ end
61
+
62
+ def initialize(metadata={})
63
+ @metadata = metadata
64
+ end
65
+
66
+ # Dispatch all missing methods to lookup calls in rpm spec metadata
67
+ def method_missing(method, *args, &block)
68
+ # proxy to metadata
69
+ if @metadata.has_key?(method)
70
+ @metadata[method]
71
+
72
+ else
73
+ super(method, *args, &block)
204
74
  end
205
- }
206
-
207
- meta[:changelog_entries] = meta[:changelog] ?
208
- meta[:changelog].split("\n\n") : []
209
- meta[:changelog_entries].collect! { |c| c.strip }.compact!
210
-
211
- self.new meta
212
- end
75
+ end
76
+
77
+ # Return gem corresponding to spec name/version
78
+ def upstream_gem
79
+ @gem ||= Polisher::Gem.from_rubygems gem_name, version
80
+ end
81
+
82
+ # Return boolean indicating if spec has a %check section
83
+ def has_check?
84
+ @metadata.has_key?(:has_check) && @metadata[:has_check]
85
+ end
86
+
87
+ # Return all the Requires for the specified gem
88
+ def requirements_for_gem(gem_name)
89
+ @metadata[:requires].nil? ? [] :
90
+ @metadata[:requires].select { |r| r.gem_name == gem_name }
91
+ end
92
+
93
+ # Return all the BuildRequires for the specified gem
94
+ def build_requirements_for_gem(gem_name)
95
+ @metadata[:build_requires].nil? ? [] :
96
+ @metadata[:build_requires].select { |r| r.gem_name == gem_name }
97
+ end
98
+
99
+ # Return bool indicating if this spec specifies all the
100
+ # requirements in the specified gem dependency
101
+ #
102
+ # @param [Gem::Dependency] gem_dep dependency which to retreive / compare
103
+ # requirements
104
+ def has_all_requirements_for?(gem_dep)
105
+ reqs = self.requirements_for_gem gem_dep.name
106
+ # create a spec requirement dependency for each expanded subrequirement,
107
+ # verify we can find a match for that
108
+ gem_dep.requirement.to_s.split(',').all? { |greq|
109
+ Gem2Rpm::Helpers.expand_requirement([greq.split]).all? { |ereq|
110
+ tereq = Requirement.new :name => "#{requirement_prefix}(#{gem_dep.name})",
111
+ :condition => ereq.first,
112
+ :version => ereq.last.to_s
113
+ reqs.any? { |req| req.matches?(tereq)}
114
+ }
115
+ }
116
+ end
117
+
118
+ # Return list of gem dependencies for which we have no
119
+ # corresponding requirements
120
+ def missing_deps_for(gem)
121
+ # Comparison by name here assuming if it is in existing spec,
122
+ # spec author will have ensured versions are correct for their purposes
123
+ gem.deps.select { |dep| requirements_for_gem(dep.name).empty? }
124
+ end
213
125
 
214
- # Update RPM::Spec metadata to new gem
215
- #
216
- # @param [Polisher::Gem] new_source new gem to update rpmspec to
217
- def update_to(new_source)
218
- update_deps_from(new_source)
219
- update_files_from(new_source)
220
- update_metadata_from(new_source)
221
- end
126
+ # Return list of gem dev dependencies for which we have
127
+ # no corresponding requirements
128
+ def missing_dev_deps_for(gem)
129
+ # Same note as in #missing_deps_for above
130
+ gem.dev_deps.select { |dep| build_requirements_for_gem(dep.name).empty? }
131
+ end
222
132
 
223
- private
224
-
225
- # Update spec dependencies from new source
226
- def update_deps_from(new_source)
227
- @metadata[:requires] =
228
- non_gem_requirements +
229
- extra_gem_requirements(new_source) +
230
- new_source.deps.collect { |r|
231
- RPM::Requirement.from_gem_dep(r)
232
- }.flatten
133
+ # Return list of dependencies of upstream gem which
134
+ # have not been included
135
+ def excluded_deps
136
+ missing_deps_for(upstream_gem)
137
+ end
233
138
 
234
- @metadata[:build_requires] =
235
- non_gem_build_requirements +
236
- extra_gem_build_requirements(new_source) +
237
- new_source.dev_deps.collect { |r|
238
- RPM::Requirement.from_gem_dep(r, true)
239
- }.flatten
240
- end
139
+ # Return boolean indicating if the specified gem is on excluded list
140
+ def excludes_dep?(gem_name)
141
+ excluded_deps.any? { |d| d.name == gem_name }
142
+ end
241
143
 
242
- # Internal helper to update spec files from new source
243
- def update_files_from(new_source)
244
- to_add = new_source.file_paths
245
- @metadata[:files] ||= {}
246
- @metadata[:files].each { |pkg,spec_files|
247
- (new_source.file_paths & to_add).each { |gem_file|
248
- # skip files already included in spec or in dir in spec
249
- has_file = spec_files.any? { |sf|
250
- gem_file.gsub(sf,'') != gem_file
251
- }
144
+ # Return list of dev dependencies of upstream gem which
145
+ # have not been included
146
+ def excluded_dev_deps
147
+ missing_dev_deps_for(upstream_gem)
148
+ end
252
149
 
253
- to_add.delete(gem_file)
254
- to_add << gem_file.rpmize if !has_file &&
255
- !Gem.ignorable_file?(gem_file)
150
+ # Return boolean indicating if the specified gem is on
151
+ # excluded dev dep list
152
+ def excludes_dev_dep?(gem_name)
153
+ excluded_dev_deps.any? { |d| d.name == gem_name }
154
+ end
155
+
156
+ # Return all gem Requires
157
+ def gem_requirements
158
+ @metadata[:requires].nil? ? [] :
159
+ @metadata[:requires].select { |r| r.gem? }
160
+ end
161
+
162
+ # Return all gem BuildRequires
163
+ def gem_build_requirements
164
+ @metadata[:build_requires].nil? ? [] :
165
+ @metadata[:build_requires].select { |r| r.gem? }
166
+ end
167
+
168
+ # Return all non gem Requires
169
+ def non_gem_requirements
170
+ @metadata[:requires].nil? ? [] :
171
+ @metadata[:requires].select { |r| !r.gem? }
172
+ end
173
+
174
+ # Return all non gem BuildRequires
175
+ def non_gem_build_requirements
176
+ @metadata[:build_requires].nil? ? [] :
177
+ @metadata[:build_requires].select { |r| !r.gem? }
178
+ end
179
+
180
+ # Return all gem requirements _not_ in the specified gem
181
+ def extra_gem_requirements(gem)
182
+ gem_reqs = gem.deps.collect { |d| requirements_for_gem(d.name) }.flatten
183
+ gem_requirements - gem_reqs
184
+ end
185
+
186
+ # Return all gem build requirements _not_ in the specified gem
187
+ def extra_gem_build_requirements(gem)
188
+ gem_reqs = gem.deps.collect { |d| requirements_for_gem(d.name) }.flatten
189
+ gem_build_requirements - gem_reqs
190
+ end
191
+
192
+ # Parse the specified rpm spec and return new RPM::Spec instance from metadata
193
+ #
194
+ # @param [String] string contents of spec to parse
195
+ # @return [Polisher::RPM::Spec] spec instantiated from rpmspec metadata
196
+ def self.parse(spec)
197
+ in_subpackage = false
198
+ in_changelog = false
199
+ in_files = false
200
+ subpkg_name = nil
201
+ meta = {:contents => spec}
202
+ spec.each_line { |l|
203
+ if l =~ COMMENT_MATCHER
204
+ ;
205
+
206
+ # TODO support optional gem prefix
207
+ elsif l =~ GEM_NAME_MATCHER
208
+ meta[:gem_name] = $1.strip
209
+ meta[:gem_name] = $1.strip
210
+
211
+ elsif l =~ SPEC_NAME_MATCHER &&
212
+ $1.strip != "%{gem_name}"
213
+ meta[:gem_name] = $1.strip
214
+
215
+ elsif l =~ SPEC_VERSION_MATCHER
216
+ meta[:version] = $1.strip
217
+
218
+ elsif l =~ SPEC_RELEASE_MATCHER
219
+ meta[:release] = $1.strip
220
+
221
+ elsif l =~ SPEC_SUBPACKAGE_MATCHER
222
+ subpkg_name = $1.strip
223
+ in_subpackage = true
224
+
225
+ elsif l =~ SPEC_REQUIRES_MATCHER &&
226
+ !in_subpackage
227
+ meta[:requires] ||= []
228
+ meta[:requires] << RPM::Requirement.parse($1.strip)
229
+
230
+ elsif l =~ SPEC_BUILD_REQUIRES_MATCHER &&
231
+ !in_subpackage
232
+ meta[:build_requires] ||= []
233
+ meta[:build_requires] << RPM::Requirement.parse($1.strip)
234
+
235
+ elsif l =~ SPEC_CHANGELOG_MATCHER
236
+ in_changelog = true
237
+
238
+ elsif l =~ SPEC_FILES_MATCHER
239
+ subpkg_name = nil
240
+ in_files = true
241
+
242
+ elsif l =~ SPEC_SUBPKG_FILES_MATCHER
243
+ subpkg_name = $1.strip
244
+ in_files = true
245
+
246
+ elsif l =~ SPEC_CHECK_MATCHER
247
+ meta[:has_check] = true
248
+
249
+ elsif in_changelog
250
+ meta[:changelog] ||= ""
251
+ meta[:changelog] << l
252
+
253
+ elsif in_files
254
+ tgt = subpkg_name.nil? ? meta[:gem_name] : subpkg_name
255
+ meta[:files] ||= {}
256
+ meta[:files][tgt] ||= []
257
+
258
+ sl = l.strip.unrpmize
259
+ meta[:files][tgt] << sl unless sl.blank?
260
+ end
256
261
  }
257
- }
258
-
259
- @metadata[:new_files] = to_add
260
- end
261
-
262
- # Internal helper to update spec metadata from new source
263
- def update_metadata_from(new_source)
264
- # update to new version
265
- @metadata[:version] = new_source.version
266
- @metadata[:release] = "1%{?dist}"
267
-
268
- # add changelog entry
269
- changelog_entry = <<EOS
262
+
263
+ meta[:changelog_entries] = meta[:changelog] ?
264
+ meta[:changelog].split("\n\n") : []
265
+ meta[:changelog_entries].collect! { |c| c.strip }.compact!
266
+
267
+ self.new meta
268
+ end
269
+
270
+ # Update RPM::Spec metadata to new gem
271
+ #
272
+ # @param [Polisher::Gem] new_source new gem to update rpmspec to
273
+ def update_to(new_source)
274
+ update_deps_from(new_source)
275
+ update_files_from(new_source)
276
+ update_metadata_from(new_source)
277
+ end
278
+
279
+ private
280
+
281
+ # Update spec dependencies from new source
282
+ def update_deps_from(new_source)
283
+ @metadata[:requires] =
284
+ non_gem_requirements +
285
+ extra_gem_requirements(new_source) +
286
+ new_source.deps.select { |r| !excludes_dep?(r.name) }
287
+ .collect { |r| RPM::Requirement.from_gem_dep(r) }.flatten
288
+
289
+ @metadata[:build_requires] =
290
+ non_gem_build_requirements +
291
+ extra_gem_build_requirements(new_source) +
292
+ new_source.dev_deps.select { |r| !excludes_dev_dep?(r.name) }
293
+ .collect { |r| RPM::Requirement.from_gem_dep(r, true) }.flatten
294
+ end
295
+
296
+ # Internal helper to update spec files from new source
297
+ def update_files_from(new_source)
298
+ to_add = new_source.file_paths
299
+ @metadata[:files] ||= {}
300
+ @metadata[:files].each { |pkg,spec_files|
301
+ (new_source.file_paths & to_add).each { |gem_file|
302
+ # skip files already included in spec or in dir in spec
303
+ has_file = spec_files.any? { |sf|
304
+ gem_file.gsub(sf,'') != gem_file
305
+ }
306
+
307
+ to_add.delete(gem_file)
308
+ to_add << gem_file.rpmize if !has_file &&
309
+ !Gem.ignorable_file?(gem_file)
310
+ }
311
+ }
312
+
313
+ @metadata[:new_files] = to_add.select { |f| !Gem.doc_file?(f) }
314
+ @metadata[:new_docs] = to_add - @metadata[:new_files]
315
+ end
316
+
317
+ # Internal helper to update spec metadata from new source
318
+ def update_metadata_from(new_source)
319
+ # update to new version
320
+ @metadata[:version] = new_source.version
321
+ @metadata[:release] = "1%{?dist}"
322
+
323
+ # add changelog entry
324
+ changelog_entry = <<EOS
270
325
  * #{Time.now.strftime("%a %b %d %Y")} #{RPM::Spec.current_author} - #{@metadata[:version]}-1
271
326
  - Update to version #{new_source.version}
272
327
  EOS
273
- @metadata[:changelog_entries] ||= []
274
- @metadata[:changelog_entries].unshift changelog_entry.rstrip
275
- end
276
-
277
- public
278
-
279
- # Return properly formatted rpmspec as string
280
- #
281
- # @return [String] string representation of rpm spec
282
- def to_string
283
- contents = @metadata[:contents]
284
-
285
- # replace version / release
286
- contents.gsub!(SPEC_VERSION_MATCHER, "Version: #{@metadata[:version]}")
287
- contents.gsub!(SPEC_RELEASE_MATCHER, "Release: #{@metadata[:release]}")
288
-
289
- # add changelog entry
290
- cp = contents.index SPEC_CHANGELOG_MATCHER
291
- cpn = contents.index "\n", cp
292
- contents = contents[0...cpn+1] +
293
- @metadata[:changelog_entries].join("\n\n")
294
-
295
- # update requires/build requires
296
- rp = contents.index SPEC_REQUIRES_MATCHER
297
- brp = contents.index SPEC_BUILD_REQUIRES_MATCHER
298
- tp = rp < brp ? rp : brp
299
-
300
- pp = contents.index SPEC_SUBPACKAGE_MATCHER
301
- pp = -1 if pp.nil?
302
-
303
- lrp = contents.rindex SPEC_REQUIRES_MATCHER, pp
304
- lbrp = contents.rindex SPEC_BUILD_REQUIRES_MATCHER, pp
305
- ltp = lrp > lbrp ? lrp : lbrp
306
-
307
- ltpn = contents.index "\n", ltp
308
-
309
- contents.slice!(tp...ltpn)
310
- contents.insert tp,
311
- (@metadata[:requires].collect { |r| "Requires: #{r.str}" } +
312
- @metadata[:build_requires].collect { |r| "BuildRequires: #{r.str}" }).join("\n")
313
-
314
- # add new files
315
- fp = contents.index SPEC_FILES_MATCHER
316
- lfp = contents.index SPEC_SUBPKG_FILES_MATCHER, fp + 1
317
- lfp = contents.index SPEC_CHANGELOG_MATCHER if lfp.nil?
318
-
319
- contents.insert lfp - 1, @metadata[:new_files].join("\n") + "\n"
320
-
321
- # return new contents
322
- contents
323
- end
324
-
325
- # Compare this spec to a sepecified upstream gem source
326
- # and return result.
327
- #
328
- # upstream_source should be an instance of Polisher::Gem,
329
- # Polisher::Gemfile, or other class defining a 'deps'
330
- # accessor that returns an array of Gem::Requirement dependencies
331
- #
332
- # Result will be a hash containing the shared dependencies as
333
- # well as those that differ and their respective differences
334
- def compare(upstream_source)
335
- same = {}
336
- diff = {}
337
- upstream_source.deps.each do |d|
338
- spec_reqs = self.requirements_for_gem(d.name)
339
- spec_reqs_specifier = spec_reqs.empty? ? nil :
340
- spec_reqs.collect { |req| req.specifier }
341
-
342
- if spec_reqs.nil?
343
- diff[d.name] = {:spec => nil,
344
- :upstream => d.requirement.to_s}
345
-
346
- elsif !spec_reqs.any? { |req| req.matches?(d) } ||
347
- !self.has_all_requirements_for?(d)
348
- diff[d.name] = {:spec => spec_reqs_specifier,
349
- :upstream => d.requirement.to_s}
350
-
351
- elsif !diff.has_key?(d.name)
352
- same[d.name] = {:spec => spec_reqs_specifier,
353
- :upstream => d.requirement.to_s }
354
- end
328
+ @metadata[:changelog_entries] ||= []
329
+ @metadata[:changelog_entries].unshift changelog_entry.rstrip
355
330
  end
331
+
332
+ public
333
+
334
+ # Return properly formatted rpmspec as string
335
+ #
336
+ # @return [String] string representation of rpm spec
337
+ def to_string
338
+ contents = @metadata[:contents]
339
+
340
+ # replace version / release
341
+ contents.gsub!(SPEC_VERSION_MATCHER, "Version: #{@metadata[:version]}")
342
+ contents.gsub!(SPEC_RELEASE_MATCHER, "Release: #{@metadata[:release]}")
343
+
344
+ # add changelog entry
345
+ cp = contents.index SPEC_CHANGELOG_MATCHER
346
+ cpn = contents.index "\n", cp
347
+ contents = contents[0...cpn+1] +
348
+ @metadata[:changelog_entries].join("\n\n")
349
+
350
+ # update requires/build requires
351
+ rp = contents.index SPEC_REQUIRES_MATCHER
352
+ brp = contents.index SPEC_BUILD_REQUIRES_MATCHER
353
+ tp = rp < brp ? rp : brp
354
+
355
+ pp = contents.index SPEC_SUBPACKAGE_MATCHER
356
+ pp = -1 if pp.nil?
357
+
358
+ lrp = contents.rindex SPEC_REQUIRES_MATCHER, pp
359
+ lbrp = contents.rindex SPEC_BUILD_REQUIRES_MATCHER, pp
360
+ ltp = lrp > lbrp ? lrp : lbrp
361
+
362
+ ltpn = contents.index "\n", ltp
363
+
364
+ contents.slice!(tp...ltpn)
365
+ contents.insert tp,
366
+ (@metadata[:requires].collect { |r| "Requires: #{r.str}" } +
367
+ @metadata[:build_requires].collect { |r| "BuildRequires: #{r.str}" }).join("\n")
368
+
369
+ # add new files
370
+ fp = contents.index SPEC_FILES_MATCHER
371
+ lfp = contents.index SPEC_SUBPKG_FILES_MATCHER, fp + 1
372
+ lfp = contents.index SPEC_CHANGELOG_MATCHER if lfp.nil?
373
+
374
+ contents.insert lfp - 1, @metadata[:new_files].join("\n") + "\n"
375
+
376
+ # add new doc files
377
+ fp = contents.index SPEC_DOC_FILES_MATCHER
378
+ fp = contents.index SPEC_FILES_MATCHER if fp.nil?
379
+ lfp = contents.index SPEC_SUBPKG_FILES_MATCHER, fp + 1
380
+ lfp = contents.index SPEC_CHANGELOG_MATCHER if lfp.nil?
356
381
 
357
- @metadata[:requires].each do |req|
358
- next unless req.gem?
359
-
360
- upstream_dep = upstream_source.deps.find { |d| d.name == req.gem_name }
361
-
362
- if upstream_dep.nil?
363
- diff[req.gem_name] = {:spec => req.specifier,
364
- :upstream => nil}
365
-
366
- elsif !req.matches?(upstream_dep)
367
- diff[req.gem_name] = {:spec => req.specifier,
368
- :upstream => upstream_dep.requirement.to_s }
369
-
370
- elsif !diff.has_key?(req.gem_name)
371
- same[req.gem_name] = {:spec => req.specifier,
372
- :upstream => upstream_dep.requirement.to_s }
382
+ contents.insert lfp - 1, @metadata[:new_docs].join("\n") + "\n"
383
+
384
+ # return new contents
385
+ contents
386
+ end
387
+
388
+ # Compare this spec to a sepecified upstream gem source
389
+ # and return result.
390
+ #
391
+ # upstream_source should be an instance of Polisher::Gem,
392
+ # Polisher::Gemfile, or other class defining a 'deps'
393
+ # accessor that returns an array of Gem::Requirement dependencies
394
+ #
395
+ # Result will be a hash containing the shared dependencies as
396
+ # well as those that differ and their respective differences
397
+ def compare(upstream_source)
398
+ same = {}
399
+ diff = {}
400
+ upstream_source.deps.each do |d|
401
+ spec_reqs = self.requirements_for_gem(d.name)
402
+ spec_reqs_specifier = spec_reqs.empty? ? nil :
403
+ spec_reqs.collect { |req| req.specifier }
404
+
405
+ if spec_reqs.nil?
406
+ diff[d.name] = {:spec => nil,
407
+ :upstream => d.requirement.to_s}
408
+
409
+ elsif !spec_reqs.any? { |req| req.matches?(d) } ||
410
+ !self.has_all_requirements_for?(d)
411
+ diff[d.name] = {:spec => spec_reqs_specifier,
412
+ :upstream => d.requirement.to_s}
413
+
414
+ elsif !diff.has_key?(d.name)
415
+ same[d.name] = {:spec => spec_reqs_specifier,
416
+ :upstream => d.requirement.to_s }
417
+ end
373
418
  end
374
- end unless @metadata[:requires].nil?
375
-
376
- {:same => same, :diff => diff}
377
- end
378
-
379
- end # class Spec
380
- end # module RPM
419
+
420
+ @metadata[:requires].each do |req|
421
+ next unless req.gem?
422
+
423
+ upstream_dep = upstream_source.deps.find { |d| d.name == req.gem_name }
424
+
425
+ if upstream_dep.nil?
426
+ diff[req.gem_name] = {:spec => req.specifier,
427
+ :upstream => nil}
428
+
429
+ elsif !req.matches?(upstream_dep)
430
+ diff[req.gem_name] = {:spec => req.specifier,
431
+ :upstream => upstream_dep.requirement.to_s }
432
+
433
+ elsif !diff.has_key?(req.gem_name)
434
+ same[req.gem_name] = {:spec => req.specifier,
435
+ :upstream => upstream_dep.requirement.to_s }
436
+ end
437
+ end unless @metadata[:requires].nil?
438
+
439
+ {:same => same, :diff => diff}
440
+ end
441
+
442
+ end # class Spec
443
+ end # module RPM
444
+ end # Component.verify("RPM::Spec")
381
445
  end # module Polisher