Class: Baltix::Spec::Rpm::Parser

Inherits:
Object
  • Object
show all
Defined in:
lib/baltix/spec/rpm/parser.rb

Constant Summary collapse

MATCHER =
/^Name:\s+([^\s]+)/i
SCHEME =
{
   name: {
      non_contexted: true,
      regexp: /^Name:\s+([^\s]+)/i,
      parse_func: :parse_name
   },
   version: {
      non_contexted: true,
      regexp: /Version:\s+([^\s]+)/i,
      parse_func: :parse_version,
      mode: :replace
   },
   epoch: {
      non_contexted: true,
      regexp: /Epoch:\s+([^\s]+)/i,
      mode: :replace
   },
   release: {
      non_contexted: true,
      regexp: /Release:\s+([^\s]+)/i,
      mode: :replace
   },
   summaries: {
      regexp: /Summary(?:\(([^\s:]+)\))?:\s+([^\s].+)/i,
      parse_func: :parse_summary,
      mode: :replace
   },
   licenses: {
      non_contexted: true,
      regexp: /License:\s+([^\s].+)/i,
      parse_func: :parse_license
   },
   group: /Group:\s+([^\s]+)/i,
   uri: /Url:\s+([^\s]+)/i,
   vcs: /Vcs:\s+([^\s]+)/i,
   packager: {
      non_contexted: true,
      regexp: /Packager:\s+(.*)\s*(?:<(.*)>)$/i,
      parse_func: :parse_packager
   },
   build_arch: /BuildArch:\s+([^\s]+)/i,
   patches: {
      non_contexted: true,
      regexp: /Patch(\d+)?:\s+([^\s]+)/i,
      parse_func: :parse_file
   },
   source_files: {
      non_contexted: true,
      regexp: /Source(\d+)?:\s+([^\s]+)/i,
      parse_func: :parse_file
   },
   build_pre_requires: {
      non_contexted: true,
      regexp: /(?:BuildPreReq|BuildRequires\(pre\)):\s+([\w\s<=>\.\-_]+)/i,
      parse_func: :parse_dep
   },
   build_requires: {
      non_contexted: true,
      regexp: /^BuildRequires:\s*([^#]+)/i,
      parse_func: :parse_dep
   },
   obsoletes: {
      regexp: /^Obsoletes:\s*([^#]+)/i,
      parse_func: :parse_dep
   },
   provides: {
      regexp: /^Provides:\s*([^#]+)/i,
      parse_func: :parse_dep
   },
   requires: {
      regexp: /^Requires:\s*([^#]+)/i,
      parse_func: :parse_dep
   },
   conflicts: {
      regexp: /^Conflicts:\s*([^#]+)/i,
      parse_func: :parse_dep
   },
   ignored_names: {
      non_contexted: true,
      regexp: /(^%ruby_ignore|--ignore=)\s*([^\s$]+)/i,
      parse_func: :parse_ignore
   },
   descriptions: {
      regexp: /^%description\s*([^\s].*)?/i,
      parse_func: :parse_description
   },
   secondaries: {
      non_contexted: true,
      regexp: /^%package\s+(.+)/i,
      parse_func: :parse_secondary
   },
   prep: {
      non_contexted: true,
      regexp: /^%prep/i,
      parse_func: :parse_plain_section
   },
   build: {
      non_contexted: true,
      regexp: /^%build/i,
      parse_func: :parse_plain_section
   },
   install: {
      non_contexted: true,
      regexp: /^%install/i,
      parse_func: :parse_plain_section
   },
   check: {
      non_contexted: true,
      regexp: /^%check/i,
      parse_func: :parse_plain_section
   },
   file_list: {
      regexp: /^%files\s*([^\s].*)?/i,
      parse_func: :parse_file_list
   },
   changes: {
      non_contexted: true,
      regexp: /^%changelog/i,
      parse_func: :parse_changes
   },
   context: {
      non_contexted: true,
      regexp: /^%(?:(?:global|define)|((?!description|package|files)[^\s]+))\s+(?:([^\s]+)\s+([^\s].*)|(.*))/i,
      parse_func: :parse_context
   },
   comment: {
      non_contexted: true,
      parse_func: :parse_comment
   }
}.to_os(hash: true)

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.match?(source_in) ⇒ Boolean

Returns:

  • (Boolean)


408
409
410
# File 'lib/baltix/spec/rpm/parser.rb', line 408

def match? source_in
   MATCHER =~ source_in
end

Instance Method Details

#aliased_names(opts) ⇒ Object



397
398
399
# File 'lib/baltix/spec/rpm/parser.rb', line 397

def aliased_names opts
   opts.context.__options&.aliased_names
end

#parse(source_in, options = {}) ⇒ Object



144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
# File 'lib/baltix/spec/rpm/parser.rb', line 144

def parse source_in, options = {}
   context = {}.to_os
   matched = {}.to_os
   match = nil
   state_in = {
      "context" => {
         "__options" => options.to_os,
         "__custom" => { 'gemname' => '%pkgname' }.to_os
      }
   }.to_os(hash: true)

   state = source(source_in).reduce(state_in) do |state, line|
      SCHEME.find do |key, rule|
         match = rule.is_a?(Regexp) && rule.match(line) ||
                 rule.is_a?(OpenStruct) && rule[:regexp] && rule[:regexp].match(line)

         if match
            if matched.name
               if matched.name != key
#               binding.pry if matched[:match][0] =~ /description/
                  store_value(state, matched[:match], matched[:name], matched[:flow], context)
                  matched = { name: key.to_s, flow: "", match: match }.to_os
               end
            else
               matched = { name: key.to_s, flow: "", match: match }.to_os
            end
         end
      end

      if matched.name
         if matched.flow
            matched.flow << line + "\n"
         else
            matched.flow = line + "\n"
         end
      else
         matched = { name: "comment", flow: line + "\n", match: [] }.to_os
      end

      state
   end

   store_value(state, matched.match, matched.name, matched.flow, context)

   #binding.pry
   state
end

#parse_changes(_, flow, *_) ⇒ Object



278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
# File 'lib/baltix/spec/rpm/parser.rb', line 278

def parse_changes _, flow, *_
   rows = flow.split("\n* ").map { |p| p.strip }.compact.map { |p| p.split("\n") }

   rows[1..-1].map do |row|
      /(?<date>^\w+\s+\w+\s+\w+\s+\w+)\s+(?<author>.*)\s*(?:<(?<email>.*)>)\s+(?:(?<epoch>[0-9]+):)?(?<version>[\w\.]+)(?:-(?<release>[\w\._]+))?$/ =~ row[0]

      {
         date: date,
         author: author.strip,
         email: email,
         version: Gem::Version.new(version),
         release: release,
         epoch: epoch,
         description: row[1..-1].join("\n")
      }.to_os
   end.reverse
end

#parse_comment(match, flow, *_) ⇒ Object



260
261
262
# File 'lib/baltix/spec/rpm/parser.rb', line 260

def parse_comment match, flow, *_
   flow
end

#parse_context(match, *_) ⇒ Object



335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
# File 'lib/baltix/spec/rpm/parser.rb', line 335

def parse_context match, *_
   if match[1]
      {
         "__macros" => {
            match[1] => match[4]&.strip || [match[2], match[3]].compact.join(" ").strip
         }
      }.to_os(hash: true)
   elsif match[2]
      {
         "__macros" => {
            match[2] => match[5]&.strip || [match[3], match[4]].compact.join(" ").strip
         }
      }.to_os(hash: true)
   else
      { match[3] => match[4] }.to_os
   end
end

#parse_context_line(line, opts) ⇒ Object



361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
# File 'lib/baltix/spec/rpm/parser.rb', line 361

def parse_context_line line, opts
   key = nil
   context = line.to_s.split(/\s+/).reduce({}.to_os) do |res, arg|
   #binding.pry
      case arg
      when '-l'
         key = :cp
      when '-n'
         key = :fullname
      else
         case key
         when :cp
            res.cp = arg
         when :fullname
            res.name = arg
         else
            res.name = "#{opts.name}-#{arg}"
         end
      end

      res
   end

   if context.name
      opts.secondaries ||= []
#         name = Baltix::Spec::Rpm::Name.parse(context[:name])
#      binding.pry
#         sel = opts["secondaries"].select { |sec| sec.name == name }

#            opts["secondaries"] << { "name" => name }.to_os if sel.blank?
   end
#      binding.pry

   context
end

#parse_default(match, *_) ⇒ Object



305
306
307
# File 'lib/baltix/spec/rpm/parser.rb', line 305

def parse_default match, *_
   match[1]
end

#parse_dep(match, *_) ⇒ Object



296
297
298
299
# File 'lib/baltix/spec/rpm/parser.rb', line 296

def parse_dep match, *_
   deps = match[1].scan(/[^\s]+(?:\s+[<=>]+\s+[^\s]+)?/)
   deps.reject {|d| /^(gem|rubygem|ruby-gem)\(/ =~ d }
end

#parse_description(match, flow, opts, context) ⇒ Object



321
322
323
324
# File 'lib/baltix/spec/rpm/parser.rb', line 321

def parse_description match, flow, opts, context
   context.replace(parse_context_line(match[1], opts))
   { context.cp || Baltix::I18n.default_locale => splitten_flow(flow) }.to_os
end

#parse_file(match, *_) ⇒ Object



264
265
266
# File 'lib/baltix/spec/rpm/parser.rb', line 264

def parse_file match, *_
   { match[1] || "0" => match[2] }.to_os
end

#parse_file_list(match, flow, opts, context) ⇒ Object



268
269
270
271
272
273
274
275
276
# File 'lib/baltix/spec/rpm/parser.rb', line 268

def parse_file_list match, flow, opts, context
   kind = {
      lib: /ruby_gemspec|ruby_gemlibdir/,
      doc: /ruby_gemdocdir/,
      exec: /_bindir/,
   }.find { |(k, re)| re =~ flow }&.[](0)
   context.replace(parse_context_line(match[1], opts).merge(kind: kind))
   splitten_flow(flow)
end

#parse_ignore(match, *_) ⇒ Object



301
302
303
# File 'lib/baltix/spec/rpm/parser.rb', line 301

def parse_ignore match, *_
   match[2].split(/,/).map {|x| x =~ /^\/(.*)/ && /#{$1}/ || x }
end

#parse_license(match, *_) ⇒ Object



326
327
328
# File 'lib/baltix/spec/rpm/parser.rb', line 326

def parse_license match, *_
   match[1].split(/(?: or |\/)/).map(&:strip)
end

#parse_name(match, *_) ⇒ Object



256
257
258
# File 'lib/baltix/spec/rpm/parser.rb', line 256

def parse_name match, *_
   Baltix::Spec::Rpm::Name.parse(match[1])
end

#parse_packager(match, *_) ⇒ Object



357
358
359
# File 'lib/baltix/spec/rpm/parser.rb', line 357

def parse_packager match, *_
   OpenStruct.new(name: match[1]&.strip, email: match[2]&.strip)
end

#parse_plain_section(_, flow, *_) ⇒ Object



309
310
311
# File 'lib/baltix/spec/rpm/parser.rb', line 309

def parse_plain_section _, flow, *_
   splitten_flow(flow)
end

#parse_secondary(match, flow, opts, context) ⇒ Object

secondary without suffix by default has kind of lib



314
315
316
317
318
319
# File 'lib/baltix/spec/rpm/parser.rb', line 314

def parse_secondary match, flow, opts, context
   context.replace(parse_context_line(match[1], opts))
   name = Baltix::Spec::Rpm::Name.parse(context.name, support_name: opts.name, aliases: aliased_names(opts))

   [{ "name" => name, "version" => opts.version, "release" => opts.release, "summaries" => opts.summaries.dup }.to_os ]
end

#parse_summary(match, _, opts, *_) ⇒ Object



330
331
332
333
# File 'lib/baltix/spec/rpm/parser.rb', line 330

def parse_summary match, _, opts, *_
   opts.summary = match[2]
   { match[1] || Baltix::I18n.default_locale => match[2] }.to_os
end

#parse_version(match, *_) ⇒ Object



353
354
355
# File 'lib/baltix/spec/rpm/parser.rb', line 353

def parse_version match, *_
   Gem::Version.new(match[1])
end

#reeval(flow, opts) ⇒ Object



243
244
245
246
247
248
249
250
251
252
253
254
# File 'lib/baltix/spec/rpm/parser.rb', line 243

def reeval flow, opts
   #binding.pry if flow =~ /%gemname/
   [opts.context.__options, opts.context.__macros, opts, opts.context.__custom].compact.reduce(flow) do |reflown_in, source|
      source.table.keys.sort_by {|x|x.size}.reverse.reduce(reflown_in) do |reflown, name|
         next reflown if /context|__macros|__options/ =~ name
         value = source[name]
         #binding.pry if flow =~ /%gemname/ && name =~ /%gemname/
         r = reflown.dup
         r.gsub!(/%({#{name}}|#{name})/, value.to_s) && value.is_a?(String) && /^%/ =~ value ? reeval(r, opts) : r
      end
   end || raise #flow
end

#secondary_for_context(opts, context) ⇒ Object



233
234
235
236
237
238
239
240
241
# File 'lib/baltix/spec/rpm/parser.rb', line 233

def secondary_for_context opts, context
   opts.secondaries.find do |sec|
   #binding.pry
      sec.name == Baltix::Spec::Rpm::Name.parse(
         context.name,
         support_name: opts.name,
         aliases: aliased_names(opts))
   end
end

#source(source_in) ⇒ Object



135
136
137
138
139
140
141
142
# File 'lib/baltix/spec/rpm/parser.rb', line 135

def source source_in
   if source_in.respond_to?(:readlines)
      source_in.rewind
      source_in.readlines
   else
      source_in.split("\n")
   end
end

#store_value(opts, match, key, flow, context) ⇒ Object



192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
# File 'lib/baltix/spec/rpm/parser.rb', line 192

def store_value opts, match, key, flow, context
   data = SCHEME[key]
   rule = data.is_a?(OpenStruct) && data.rule || data
   parse_func = data.is_a?(OpenStruct) && data.parse_func || :parse_default
   non_contexted = data.is_a?(OpenStruct) && data.non_contexted
   reflown = reeval(flow, opts)
   rematched = match.to_a.map { |x| x.is_a?(String) && reeval(x, opts) || x }
   value = method(parse_func)[rematched, reflown, opts, context]
   mode = data.is_a?(OpenStruct) && data.mode || :append
   copts = !non_contexted && context.name && opts.secondaries.find do |sec|
      #binding.pry
      sec.name == Baltix::Spec::Rpm::Name.parse(
         context.name,
         support_name: opts.name,
         aliases: aliased_names(opts))
   end || opts
   #binding.pry if key =~ /summar/
   #binding.pry if context[:kind]
   if !non_contexted && context.kind && context.kind.to_s != copts["name"].kind
      copts["name"] =
         Baltix::Spec::Rpm::Name.parse(copts["name"].original_fullname,
            kind: context.kind,
            support_name: copts["name"].support_name)
   end

   copts[key] =
   case copts[key]
   when NilClass
      value
   when Array
      copts[key] | [ value.is_a?(OpenStruct) && value || value ].flatten
   when OpenStruct
      copts[key].deep_merge(value, mode: mode)
   else
      value
   end

   #binding.pry if key =~ /summar/
   opts
end