cocoapods-keys 1.2.1 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +10 -0
- data/.rubocop_cocoapods.yml +116 -0
- data/.rubocop_todo.yml +39 -0
- data/CHANGELOG.md +5 -1
- data/Gemfile.lock +19 -1
- data/README.md +22 -19
- data/Rakefile +3 -2
- data/SWIFT_PROJECTS.md +31 -0
- data/cocoapods_keys.gemspec +1 -0
- data/lib/cocoapods_keys.rb +1 -1
- data/lib/cocoapods_plugin.rb +1 -1
- data/lib/key_master.rb +20 -14
- data/lib/keyring.rb +6 -7
- data/lib/keyring_liberator.rb +13 -15
- data/lib/name_whisperer.rb +28 -32
- data/lib/plugin.rb +44 -30
- data/lib/pod/command/keys.rb +1 -3
- data/lib/pod/command/keys/get.rb +9 -12
- data/lib/pod/command/keys/list.rb +21 -24
- data/lib/pod/command/keys/rm.rb +18 -19
- data/lib/pod/command/keys/set.rb +8 -10
- data/lib/preinstaller.rb +15 -13
- data/spec/functional_spec.rb +7 -16
- data/spec/key_master_spec.rb +4 -36
- data/spec/keyring_liberator_spec.rb +11 -12
- data/spec/plugin_spec.rb +193 -1
- data/spec/spec_helper.rb +5 -4
- metadata +20 -2
data/lib/keyring.rb
CHANGED
@@ -1,21 +1,21 @@
|
|
1
|
-
require
|
1
|
+
require 'osx_keychain'
|
2
2
|
|
3
3
|
module CocoaPodsKeys
|
4
4
|
class Keyring
|
5
5
|
attr_accessor :keys, :path, :name
|
6
6
|
|
7
|
-
def initialize(name, path, keys=[])
|
8
|
-
@name = name
|
7
|
+
def initialize(name, path, keys = [])
|
8
|
+
@name = name.to_s
|
9
9
|
@path = path
|
10
10
|
@keys = keys
|
11
11
|
end
|
12
12
|
|
13
13
|
def self.from_hash(hash)
|
14
|
-
new(hash[
|
14
|
+
new(hash['name'], hash['path'], hash['keys'])
|
15
15
|
end
|
16
16
|
|
17
17
|
def to_hash
|
18
|
-
{
|
18
|
+
{ 'keys' => @keys, 'path' => @path, 'name' => @name }
|
19
19
|
end
|
20
20
|
|
21
21
|
def code_name
|
@@ -23,7 +23,7 @@ module CocoaPodsKeys
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def self.keychain_prefix
|
26
|
-
|
26
|
+
'cocoapods-keys-'
|
27
27
|
end
|
28
28
|
|
29
29
|
def save(key, value)
|
@@ -37,6 +37,5 @@ module CocoaPodsKeys
|
|
37
37
|
@keys.map { |key| [key, keychain[self.class.keychain_prefix + name, key]] }
|
38
38
|
]
|
39
39
|
end
|
40
|
-
|
41
40
|
end
|
42
41
|
end
|
data/lib/keyring_liberator.rb
CHANGED
@@ -1,40 +1,39 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
1
|
+
require 'digest'
|
2
|
+
require 'yaml'
|
3
|
+
require 'pathname'
|
4
4
|
|
5
5
|
module CocoaPodsKeys
|
6
6
|
class KeyringLiberator
|
7
|
-
|
8
7
|
# Gets given a gives back a Keyring for the project
|
9
8
|
# by basically parsing it out of ~/.cocoapods/keys/"pathMD5".yml
|
10
9
|
|
11
10
|
def self.keys_dir
|
12
|
-
|
11
|
+
Pathname('~/.cocoapods/keys/').expand_path
|
13
12
|
end
|
14
13
|
|
15
14
|
def self.yaml_path_for_path(path)
|
16
|
-
sha = Digest::MD5.hexdigest(path)
|
17
|
-
|
15
|
+
sha = Digest::MD5.hexdigest(path.to_s)
|
16
|
+
keys_dir + (sha + '.yml')
|
18
17
|
end
|
19
18
|
|
20
19
|
def self.get_keyring(path)
|
21
20
|
get_keyring_at_path(yaml_path_for_path(path))
|
22
21
|
end
|
23
|
-
|
22
|
+
|
24
23
|
def self.get_keyring_named(name)
|
25
|
-
|
24
|
+
get_all_keyrings.find { |k| k.name == name }
|
26
25
|
end
|
27
26
|
|
28
27
|
def self.save_keyring(keyring)
|
29
|
-
|
28
|
+
keys_dir.mkpath
|
30
29
|
|
31
|
-
|
30
|
+
yaml_path_for_path(keyring.path).open('w') { |f| f.write(YAML.dump(keyring.to_hash)) }
|
32
31
|
end
|
33
32
|
|
34
33
|
def self.get_all_keyrings
|
35
|
-
return [] unless
|
34
|
+
return [] unless keys_dir.directory?
|
36
35
|
rings = []
|
37
|
-
|
36
|
+
Pathname.glob(keys_dir + '*.yml').each do |path|
|
38
37
|
rings << get_keyring_at_path(path)
|
39
38
|
end
|
40
39
|
rings
|
@@ -43,8 +42,7 @@ module CocoaPodsKeys
|
|
43
42
|
private
|
44
43
|
|
45
44
|
def self.get_keyring_at_path(path)
|
46
|
-
Keyring.from_hash(YAML.load(
|
45
|
+
Keyring.from_hash(YAML.load(path.read)) if path.file?
|
47
46
|
end
|
48
|
-
|
49
47
|
end
|
50
48
|
end
|
data/lib/name_whisperer.rb
CHANGED
@@ -1,44 +1,40 @@
|
|
1
1
|
require 'cocoapods'
|
2
2
|
|
3
3
|
module CocoaPodsKeys
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
user_xcodeproj = xcodeproj_from_podfile(podfile)
|
10
|
-
end
|
11
|
-
user_xcodeproj ||= self.search_folders_for_xcodeproj
|
12
|
-
user_xcodeproj.gsub(".xcodeproj", "")
|
4
|
+
class NameWhisperer
|
5
|
+
def self.get_project_name
|
6
|
+
podfile = Pod::Config.instance.podfile
|
7
|
+
if podfile
|
8
|
+
user_xcodeproj = xcodeproj_from_podfile(podfile)
|
13
9
|
end
|
10
|
+
user_xcodeproj ||= search_folders_for_xcodeproj
|
11
|
+
user_xcodeproj.basename('.xcodeproj')
|
12
|
+
end
|
14
13
|
|
15
|
-
|
14
|
+
private
|
16
15
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
end
|
21
|
-
nil
|
16
|
+
def self.xcodeproj_from_podfile(podfile)
|
17
|
+
unless podfile.target_definition_list.empty?
|
18
|
+
return podfile.target_definition_list.first.user_project_path
|
22
19
|
end
|
20
|
+
end
|
23
21
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
end
|
38
|
-
answer
|
39
|
-
|
22
|
+
def self.search_folders_for_xcodeproj
|
23
|
+
xcodeprojects = Pathname.glob('**/*.xcodeproj')
|
24
|
+
if xcodeprojects.length == 1
|
25
|
+
Pathname(xcodeprojects.first).basename
|
26
|
+
else
|
27
|
+
error_message = (xcodeprojects.length > 1) ? 'found too many' : "couldn't find any"
|
28
|
+
UI.puts 'CocoaPods-Keys ' + error_message + ' Xcode projects. Please give a name for this project.'
|
29
|
+
|
30
|
+
answer = ''
|
31
|
+
loop do
|
32
|
+
UI.print ' > '
|
33
|
+
answer = UI.gets.strip
|
34
|
+
break if answer.length > 0
|
40
35
|
end
|
36
|
+
answer
|
41
37
|
end
|
42
|
-
|
43
38
|
end
|
39
|
+
end
|
44
40
|
end
|
data/lib/plugin.rb
CHANGED
@@ -1,48 +1,65 @@
|
|
1
1
|
require 'cocoapods-core'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'active_support/core_ext/hash/indifferent_access'
|
2
4
|
|
3
5
|
module CocoaPodsKeys
|
4
6
|
class << self
|
7
|
+
include FileUtils
|
5
8
|
|
6
9
|
def setup
|
7
10
|
require 'preinstaller'
|
8
11
|
|
9
12
|
PreInstaller.new(user_options).setup
|
10
|
-
|
13
|
+
|
14
|
+
keys_path = Pod::Config.instance.installation_root + 'Pods/CocoaPodsKeys/'
|
15
|
+
|
11
16
|
# move our podspec in to the Pods
|
12
|
-
|
13
|
-
podspec_path =
|
14
|
-
|
15
|
-
|
17
|
+
mkdir_p keys_path
|
18
|
+
podspec_path = Pathname(__dir__) + '../templates' + 'Keys.podspec.json'
|
19
|
+
cp podspec_path, keys_path
|
20
|
+
|
16
21
|
# Get all the keys
|
17
22
|
local_user_options = user_options || {}
|
18
|
-
project = local_user_options.fetch(
|
19
|
-
keyring = KeyringLiberator.get_keyring_named(project) || KeyringLiberator.get_keyring(
|
20
|
-
raise Pod::Informative,
|
21
|
-
|
23
|
+
project = local_user_options.fetch('project') { CocoaPodsKeys::NameWhisperer.get_project_name }
|
24
|
+
keyring = KeyringLiberator.get_keyring_named(project) || KeyringLiberator.get_keyring(Pathname.pwd)
|
25
|
+
raise Pod::Informative, 'Could not load keyring' unless keyring
|
26
|
+
|
22
27
|
# Create the h & m files in the same folder as the podspec
|
23
28
|
key_master = KeyMaster.new(keyring)
|
24
|
-
interface_file =
|
25
|
-
implementation_file =
|
26
|
-
|
29
|
+
interface_file = keys_path + (key_master.name + '.h')
|
30
|
+
implementation_file = keys_path + (key_master.name + '.m')
|
31
|
+
|
27
32
|
File.write(interface_file, key_master.interface)
|
28
33
|
File.write(implementation_file, key_master.implementation)
|
29
|
-
|
34
|
+
|
30
35
|
# Add our template podspec
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
36
|
+
add_keys_to_pods(keys_path, user_options)
|
37
|
+
end
|
38
|
+
|
39
|
+
def add_keys_to_pods(keys_path, options)
|
40
|
+
keys_targets = options['target'] || options['targets']
|
41
|
+
|
42
|
+
if keys_targets
|
43
|
+
# Get a list of targets, even if only one was specified
|
44
|
+
keys_target_list = ([] << keys_targets).flatten
|
45
|
+
|
46
|
+
# Iterate through each target specified in the Keys plugin
|
47
|
+
keys_target_list.each do |keys_target|
|
48
|
+
# Find a matching Pod target
|
49
|
+
pod_target = podfile.root_target_definitions.flat_map(&:children).find do |target|
|
50
|
+
target.label == "Pods-#{keys_target}"
|
51
|
+
end
|
52
|
+
|
53
|
+
if pod_target
|
54
|
+
pod_target.store_pod 'Keys', :path => keys_path.to_path
|
55
|
+
else
|
56
|
+
Pod::UI.puts "Could not find a target named '#{keys_target}' in your Podfile. Stopping keys".red
|
57
|
+
end
|
41
58
|
end
|
42
59
|
|
43
60
|
else
|
44
61
|
# otherwise let it go in global
|
45
|
-
podfile.pod 'Keys', :path =>
|
62
|
+
podfile.pod 'Keys', :path => keys_path.to_path
|
46
63
|
end
|
47
64
|
end
|
48
65
|
|
@@ -53,13 +70,10 @@ module CocoaPodsKeys
|
|
53
70
|
end
|
54
71
|
|
55
72
|
def user_options
|
56
|
-
options = podfile.plugins[
|
73
|
+
options = podfile.plugins['cocoapods-keys']
|
57
74
|
# Until CocoaPods provides a HashWithIndifferentAccess, normalize the hash keys here.
|
58
75
|
# See https://github.com/CocoaPods/CocoaPods/issues/3354
|
59
|
-
options.
|
60
|
-
normalized_hash[key.to_s] = value
|
61
|
-
normalized_hash
|
62
|
-
end
|
76
|
+
options.with_indifferent_access
|
63
77
|
end
|
64
78
|
end
|
65
79
|
end
|
@@ -74,7 +88,7 @@ module Pod
|
|
74
88
|
end
|
75
89
|
|
76
90
|
def validates_for_keys
|
77
|
-
|
91
|
+
podfile && podfile.plugins && !podfile.plugins['cocoapods-keys'].nil?
|
78
92
|
end
|
79
93
|
end
|
80
94
|
end
|
data/lib/pod/command/keys.rb
CHANGED
@@ -1,13 +1,12 @@
|
|
1
1
|
module Pod
|
2
2
|
class Command
|
3
|
-
|
4
3
|
class Keys < Command
|
5
4
|
require 'pod/command/keys/list'
|
6
5
|
require 'pod/command/keys/set'
|
7
6
|
require 'pod/command/keys/get'
|
8
7
|
require 'pod/command/keys/rm'
|
9
8
|
|
10
|
-
self.summary =
|
9
|
+
self.summary = 'A key value store for environment settings in Cocoa Apps.'
|
11
10
|
|
12
11
|
self.description = <<-DESC
|
13
12
|
CocoaPods Keys will store sensitive data in your Mac's keychain. Then on running pod install they will be installed into your app's source code via the Pods library.
|
@@ -15,7 +14,6 @@ module Pod
|
|
15
14
|
|
16
15
|
self.abstract_command = true
|
17
16
|
self.default_subcommand = 'list'
|
18
|
-
|
19
17
|
end
|
20
18
|
end
|
21
19
|
end
|
data/lib/pod/command/keys/get.rb
CHANGED
@@ -1,12 +1,11 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require 'keyring_liberator'
|
2
|
+
require 'name_whisperer'
|
3
3
|
|
4
4
|
module Pod
|
5
5
|
class Command
|
6
6
|
class Keys
|
7
|
-
|
8
7
|
class Get < Keys
|
9
|
-
self.summary =
|
8
|
+
self.summary = 'Print a values of a key.'
|
10
9
|
|
11
10
|
self.description = <<-DESC
|
12
11
|
Outputs the value of a key to SDTOUT
|
@@ -26,33 +25,31 @@ module Pod
|
|
26
25
|
def validate!
|
27
26
|
super
|
28
27
|
verify_podfile_exists!
|
29
|
-
help!
|
28
|
+
help! 'A key name is required for lookup.' unless @key_name
|
30
29
|
end
|
31
30
|
|
32
31
|
def run
|
33
32
|
keyring = get_current_keyring
|
34
|
-
|
35
|
-
|
36
|
-
return
|
33
|
+
unless keyring
|
34
|
+
raise Informative, 'Could not find a project for this folder'
|
37
35
|
end
|
38
36
|
|
39
37
|
if keyring.keys.include? @key_name
|
40
38
|
data = keyring.keychain_data
|
41
|
-
puts data[@key_name]
|
39
|
+
UI.puts data[@key_name]
|
42
40
|
else
|
43
|
-
|
41
|
+
raise Informative, 'Could not find value'
|
44
42
|
end
|
45
43
|
end
|
46
44
|
|
47
45
|
def get_current_keyring
|
48
|
-
current_dir =
|
46
|
+
current_dir = Pathname.pwd
|
49
47
|
keyring = CocoaPodsKeys::KeyringLiberator.get_keyring current_dir
|
50
48
|
if !keyring && @project_name
|
51
49
|
return CocoaPodsKeys::KeyringLiberator.get_keyring_named @project_name
|
52
50
|
end
|
53
51
|
keyring
|
54
52
|
end
|
55
|
-
|
56
53
|
end
|
57
54
|
end
|
58
55
|
end
|
@@ -3,9 +3,8 @@ require 'keyring_liberator'
|
|
3
3
|
module Pod
|
4
4
|
class Command
|
5
5
|
class Keys
|
6
|
-
|
7
6
|
class List < Keys
|
8
|
-
self.summary =
|
7
|
+
self.summary = 'Lists all known keys and values.'
|
9
8
|
|
10
9
|
self.description = <<-DESC
|
11
10
|
Shows all the current keys and values for your current working directory.
|
@@ -14,41 +13,39 @@ module Pod
|
|
14
13
|
DESC
|
15
14
|
|
16
15
|
def run
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
16
|
+
# List all settings for current app
|
17
|
+
this_keyring = CocoaPodsKeys::KeyringLiberator.get_keyring(Pathname.pwd)
|
18
|
+
if this_keyring
|
19
|
+
display_current_keyring this_keyring
|
20
|
+
end
|
21
|
+
|
22
|
+
# List all known bundle ids
|
23
|
+
|
24
|
+
all_keyrings = CocoaPodsKeys::KeyringLiberator.get_all_keyrings
|
25
|
+
all_keyrings.each do |keyring|
|
26
|
+
display_keyring(keyring) if !this_keyring || keyring.path != this_keyring.path
|
27
|
+
end
|
29
28
|
end
|
30
29
|
|
31
30
|
def display_current_keyring(keyring)
|
32
|
-
puts "Keys for #{keyring.name}"
|
31
|
+
UI.puts "Keys for #{keyring.name}"
|
33
32
|
data = keyring.keychain_data
|
34
33
|
data.each_with_index do |(key, value), index|
|
35
|
-
prefix = (index == data.length - 1) ?
|
36
|
-
puts prefix + " #{key} - #{ value}"
|
34
|
+
prefix = (index == data.length - 1) ? ' └ ' : ' ├ '
|
35
|
+
UI.puts prefix + " #{key} - #{ value}"
|
37
36
|
end
|
38
|
-
puts
|
37
|
+
UI.puts
|
39
38
|
end
|
40
39
|
|
41
40
|
def display_keyring(keyring)
|
42
|
-
puts "#{keyring.name} - #{keyring.path}"
|
41
|
+
UI.puts "#{keyring.name} - #{keyring.path}"
|
43
42
|
if keyring.keys.length == 1
|
44
|
-
puts
|
43
|
+
UI.puts ' └ ' + keyring.keys[0]
|
45
44
|
else
|
46
|
-
puts
|
45
|
+
UI.puts ' └ ' + keyring.keys[0...-1].join(' ') + ' & ' + keyring.keys[-1]
|
47
46
|
end
|
48
|
-
puts
|
47
|
+
UI.puts
|
49
48
|
end
|
50
|
-
|
51
|
-
|
52
49
|
end
|
53
50
|
end
|
54
51
|
end
|
data/lib/pod/command/keys/rm.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
1
|
+
require 'keyring_liberator'
|
2
|
+
require 'keyring'
|
3
|
+
require 'name_whisperer'
|
4
|
+
require 'shellwords'
|
4
5
|
|
5
6
|
module Pod
|
6
7
|
class Command
|
7
8
|
class Keys
|
8
|
-
|
9
9
|
class Rm < Keys
|
10
|
-
self.summary =
|
10
|
+
self.summary = 'Remove a key-value pair from a project.'
|
11
11
|
|
12
12
|
self.description = <<-DESC
|
13
13
|
Remove a key, and it's value from a project
|
@@ -26,45 +26,44 @@ module Pod
|
|
26
26
|
def validate!
|
27
27
|
super
|
28
28
|
verify_podfile_exists!
|
29
|
-
help!
|
29
|
+
help! 'A key name is required for lookup.' unless @key_name
|
30
30
|
end
|
31
31
|
|
32
32
|
def run
|
33
33
|
keyring = get_current_keyring
|
34
|
-
|
35
|
-
|
36
|
-
return
|
34
|
+
unless keyring
|
35
|
+
raise Informative, 'Could not find a project to remove the key from.'
|
37
36
|
end
|
38
37
|
|
39
38
|
if keyring.keys.include? @key_name
|
40
|
-
keyring.save(@key_name,
|
39
|
+
keyring.save(@key_name, '')
|
41
40
|
keyring.keys.delete @key_name
|
42
41
|
CocoaPodsKeys::KeyringLiberator.save_keyring(keyring)
|
43
42
|
|
44
43
|
prefix = CocoaPodsKeys::Keyring.keychain_prefix
|
45
|
-
|
44
|
+
login = prefix + keyring.name
|
45
|
+
delete_generic = `security delete-generic-password -a #{@key_name.shellescape} -l #{login.shellescape} 2>&1`
|
46
46
|
|
47
|
-
if delete_generic.include?
|
48
|
-
|
49
|
-
elsif delete_generic.include?
|
50
|
-
|
47
|
+
if delete_generic.include? 'security: SecKeychainSearchCopyNext: The specified item could not be found in the keychain.'
|
48
|
+
raise Informative, "Removed value for #{@key_name}, but could not delete from Keychain."
|
49
|
+
elsif delete_generic.include? 'password has been deleted.'
|
50
|
+
raise Informative, "Removed value for #{@key_name}, and deleted associated key in Keychain."
|
51
51
|
else
|
52
|
-
|
52
|
+
raise Informative, "Removed value for #{@key_name}."
|
53
53
|
end
|
54
54
|
else
|
55
|
-
|
55
|
+
raise Informative, "Could not find key named #{@key_name}."
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
59
59
|
def get_current_keyring
|
60
|
-
current_dir =
|
60
|
+
current_dir = Pathname.pwd
|
61
61
|
keyring = CocoaPodsKeys::KeyringLiberator.get_keyring current_dir
|
62
62
|
if !keyring && @project_name
|
63
63
|
return CocoaPodsKeys::KeyringLiberator.get_keyring_named @project_name
|
64
64
|
end
|
65
65
|
keyring
|
66
66
|
end
|
67
|
-
|
68
67
|
end
|
69
68
|
end
|
70
69
|
end
|