cocoapods-git-private-repo 0.1.2 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3f0407365e723398f091ede37a3f5895cd17748fa1f3b71111860799a33b491b
4
- data.tar.gz: 0a5b341a278b0f79bc7f753c3e022521e107fd8621d94ac8986c06762c173ed0
3
+ metadata.gz: 864c5d089acf55f2e26da12c399a5df85915109bd7f0da8ebd3e205e6c27d4f9
4
+ data.tar.gz: a63a4821072bd6970efc076d919cd1bb4daa636fbeaa41e5ed025b09ca92c039
5
5
  SHA512:
6
- metadata.gz: 8204b5770defacd3e49718c45a6f4c58e71398340065cde8cacf9ce540ece4a18ce8e09fc5bed128963db0ffd626e59dcae56b6e201b7bf8093df22bb1209715
7
- data.tar.gz: 26d7ba9d5c55322aedd894b5ea0c4659680823780d486fbbbfb9a1e15da2c3c5d591bac202c811008be48f959fe8feab8582f9158dcb466c851b7bb134b121b6
6
+ metadata.gz: f8628fe232f7d30d4d861e72700202312c8aa213623c8382046d8474045430fa2224a0e50622932c621f93cc76ca425e646f57d57b0e579cd19bef68d64a41be
7
+ data.tar.gz: 6bb9499b704b003831e64bd203635f46b5116ed995d3361c5f1d6f0dd3b4c8814334cebc700dcf4e61d08218a37800efbc9d02305f602a466b7346f8d480d486
@@ -1,3 +1,3 @@
1
1
  module CocoapodsGitPrivateRepo
2
- VERSION = "0.1.2"
2
+ VERSION = "0.1.3"
3
3
  end
@@ -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
@@ -1,2 +1 @@
1
- require 'cocoapods-git-private-repo/cocoapods_downloader'
2
- require 'cocoapods-git-private-repo/cocoapods_sources_manager'
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.2
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nonthawat Srichad
@@ -53,10 +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
- - lib/cocoapods-git-private-repo/cocoapods_sources_manager.rb
58
56
  - lib/cocoapods-git-private-repo/gem_version.rb
59
- - lib/cocoapods-git-private-repo/git_private_repo_downloader.rb
57
+ - lib/cocoapods-git-private-repo/git_private_repo_executable.rb
60
58
  - lib/cocoapods_plugin.rb
61
59
  - spec/spec_helper.rb
62
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,67 +0,0 @@
1
- require 'cocoapods-core/source'
2
- require 'json'
3
-
4
- module Pod
5
- module GitPrivateRepoSourceExtension
6
- def repo_git(args, include_error: false)
7
- # Check for private key in configuration
8
- if private_key_path = find_private_key_for_repo
9
- # Build git command with SSH key
10
- command = "GIT_SSH_COMMAND='ssh -i #{private_key_path} -o IdentitiesOnly=yes' git -C \"#{repo}\" " << args.join(' ')
11
- command << ' 2>&1' if include_error
12
-
13
- (`#{command}` || '').strip
14
- else
15
- # Use original implementation if no private key is found
16
- super(args, include_error: include_error)
17
- end
18
- end
19
-
20
- def update_git_repo(show_output = false)
21
- # If we have a private key, use our custom implementation
22
- if private_key_path = find_private_key_for_repo
23
- command = ['pull']
24
- command << '--progress' if show_output
25
- repo_git(command)
26
- else
27
- # Use original implementation if no private key is found
28
- super(show_output)
29
- end
30
- end
31
-
32
- private
33
-
34
- def find_private_key_for_repo
35
- # Check if a JSON configuration file exists with private key mappings
36
- json_config_path = 'keys.json'
37
- return nil unless File.exist?(json_config_path)
38
-
39
- private_key_configs = JSON.parse(File.read(json_config_path))
40
-
41
- # Find a matching repo URL in the configuration
42
- if private_key_configs.is_a?(Array)
43
- # Directly get git remote url from repo to avoid recursion
44
- repo_url = get_git_remote_url(repo)
45
- return nil unless repo_url
46
-
47
- matching_config = private_key_configs.find { |config| config["url"] == repo_url }
48
- return matching_config["key_path"] if matching_config && matching_config["key_path"]
49
- end
50
-
51
- nil
52
- end
53
-
54
- # Safely get the git remote URL directly without using Source#url
55
- def get_git_remote_url(repo_path)
56
- return nil unless repo_path
57
-
58
- # Use git directly to get URL from the repo config
59
- url_command = "git -C \"#{repo_path}\" config --get remote.origin.url"
60
- remote_url = `#{url_command}`.strip
61
- return remote_url unless remote_url.empty?
62
- end
63
- end
64
-
65
- # Prepend the module to Source to override methods
66
- Source.prepend(GitPrivateRepoSourceExtension)
67
- 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