For #1795
This replaces another library which uses ffi with an implementation
that doesn't need ffi.
I am not certain this is an exact replacement, but for my casual tests,
comparing .txz files generated before/after this commit, things seem ok.
This would benefit from real freebsd testing, though.
This removes fpm's direct use of FFI and removes `ffi` as a direct
dependency. For #1795
Cases:
* A unix socket.
* A named pipe
* A charDev should now fail (like /dev/tty)
* A blockDev should now fail (like /dev/sda1)
NOTE: In this change, chardev and blockdev support have been removed.
These "copies" previously were just calling `mknod` with identical
mode, basically copying the `mode` from stat(2) to mknod(2).
Exceptions are now thrown for chardev and blockdev.
Test cases:
# Try to package a named pipe.
% mkfifo /tmp/z.pipe
% bundle exec bin/fpm -s dir -t rpm -n example /tmp/z.pipe
Created package {:path=>"example-1.0-1.x86_64.rpm"}
% rpm -qlvp example-1.0-1.x86_64.rpm
prw-rw-r-- 1 root root 0 Jun 17 22:40 /tmp/z.pipe
# Create the unix socket
% nc -lU /tmp/z.sock
# Package it into an rpm
% bin/fpm -s dir -t rpm -n example /tmp/z.sock |& less
{:timestamp=>"2021-06-17T22:33:27.780347-0700", :message=>"Created package", :path=>"example-1.0-1.x86_64.rpm"}
# Verify the file is of socket type ('s' at beginning of file mode
% rpm -qlvp example-1.0-1.x86_64.rpm
srwxrwxr-x 1 root root 0 Jun 17 22:33 /tmp/z.sock
Previously, rexml was included standard in Ruby. However, in 3.0.0, ruby
moved this library to be a "bundled gem", per the release notes:
https://www.ruby-lang.org/en/news/2020/12/25/ruby-3-0-0-released/
> The following default gems are now bundled gems.
> * rexml
Tested on Ruby 2.7.0 and 3.0.1 w/ bundler and it works.
```
% (rbenv shell 3.0.1; bundle install; bundle exec bin/fpm -s empty -t empty -n example)
% (rbenv shell 2.7.0; bundle install; bundle exec bin/fpm -s empty -t empty -n example)
```
Fixes#1793
ffi 1.13 requires Ruby 2.3, which is not supplied by many still-supported distros (e.g Centos/RHEL 7), 1.12.X works there, so restrict to that.
Addresses #1708
rubies >= 2.5 ship with JSON 2.x, so allowing bundler to resolve to newer
implementations eliminates conflicts with dependency trees that include JSON
2.x.
Breaking changes for JSON 2.x include removed support for older rubies [1],
so specifying in this manner ensures that older rubies can find 1.x, while
newer ones can resolve to 2.x
[1]: https://github.com/flori/json/blob/master/CHANGES.md#2015-09-11-200
Resolves: https://github.com/jordansissel/fpm/issues/1599
Long term, we'll probably have a "smart" post-install that will choose
the correct service (systemd, etc) to install based on the platform
doing the installation, not the platform creating the package :)
Adds dependencies on pleaserun and upgrades clamp to suit.
Example using the defaults in pleaserun:
# Create a package called 'example-service' that installs a service named 'example'
% bin/fpm -s pleaserun -t rpm -n example-service --pleaserun-name example =logger hello world
No platform selected. Autodetecting... {:platform=>"systemd", :version=>"default", :level=>:warn}
Writing file {:destination=>"/tmp/package-pleaserun-staging20160513-12576-1ozurnf/lib/systemd/system/example.service"}
Writing install actions. You will want to run this script to properly activate your service on the target host {:path=>"/tmp/package-pleaserun-staging20160513-12576-1ozurnf/install_actions.sh"}
Created package {:path=>"example-service-1.0-1.x86_64.rpm"}
# ^^ The above service will execute "logger hello world"
# What's in our rpm?
% rpm -qlp example-service-1.0-1.x86_64.rpm
/lib/systemd/system/example.service
# What about any post-install steps?
% rpm -qp example-service-1.0-1.x86_64.rpm --scripts
postinstall scriptlet (using /bin/sh):
systemctl --system daemon-reload
# Install it.
% sudo rpm -ivh example-service-1.0-1.x86_64.rpm
# Start it.
% sudo systemctl start example
# Check the logs!
% sudo tail -n1 /var/log/messages
May 13 03:32:55 localhost root: hello world
Example choosing 'sysv' as the platform:
% bin/fpm -s pleaserun -t rpm -n example-service --pleaserun-platform sysv --pleaserun-name example =logger hello world
Writing file
{:destination=>"/tmp/package-pleaserun-staging20160513-13675-xae6xd/etc/init.d/example"}
Writing file
{:destination=>"/tmp/package-pleaserun-staging20160513-13675-xae6xd/etc/default/example"}
Created package {:path=>"example-service-1.0-1.x86_64.rpm"}
% rpm -qlp example-service-1.0-1.x86_64.rpm
/etc/default/example
/etc/init.d/example
Controlling where output is sent is necessary if you want to use fpm as
a library rather just a command line tool.
This is implemented using the open4 rubygem because the open3 that ships
with ruby 1.8.7's stdlib doesn't set $? so you can't get the exit
status of the process.
The negative side effect of this change is that it introduces buffering,
so you don't get stderr and stdout in the order in which they were
output. And the output isn't sent to the terminal until the process has
completed, which is annoying. Perhaps it's possible to do something
with threads to solve this problem.