Skip to content

Commit

Permalink
Merge branch 'main' into pull/2009
Browse files Browse the repository at this point in the history
  • Loading branch information
jordansissel authored Dec 9, 2024
2 parents c326b39 + e7e7449 commit b2f2fc6
Show file tree
Hide file tree
Showing 6 changed files with 158 additions and 13 deletions.
12 changes: 12 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
Release Notes and Change Log
============================

Unreleased (...)
^^^^^^^^^^^^^^^^

This is a stub of changes since the last release.
* https://github.com/jordansissel/fpm/pull/2068 (`#2068`_; Matt Ezell, `#2074`_; hussainbani)
* https://github.com/jordansissel/fpm/pull/2009 (`#2009`_; Ștefan Rusu)
* https://github.com/jordansissel/fpm/pull/2082 (`#2082`_; Wayne Heaney)
* https://github.com/jordansissel/fpm/pull/2064 (`#2064`_; David Newhall II)
* https://github.com/jordansissel/fpm/pull/2067 (`#2067`_; Jordan Sissel)
* https://github.com/jordansissel/fpm/pull/2065 (`#2065`_; phillipp)


1.15.1 (January 31, 2023)
^^^^^^^^^^^^^^^^^^^^^^^^^
* Ruby 3.2.0 now supported. This fixes error 'undefined method exists? for File' '(`#1981`_, `#1988`_; Nicholas Hubbard, romulasry)
Expand Down
70 changes: 64 additions & 6 deletions lib/fpm/package/deb.rb
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,19 @@ class FPM::Package::Deb < FPM::Package
value
end

option "--compression-level", "[0-9]", "Select a compression level. 0 is none or minimal. 9 is max compression.",
# Specify which compression level to use on the compressor backend, when building a package
:default => nil do |value|
valint = value.to_i
# if self.attributes[:deb_compression].nil?
# raise "Can't specify a compression level with compression disabled"
# end
unless value =~ /^\d$/ && valint >= 0 && valint <= 9
raise "Invalid compression level '#{value}'. Valid values are integers between 0 and 9 inclusive."
end
valint
end

option "--dist", "DIST-TAG", "Set the deb distribution.", :default => "unstable"

# Take care about the case when we want custom control file but still use fpm ...
Expand Down Expand Up @@ -210,6 +223,11 @@ class FPM::Package::Deb < FPM::Package
next File.expand_path(file)
end

