cocoapods-ybin 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 5f1f6223b5c5c46f4b4d4a8c9e9f719021748aae3d1c82dcb7fad73cac20df87
4
+ data.tar.gz: ec6dd6b52a577f0f0d2678da3bf66865fe6bcd81768101f50d06bf9d9292e2fb
5
+ SHA512:
6
+ metadata.gz: cf8f987c7cf3d67ec46b0cab7f5d1eb14089e725ba3e69bf02d456c78cdf248735729e65600cf49f602f7c26707db596838f6b5d5c3edeb1c7405ec8589c0449
7
+ data.tar.gz: abc5d9345614640b4ca7ca33ef878563efd56f0bd6b893d854450978b4822f73b68af40e46d3f13d8bea983aa934e722d82979e6aa98bafe32e93b6d9c63888e
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2020 monetking <houmanager@qq.com>
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,11 @@
1
+ # cocoapods-ybin
2
+
3
+ A description of cocoapods-ybin.
4
+
5
+ ## Installation
6
+
7
+ $ gem install cocoapods-ybin
8
+
9
+ ## Usage
10
+
11
+ $ pod spec ybin POD_NAME
@@ -0,0 +1 @@
1
+ require 'cocoapods-ybin/gem_version'
@@ -0,0 +1 @@
1
+ require 'cocoapods-ybin/command/ybin'
@@ -0,0 +1,10 @@
1
+ require 'cocoapods-ybin/command/ybin/link'
2
+
3
+ module Pod
4
+ class Command
5
+ class Ybin < Command
6
+ self.abstract_command = true
7
+ self.summary = '将二进制库与源码建立映射,实现断点自动跳入对应源码部分进行调试应用程序。作者: houmanager@qq.com'
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,437 @@
1
+ module Pod
2
+ class Command
3
+ class Ybin < Command
4
+ class Link < Ybin
5
+
6
+ autoload :Analyzer, 'cocoapods/installer/analyzer'
7
+ self.summary = '二进制库源码映射工具'
8
+
9
+ self.description = <<-DESC
10
+ 二进制库源码映射工具. 作者: houmanager@qq.com
11
+ DESC
12
+
13
+ self.arguments = [
14
+ CLAide::Argument.new('NAME', false)
15
+ ]
16
+ def self.options
17
+ [
18
+ ['--list', '查询所有已映射源码库'],
19
+ ['--remove', '删除源码映射(多个空格隔开)'],
20
+ ['--remove-all', '删除所有源码映射'],
21
+ ['--lib-version', '查询 Podfile 所有依赖库的版本']
22
+ ]
23
+ end
24
+
25
+ def initialize(argv)
26
+ # @name = argv.shift_argument
27
+
28
+ @names = argv.arguments! unless argv.arguments.empty?
29
+ @list = argv.flag?('list', false)
30
+ @link = argv.flag?('link', false)
31
+ @remove = argv.flag?('remove', false)
32
+ @remove_all = argv.flag?('remove-all', false)
33
+ @lib_version = argv.flag?('lib-version', false)
34
+
35
+ @config = Pod::Config.instance
36
+ super
37
+ end
38
+
39
+ def validate!
40
+ super
41
+ # help! 'A Pod option is required.' unless @name
42
+ banner! if @help
43
+ end
44
+
45
+ def run
46
+
47
+ if @link && @list && @remove && @remove_all && @lib_version
48
+ UI.puts "[Error] 请选择合适的命令, 不支持同时多个Option\n".red
49
+ help!
50
+ return
51
+ end
52
+
53
+ if @list
54
+ analyzerPodFileLock
55
+ linked_list
56
+ elsif @remove
57
+ analyzerPodFileLock
58
+ linked_remove
59
+ elsif @remove_all
60
+ analyzerPodFileLock
61
+ linked_remove_all
62
+ elsif @lib_version
63
+ analyzerPodFileLock
64
+ read_podfile_lock_version
65
+ elsif @names
66
+ analyzerPodFileLock
67
+ linkLibSource
68
+ else
69
+ help!
70
+ end
71
+ end
72
+
73
+ # 映射源码
74
+ def linkLibSource
75
+
76
+ if @names.nil?
77
+ UI.puts "[Error] 请输入需要映射的组件库. 示例: $ pod ybin foo\n".red
78
+ return
79
+ else
80
+ if @names.count > 1
81
+ UI.puts "[Error] 不支持一次映射多个源码. 示例: $ pod ybin foo\n".red
82
+ return
83
+ end
84
+ end
85
+
86
+ user_lib_name = @names.first.chomp.strip
87
+ lib_version = get_lib_version(user_lib_name)
88
+ if lib_version == nil || lib_version == ""
89
+ print "\n[!]Podfile 无法获取".yellow " #{user_lib_name} ".green "版本号, 但仍支持源码映射\n".yellow
90
+ else
91
+
92
+ is_contain_lib = linked_list_contain(user_lib_name)
93
+ if is_contain_lib
94
+ print "\n[Error] #{user_lib_name} 已映射 (#{lib_version}), 如需重新映射,请先删除\n\n".red
95
+ return
96
+ else
97
+ print "\n#{project_name} Using ".green "#{user_lib_name} (#{lib_version})\n".green
98
+ end
99
+ end
100
+
101
+ config = config_with_asker
102
+ lib_path = config["libPath"]
103
+ sourcePath = config["sourcePath"]
104
+
105
+ if lib_path == "" || !File.exist?(lib_path)
106
+ UI.puts "\n[Error] 二进制文件不存在, 请检查文件位置!\n".red
107
+ return
108
+ end
109
+
110
+ if sourcePath == "" || !File.exist?(sourcePath)
111
+ UI.puts "\n[Error] 源码文件不存在, 请检查文件位置!\n".red
112
+ return
113
+ end
114
+
115
+ lib_name = source_lib_name(lib_path)
116
+ link_source_code(lib_path, sourcePath, lib_name)
117
+ end
118
+
119
+ def link_source_code(lib_path, sourcePath, lib_name)
120
+
121
+ comp_dir_path = `dwarfdump "#{lib_path}" | grep "AT_comp_dir" | head -1 | cut -d \\" -f2`
122
+ if comp_dir_path == nil || comp_dir_path == ""
123
+ UI.puts "\n[Error] #{lib_name} 不支持映射源码库\n".red
124
+ return
125
+ end
126
+
127
+ lib_debug_path = comp_dir_path.chomp.strip
128
+ if File.exist?(lib_debug_path) || File.directory?(lib_debug_path) || File.symlink?(lib_debug_path)
129
+ print "源码文件: #{lib_debug_path} 已存在,无法源码映射,防止误删请检查:"
130
+ UI.puts "\n1、源码已映射,无需重复映射 \n2、开发源码(无需映射,即可调试) \n3、其他重复文件, 请手动移动/移除\n".red
131
+
132
+ else
133
+
134
+ begin
135
+ FileUtils.mkdir_p(lib_debug_path)
136
+ rescue SystemCallError
137
+ array = lib_debug_path.split('/')
138
+ if array.length > 3
139
+ root_path = '/' + array[1] + '/' + array[2]
140
+ unless File.exist?(root_path)
141
+ UI.puts "[Error] 无权限创建文件夹,请手动创建#{root_path}文件夹,再重试\n".red
142
+ end
143
+ end
144
+ end
145
+
146
+ FileUtils.rm_rf(lib_debug_path)
147
+ if Pathname.new(lib_path).extname == ".a"
148
+ `ln -s #{sourcePath} #{lib_debug_path}`
149
+ else
150
+ `ln -s #{sourcePath} #{lib_debug_path}/#{lib_name}`
151
+ end
152
+ check_linked(lib_path, lib_debug_path, lib_name)
153
+ end
154
+ end
155
+
156
+ def check_linked(lib_path, sourcePath, lib_name)
157
+
158
+ source_path = `dwarfdump "#{lib_path}" | grep -E "DW_AT_decl_file.*#{lib_name}.*\\.m|\\.c" | head -1 | cut -d \\" -f2`
159
+ source_path = source_path.chomp.strip
160
+ if File.exist?(source_path)
161
+ UI.puts "🍺🍺🍺 Successfully! 源码映射成功\n".green
162
+ recordLinknSuccessLib(lib_name, lib_path, sourcePath)
163
+ else
164
+ UI.puts "[Error] 源码 #{source_path} 不存在, 请检查源码版本 或 存储位置\n".red
165
+ end
166
+ end
167
+
168
+ # 移除单个映射
169
+ def linked_remove
170
+ if @names.nil?
171
+ UI.puts "[Error] 请输入要删除的组件库. 实例: $ pod ybin --remove xxx yyy zzz\n".red
172
+ return
173
+ end
174
+
175
+ @names.each do |name|
176
+
177
+ lib_linked_path = get_lib_linked_path(name)
178
+ if lib_linked_path.nil? || lib_linked_path == ""
179
+ UI.puts "[Error] #{name} 的映射不存在, 无需移除".red
180
+ else
181
+ if File.exist?(lib_linked_path)
182
+ FileUtils.rm_rf(lib_linked_path)
183
+ removeLinkedFileRecord(name)
184
+ UI.puts "#{name} 成功移除".green
185
+ else
186
+ UI.puts "[Error] #{name} 的映射不存在, 请手动核查: #{lib_linked_path}".red
187
+ end
188
+ end
189
+ end
190
+ print "\n"
191
+ end
192
+
193
+ # 移除所有映射
194
+ def linked_remove_all
195
+
196
+ if File.exist?(source_record_file_path)
197
+ records = JSON.parse(File.read(source_record_file_path))
198
+
199
+ if records.count > 0
200
+ records.each.with_index(0) do |record, index|
201
+ lib_linked_path = record["source_path"]
202
+ lib_name = record["lib_name"]
203
+ if File.exist?(lib_linked_path)
204
+ FileUtils.rm_rf(lib_linked_path)
205
+ removeLinkedFileRecord(lib_name)
206
+ UI.puts "#{lib_name} removing...".green
207
+ end
208
+ end
209
+ UI.puts "\n已全部移除\n".green
210
+ else
211
+ UI.puts "无记录\n".green
212
+ end
213
+ end
214
+ end
215
+
216
+ # 查询映射列表
217
+ def linked_list
218
+
219
+ records = JSON.parse(File.read(source_record_file_path))
220
+ if records.count > 0
221
+ records.each.with_index(1) do |record, index|
222
+ UI.puts "#{index}. #{record["lib_name"]}(#{record["lib_version"]}) ".green "Source: #{record["source_path"]}".yellow
223
+ end
224
+ else
225
+ UI.puts "无记录".green
226
+ end
227
+ print "\n"
228
+ end
229
+
230
+ private
231
+
232
+
233
+ def linked_list_contain(lib_name)
234
+
235
+ is_contain_lib = false
236
+ records = JSON.parse(File.read(source_record_file_path))
237
+ records.each.with_index(1) do |record, index|
238
+ if record["lib_name"] == lib_name
239
+ is_contain_lib = true
240
+ break
241
+ end
242
+ end
243
+ is_contain_lib
244
+ end
245
+
246
+ def source_root
247
+ cache_root_dir_name = ".ybin"
248
+ user_home_path = Dir.home
249
+ cache_root_path = File.join(user_home_path, cache_root_dir_name);
250
+ FileUtils.mkdir_p(cache_root_path) unless File.exist? cache_root_path
251
+ cache_root_path
252
+ end
253
+
254
+ def source_record_file_path
255
+ source_r_path = File.join(source_root.to_s, 'ybin_source_links.json')
256
+ source_r_path
257
+ end
258
+
259
+ def source_lib_name(filePath)
260
+ file_name = File.basename(filePath, ".a")
261
+ file_name = file_name[3..file_name.length]
262
+ file_name
263
+ end
264
+
265
+ def project_name
266
+ targets = @aggregate_targets.map(&:user_project_path).compact.uniq
267
+ project_name = ""
268
+ if targets.count == 1
269
+ project_name = targets.first.basename('.xcodeproj')
270
+ end
271
+ project_name
272
+ end
273
+
274
+ def recordLinknSuccessLib(lib_name, lib_path, sourcePath)
275
+
276
+ if File.exist?(source_record_file_path)
277
+ record = JSON.parse(File.read(source_record_file_path))
278
+
279
+ record_libNames = Array.new
280
+ record.each do |sub|
281
+ record_libNames.push(sub['lib_name'])
282
+ end
283
+
284
+ if record_libNames.include?(lib_name)
285
+
286
+ replace_index = record_libNames.index(lib_name)
287
+ record[replace_index] = generate_record_item(lib_name, lib_path, sourcePath)
288
+ record_item_json = JSON.generate(record)
289
+
290
+ FileUtils.rm_rf(source_record_file_path) if File.exist?(source_record_file_path)
291
+ File.open(source_record_file_path, 'w') { |file| file.write(record_item_json)}
292
+ else
293
+
294
+ record.push(generate_record_item(lib_name, lib_path, sourcePath))
295
+ record_item_json = JSON.generate(record)
296
+
297
+ FileUtils.rm_rf(source_record_file_path) if File.exist?(source_record_file_path)
298
+ File.open(source_record_file_path, 'w') { |file| file.write(record_item_json)}
299
+ end
300
+ else
301
+ record_items = Array.new
302
+ record_items.push(generate_record_item(lib_name, lib_path, sourcePath))
303
+ record_item_json = JSON.generate(record_items)
304
+ File.open(source_record_file_path, 'w') { |file| file.write(record_item_json)}
305
+ end
306
+ end
307
+
308
+ def generate_record_item(lib_name, lib_path, source_path)
309
+ lib_version = get_lib_version(lib_name.chomp.strip)
310
+ record_item = {:lib_name => lib_name, :lib_version => lib_version, :lib_path => lib_path, :source_path => source_path}
311
+ record_item
312
+ end
313
+
314
+ def removeLinkedFileRecord(lib_name)
315
+
316
+ if File.exist?(source_record_file_path)
317
+ records = JSON.parse(File.read(source_record_file_path))
318
+
319
+ lib_name_index = -1
320
+ records.each.with_index(0) do |record, index|
321
+ if record["lib_name"] == lib_name
322
+ lib_name_index = index
323
+ break
324
+ end
325
+ end
326
+
327
+ if lib_name_index >= 0
328
+ records.delete_at(lib_name_index)
329
+ record_item_json = JSON.generate(records)
330
+
331
+ FileUtils.rm_rf(source_record_file_path) if File.exist?(source_record_file_path)
332
+ File.open(source_record_file_path, 'w') { |file| file.write(record_item_json)}
333
+ end
334
+ end
335
+ end
336
+
337
+ def analyzerPodFileLock
338
+
339
+ podfile_lock = File.join(Pathname.pwd, "Podfile.lock")
340
+ if File.exist?(podfile_lock)
341
+ else
342
+ UI.puts "[!] 未匹配到 Podfile.lock 文件, 无法获取 Pod 管理信息".red
343
+ return
344
+ end
345
+ @lockfile ||= Lockfile.from_file(Pathname.new(podfile_lock))
346
+
347
+ UI.section "Analyzer Podfile" do
348
+ analyzer = Pod::Installer::Analyzer.new(config.sandbox, config.podfile, @lockfile)
349
+ @analysis_result = analyzer.analyze
350
+ @aggregate_targets = @analysis_result.targets
351
+ @pod_targets = @analysis_result.pod_targets
352
+ end
353
+ end
354
+
355
+ def read_podfile_lock_version
356
+ if @analysis_result.nil?
357
+ return
358
+ end
359
+
360
+ UI.section "#{project_name} 通过 Cocoapods 管理的依赖库(含 dependency)版本:".yellow do
361
+ root_specs = @analysis_result.specifications.map(&:root).uniq
362
+ pods_to_install = @analysis_result.sandbox_state.added | @analysis_result.sandbox_state.changed
363
+ root_specs.sort_by(&:name).each.with_index(1) do |spec, index|
364
+ if pods_to_install.include?(spec.name)
365
+ else
366
+ UI.puts "#{index}. #{spec}".green
367
+ end
368
+ end
369
+ print "\n"
370
+ end
371
+ end
372
+
373
+ def get_lib_version(lib_name)
374
+ if @analysis_result.nil?
375
+ return
376
+ end
377
+
378
+ lib_version = ''
379
+ root_specs = @analysis_result.specifications.map(&:root).uniq
380
+ pods_to_install = @analysis_result.sandbox_state.added | @analysis_result.sandbox_state.changed
381
+ root_specs.sort_by(&:name).each.with_index(1) do |spec, index|
382
+ if pods_to_install.include?(spec.name)
383
+ else
384
+ if spec.name == lib_name
385
+ lib_version = spec.version
386
+ break
387
+ end
388
+ end
389
+ end
390
+ lib_version
391
+ end
392
+
393
+ def get_lib_linked_path(lib_name)
394
+ records = JSON.parse(File.read(source_record_file_path))
395
+ lib_linked_path = ""
396
+ records.each do |record|
397
+ if record["lib_name"] == lib_name
398
+ lib_linked_path = record["source_path"]
399
+ break
400
+ end
401
+ end
402
+ lib_linked_path
403
+ end
404
+
405
+ def template_source
406
+ {
407
+ 'libPath' => { question: '1/2 请输入映射源码的二进制库.a 的路径(如:/Users/xxx/Desktop/Workspace/xxx.a)' },
408
+ 'sourcePath' => { question: '2/2 源码位置(注意版本是否匹配)' },
409
+ }
410
+ end
411
+
412
+ def config_with_asker
413
+ config = {}
414
+ template_source.each do |k, v|
415
+ config[k] = get_require_path(v[:question])
416
+ end
417
+ print "\n"
418
+ config
419
+ end
420
+
421
+ def get_require_path(question)
422
+
423
+ Pod::UI.puts "\n#{question}".yellow
424
+ answer = ''
425
+ loop do
426
+ print "->".green
427
+ answer = STDIN.gets.chomp.strip
428
+ next if answer.empty?
429
+ break
430
+ end
431
+ answer
432
+ end
433
+
434
+ end
435
+ end
436
+ end
437
+ end
@@ -0,0 +1,3 @@
1
+ module CocoapodsYbin
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,8 @@
1
+
2
+ # Pod::HooksManager.register('cocoapods-ybin', :pre_install) do |_context, _|
3
+ #
4
+ # end
5
+
6
+ # Pod::HooksManager.register('cocoapods-ybin', :source_provider) do |context, _|
7
+ #
8
+ # end
@@ -0,0 +1,3 @@
1
+ require 'cocoapods-ybin/command'
2
+ require 'cocoapods-ybin/gem_version'
3
+ require 'cocoapods-ybin/source_provider_hook'
@@ -0,0 +1,12 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+
3
+ module Pod
4
+ describe Command::Ybin do
5
+ describe 'CLAide' do
6
+ it 'registers it self' do
7
+ Command.parse(%w{ ybin }).should.be.instance_of Command::Ybin
8
+ end
9
+ end
10
+ end
11
+ end
12
+
@@ -0,0 +1,50 @@
1
+ require 'pathname'
2
+ ROOT = Pathname.new(File.expand_path('../../', __FILE__))
3
+ $:.unshift((ROOT + 'lib').to_s)
4
+ $:.unshift((ROOT + 'spec').to_s)
5
+
6
+ require 'bundler/setup'
7
+ require 'bacon'
8
+ require 'mocha-on-bacon'
9
+ require 'pretty_bacon'
10
+ require 'pathname'
11
+ require 'cocoapods'
12
+
13
+ Mocha::Configuration.prevent(:stubbing_non_existent_method)
14
+
15
+ require 'cocoapods_plugin'
16
+
17
+ #-----------------------------------------------------------------------------#
18
+
19
+ module Pod
20
+
21
+ # Disable the wrapping so the output is deterministic in the tests.
22
+ #
23
+ UI.disable_wrap = true
24
+
25
+ # Redirects the messages to an internal store.
26
+ #
27
+ module UI
28
+ @output = ''
29
+ @warnings = ''
30
+
31
+ class << self
32
+ attr_accessor :output
33
+ attr_accessor :warnings
34
+
35
+ def puts(message = '')
36
+ @output << "#{message}\n"
37
+ end
38
+
39
+ def warn(message = '', actions = [])
40
+ @warnings << "#{message}\n"
41
+ end
42
+
43
+ def print(message)
44
+ @output << message
45
+ end
46
+ end
47
+ end
48
+ end
49
+
50
+ #-----------------------------------------------------------------------------#
metadata ADDED
@@ -0,0 +1,126 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cocoapods-ybin
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - monetking
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-09-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: cocoapods
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: cocoapods-generate
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: parallel
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: cocoapods-ybin is a plug-in for link source and binary.
84
+ email:
85
+ - houmanager@qq.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - LICENSE.txt
91
+ - README.md
92
+ - lib/cocoapods-ybin.rb
93
+ - lib/cocoapods-ybin/command.rb
94
+ - lib/cocoapods-ybin/command/ybin.rb
95
+ - lib/cocoapods-ybin/command/ybin/link.rb
96
+ - lib/cocoapods-ybin/gem_version.rb
97
+ - lib/cocoapods-ybin/source_provider_hook.rb
98
+ - lib/cocoapods_plugin.rb
99
+ - spec/command/ybin_spec.rb
100
+ - spec/spec_helper.rb
101
+ homepage: https://github.com/monetking/cocoapods-ybin.git
102
+ licenses:
103
+ - MIT
104
+ metadata: {}
105
+ post_install_message:
106
+ rdoc_options: []
107
+ require_paths:
108
+ - lib
109
+ required_ruby_version: !ruby/object:Gem::Requirement
110
+ requirements:
111
+ - - ">="
112
+ - !ruby/object:Gem::Version
113
+ version: '0'
114
+ required_rubygems_version: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ version: '0'
119
+ requirements: []
120
+ rubygems_version: 3.0.3
121
+ signing_key:
122
+ specification_version: 4
123
+ summary: link source and binary.
124
+ test_files:
125
+ - spec/command/ybin_spec.rb
126
+ - spec/spec_helper.rb