class EcoRake module Shell module Gpg include EcoRake::Shell::Command include EcoRake::Shell::Files GPG_VERSION_REGEX = /^gpg.*?gnupg.*?(?\d+)\.(?\d+)\./i.freeze # @note # 1. The ENV var `GPG_KEY` specifies the `passphrase` to be able to use the # private gpg key (suppsedly installed in the user's local `gpg keyring`). # 2. Depending on the `gpg` version, the option to prevent the interactive passphrase to prompt # is different. This is the reason why we check what is the option for a `loopback` # @param gpg_file [String] the file meant to be decrypted. # @return [String] the command to decrypt `gpg_file` def decrypt_command(gpg_file, gpg_key: ENV["GPG_KEY"], ignore_mdc_error: false) csv_file = gpg_to_csv_filename(gpg_file) no_error = ignore_mdc_error ? '--ignore-mdc-error' : nil loopback = gpg_version_gte?(major: 2, minor: 1)? "--pinentry-mode=loopback" : "--batch --yes" args = [ no_error, loopback, '--passphrase', double_quote(gpg_key), '-o', double_quote(csv_file), '-d', double_quote(gpg_file) ] string_cmd('gpg', *args) end private # TODO: use a common end point from `Command` def shell_gpg_version `gpg --version` end # Checks if the host `gpg` version is **greater than or equal** (`gte`) to `major` and `minor` # @note the versioning format is `MAJOR.MINOR.PATCH` # @example if the host has this gpg version: `gpg (GnuPG) 2.1.10`. The following is to be expected: # 1. `gpg_version_gte?(major: 1, minor: 10)` return `true` # 2. `gpg_version_gte?(major: 3, minor: 0)` return `false` # 3. `gpg_version_gte?(major: 2, minor: 0)` return `true` # 4. `gpg_version_gte?(major: 2, minor: 1)` return `true` # 5. `gpg_version_gte?(major: 2, minor: 3)` return `false` # @return [Boolean] def gpg_version_gte?(major:, minor:) result = shell_gpg_version return false unless match = result.match(GPG_VERSION_REGEX) maj = match[:maj].to_i min = match[:min].to_i (maj >= major) && (min >= minor) end end end end