option "--systemd-path", "FILEPATH", "Relative path to the systemd service directory",
:default => "lib/systemd/system" do |file|
next file.gsub(/^\/*/, '')
end

option "--systemd-enable", :flag , "Enable service on install or upgrade", :default => false

option "--systemd-auto-start", :flag , "Start service after install or upgrade", :default => false
Expand Down Expand Up @@ -262,6 +280,9 @@ def architecture
when "noarch"
# Debian calls noarch "all"
@architecture = "all"
when "ppc64le"
# Debian calls ppc64le "ppc64el"
@architecture = "ppc64el"
end
return @architecture
end # def architecture
Expand Down Expand Up @@ -534,7 +555,7 @@ def output(output_path)
raise FPM::InvalidPackageConfiguration, "Invalid systemd unit file extension: #{extname}. Expected .service or .timer, or no extension."
end

dest_systemd = staging_path("lib/systemd/system/#{name_with_extension}")
dest_systemd = staging_path(File.join(attributes[:deb_systemd_path], "#{name_with_extension}"))
mkdir_p(File.dirname(dest_systemd))
FileUtils.cp(systemd, dest_systemd)
File.chmod(0644, dest_systemd)
Expand Down Expand Up @@ -646,7 +667,8 @@ def output(output_path)
extname = File.extname(systemd)
name_with_extension = extname.empty? ? "#{name}.service" : name

dest_systemd = staging_path("lib/systemd/system/#{name_with_extension}")
dest_systemd = staging_path(File.join(attributes[:deb_systemd_path], "#{name_with_extension}"))

mkdir_p(File.dirname(dest_systemd))
FileUtils.cp(systemd, dest_systemd)
File.chmod(0644, dest_systemd)
Expand All @@ -660,22 +682,29 @@ def output(output_path)
datatar = build_path("data.tar.gz")
controltar = build_path("control.tar.gz")
compression_flags = ["-z"]
# gnu tar obeys GZIP environment variable with options for gzip; -n = forget original filename and date
compressor_options = {"GZIP" => "-#{self.attributes[:deb_compression_level] || 9}" +
"#{'n' if tar_cmd_supports_sort_names_and_set_mtime? and not attributes[:source_date_epoch].nil?}"}
when "bzip2"
datatar = build_path("data.tar.bz2")
controltar = build_path("control.tar.gz")
compression_flags = ["-j"]
compressor_options = {"BZIP" => "-#{self.attributes[:deb_compression_level] || 9}"}
when "xz"
datatar = build_path("data.tar.xz")
controltar = build_path("control.tar.xz")
compression_flags = ["-J"]
compressor_options = {"XZ_OPT" => "-#{self.attributes[:deb_compression_level] || 3}"}
when "zst"
datatar = build_path("data.tar.zst")
controltar = build_path("control.tar.zst")
compression_flags = ["--use-compress-program", "zstd"]
compressor_options = {"ZSTD_CLEVEL" => "-#{self.attributes[:deb_compression_level] || 3}"}
when "none"
datatar = build_path("data.tar")
controltar = build_path("control.tar")
compression_flags = []
compressor_options = {}
else
raise FPM::InvalidPackageConfiguration,
"Unknown compression type '#{self.attributes[:deb_compression]}'"
Expand All @@ -684,9 +713,8 @@ def output(output_path)
if tar_cmd_supports_sort_names_and_set_mtime? and not attributes[:source_date_epoch].nil?
# Use gnu tar options to force deterministic file order and timestamp
args += ["--sort=name", ("--mtime=@%s" % attributes[:source_date_epoch])]
# gnu tar obeys GZIP environment variable with options for gzip; -n = forget original filename and date
args.unshift({"GZIP" => "-9n"})
end
args.unshift(compressor_options)
safesystem(*args)

# pack up the .deb, which is just an 'ar' archive with 3 files
Expand Down Expand Up @@ -726,9 +754,17 @@ def converted_from(origin)
self.dependencies = self.dependencies.collect do |dep|
fix_dependency(dep)
end.flatten

# If an invalid depends field was found i.e. /bin.sh then fix_depends will blank it
# Make sure we remove this blank here
self.dependencies = self.dependencies.reject { |p| p.empty? }

self.provides = self.provides.collect do |provides|
fix_provides(provides)
end.flatten
# If an invalid provides field was found i.e. mypackage(arch) then fix_provides will blank it
# Make sure we remove this blank here
self.provides = self.provides.reject { |p| p.empty? }

if origin == FPM::Package::CPAN
# The fpm cpan code presents dependencies and provides fields as perl(ModuleName)
Expand Down Expand Up @@ -829,6 +865,18 @@ def fix_dependency(dep)
end
end

if dep.start_with?("/")
logger.warn("Blanking 'dependency' field '#{dep}' because it's invalid")
dep = ""
return dep
end

if dep.include?("rpmlib")
logger.warn("Blanking 'dependency' field '#{dep}' because it's invalid")
dep = ""
return dep
end

name_re = /^[^ \(]+/
name = dep[name_re]
if name =~ /[A-Z]/
Expand Down Expand Up @@ -922,6 +970,11 @@ def fix_provides(provides)
provides = provides.gsub("_", "-")
end

if provides.include?("(") and !provides.include?("(=")
logger.warn("Blanking 'provides' field '#{provides}' because it's invalid")
provides = ""
end

if m = provides.match(/^([A-Za-z0-9_-]+)\s*=\s*(\d+.*$)/)
logger.warn("Replacing 'provides' entry #{provides} with syntax 'name (= version)'")
provides = "#{m[1]} (= #{m[2]})"
Expand Down Expand Up @@ -956,15 +1009,21 @@ def write_control_tarball
when "gz", "bzip2", nil
controltar = "control.tar.gz"
compression_flags = ["-z"]
# gnu tar obeys GZIP environment variable with options for gzip; -n = forget original filename and date
compressor_options = {"GZIP" => "-#{self.attributes[:deb_compression_level] || 9}" +
"#{'n' if tar_cmd_supports_sort_names_and_set_mtime? and not attributes[:source_date_epoch].nil?}"}
when "xz"
controltar = "control.tar.xz"
compression_flags = ["-J"]
compressor_options = {"XZ_OPT" => "-#{self.attributes[:deb_compression_level] || 3}"}
when "zst"
controltar = "control.tar.zst"
compression_flags = ["--use-compress-program", "zstd"]
compressor_options = {"ZSTD_CLEVEL" => "-#{self.attributes[:deb_compression_level] || 3}"}
when "none"
controltar = "control.tar"
compression_flags = []
compressor_options = {}
else
raise FPM::InvalidPackageConfiguration,
"Unknown compression type '#{self.attributes[:deb_compression]}'"
Expand All @@ -979,9 +1038,8 @@ def write_control_tarball
if tar_cmd_supports_sort_names_and_set_mtime? and not attributes[:source_date_epoch].nil?
# Force deterministic file order and timestamp
args += ["--sort=name", ("--mtime=@%s" % attributes[:source_date_epoch])]
# gnu tar obeys GZIP environment variable with options for gzip; -n = forget original filename and date
args.unshift({"GZIP" => "-9n"})
end
args.unshift(compressor_options)
safesystem(*args)
end

Expand Down
16 changes: 11 additions & 5 deletions lib/fpm/package/python.rb
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ class FPM::Package::Python < FPM::Package
option "--setup-py-arguments", "setup_py_argument",
"Arbitrary argument(s) to be passed to setup.py",
:multivalued => true, :attribute_name => :python_setup_py_arguments,
:default => []
:default => []
option "--internal-pip", :flag,
"Use the pip module within python to install modules - aka 'python -m pip'. This is the recommended usage since Python 3.4 (2014) instead of invoking the 'pip' script",
:attribute_name => :python_internal_pip,
Expand Down Expand Up @@ -171,13 +171,19 @@ def download_if_necessary(package, version=nil)
# behind a directory with the Python package extracted and ready to be used.
# For example, `pip download ... Django` puts `Django-4.0.4.tar.tz` into the build_path directory.
# If we expect `pip` to leave an unknown-named file in the `build_path` directory, let's check for
# a single file and unpack it. I don't know if it will /always/ be a .tar.gz though.
files = ::Dir.glob(File.join(build_path, "*.tar.gz"))
# a single file and unpack it.
files = ::Dir.glob(File.join(build_path, "*.{tar.gz,zip}"))
if files.length != 1
raise "Unexpected directory layout after `pip download ...`. This might be an fpm bug? The directory is #{build_path}"
end

safesystem("tar", "-zxf", files[0], "-C", target)
if files[0].end_with?("tar.gz")
safesystem("tar", "-zxf", files[0], "-C", target)
elsif files[0].end_with?("zip")
safesystem("unzip", files[0], "-d", target)
else
raise "Unexpected file format after `pip download ...`. This might be an fpm bug? The file is #{files[0]}"
end
else
# no pip, use easy_install
logger.debug("no pip, defaulting to easy_install", :easy_install => attributes[:python_easyinstall])
Expand Down Expand Up @@ -230,7 +236,7 @@ def load_package_info(setup_py)

output = ::Dir.chdir(setup_dir) do
tmp = build_path("metadata.json")
setup_cmd = "env PYTHONPATH=#{pylib}:$PYTHONPATH #{attributes[:python_bin]} " \
setup_cmd = "env PYTHONPATH=#{pylib.shellescape}:$PYTHONPATH #{attributes[:python_bin]} " \
"setup.py --command-packages=pyfpm get_metadata --output=#{tmp}"

if attributes[:python_obey_requirements_txt?]
Expand Down
32 changes: 31 additions & 1 deletion lib/fpm/package/rpm.rb
Original file line number Diff line number Diff line change
Expand Up @@ -275,9 +275,39 @@ def iteration
return @iteration ? @iteration : 1
end # def iteration

# Generate a generic changelog or return an existing definition
def changelog
if attributes[:rpm_changelog]
return attributes[:rpm_changelog]
end

reldate = if attributes[:source_date_epoch].nil?
Time.now()
else
Time.at(attributes[:source_date_epoch].to_i)
end
changed = reldate.strftime("%a %b %_e %Y")
changev = "#{version}-#{iteration}"
changev += "%{?dist}" if attributes[:rpm_dist]

"* #{changed} #{maintainer} - #{changev}\n- Package created with FPM\n"
end

# See FPM::Package#converted_from
def converted_from(origin)
if origin == FPM::Package::Gem
if origin == FPM::Package::CPAN
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
elsif origin == FPM::Package::Gem
fixed_deps = []
self.dependencies.collect do |dep|
# Gem dependency operator "~>" is not compatible with rpm. Translate any found.
Expand Down
39 changes: 39 additions & 0 deletions spec/fpm/package/rpm_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,45 @@ def subject.render_template; @rpmspec = template("rpm.erb").result(binding); end
File.unlink(@target)
end
end # dist

context "changelog" do
it "should generate a changelog in the release" do
subject.name = "example"
subject.attributes[:rpm_dist] = 'rhel'
subject.version = "1.2.3"
subject.maintainer = "Spec Test <[email protected]>"
@target = Stud::Temporary.pathname

# Write RPM
subject.output(@target)

@rpm = ::RPM::File.new(@target)
insist { @rpm.tags[:changelogname] } == [ "Spec Test <[email protected]> - 1.2.3-1.rhel" ]
insist { @rpm.tags[:changelogtext] } == [ "- Package created with FPM" ]

File.unlink(@target)
end

it "should have the changelog in the release" do
subject.name = "example"
subject.attributes[:rpm_changelog] = <<CHANGELOG
* Tue May 31 2016 Example Maintainers <[email protected]> - 1.0-1
- First example package
CHANGELOG
subject.version = "1.0"
@target = Stud::Temporary.pathname

# Write RPM
subject.output(@target)

@rpm = ::RPM::File.new(@target)
insist { @rpm.tags[:changelogtime] } == [ 1464696000 ]
insist { @rpm.tags[:changelogname] } == [ "Example Maintainers <[email protected]> - 1.0-1" ]
insist { @rpm.tags[:changelogtext] } == [ "- First example package" ]

File.unlink(@target)
end
end # changelog
end # #output

describe "prefix attribute" do
Expand Down
2 changes: 1 addition & 1 deletion templates/rpm.erb
Original file line number Diff line number Diff line change
Expand Up @@ -260,4 +260,4 @@ fi
<% end -%>

%changelog
<%= attributes[:rpm_changelog] %>
<%= changelog %>

0 comments on commit b2f2fc6

Please sign in to comment.