From 2b31fd00076219f021421d3c9286f74002b9d28e Mon Sep 17 00:00:00 2001 From: Christian Sampaio Date: Thu, 31 Dec 2015 15:43:53 -0200 Subject: [PATCH] Adding the option to remove multiple keys at once by using wildcard pattern matching or a new argument option '--all' --- README.md | 5 ++- lib/pod/command/keys/rm.rb | 76 ++++++++++++++++++++++++++++---------- 2 files changed, 60 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 51bcddd..70ce975 100644 --- a/README.md +++ b/README.md @@ -99,7 +99,10 @@ CocoaPods-keys has 3 other commands: Which will output the value of the key to STDOUT, useful for scripting. * `pod keys rm [key] [optional project]` - Will remove a key from a project. + Will remove a key from a project. + + If Wildcards are included, it will remove the keys matching the pattern. E.g.: `pod keys rm "G*og*"` will remove *all* the keys that begin with 'G', have 'og' in the middle and end with anything. + To nuke all the keys, run either `pod keys rm "*"` or `pod keys rm --all` * `pod keys generate [optional project]` Will generate the obfuscated Objective-C keys class (mainly used internally). diff --git a/lib/pod/command/keys/rm.rb b/lib/pod/command/keys/rm.rb index ffd26c8..4b4ef5f 100644 --- a/lib/pod/command/keys/rm.rb +++ b/lib/pod/command/keys/rm.rb @@ -7,26 +7,39 @@ module Pod class Command class Keys class Rm < Keys - self.summary = 'Remove a key-value pair from a project.' + self.summary = 'Removes key-value pairs from a project.' self.description = <<-DESC - Remove a key, and it's value from a project + Removes a key, and it's value from a project. + + If Wildcards are included, it will remove the keys matching the pattern. + E.g.: `pod keys rm \"G*og*\"` will remove *all* the keys that begin + with 'G', have 'og' in the middle and end with anything. + + To nuke all the keys, run either `pod keys rm "*"` or `pod keys rm --all` A second optional operator can be done to force a project name. DESC self.arguments = [CLAide::Argument.new('key', true), CLAide::Argument.new('project_name', false)] + def self.options + [[ + '--all', 'Remove all the stored keys without asking' + ]].concat(super) + end + def initialize(argv) @key_name = argv.shift_argument @project_name = argv.shift_argument + @wipe_all = argv.flag?('all') super end def validate! super verify_podfile_exists! - help! 'A key name is required for lookup.' unless @key_name + help! 'A key name is required for lookup.' unless @key_name || @wipe_all end def run @@ -35,26 +48,49 @@ def run raise Informative, 'Could not find a project to remove the key from.' end - if keyring.keys.include? @key_name - keyring.save(@key_name, '') - keyring.keys.delete @key_name - CocoaPodsKeys::KeyringLiberator.save_keyring(keyring) - - prefix = CocoaPodsKeys::Keyring.keychain_prefix - login = prefix + keyring.name - delete_generic = `security delete-generic-password -a #{@key_name.shellescape} -l #{login.shellescape} 2>&1` - - if delete_generic.include? 'security: SecKeychainSearchCopyNext: The specified item could not be found in the keychain.' - raise Informative, "Removed value for #{@key_name}, but could not delete from Keychain." - elsif delete_generic.include? 'password has been deleted.' - raise Informative, "Removed value for #{@key_name}, and deleted associated key in Keychain." - else - raise Informative, "Removed value for #{@key_name}." - end + if @wipe_all + @key_name = '*' + end + + matching_keys = matches(keyring.keys) + if matching_keys.count > 0 + messages = matching_keys.map { |e| delete_key(e, keyring) } + raise Informative, messages.join("\n") + else + raise Informative, "Could not find key that matched \"#{@key_name}\"." + end + end + + def delete_key(key, keyring) + keyring.save(key, '') + keyring.keys.delete key + CocoaPodsKeys::KeyringLiberator.save_keyring(keyring) + + prefix = CocoaPodsKeys::Keyring.keychain_prefix + login = prefix + keyring.name + delete_generic = `security delete-generic-password -a #{key.shellescape} -l #{login.shellescape} 2>&1` + + if delete_generic.include? 'security: SecKeychainSearchCopyNext: The specified item could not be found in the keychain.' + return "Removed value for #{key}, but could not delete from Keychain." + elsif delete_generic.include? 'password has been deleted.' + return "Removed value for #{key}, and deleted associated key in Keychain." else - raise Informative, "Could not find key named #{@key_name}." + return "Removed value for #{key}." end end + + def matches(keys) + if @key_name.include? '*' + return keys.select { |e| e =~ create_regex(@key_name) } + else + return keys.select { |e| e == @key_name } + end + end + + def create_regex(pattern) + regex_str = "^#{pattern.gsub('*', '.*')}$" + Regexp.new(regex_str) + end end end end