Class: FPM::Package::RPM
- Inherits:
-
FPM::Package
- Object
- FPM::Package
- FPM::Package::RPM
- Defined in:
- lib/fpm/package/rpm.rb
Overview
RPM Package type.
Build RPMs without having to waste hours reading Maximum-RPM. Well, in case you want to read it, here: www.rpm.org/max-rpm/
The following attributes are supported:
-
:rpm_rpmbuild_define - an array of definitions to give to rpmbuild. These are used, verbatim, each as: –define ITEM
Constant Summary collapse
- DIGEST_ALGORITHM_MAP =
{ "md5" => 1, "sha1" => 2, "sha256" => 8, "sha384" => 9, "sha512" => 10 }
- COMPRESSION_MAP =
{ "none" => "w0.gzdio", "xz" => ".xzdio", "xzmt" => "T.xzdio", "gzip" => ".gzdio", "bzip2" => ".bzdio" }
Instance Attribute Summary
Attributes inherited from FPM::Package
#attributes, #attrs, #category, #config_files, #conflicts, #dependencies, #description, #directories, #license, #maintainer, #name, #provides, #replaces, #scripts, #url, #vendor
Instance Method Summary collapse
-
#architecture ⇒ Object
Handle any architecture naming conversions.
-
#build_sub_dir ⇒ Object
def prefix.
-
#converted_from(origin) ⇒ Object
See FPM::Package#converted_from.
-
#digest_algorithm ⇒ Object
def payload_compression.
-
#epoch ⇒ Object
The default epoch value must be nil, see #381.
-
#input(path) ⇒ Object
def rpm_get_trigger.
-
#iteration ⇒ Object
This method ensures a default value for iteration if none is provided.
-
#output(output_path) ⇒ Object
def prefixed_path.
-
#payload_compression ⇒ Object
def to_s.
-
#prefix ⇒ Object
def output.
-
#prefixed_path(path) ⇒ Object
def input.
-
#summary ⇒ Object
def build_sub_dir.
- #to_s(format = nil) ⇒ Object
-
#version ⇒ Object
def summary.
Methods inherited from FPM::Package
apply_options, #build_path, #cleanup, #cleanup_build, #cleanup_staging, #convert, default_attributes, #edit_file, #files, inherited, #initialize, option, #script, #staging_path, #type, type, types
Methods included from Util
#ar_cmd, #ar_cmd_deterministic?, #copied_entries, #copy_entry, #copy_metadata, #default_shell, #erbnew, #execmd, #expand_pessimistic_constraints, #logger, #program_exists?, #program_in_path?, #safesystem, #safesystemout, #tar_cmd, #tar_cmd_supports_sort_names_and_set_mtime?
Constructor Details
This class inherits a constructor from FPM::Package
Instance Method Details
#architecture ⇒ Object
Handle any architecture naming conversions. For example, debian calls amd64 what redhat calls x86_64, this method fixes those types of things.
252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 |
# File 'lib/fpm/package/rpm.rb', line 252 def architecture case @architecture when nil return %x{uname -m}.chomp # default to current arch when "amd64" # debian and redhat disagree on architecture names return "x86_64" when "arm64" # debian and redhat disagree on architecture names return "aarch64" when "native" return %x{uname -m}.chomp # 'native' is current arch when "all" # Translate fpm "all" arch to what it means in RPM. return "noarch" else return @architecture end end |
#build_sub_dir ⇒ Object
def prefix
621 622 623 624 |
# File 'lib/fpm/package/rpm.rb', line 621 def build_sub_dir return "BUILD" #return File.join("BUILD", prefix) end |
#converted_from(origin) ⇒ Object
See FPM::Package#converted_from
300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 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 |
# File 'lib/fpm/package/rpm.rb', line 300 def converted_from(origin) if origin == FPM::Package::CPAN if !attributes[:rpm_old_perl_dependency_name?] fixed_deps = [] self.dependencies.collect do |dep| # RPM package "perl" is a metapackage which install all the Perl bits and core modules, then gcc... # this must be replaced by perl-interpreter if name=/^perl([\s<>=].*)$/.match(dep) fixed_deps.push("perl-interpreter#{name[1]}") else fixed_deps.push(dep) end end self.dependencies = fixed_deps end elsif origin == FPM::Package::Gem fixed_deps = [] self.dependencies.collect do |dep| # Gem dependency operator "~>" is not compatible with rpm. Translate any found. fixed_deps = fixed_deps + (dep) end self.dependencies = fixed_deps # Convert 'rubygem-foo' provides values to 'rubygem(foo)' # since that's what most rpm packagers seem to do. self.provides = self.provides.collect do |provides| # Tries to match rubygem_prefix [1], gem_name [2] and version [3] if present # and return it in rubygem_prefix(gem_name) form if name=/^(#{attributes[:gem_package_name_prefix]})-([^\s]+)\s*(.*)$/.match(provides) "#{name[1]}(#{name[2]})#{name[3] ? " #{name[3]}" : ""}" else provides end end if !self.attributes[:rpm_verbatim_gem_dependencies?] self.dependencies = self.dependencies.collect do |dependency| # Tries to match rubygem_prefix [1], gem_name [2] and version [3] if present # and return it in rubygem_prefix(gem_name) form if name=/^(#{attributes[:gem_package_name_prefix]})-([^\s]+)\s*(.*)$/.match(dependency) "#{name[1]}(#{name[2]})#{name[3] ? " #{name[3]}" : ""}" else dependency end end end end # Convert != dependency as Conflict =, as rpm doesn't understand != self.dependencies = self.dependencies.select do |dep| name, op, version = dep.split(/\s+/) dep_ok = true if op == '!=' self.conflicts << "#{name} = #{version}" dep_ok = false end dep_ok end # if --ignore-iteration-in-dependencies is true convert foo = X, to # foo >= X , foo < X+1 if self.attributes[:rpm_ignore_iteration_in_dependencies?] self.dependencies = self.dependencies.collect do |dep| name, op, version = dep.split(/\s+/) if op == '=' nextversion = version.split('.').collect { |v| v.to_i } nextversion[-1] += 1 nextversion = nextversion.join(".") logger.warn("Converting dependency #{dep} to #{name} >= #{version}, #{name} < #{nextversion}") ["#{name} >= #{version}", "#{name} < #{nextversion}"] else dep end end.flatten end setscript = proc do |scriptname| script_path = self.attributes[scriptname] # Skip scripts not set next if script_path.nil? if !File.exist?(script_path) logger.error("No such file (for #{scriptname.to_s}): #{script_path.inspect}") script_errors << script_path end # Load the script into memory. scripts[scriptname] = File.read(script_path) end setscript.call(:rpm_verifyscript) setscript.call(:rpm_posttrans) setscript.call(:rpm_pretrans) end |
#digest_algorithm ⇒ Object
def payload_compression
679 680 681 |
# File 'lib/fpm/package/rpm.rb', line 679 def digest_algorithm return DIGEST_ALGORITHM_MAP[attributes[:rpm_digest]] end |
#epoch ⇒ Object
The default epoch value must be nil, see #381
645 646 647 648 649 650 651 652 653 |
# File 'lib/fpm/package/rpm.rb', line 645 def epoch return @epoch if @epoch.is_a?(Numeric) if @epoch.nil? or @epoch.empty? return nil end return @epoch end |
#input(path) ⇒ Object
def rpm_get_trigger
410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 |
# File 'lib/fpm/package/rpm.rb', line 410 def input(path) rpm = ::RPM::File.new(path) = {} rpm.header..each do |tag| [tag.tag] = tag.value end self.architecture = [:arch] self.category = [:group] self.description = [:description] self.epoch = ([:epoch] || [nil]).first # for some reason epoch is an array self.iteration = [:release] self.license = [:license] self.maintainer = maintainer self.name = [:name] self.url = [:url] self.vendor = [:vendor] self.version = [:version] self.scripts[:before_install] = [:prein] self.scripts[:after_install] = [:postin] self.scripts[:before_remove] = [:preun] self.scripts[:after_remove] = [:postun] self.scripts[:rpm_verifyscript] = [:verifyscript] self.scripts[:rpm_posttrans] = [:posttrans] self.scripts[:rpm_pretrans] = [:pretrans] # TODO(sissel): prefix these scripts above with a shebang line if there isn't one? # Also taking into account the value of tags[preinprog] etc, something like: # #!#{tags[:preinprog]} # #{tags[prein]} if ![:triggerindex].nil? val = [:triggerindex].zip([:triggername],[:triggerflags],[:triggerversion]).group_by{ |x| x[0]} val = val.collect do |order,data| new_data = data.collect { |x| [ x[1], rpm.operator(x[2]), x[3]].join(" ").strip}.join(", ") [order, rpm_get_trigger_type(data[0][2]), new_data] end val.each do |order, attr,data| self.attributes[attr] = [] if self.attributes[attr].nil? scriptprog = ([:triggerscriptprog][order] == '/bin/sh') ? "" : "-p #{[:triggerscriptprog][order]}" self.attributes[attr] << [data,[:triggerscripts][order],scriptprog] end end if !attributes[:no_auto_depends?] self.dependencies += rpm.requires.collect do |name, operator, version| [name, operator, version].join(" ") end end self.conflicts += rpm.conflicts.collect do |name, operator, version| [name, operator, version].join(" ") end self.provides += rpm.provides.collect do |name, operator, version| [name, operator, version].join(" ") end #input.replaces += replaces self.config_files += rpm.config_files # rpms support '%dir' things for specifying empty directories to package, # but the rpm header itself doesn't actually record this information. # so there's no 'directories' to copy, so don't try to merge in the # 'directories' feature. # TODO(sissel): If you want this feature, we'll have to find scan # the extracted rpm for empty directories. I'll wait until someone asks for # this feature #self.directories += rpm.directories # Extract to the staging directory rpm.extract(staging_path) end |
#iteration ⇒ Object
This method ensures a default value for iteration if none is provided.
271 272 273 274 275 276 277 278 279 |
# File 'lib/fpm/package/rpm.rb', line 271 def iteration if @iteration.kind_of?(String) and @iteration.include?("-") logger.warn("Package iteration '#{@iteration}' includes dashes, converting" \ " to underscores. rpmbuild does not allow the dashes in the package iteration (called 'Release' in rpm)") @iteration = @iteration.gsub(/-/, "_") end return @iteration ? @iteration : 1 end |
#output(output_path) ⇒ Object
def prefixed_path
488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 |
# File 'lib/fpm/package/rpm.rb', line 488 def output(output_path) output_check(output_path) %w(BUILD RPMS SRPMS SOURCES SPECS).each { |d| FileUtils.mkdir_p(build_path(d)) } args = ["rpmbuild", "-bb"] if %x{uname -m}.chomp != self.architecture rpm_target = self.architecture end # issue #309 if !attributes[:rpm_os].nil? rpm_target = "#{architecture}-unknown-#{attributes[:rpm_os]}" end # issue #707 if !rpm_target.nil? args += ["--target", rpm_target] end # set the rpm dist tag args += ["--define", "dist .#{attributes[:rpm_dist]}"] if attributes[:rpm_dist] args += [ "--buildroot", "#{build_path}/BUILD", "--define", "buildroot #{build_path}/BUILD", "--define", "_topdir #{build_path}", "--define", "_sourcedir #{build_path}", "--define", "_rpmdir #{build_path}/RPMS", "--define", "_tmppath #{attributes[:workdir]}" ] args += ["--sign"] if attributes[:rpm_sign?] if attributes[:rpm_auto_add_directories?] fs_dirs_list = File.join(template_dir, "rpm", "filesystem_list") fs_dirs = File.readlines(fs_dirs_list).reject { |x| x =~ /^\s*#/}.map { |x| x.chomp } fs_dirs.concat((attributes[:auto_add_exclude_directories] or [])) Find.find(staging_path) do |path| next if path == staging_path if File.directory? path and !File.symlink? path add_path = path.gsub(/^#{staging_path}/,'') self.directories << add_path if not fs_dirs.include? add_path end end else self.directories = self.directories.map { |x| self.prefixed_path(x) } alldirs = [] self.directories.each do |path| Find.find(File.join(staging_path, path)) do |subpath| if File.directory? subpath and !File.symlink? subpath alldirs << subpath.gsub(/^#{staging_path}/, '') end end end self.directories = alldirs end # include external config files (attributes[:config_files] or []).each do |conf| dest_conf = File.join(staging_path, conf) if File.exist?(dest_conf) logger.debug("Using --config-file from staging area", :path => conf) elsif File.exist?(conf) logger.info("Copying --config-file from local path", :path => conf) FileUtils.mkdir_p(File.dirname(dest_conf)) FileUtils.cp_r conf, dest_conf else logger.error("Failed to find given --config-file", :path => conf) raise "Could not find config file '#{conf}' in staging area or on host. This can happen if you specify `--config-file '#{conf}'` but this file does not exist in the source package and also does not exist in filesystem." end end # scan all conf file paths for files and add them allconfigs = [] self.config_files.each do |path| cfg_path = File.join(staging_path, path) raise "Config file path #{cfg_path} does not exist" unless File.exist?(cfg_path) Find.find(cfg_path) do |p| allconfigs << p.gsub("#{staging_path}/", '') if File.file? p end end allconfigs.sort!.uniq! self.config_files = allconfigs.map { |x| File.join("/", x) } # add init script if present (attributes[:rpm_init_list] or []).each do |init| name = File.basename(init, ".init") dest_init = File.join(staging_path, "etc/init.d/#{name}") FileUtils.mkdir_p(File.dirname(dest_init)) FileUtils.cp init, dest_init File.chmod(0755, dest_init) end (attributes[:rpm_rpmbuild_define] or []).each do |define| args += ["--define", define] end # copy all files from staging to BUILD dir # [#1538] Be sure to preserve the original timestamps. Find.find(staging_path) do |path| src = path.gsub(/^#{staging_path}/, '') dst = File.join(build_path, build_sub_dir, src) copy_entry(path, dst, preserve=true) end rpmspec = template("rpm.erb").result(binding) specfile = File.join(build_path("SPECS"), "#{name}.spec") File.write(specfile, rpmspec) edit_file(specfile) if attributes[:edit?] args << specfile logger.info("Running rpmbuild", :args => args) safesystem(*args) ::Dir["#{build_path}/RPMS/**/*.rpm"].each do |rpmpath| # This should only output one rpm, should we verify this? FileUtils.cp(rpmpath, output_path) end end |
#payload_compression ⇒ Object
def to_s
670 671 672 673 674 675 676 677 |
# File 'lib/fpm/package/rpm.rb', line 670 def payload_compression if attributes[:rpm_compression] == 'none' # when 'none' ignore any compression level and return w0.gzdio return COMPRESSION_MAP[attributes[:rpm_compression]] else return "w#{attributes[:rpm_compression_level]}" + COMPRESSION_MAP[attributes[:rpm_compression]] end end |
#prefix ⇒ Object
def output
613 614 615 616 617 618 619 |
# File 'lib/fpm/package/rpm.rb', line 613 def prefix if attributes[:prefix] and attributes[:prefix] != '/' return attributes[:prefix].chomp('/') else return "/" end end |
#prefixed_path(path) ⇒ Object
def input
484 485 486 |
# File 'lib/fpm/package/rpm.rb', line 484 def prefixed_path(path) Pathname.new(path).absolute?() ? path : File.join(self.prefix, path) end |
#summary ⇒ Object
def build_sub_dir
626 627 628 629 630 631 632 |
# File 'lib/fpm/package/rpm.rb', line 626 def summary if !attributes[:rpm_summary] return @description.split("\n").find { |line| !line.strip.empty? } || "_" end return attributes[:rpm_summary] end |
#to_s(format = nil) ⇒ Object
659 660 661 662 663 664 665 666 667 668 |
# File 'lib/fpm/package/rpm.rb', line 659 def to_s(format=nil) if format.nil? format = if attributes[:rpm_dist] "NAME-VERSION-ITERATION.DIST.ARCH.EXTENSION" else "NAME-VERSION-ITERATION.ARCH.EXTENSION" end end return super(format.gsub("DIST", to_s_dist)) end |
#version ⇒ Object
def summary
634 635 636 637 638 639 640 641 642 |
# File 'lib/fpm/package/rpm.rb', line 634 def version if @version.kind_of?(String) and @version.include?("-") logger.warn("Package version '#{@version}' includes dashes, converting" \ " to underscores") @version = @version.gsub(/-/, "_") end return @version end |