diff --git a/CHANGELOG b/CHANGELOG index 0762e81..3585c43 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,6 @@ +* Allow forwarding of select gpg options with commands like +--gpg-homedir. run `gem verify --help` to see a list of all options. + * Fail gracefully when rubygems.org doesn't return owner list, for example when a gem has never been published to rubygems.org. diff --git a/lib/rubygems/openpgp/gpg_options.rb b/lib/rubygems/openpgp/gpg_options.rb new file mode 100644 index 0000000..a963f87 --- /dev/null +++ b/lib/rubygems/openpgp/gpg_options.rb @@ -0,0 +1,46 @@ +require 'shellwords' + + +module Gem::OpenPGP + extend Shellwords + + WHITELISTED_GPG_OPTIONS = { + "homedir" => "dir", + "verbose" => nil, + "default-user" => "user_id", + "local-user" => "user_id", + "passphrase-fd" => "file_descriptor", + "passphrase-file" => "file_name" + } + + def self.gpg_options + @gpg_options ||= {} + @gpg_options + end + + def self.add_gpg_options cmd + WHITELISTED_GPG_OPTIONS.each_pair do |flag, arg| + mangled_flag = "--gpg-#{flag}" + mangled_flag += " #{arg}" if arg.is_a? String + + cmd.add_option(mangled_flag,"Forward option --#{flag} to gpg") do |value, options| + value = true if arg.nil? #boolean + gpg_options[flag] = value + end + end + end + + def self.get_gpg_options + options = [] + gpg_options.each_pair do |flag, value| + new_flag = "--#{flag}" + if value.is_a? String + new_flag += " " + shellescape(value) + end + options << new_flag + end + + options.join(" ") + end + +end diff --git a/lib/rubygems/openpgp/signing.rb b/lib/rubygems/openpgp/signing.rb index c15f6a8..aa1f365 100644 --- a/lib/rubygems/openpgp/signing.rb +++ b/lib/rubygems/openpgp/signing.rb @@ -24,7 +24,7 @@ def self.detach_sign data, key_id=nil, homedir=nil homedir_flag = "" homedir_flag = "--homedir #{shellescape(homedir)}" if homedir - gpg_args = "#{key_flag} #{homedir_flag} --detach-sign --armor" + gpg_args = "#{key_flag} #{homedir_flag} #{Gem::OpenPGP.get_gpg_options} --detach-sign --armor" gpg_results = GPGStatusParser.run_gpg(gpg_args, data) did_gpg_error? gpg_results diff --git a/lib/rubygems/openpgp/verification.rb b/lib/rubygems/openpgp/verification.rb index 65cc963..912ae12 100644 --- a/lib/rubygems/openpgp/verification.rb +++ b/lib/rubygems/openpgp/verification.rb @@ -36,7 +36,7 @@ def self.verify file_name, data, sig, get_key=false, homedir=nil homedir_flags = "" homedir_flags = "--homedir #{homedir}" if homedir - gpg_args = "#{get_key_params} #{homedir_flags} --with-colons --verify #{sig_file.path} #{data_file.path}" + gpg_args = "#{get_key_params} #{homedir_flags} #{Gem::OpenPGP.get_gpg_options} --with-colons --verify #{sig_file.path} #{data_file.path}" status_info = {:file_name => file_name} gpg_results = GPGStatusParser.run_gpg(gpg_args) { |message| verify_extract_status_info(message, status_info) } diff --git a/lib/rubygems_plugin.rb b/lib/rubygems_plugin.rb index bacf8a6..a974672 100644 --- a/lib/rubygems_plugin.rb +++ b/lib/rubygems_plugin.rb @@ -1,4 +1,11 @@ require 'rubygems/gem_openpgp' require 'rubygems/openpgp/sign_plugins' require 'rubygems/openpgp/verify_plugins' +require 'rubygems/openpgp/gpg_options' + +# Add gpg forwarding options +[:sign, :verify, :build, :install].each do |cmd_name| + cmd = Gem::CommandManager.instance[cmd_name] + Gem::OpenPGP.add_gpg_options(cmd) +end diff --git a/rubygems-openpgp.gemspec b/rubygems-openpgp.gemspec index 0f5d810..2662dd0 100644 --- a/rubygems-openpgp.gemspec +++ b/rubygems-openpgp.gemspec @@ -20,9 +20,11 @@ Gem::Specification.new do |s| "lib/rubygems/openpgp/verify_plugins.rb", "lib/rubygems/openpgp/sign_plugins.rb", "lib/rubygems/openpgp/owner_check.rb", + "lib/rubygems/openpgp/gpg_options.rb", "lib/rubygems/openpgp/openpgpexception.rb"] s.test_files = ["test/test_keymaster.rb", "test/test_rubygems-openpgp.rb", + "test/test_gpg_options.rb", "test/pablo_escobar_seckey.asc", "test/pablo_escobar_pubkey.asc", "test/unsigned_hola-0.0.0.gem"] diff --git a/test/test_gpg_options.rb b/test/test_gpg_options.rb new file mode 100644 index 0000000..3b40ed1 --- /dev/null +++ b/test/test_gpg_options.rb @@ -0,0 +1,41 @@ +require 'test/unit' +require 'mocha/setup' + +require "rubygems/command" +require 'rubygems/openpgp/gpg_options' + +class Gem::Commands::TestCommand < Gem::Command +end + +class GpgOptionsText < Test::Unit::TestCase + def setup + @test_cmd = Gem::Command.new "test", "summary" + Gem::OpenPGP.add_gpg_options(@test_cmd) + end + + def teardown + Gem::OpenPGP.instance_variable_set(:@gpg_options,{}) + end + + def test_option_with_argument + @test_cmd.handle_options %W[--gpg-homedir /home/foo/alt-dir] + assert_equal Gem::OpenPGP.gpg_options["homedir"], "/home/foo/alt-dir" + end + + def test_option_with_argument_build + @test_cmd.handle_options %W[--gpg-homedir /home/foo/alt-dir] + assert_equal Gem::OpenPGP.get_gpg_options, "--homedir /home/foo/alt-dir" + end + + def test_option + @test_cmd.handle_options %W[--gpg-verbose] + assert_equal Gem::OpenPGP.gpg_options["verbose"], true + end + + def test_option_build + @test_cmd.handle_options %W[--gpg-verbose] + assert_equal Gem::OpenPGP.get_gpg_options, "--verbose" + end + + +end