diff --git a/docs/cli-reference.rst b/docs/cli-reference.rst index 744bfe9b2..f013590a9 100644 --- a/docs/cli-reference.rst +++ b/docs/cli-reference.rst @@ -210,6 +210,9 @@ General Options * ``--deb-templates FILEPATH`` - (deb only) Add FILEPATH as debconf templates file. +* ``--deb-trigger FILEPATH`` + - (deb only) Add FILEPATH as trigger script + * ``--deb-upstart FILEPATH`` - (deb only) Add FILEPATH as an upstart script diff --git a/docs/snippets.rst b/docs/snippets.rst new file mode 100644 index 000000000..b8e7fc7c2 --- /dev/null +++ b/docs/snippets.rst @@ -0,0 +1,8 @@ +Snippets For Argument Usage +========= + +.. toctree:: + :maxdepth: 1 + :glob: + + snippets/* diff --git a/docs/snippets/deb-trigger.rst b/docs/snippets/deb-trigger.rst new file mode 100644 index 000000000..bc6f56226 --- /dev/null +++ b/docs/snippets/deb-trigger.rst @@ -0,0 +1,88 @@ +Debian Triggers +=============== + +Debian packages can install commands to be run after installation and configuration of all packages. +Those commands are called triggers as other packages can ask the package manager to run those. + +Sample trigger script +--------------------- + +This script defines two triggers. First the label based trigger `some-trigger` which runs `some-command`. Second the path based trigger `/etc/foobar` which runs a find-command. + +:: + + for trigger in "$@"; do + case "$trigger" in + some-trigger) + some-command + ;; + /etc/foobar) + find /etc/foobar -type f -ls + ;; + esac + done + +Install trigger +--------------- + +The following fpm command installs the trigger: + + fpm --deb-trigger /path/to/triggers.sh + +The resulting postinst-script in the packages looks like this: + +:: + + #!/bin/sh + + after_upgrade() { + : + } + + after_install() { + : + } + + triggered() { + : + for trigger in "$@"; do + case "$trigger" in + some-trigger) + some-command + ;; + /etc/foobar) + find /etc/foobar -type f -ls + ;; + esac + done + } + + if [ "${1}" = "configure" -a -z "${2}" ] || \ + [ "${1}" = "abort-remove" ] + then + # "after install" here + # "abort-remove" happens when the pre-removal script failed. + # In that case, this script, which should be idemptoent, is run + # to ensure a clean roll-back of the removal. + after_install + elif [ "${1}" = "configure" -a -n "${2}" ] + then + upgradeFromVersion="${2}" + # "after upgrade" here + # NOTE: This slot is also used when deb packages are removed, + # but their config files aren't, but a newer version of the + # package is installed later, called "Config-Files" state. + # basically, that still looks a _lot_ like an upgrade to me. + after_upgrade "${2}" + elif [ "${1}" = "triggered" ] + then + # "triggered" here + # NOTE: This slot allows implementing package triggers according to + # https://wiki.debian.org/DpkgTriggers + shift + triggered "${@}" + elif echo "${1}" | grep -E -q "(abort|fail)" + then + echo "Failed to install before the post-installation script was run." >&2 + exit 1 + fi diff --git a/lib/fpm/command.rb b/lib/fpm/command.rb index d2c2d78a7..19a583f41 100644 --- a/lib/fpm/command.rb +++ b/lib/fpm/command.rb @@ -212,7 +212,6 @@ def help(*args) "Currently only supports deb, rpm and pacman packages." do |val| File.expand_path(val) # Get the full path to the script end # --before-upgrade - option "--template-scripts", :flag, "Allow scripts to be templated. This lets you use ERB to template your " \ "packaging scripts (for --after-install, etc). For example, you can do " \ diff --git a/lib/fpm/package/deb.rb b/lib/fpm/package/deb.rb index f9ab72358..eb4cc7a9c 100644 --- a/lib/fpm/package/deb.rb +++ b/lib/fpm/package/deb.rb @@ -23,7 +23,6 @@ class FPM::Package::Deb < FPM::Package :after_install => "postinst", :before_remove => "prerm", :after_remove => "postrm", - :after_purge => "postrm", } unless defined?(SCRIPT_MAP) # The list of supported compression types. Default is gz (gzip) @@ -200,6 +199,12 @@ class FPM::Package::Deb < FPM::Package next File.expand_path(file) end + option "--trigger", "FILE", "Add FILE as trigger script. " \ + "See https://wiki.debian.org/DpkgTriggers and " \ + "https://stackoverflow.com/questions/15276535/dpkg-how-to-use-trigger" do |file| + next File.expand_path(file) + end # --trigger + option "--upstart", "FILEPATH", "Add FILEPATH as an upstart script", :multivalued => true do |file| next File.expand_path(file) @@ -527,23 +532,26 @@ def output(output_path) attributes[:deb_systemd] << name end - if script?(:before_upgrade) or script?(:after_upgrade) or attributes[:deb_systemd].any? - puts "Adding action files" - if script?(:before_install) or script?(:before_upgrade) - scripts[:before_install] = template("deb/preinst_upgrade.sh.erb").result(binding) - end - if script?(:before_remove) or not attributes[:deb_systemd].empty? - scripts[:before_remove] = template("deb/prerm_upgrade.sh.erb").result(binding) - end - if script?(:after_install) or script?(:after_upgrade) or attributes[:deb_systemd].any? - scripts[:after_install] = template("deb/postinst_upgrade.sh.erb").result(binding) - end - if script?(:after_remove) - scripts[:after_remove] = template("deb/postrm_upgrade.sh.erb").result(binding) - end - if script?(:after_purge) - scripts[:after_purge] = template("deb/postrm_upgrade.sh.erb").result(binding) - end + if not attributes[:deb_trigger].nil? + scripts[:deb_trigger] = File.read(attributes[:deb_trigger]) + end + + if not attributes[:deb_after_purge].nil? + scripts[:after_purge] = File.read(attributes[:deb_after_purge]) + end + + puts "Adding action files" + if script?(:before_install) or script?(:before_upgrade) + scripts[:before_install] = template("deb/preinst_upgrade.sh.erb").result(binding) + end + if script?(:before_remove) or attributes[:deb_systemd].any? + scripts[:before_remove] = template("deb/prerm_upgrade.sh.erb").result(binding) + end + if script?(:after_install) or script?(:after_upgrade) or attributes[:deb_systemd].any? or script?(:deb_trigger) + scripts[:after_install] = template("deb/postinst_upgrade.sh.erb").result(binding) + end + if script?(:after_remove) or script?(:after_purge) + scripts[:after_remove] = template("deb/postrm_upgrade.sh.erb").result(binding) end # There are two changelogs that may appear: @@ -593,7 +601,9 @@ def output(output_path) if File.exists?(dest_changelog) and not File.exists?(dest_upstream_changelog) # see https://www.debian.org/doc/debian-policy/ch-docs.html#s-changelogs - File.rename(dest_changelog, dest_upstream_changelog) + # to solve Lintian rule debian-changelog-file-missing-or-wrong-name the file + # is copied and not renamed + FileUtils.cp(dest_changelog, dest_upstream_changelog) end attributes.fetch(:deb_init_list, []).each do |init| diff --git a/templates/deb/postinst_upgrade.sh.erb b/templates/deb/postinst_upgrade.sh.erb index 80a956450..66d8ac800 100644 --- a/templates/deb/postinst_upgrade.sh.erb +++ b/templates/deb/postinst_upgrade.sh.erb @@ -60,6 +60,17 @@ $debsystemctl start <%= service %> >/dev/null || true <% end -%> } +triggered() { +<%# Making sure that at least one command is in the function -%> +<%# avoids a lot of potential errors, including the case that -%> +<%# the script is non-empty, but just whitespace and/or comments -%> + : +<%# if any trigger specified, loop through and start them -%> +<% if script?(:deb_trigger) -%> +<%= script(:deb_trigger) %> +<% end -%> +} + if [ "${1}" = "configure" -a -z "${2}" ] || \ [ "${1}" = "abort-remove" ] then @@ -77,6 +88,13 @@ then # package is installed later, called "Config-Files" state. # basically, that still looks a _lot_ like an upgrade to me. after_upgrade "${2}" +elif [ "${1}" = "triggered" ] +then + # "triggered" here + # NOTE: This slot allows implementing package triggers according to + # https://wiki.debian.org/DpkgTriggers + shift + triggered "${@}" elif echo "${1}" | grep -E -q "(abort|fail)" then echo "Failed to install before the post-installation script was run." >&2