cocoapods-git-private-repo 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/cocoapods-git-private-repo/gem_version.rb +1 -1
- data/lib/cocoapods-git-private-repo/git_private_repo_executable.rb +297 -0
- data/lib/cocoapods_plugin.rb +1 -1
- metadata +2 -3
- data/lib/cocoapods-git-private-repo/cocoapods-downloader.rb +0 -17
- data/lib/cocoapods-git-private-repo/git_private_repo_downloader.rb +0 -39
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 864c5d089acf55f2e26da12c399a5df85915109bd7f0da8ebd3e205e6c27d4f9
|
4
|
+
data.tar.gz: a63a4821072bd6970efc076d919cd1bb4daa636fbeaa41e5ed025b09ca92c039
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f8628fe232f7d30d4d861e72700202312c8aa213623c8382046d8474045430fa2224a0e50622932c621f93cc76ca425e646f57d57b0e579cd19bef68d64a41be
|
7
|
+
data.tar.gz: 6bb9499b704b003831e64bd203635f46b5116ed995d3361c5f1d6f0dd3b4c8814334cebc700dcf4e61d08218a37800efbc9d02305f602a466b7346f8d480d486
|
@@ -0,0 +1,297 @@
|
|
1
|
+
require 'cocoapods'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module Pod
|
5
|
+
# Monkey patch for the Executable module to handle SSH keys
|
6
|
+
module Executable
|
7
|
+
class << self
|
8
|
+
alias_method :original_execute_command, :execute_command
|
9
|
+
alias_method :original_capture_command, :capture_command
|
10
|
+
|
11
|
+
# Override execute_command to handle SSH keys for git commands
|
12
|
+
def execute_command(executable, command, raise_on_failure = true)
|
13
|
+
# Only apply SSH key for git commands
|
14
|
+
if executable.to_s == 'git'
|
15
|
+
# Check if a private key should be used for this git command
|
16
|
+
private_key_path = find_private_key_for_command(command)
|
17
|
+
|
18
|
+
if private_key_path
|
19
|
+
UI.message("Using private key: #{private_key_path} for git command") if Config.instance.verbose?
|
20
|
+
|
21
|
+
bin = which!(executable)
|
22
|
+
command = command.map(&:to_s)
|
23
|
+
full_command = "#{bin} #{command.join(' ')}"
|
24
|
+
|
25
|
+
if Config.instance.verbose?
|
26
|
+
UI.message("$ #{full_command} (with SSH key)")
|
27
|
+
stdout = Indenter.new(STDOUT)
|
28
|
+
stderr = Indenter.new(STDERR)
|
29
|
+
else
|
30
|
+
stdout = Indenter.new
|
31
|
+
stderr = Indenter.new
|
32
|
+
end
|
33
|
+
|
34
|
+
# Create environment with SSH key setting
|
35
|
+
env = { "GIT_SSH_COMMAND" => "ssh -i #{private_key_path} -o IdentitiesOnly=yes" }
|
36
|
+
|
37
|
+
UI.message("Executing command environment: #{env.inspect}") if Config.instance.verbose?
|
38
|
+
|
39
|
+
require 'open3'
|
40
|
+
status = nil
|
41
|
+
|
42
|
+
# Execute with environment
|
43
|
+
Open3.popen3(env, bin, *command) do |i, o, e, t|
|
44
|
+
reader_threads = []
|
45
|
+
reader_threads << reader(o, stdout)
|
46
|
+
reader_threads << reader(e, stderr)
|
47
|
+
i.close
|
48
|
+
|
49
|
+
status = t.value
|
50
|
+
|
51
|
+
o.flush
|
52
|
+
e.flush
|
53
|
+
sleep(0.01)
|
54
|
+
|
55
|
+
# Wait for reader threads to complete
|
56
|
+
reader_threads.each(&:join)
|
57
|
+
end
|
58
|
+
|
59
|
+
stdout = stdout.join
|
60
|
+
stderr = stderr.join
|
61
|
+
output = stdout + stderr
|
62
|
+
|
63
|
+
unless status.success?
|
64
|
+
if raise_on_failure
|
65
|
+
raise Informative, "#{full_command}\n\n#{output}"
|
66
|
+
else
|
67
|
+
UI.message("[!] Failed: #{full_command}".red)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
return output
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# Fall back to original implementation for non-git commands
|
76
|
+
# or git commands that don't need SSH keys
|
77
|
+
original_execute_command(executable, command, raise_on_failure)
|
78
|
+
end
|
79
|
+
|
80
|
+
# Override capture_command to handle SSH keys for git commands
|
81
|
+
def capture_command(executable, command, capture: :merge, env: {}, **kwargs)
|
82
|
+
# Only apply SSH key for git commands
|
83
|
+
if executable.to_s == 'git'
|
84
|
+
# Check if a private key should be used for this git command
|
85
|
+
private_key_path = find_private_key_for_command(command)
|
86
|
+
|
87
|
+
if private_key_path
|
88
|
+
UI.message("Using private key: #{private_key_path} for git command (capture)") if Config.instance.verbose?
|
89
|
+
|
90
|
+
# Add SSH key setting to the environment
|
91
|
+
git_ssh_cmd = "ssh -i #{private_key_path} -o IdentitiesOnly=yes"
|
92
|
+
ssh_env = { "GIT_SSH_COMMAND" => git_ssh_cmd }
|
93
|
+
|
94
|
+
# Merge with any existing environment variables
|
95
|
+
env = env.merge(ssh_env)
|
96
|
+
|
97
|
+
UI.message("Executing capture_command with environment: #{env.inspect}") if Config.instance.verbose?
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
# Call the original method with possibly modified environment
|
102
|
+
original_capture_command(executable, command, capture: capture, env: env, **kwargs)
|
103
|
+
end
|
104
|
+
|
105
|
+
# Override capture_command! to use our overridden capture_command
|
106
|
+
def capture_command!(executable, command, **kwargs)
|
107
|
+
capture_command(executable, command, **kwargs).tap do |result|
|
108
|
+
result = Array(result)
|
109
|
+
status = result.last
|
110
|
+
unless status.success?
|
111
|
+
output = result[0..-2].join
|
112
|
+
|
113
|
+
# If this is a git command that might have used a private key
|
114
|
+
if executable.to_s == 'git'
|
115
|
+
private_key_path = find_private_key_for_command(command)
|
116
|
+
if private_key_path
|
117
|
+
error_message = enhance_ssh_error_message(output, private_key_path)
|
118
|
+
raise Informative, "#{executable} #{command.join(' ')}\n\n#{error_message}".strip
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
# Default error handler
|
123
|
+
raise Informative, "#{executable} #{command.join(' ')}\n\n#{output}".strip
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
# Helper method to determine if a private key should be used
|
129
|
+
def find_private_key_for_command(command)
|
130
|
+
# Extract repository URL from git commands
|
131
|
+
repo_url = extract_repo_url_from_command(command)
|
132
|
+
|
133
|
+
return nil unless repo_url
|
134
|
+
|
135
|
+
# Find keys.json in standard locations
|
136
|
+
json_config_path = find_json_config_path()
|
137
|
+
|
138
|
+
return nil unless json_config_path && File.exist?(json_config_path)
|
139
|
+
|
140
|
+
begin
|
141
|
+
private_key_configs = JSON.parse(File.read(json_config_path))
|
142
|
+
|
143
|
+
# Find a matching URL in the configuration
|
144
|
+
if private_key_configs.is_a?(Array)
|
145
|
+
matching_config = private_key_configs.find { |config| config["url"] == repo_url }
|
146
|
+
|
147
|
+
return matching_config["key_path"] if matching_config && matching_config["key_path"]
|
148
|
+
end
|
149
|
+
rescue => e
|
150
|
+
UI.warn "Error reading keys.json: #{e.message}" if Config.instance.verbose?
|
151
|
+
end
|
152
|
+
|
153
|
+
nil
|
154
|
+
end
|
155
|
+
|
156
|
+
# Get the path to the keys.json configuration file
|
157
|
+
# Searches in several standard locations related to the Podfile
|
158
|
+
def find_json_config_path
|
159
|
+
# First, look in the current directory
|
160
|
+
return 'keys.json' if File.exist?('keys.json')
|
161
|
+
|
162
|
+
# Get the Podfile path
|
163
|
+
podfile_path = find_podfile_path
|
164
|
+
return nil unless podfile_path
|
165
|
+
|
166
|
+
# Look for keys.json next to the Podfile
|
167
|
+
podfile_dir = File.dirname(podfile_path)
|
168
|
+
config_next_to_podfile = File.join(podfile_dir, 'keys.json')
|
169
|
+
return config_next_to_podfile if File.exist?(config_next_to_podfile)
|
170
|
+
|
171
|
+
# Also check in the .cocoapods directory if it exists
|
172
|
+
cocoapods_dir = File.join(podfile_dir, '.cocoapods')
|
173
|
+
if Dir.exist?(cocoapods_dir)
|
174
|
+
config_in_cocoapods = File.join(cocoapods_dir, 'keys.json')
|
175
|
+
return config_in_cocoapods if File.exist?(config_in_cocoapods)
|
176
|
+
end
|
177
|
+
|
178
|
+
# Finally, check user's home directory
|
179
|
+
home_config = File.expand_path('~/.cocoapods/keys.json')
|
180
|
+
return home_config if File.exist?(home_config)
|
181
|
+
|
182
|
+
# Could not find keys.json
|
183
|
+
nil
|
184
|
+
end
|
185
|
+
|
186
|
+
# Find the path to the Podfile in the current project
|
187
|
+
def find_podfile_path
|
188
|
+
# First try the Pod::Config singleton if it exists and is initialized
|
189
|
+
begin
|
190
|
+
if Pod.const_defined?(:Config) && !Pod::Config.instance.nil? && Pod::Config.instance.installation_root
|
191
|
+
podfile_path = File.join(Pod::Config.instance.installation_root, 'Podfile')
|
192
|
+
return podfile_path if File.exist?(podfile_path)
|
193
|
+
end
|
194
|
+
rescue => e
|
195
|
+
puts "Error accessing Pod::Config: #{e.message}" if Config.instance.verbose?
|
196
|
+
end
|
197
|
+
|
198
|
+
# If that fails, try searching up from the current directory
|
199
|
+
current_dir = Dir.pwd
|
200
|
+
while current_dir != '/'
|
201
|
+
podfile_path = File.join(current_dir, 'Podfile')
|
202
|
+
return podfile_path if File.exist?(podfile_path)
|
203
|
+
current_dir = File.dirname(current_dir)
|
204
|
+
end
|
205
|
+
|
206
|
+
# Also try all parent directories of the repo being cloned if we're in a git command
|
207
|
+
if defined?(@repo_path) && @repo_path
|
208
|
+
current_dir = File.dirname(@repo_path)
|
209
|
+
while current_dir != '/'
|
210
|
+
podfile_path = File.join(current_dir, 'Podfile')
|
211
|
+
return podfile_path if File.exist?(podfile_path)
|
212
|
+
current_dir = File.dirname(current_dir)
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
nil
|
217
|
+
end
|
218
|
+
|
219
|
+
# Extract repository URL from git commands like clone, fetch, etc.
|
220
|
+
def extract_repo_url_from_command(command)
|
221
|
+
# Common git commands that include repository URLs
|
222
|
+
if command.include?('clone')
|
223
|
+
# git clone URL [DIR]
|
224
|
+
idx = command.index('clone')
|
225
|
+
repo_url = command[idx + 1] if idx && command.size > idx + 1
|
226
|
+
|
227
|
+
# Store the destination directory for potential Podfile lookup later
|
228
|
+
if idx && command.size > idx + 2
|
229
|
+
@repo_path = command[idx + 2]
|
230
|
+
end
|
231
|
+
|
232
|
+
return repo_url
|
233
|
+
elsif command.include?('fetch') || command.include?('pull')
|
234
|
+
# Find the path parameter in the command
|
235
|
+
path = nil
|
236
|
+
|
237
|
+
# Look for directory parameter (git -C path fetch/pull)
|
238
|
+
if c_idx = command.index('-C')
|
239
|
+
if c_idx + 1 < command.size
|
240
|
+
path = command[c_idx + 1]
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
return nil unless path
|
245
|
+
|
246
|
+
# Fetch the origin URL from git config using the path
|
247
|
+
return get_origin_url(path)
|
248
|
+
end
|
249
|
+
|
250
|
+
nil
|
251
|
+
end
|
252
|
+
|
253
|
+
# Get the origin URL from git config
|
254
|
+
def get_origin_url(path = nil)
|
255
|
+
# Try to get the origin URL from the git config
|
256
|
+
begin
|
257
|
+
if path && File.directory?(path)
|
258
|
+
# If we have a path, use it to get the remote URL
|
259
|
+
url_command = "git -C \"#{path}\" config --get remote.origin.url"
|
260
|
+
else
|
261
|
+
# Otherwise use the current directory
|
262
|
+
url_command = "git config --get remote.origin.url"
|
263
|
+
end
|
264
|
+
|
265
|
+
result = `#{url_command}`.strip
|
266
|
+
|
267
|
+
return result unless result.empty?
|
268
|
+
rescue => e
|
269
|
+
puts "Error getting origin URL: #{e.message}" if Config.instance.verbose?
|
270
|
+
nil
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
# This is the original reader method from Pod::Executable
|
275
|
+
def reader(input, output)
|
276
|
+
Thread.new do
|
277
|
+
buf = ''
|
278
|
+
begin
|
279
|
+
loop do
|
280
|
+
buf << input.readpartial(4096)
|
281
|
+
loop do
|
282
|
+
string, separator, buf = buf.partition(/[\r\n]/)
|
283
|
+
if separator.empty?
|
284
|
+
buf = string
|
285
|
+
break
|
286
|
+
end
|
287
|
+
output << (string << separator)
|
288
|
+
end
|
289
|
+
end
|
290
|
+
rescue EOFError, IOError
|
291
|
+
output << (buf << $/) unless buf.empty?
|
292
|
+
end
|
293
|
+
end
|
294
|
+
end
|
295
|
+
end # end of class << self
|
296
|
+
end # end of module Executable
|
297
|
+
end # end of module Pod
|
data/lib/cocoapods_plugin.rb
CHANGED
@@ -1 +1 @@
|
|
1
|
-
require 'cocoapods-git-private-repo/
|
1
|
+
require 'cocoapods-git-private-repo/git_private_repo_executable'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cocoapods-git-private-repo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nonthawat Srichad
|
@@ -53,9 +53,8 @@ files:
|
|
53
53
|
- Rakefile
|
54
54
|
- cocoapods-git-private-repo.gemspec
|
55
55
|
- lib/cocoapods-git-private-repo.rb
|
56
|
-
- lib/cocoapods-git-private-repo/cocoapods-downloader.rb
|
57
56
|
- lib/cocoapods-git-private-repo/gem_version.rb
|
58
|
-
- lib/cocoapods-git-private-repo/
|
57
|
+
- lib/cocoapods-git-private-repo/git_private_repo_executable.rb
|
59
58
|
- lib/cocoapods_plugin.rb
|
60
59
|
- spec/spec_helper.rb
|
61
60
|
homepage: https://github.com/nonth/cocoapods-git-private-repo
|
@@ -1,17 +0,0 @@
|
|
1
|
-
require 'cocoapods-git-private-repo/git_private_repo_downloader'
|
2
|
-
|
3
|
-
module Pod
|
4
|
-
module Downloader
|
5
|
-
class <<self
|
6
|
-
alias_method :real_downloader_class_by_key, :downloader_class_by_key
|
7
|
-
end
|
8
|
-
|
9
|
-
def self.downloader_class_by_key
|
10
|
-
original = self.real_downloader_class_by_key
|
11
|
-
original[:git] = GitPrivateRepoDownloader
|
12
|
-
|
13
|
-
original
|
14
|
-
end
|
15
|
-
|
16
|
-
end
|
17
|
-
end
|
@@ -1,39 +0,0 @@
|
|
1
|
-
module Pod
|
2
|
-
module Downloader
|
3
|
-
class GitPrivateRepoDownloader < Git
|
4
|
-
def initialize(target_path, url, options)
|
5
|
-
super(target_path, url, options)
|
6
|
-
|
7
|
-
# Check if a JSON configuration file exists with private key mappings
|
8
|
-
json_config_path = 'keys.json'
|
9
|
-
|
10
|
-
# Only proceed with JSON processing if the file exists
|
11
|
-
return unless File.exist?(json_config_path)
|
12
|
-
|
13
|
-
begin
|
14
|
-
require 'json'
|
15
|
-
private_key_configs = JSON.parse(File.read(json_config_path))
|
16
|
-
|
17
|
-
# Find a matching URL in the array of objects and no private_key_path is already set
|
18
|
-
if !options[:private_key_path] && private_key_configs.is_a?(Array)
|
19
|
-
matching_config = private_key_configs.find { |config| config["url"] == url }
|
20
|
-
|
21
|
-
if matching_config && matching_config["key_path"]
|
22
|
-
options[:private_key_path] = matching_config["key_path"]
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
def execute_command(executable, command, raise_on_failure = false)
|
29
|
-
if executable == 'git' && options[:private_key_path]
|
30
|
-
private_key = options[:private_key_path]
|
31
|
-
|
32
|
-
command = command + ['-c', "core.sshCommand=ssh -i #{private_key}"]
|
33
|
-
end
|
34
|
-
|
35
|
-
super(executable, command, raise_on_failure)
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|