From 49093c353382c095a56706ad46ab297e61047374 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20Beauz=C3=A9e-Luyssen?= Date: Thu, 23 Nov 2023 17:08:22 +0100 Subject: [PATCH 1/6] deb: add a --compression-level option Fix #2006 --- lib/fpm/package/deb.rb | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/lib/fpm/package/deb.rb b/lib/fpm/package/deb.rb index 4d97dfb0cc..5c80badad0 100644 --- a/lib/fpm/package/deb.rb +++ b/lib/fpm/package/deb.rb @@ -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 ... @@ -642,18 +655,24 @@ 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 "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]}'" @@ -662,9 +681,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 @@ -721,7 +739,7 @@ def converted_from(origin) else # Also replace '::' in the perl module name with '-' modulename = m["name"].gsub("::", "-") - + # Fix any upper-casing or other naming concerns Debian has about packages name = "#{attributes[:cpan_package_name_prefix]}-#{modulename}" @@ -934,12 +952,17 @@ 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 "none" controltar = "control.tar" compression_flags = [] + compressor_options = {} else raise FPM::InvalidPackageConfiguration, "Unknown compression type '#{self.attributes[:deb_compression]}'" @@ -954,9 +977,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 From c9d749a3a793bda82527d232da815dc2c1b8c7e4 Mon Sep 17 00:00:00 2001 From: Gordon Bleux <33967640+UiP9AV6Y@users.noreply.github.com> Date: Thu, 14 Dec 2023 21:21:33 +0100 Subject: [PATCH 2/6] rpm: generate changelog if none is provided `rpmlint` considers a lack of a changelog an error. this is a similar behaviour to the DEB packager, where a generic default changelog is generated unless one is provided explicitly. --- lib/fpm/package/rpm.rb | 18 +++++++++++++++++ spec/fpm/package/rpm_spec.rb | 39 ++++++++++++++++++++++++++++++++++++ templates/rpm.erb | 2 +- 3 files changed, 58 insertions(+), 1 deletion(-) diff --git a/lib/fpm/package/rpm.rb b/lib/fpm/package/rpm.rb index a925256561..0159c7e121 100644 --- a/lib/fpm/package/rpm.rb +++ b/lib/fpm/package/rpm.rb @@ -275,6 +275,24 @@ 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 diff --git a/spec/fpm/package/rpm_spec.rb b/spec/fpm/package/rpm_spec.rb index 77d62abc9d..015a801f4a 100644 --- a/spec/fpm/package/rpm_spec.rb +++ b/spec/fpm/package/rpm_spec.rb @@ -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 " + @target = Stud::Temporary.pathname + + # Write RPM + subject.output(@target) + + @rpm = ::RPM::File.new(@target) + insist { @rpm.tags[:changelogname] } == [ "Spec Test - 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] = < - 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 - 1.0-1" ] + insist { @rpm.tags[:changelogtext] } == [ "- First example package" ] + + File.unlink(@target) + end + end # changelog end # #output describe "prefix attribute" do diff --git a/templates/rpm.erb b/templates/rpm.erb index 0e851f26d9..584038f636 100644 --- a/templates/rpm.erb +++ b/templates/rpm.erb @@ -260,4 +260,4 @@ fi <% end -%> %changelog -<%= attributes[:rpm_changelog] %> +<%= changelog %> From 5960c8c4a7ec3758792416dea0ec3bae47fb2f35 Mon Sep 17 00:00:00 2001 From: Kristof Willaert Date: Thu, 16 May 2024 18:13:54 +0200 Subject: [PATCH 3/6] Escape the pylib path when using it in a shell command --- lib/fpm/package/python.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/fpm/package/python.rb b/lib/fpm/package/python.rb index 5754a053d4..04533ddcaf 100644 --- a/lib/fpm/package/python.rb +++ b/lib/fpm/package/python.rb @@ -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, @@ -230,7 +230,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?] From 5092c5f659e856f017bf1b7204db1cee8ec2ea72 Mon Sep 17 00:00:00 2001 From: Reinier Schoof Date: Wed, 26 Jun 2024 15:54:02 +0200 Subject: [PATCH 4/6] Add option --deb-systemd-path This option will allow you to override the path within the staging directory systemd service files are moved to in debian packages. On some systems systemd should not go in the hardcoded /lib/systemd/system but in /usr/lib/systemd/system instead. Many systems have the both symlinked, but not all so assuming /lib/systemd/system can be dangerous. Signed-off-by: Reinier Schoof --- lib/fpm/package/deb.rb | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/fpm/package/deb.rb b/lib/fpm/package/deb.rb index 4d97dfb0cc..71cccd84ff 100644 --- a/lib/fpm/package/deb.rb +++ b/lib/fpm/package/deb.rb @@ -210,6 +210,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 @@ -518,7 +523,7 @@ def output(output_path) attributes[:deb_systemd] = [] attributes.fetch(:deb_systemd_list, []).each do |systemd| name = File.basename(systemd, ".service") - dest_systemd = staging_path("lib/systemd/system/#{name}.service") + dest_systemd = staging_path(File.join(attributes[:deb_systemd_path], "#{name}.service")) mkdir_p(File.dirname(dest_systemd)) FileUtils.cp(systemd, dest_systemd) File.chmod(0644, dest_systemd) @@ -628,7 +633,7 @@ def output(output_path) attributes.fetch(:deb_systemd_list, []).each do |systemd| name = File.basename(systemd, ".service") - dest_systemd = staging_path("lib/systemd/system/#{name}.service") + dest_systemd = staging_path(File.join(attributes[:deb_systemd_path], "#{name}.service")) mkdir_p(File.dirname(dest_systemd)) FileUtils.cp(systemd, dest_systemd) File.chmod(0644, dest_systemd) From 790f53c766ff9f8ac507fc7221afcabfbc07537d Mon Sep 17 00:00:00 2001 From: Matt Ezell Date: Mon, 23 Sep 2024 10:33:57 -0400 Subject: [PATCH 5/6] Support pip download returning a zip file Signed-off-by: Matt Ezell --- lib/fpm/package/python.rb | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/fpm/package/python.rb b/lib/fpm/package/python.rb index 5754a053d4..7e0dfac1d3 100644 --- a/lib/fpm/package/python.rb +++ b/lib/fpm/package/python.rb @@ -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]) From 512f4a9eb3295106abc903ac4424e1323f766e51 Mon Sep 17 00:00:00 2001 From: Jordan Sissel Date: Sat, 7 Dec 2024 23:28:42 -0800 Subject: [PATCH 6/6] Fix syntax I broke when doing a merge conflict --- lib/fpm/package/deb.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/fpm/package/deb.rb b/lib/fpm/package/deb.rb index c61094730a..c996bfcb10 100644 --- a/lib/fpm/package/deb.rb +++ b/lib/fpm/package/deb.rb @@ -696,7 +696,7 @@ def output(output_path) datatar = build_path("data.tar.zst") controltar = build_path("control.tar.zst") compression_flags = ["-I zstd"] - compressor_options = {"ZSTD_CLEVEL", "-#{self.attributes[:deb_compression_level] || 3}"} + compressor_options = {"ZSTD_CLEVEL" => "-#{self.attributes[:deb_compression_level] || 3}"} when "none" datatar = build_path("data.tar") controltar = build_path("control.tar") @@ -991,7 +991,7 @@ def write_control_tarball when "zst" controltar = "control.tar.zst" compression_flags = ["-I zstd"] - compressor_options = {"ZSTD_CLEVEL", "-#{self.attributes[:deb_compression_level] || 3}"} + compressor_options = {"ZSTD_CLEVEL" => "-#{self.attributes[:deb_compression_level] || 3}"} when "none" controltar = "control.tar" compression_flags = []