podfileDep 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: '058842804957a777686796303c5dfba2878f93d7dde88957bffda2ab3ca2dde1'
4
+ data.tar.gz: 170b78f5c875d1ffadfca8b645ad3b50231f329acf96c39b2a67d87e5c8e78fb
5
+ SHA512:
6
+ metadata.gz: 44a48d4679b5fd5ffb26fad9dfa4cfe7698350f69786b6d4f1fc2d8dbb6e7a0d0060e3a8e7c9de50e835dd3c089d27e5ce8a0db33aba1110ab25f47728915504
7
+ data.tar.gz: 03fb2d60e8c3f0e7bc345e47388d855054bd31e409b447167fb3d067e4d9b29889b492b75f4664f7bc1edbe36e0c23873c64b2d9a3f33fed4a86a3f25fe32702
data/.gitignore ADDED
@@ -0,0 +1,8 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
@@ -0,0 +1,74 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as
6
+ contributors and maintainers pledge to making participation in our project and
7
+ our community a harassment-free experience for everyone, regardless of age, body
8
+ size, disability, ethnicity, gender identity and expression, level of experience,
9
+ nationality, personal appearance, race, religion, or sexual identity and
10
+ orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to creating a positive environment
15
+ include:
16
+
17
+ * Using welcoming and inclusive language
18
+ * Being respectful of differing viewpoints and experiences
19
+ * Gracefully accepting constructive criticism
20
+ * Focusing on what is best for the community
21
+ * Showing empathy towards other community members
22
+
23
+ Examples of unacceptable behavior by participants include:
24
+
25
+ * The use of sexualized language or imagery and unwelcome sexual attention or
26
+ advances
27
+ * Trolling, insulting/derogatory comments, and personal or political attacks
28
+ * Public or private harassment
29
+ * Publishing others' private information, such as a physical or electronic
30
+ address, without explicit permission
31
+ * Other conduct which could reasonably be considered inappropriate in a
32
+ professional setting
33
+
34
+ ## Our Responsibilities
35
+
36
+ Project maintainers are responsible for clarifying the standards of acceptable
37
+ behavior and are expected to take appropriate and fair corrective action in
38
+ response to any instances of unacceptable behavior.
39
+
40
+ Project maintainers have the right and responsibility to remove, edit, or
41
+ reject comments, commits, code, wiki edits, issues, and other contributions
42
+ that are not aligned to this Code of Conduct, or to ban temporarily or
43
+ permanently any contributor for other behaviors that they deem inappropriate,
44
+ threatening, offensive, or harmful.
45
+
46
+ ## Scope
47
+
48
+ This Code of Conduct applies both within project spaces and in public spaces
49
+ when an individual is representing the project or its community. Examples of
50
+ representing a project or community include using an official project e-mail
51
+ address, posting via an official social media account, or acting as an appointed
52
+ representative at an online or offline event. Representation of a project may be
53
+ further defined and clarified by project maintainers.
54
+
55
+ ## Enforcement
56
+
57
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
+ reported by contacting the project team at 2975745207@qq.com. All
59
+ complaints will be reviewed and investigated and will result in a response that
60
+ is deemed necessary and appropriate to the circumstances. The project team is
61
+ obligated to maintain confidentiality with regard to the reporter of an incident.
62
+ Further details of specific enforcement policies may be posted separately.
63
+
64
+ Project maintainers who do not follow or enforce the Code of Conduct in good
65
+ faith may face temporary or permanent repercussions as determined by other
66
+ members of the project's leadership.
67
+
68
+ ## Attribution
69
+
70
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
+ available at [http://contributor-covenant.org/version/1/4][version]
72
+
73
+ [homepage]: http://contributor-covenant.org
74
+ [version]: http://contributor-covenant.org/version/1/4/
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in podfileDep.gemspec
6
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2023 lihaifeng
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,43 @@
1
+ # PodfileDep
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/podfileDep`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ TODO: Delete this and the text above, and describe your gem
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'podfileDep'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install podfileDep
22
+
23
+ ## Usage
24
+
25
+ TODO: Write usage instructions here
26
+
27
+ ## Development
28
+
29
+ After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
+
31
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
+
33
+ ## Contributing
34
+
35
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/podfileDep. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
36
+
37
+ ## License
38
+
39
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
40
+
41
+ ## Code of Conduct
42
+
43
+ Everyone interacting in the PodfileDep project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/podfileDep/blob/master/CODE_OF_CONDUCT.md).
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "podfileDep"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,3 @@
1
+ module PodfileDep
2
+ VERSION = "1.0.0"
3
+ end
data/lib/podfileDep.rb ADDED
@@ -0,0 +1,798 @@
1
+ require 'pathname'
2
+ require 'yaml'
3
+
4
+ module PodfileDep
5
+
6
+ $openImportCheck = false
7
+ $podfile_thirdParty = 'PodfileThirdParty.yaml'
8
+ $podfile_module = 'PodfileModule.yaml'
9
+ $podfile_local = 'PodfileLocal.yaml'
10
+ $podfile_lock = 'Podfile.lock'
11
+
12
+
13
+ class PodDependency
14
+ attr_reader :pod, :version, :git, :tag, :branch, :podspec, :configurations, :path, :inhibit_warnings, :source, :binary
15
+ def initialize(module_name, pod, version, git, tag, branch, podspec, configurations, path, inhibit_warnings, source, binary)
16
+ @module_name = module_name
17
+ @pod = pod
18
+ @version = version
19
+ @git = git
20
+ @tag = tag
21
+ @branch = branch
22
+ @podspec = podspec
23
+ @configurations = configurations
24
+ @path = path
25
+ @inhibit_warnings = inhibit_warnings
26
+ @source = source
27
+ @binary = binary
28
+ end
29
+ end
30
+
31
+ def PodfileDep.setup(targets, openImportCheck)
32
+ $openImportCheck = openImportCheck
33
+
34
+ PodfileDep.checkFile()
35
+ PodfileDep.checkParam(targets)
36
+
37
+ PodfileDep.generateLocal()
38
+ PodfileDep.generateModule($podfile_module, "企业内部组件", "TestPodName")
39
+ PodfileDep.generateModule($podfile_thirdParty, "第三方组件", "Masonry")
40
+
41
+ # 读取依赖
42
+ lock_dependencies = PodfileDep.lockDeps()
43
+
44
+ all_dependencies = {}
45
+ PodfileDep.readYamlDep(all_dependencies, $podfile_thirdParty, false)
46
+ PodfileDep.readYamlDep(all_dependencies, $podfile_module, false)
47
+ PodfileDep.readYamlDep(all_dependencies, $podfile_local, true)
48
+
49
+ PodfileDep.logDeps(all_dependencies)
50
+
51
+ result = PodfileDep.generateTargetsDep(targets, all_dependencies)
52
+
53
+ PodfileDep.logChangedDep(all_dependencies, lock_dependencies)
54
+
55
+ return result
56
+ end
57
+
58
+ def PodfileDep.checkFile()
59
+ unless File.exist?("Podfile") then
60
+ puts "本脚本文件必须和Podfile文件同级目录"
61
+ exit!
62
+ end
63
+ end
64
+
65
+ def PodfileDep.checkParam(targets)
66
+ msg = "❌ setup里参数需要填写target名字, 参数类型是字符串格式的数组。例如[\"test1\", \"test2\"]"
67
+ unless targets.class == Array
68
+ puts msg
69
+ exit!
70
+ end
71
+
72
+ targets.each { |target|
73
+ unless target.class == String
74
+ puts msg
75
+ exit!
76
+ end
77
+ }
78
+ end
79
+
80
+ def PodfileDep.lockDeps()
81
+ result = {}
82
+
83
+ unless File.exist?($podfile_lock)
84
+ return result
85
+ end
86
+
87
+ dependencies_yaml = YAML.load_file($podfile_lock)
88
+ if dependencies_yaml.key?('DEPENDENCIES')
89
+ temp_dependencies = dependencies_yaml['DEPENDENCIES']
90
+ temp_dependencies.each { |item|
91
+ old_dependency = item.split(' (')
92
+ result[old_dependency[0]] = old_dependency[1]
93
+ }
94
+ end
95
+ return result
96
+ end
97
+
98
+ def PodfileDep.generateLocal()
99
+ if File.exist?($podfile_local) then
100
+ return
101
+ end
102
+ content = "
103
+ # 1、本依赖配置文件优先级最高, 用来覆盖其他两个依赖的yaml文件中的组件。 尝试打开以下注释, 修改对应字段, 然后执行pod install
104
+ # 2、PODS下边的配置是数组形式, 如果有多个就写多个
105
+ # 3、请将本文件加入到忽略文件中
106
+
107
+ PODS:
108
+
109
+ # - module: Masonry
110
+ # pod: Masonry
111
+ # path: ~/CodePath
112
+
113
+ "
114
+ File.open($podfile_local, 'w') { |file|
115
+ file.write(content)
116
+ }
117
+ end
118
+
119
+ def PodfileDep.generateModule(yaml_module, prefix, pod_name)
120
+ if File.exist?(yaml_module) then
121
+ return
122
+ end
123
+
124
+ content = "
125
+ # #{prefix}
126
+ # 1、优先级:path > podspec > version > tag > branch (git字段是tag字段或branch字段不为空时用到, source字段是version不为空时用到, path字段就是直接从对应的路径读取依赖)
127
+ # 2、为方便查看, 建议将本文件拖入壳工程引用
128
+
129
+ # 如果 source = null && binary = false 则source默认使用这个
130
+ SOURCE: 这里替换成源码的source
131
+
132
+ # 如果 source = null && binary = true 则source默认使用这个
133
+ BINARY_SOURCE: 这里替换成二进制的source
134
+
135
+ PODS:
136
+
137
+ # - module: #{pod_name}
138
+ # pod: #{pod_name}
139
+ # path: null
140
+ # podspec: null
141
+ # version: 1.1.0
142
+ # git: null
143
+ # tag: null
144
+ # branch: null
145
+ # configurations: null
146
+ # inhibit_warnings: true
147
+ # source: null
148
+ # binary: true
149
+ "
150
+ File.open(yaml_module, 'w') { |file|
151
+ file.write(content)
152
+ }
153
+ end
154
+
155
+ def PodfileDep.readYamlDep(all_dependencies, yamlName, canCover)
156
+ unless File.exist?(yamlName)
157
+ puts "文件不存在:"+yamlName
158
+ return
159
+ end
160
+
161
+ begin
162
+ dependencies_yaml = YAML.load_file(yamlName)
163
+ rescue Exception => e
164
+ puts e
165
+ puts yamlName+'文件解析异常, 请检查 ⬆️'
166
+ exit!
167
+ end
168
+
169
+ unless dependencies_yaml.class == Hash
170
+ puts "文件不是keyValue形式:"+yamlName
171
+ return
172
+ end
173
+
174
+ unless dependencies_yaml.key?('PODS')
175
+ puts "文件内的key[PODS]不存在:"+yamlName
176
+ return
177
+ end
178
+
179
+ unless dependencies_yaml['PODS'].class == Array
180
+ puts "文件配置的依赖PODS下边不是数组形式:"+yamlName
181
+ return
182
+ end
183
+
184
+ # 读取默认源码source
185
+ default_source = nil
186
+ if dependencies_yaml.key?('SOURCE') and dependencies_yaml['SOURCE'].class == String
187
+ default_source = dependencies_yaml['SOURCE']
188
+ end
189
+
190
+ # 读取默认二进制source
191
+ default_binary_source = nil
192
+ if dependencies_yaml.key?('BINARY_SOURCE') and dependencies_yaml['BINARY_SOURCE'].class == String
193
+ default_binary_source = dependencies_yaml['BINARY_SOURCE']
194
+ end
195
+
196
+ dependencies = dependencies_yaml['PODS']
197
+ puts "解析:"+yamlName + " 共"+dependencies.size.to_s + "个依赖"
198
+
199
+ # 遍历依赖库列表
200
+ dependencies.each { |dependency|
201
+
202
+ # 不能覆盖,有重复依赖
203
+ if all_dependencies.key?(dependency['pod'])
204
+ # 能被覆盖
205
+ if canCover
206
+ puts '✅ 已经存在: ' + dependency['pod'] + ', 该依赖被'+yamlName+'中依赖替换'
207
+ else
208
+ puts '❌ 发现重复的组件依赖: [' + dependency['pod'] + '],请检查依赖文件,删除重复依赖'
209
+ exit!
210
+ end
211
+ end
212
+
213
+ # 如果source不存在, 则使用默认的
214
+ unless dependency['source']
215
+ dependency['source'] = dependency['binary'] ? default_binary_source : default_source
216
+ end
217
+
218
+ # 校验
219
+ if not dependency['path'] and not dependency['source'] and dependency['version']
220
+ puts '❌ 请为组件'+dependency['pod']+'配置source字段或在'+ yamlName+'顶层设置默认source(字段:SOURCE和BINARY_SOURCE)'
221
+ exit!
222
+ end
223
+
224
+ # 警告
225
+ if dependency['path'] and not canCover
226
+ puts '⚠️ 组件'+dependency['pod']+'使用path依赖方式应该写在'+ $podfile_local
227
+ end
228
+
229
+ if dependency['podspec'] and not canCover
230
+ puts '⚠️ 组件'+dependency['pod']+'使用podspec依赖方式应该写在'+ $podfile_local
231
+ end
232
+
233
+ # 生成依赖对象
234
+ module_name = dependency['module']
235
+ pod = dependency['pod']
236
+ version = dependency['version']
237
+ git = dependency['git']
238
+ tag = dependency['tag']
239
+ branch = dependency['branch']
240
+ podspec = dependency['podspec']
241
+ configurations = dependency['configurations']
242
+ path = dependency['path']
243
+ inhibit_warnings = dependency['inhibit_warnings'] ? dependency['inhibit_warnings'] : false
244
+ source = dependency['source']
245
+ binary = dependency['binary']
246
+
247
+ unless pod then
248
+ puts yamlName + ': pod 字段(pod组件名字)必须存在,请检查'
249
+ exit!
250
+ end
251
+
252
+ unless path or podspec or version or git or tag or branch then
253
+ puts yamlName + ': path/podspec/version/git/tag/branch 字段需至少有一个存在,请检查'
254
+ exit!
255
+ end
256
+
257
+ pod_dependency = PodDependency.new(module_name, pod, version, git, tag, branch, podspec, configurations, path, inhibit_warnings, source, binary);
258
+
259
+ # 加入全部的依赖map中
260
+ all_dependencies[dependency['pod']] = pod_dependency
261
+
262
+ }
263
+ end
264
+
265
+ def PodfileDep.logDeps(all_dependencies)
266
+ puts "\n➡️ 解析依赖总数共计:#{all_dependencies.size}个"
267
+ puts '⬇️ 按照 Podfile 格式打印一遍'
268
+ all_dependencies.each_value { |dependency|
269
+
270
+ # 执行打印
271
+ if dependency.path #路径引用
272
+ puts_result = 'pod \'' + dependency.pod + '\''
273
+ puts_result += ', :path => \'' + dependency.path + '\''
274
+ if dependency.configurations
275
+ puts_result += ', :configurations => [\'' + dependency.configurations.join('\', \'') + '\']'
276
+ end
277
+ if dependency.inhibit_warnings
278
+ puts_result += ', :inhibit_warnings => true'
279
+ end
280
+ puts puts_result
281
+ elsif dependency.podspec #podspec引用
282
+ puts_result = 'pod \'' + dependency.pod + '\''
283
+ if dependency.podspec
284
+ puts_result += ', :podspec => \'' + dependency.podspec + '\''
285
+ end
286
+ if dependency.configurations
287
+ puts_result += ', :configurations => [\'' + dependency.configurations.join('\', \'') + '\']'
288
+ end
289
+ if dependency.inhibit_warnings
290
+ puts_result += ', :inhibit_warnings => true'
291
+ end
292
+ puts puts_result
293
+ elsif dependency.version #版本号引用
294
+ puts_result = 'pod \'' + dependency.pod + '\', \'' + dependency.version.to_s + '\''
295
+ if dependency.configurations
296
+ puts_result += ', :configurations => [\'' + dependency.configurations.join('\', \'') + '\']'
297
+ end
298
+ if dependency.inhibit_warnings
299
+ puts_result += ', :inhibit_warnings => true'
300
+ end
301
+ if dependency.source
302
+ puts_result += ', :source => \'' + dependency.source + '\''
303
+ end
304
+ puts puts_result
305
+ elsif dependency.git #git仓库引用
306
+ puts_result = 'pod \'' + dependency.pod + '\''
307
+ if dependency.git
308
+ puts_result += ', :git => \'' + dependency.git + '\''
309
+ end
310
+ if dependency.tag
311
+ puts_result += ', :tag => \'' + dependency.tag + '\''
312
+ elsif dependency.branch
313
+ puts_result += ', :branch => \'' + dependency.branch + '\''
314
+ end
315
+ if dependency.configurations
316
+ puts_result += ', :configurations => [\'' + dependency.configurations.join('\', \'') + '\']'
317
+ end
318
+ if dependency.inhibit_warnings
319
+ puts_result += ', :inhibit_warnings => true'
320
+ end
321
+ puts puts_result
322
+ else # 路径 版本号 git地址 podspec 均未指定 去指定的source中找(source不会为空)
323
+ puts_result = 'pod \'' + dependency.pod + '\''
324
+ if dependency.configurations
325
+ puts_result += ', :configurations => [\'' + dependency.configurations.join('\', \'') + '\']'
326
+ end
327
+ if dependency.inhibit_warnings
328
+ puts_result += ', :inhibit_warnings => true'
329
+ end
330
+ if dependency.source
331
+ puts_result += ', :source => \'' + dependency.source + '\''
332
+ end
333
+ puts puts_result
334
+ end
335
+ }
336
+ puts '⬆️ 打印完毕'
337
+ end
338
+
339
+ def PodfileDep.generateTargetsDep(targets, all_dependencies)
340
+
341
+ tempArray = []
342
+ all_dependencies.each_value { |value|
343
+ tempArray << value
344
+ }
345
+
346
+ result = {}
347
+ targets.each { |target|
348
+ result[target] = tempArray
349
+ }
350
+ return result
351
+ end
352
+
353
+ def PodfileDep.logNewDependency(lock_dependencies, new_dependency)
354
+ new_add = true
355
+ lock_dependencies.each_key { |old_dependency|
356
+ if old_dependency == new_dependency
357
+ new_add = false
358
+ break
359
+ end
360
+ }
361
+
362
+ if new_add == true
363
+ puts '🈶 新增依赖: ' + new_dependency
364
+ end
365
+ end
366
+
367
+ def PodfileDep.logRemoveDependency(new_dependencies, old_dependency)
368
+
369
+ old_remove = true
370
+ new_dependencies.each { |new_dependency|
371
+ if old_dependency == new_dependency
372
+ old_remove = false
373
+ break
374
+ end
375
+ }
376
+
377
+ if old_remove == true
378
+ puts '🈚️ 删除依赖: ' + old_dependency
379
+ end
380
+ end
381
+
382
+ def PodfileDep.podfilePod()
383
+ work_dir = FileUtils.pwd()
384
+ podfile_path = work_dir + '/Podfile'
385
+ res = Array.new()
386
+ unless File.exist?(podfile_path) then
387
+ return res
388
+ end
389
+ lineArr = IO.readlines(podfile_path)
390
+ lineArr.each { |line|
391
+ line = line.gsub(" ", "")
392
+ if line.start_with?("pod\'")
393
+ arr = line.split("\'")
394
+ if arr.size>1 then
395
+ res << arr[1]
396
+ end
397
+ end
398
+ }
399
+ return res
400
+ end
401
+
402
+ def PodfileDep.logChangedDep(all_dependencies, lock_dependencies)
403
+ new_dependencies = PodfileDep.podfilePod()
404
+
405
+ all_dependencies.each_key { |key|
406
+ new_dependencies << key
407
+ }
408
+
409
+ new_dependencies.each { |item|
410
+ PodfileDep.logNewDependency(lock_dependencies, item)
411
+ }
412
+
413
+ lock_dependencies.each_key { |old_dependency|
414
+ PodfileDep.logRemoveDependency(new_dependencies, old_dependency)
415
+ }
416
+ end
417
+
418
+ def PodfileDep.logIndirectDependencies()
419
+
420
+ # 判断yaml文件是否存在
421
+ unless File.exist?($podfile_lock)
422
+ return
423
+ end
424
+
425
+ # 内容读取
426
+ dependencies_lock = YAML.load_file($podfile_lock)
427
+
428
+ dependencies = dependencies_lock['DEPENDENCIES']
429
+ unless dependencies
430
+ return
431
+ end
432
+
433
+ check_sums = dependencies_lock['SPEC CHECKSUMS']
434
+ unless check_sums
435
+ return
436
+ end
437
+
438
+ # 数组处理
439
+ checkValues = dependencies.collect! {|item|
440
+ item.split(' (')[0]
441
+ }
442
+ checkValues = dependencies.collect! {|item|
443
+ item.split('/')[0]
444
+ }
445
+
446
+ puts ''
447
+ check_sums.each{ |array|
448
+ beCheckValue = array[0]
449
+ unless checkValues.include?(beCheckValue)
450
+ puts '↪️ 间接依赖: '+ beCheckValue
451
+ end
452
+ }
453
+ end
454
+
455
+ def PodfileDep.logUnusedDependencies()
456
+
457
+ # 判断yaml文件是否存在
458
+ unless File.exist?($podfile_lock)
459
+ return
460
+ end
461
+
462
+ # 内容读取
463
+ dependencies_lock = YAML.load_file($podfile_lock)
464
+
465
+ dependencies = dependencies_lock['PODS']
466
+ unless dependencies
467
+ return
468
+ end
469
+
470
+ # 数组处理
471
+ checkValues = Array.new
472
+ allValues = Array.new
473
+ dependencies.each {|item|
474
+ if item.class == Hash then
475
+ item.each { |key, value|
476
+ item = key
477
+ allValues.concat(value)
478
+ }
479
+ end
480
+ item.split(' (')[0]
481
+ checkValues << item
482
+ }
483
+
484
+ # 数组处理
485
+ checkValues.collect! { |value|
486
+ value.split(' (')[0]
487
+ }
488
+ allValues.collect! { |value|
489
+ value.split(' (')[0]
490
+ }
491
+
492
+ # 处理有的只依赖了子仓库
493
+ allValues1 = allValues + []
494
+ allValues1.collect! { |value|
495
+ value.split('/')[0]
496
+ }
497
+
498
+
499
+ # 壳工程中的文件 只查找main.m 因为有的文件可能没有使用到
500
+ main_path = %x(find . -name "main.m")
501
+ main_path = PathUtil.expandPath(main_path)
502
+
503
+ checkValues.each { |item|
504
+ if not allValues.include?(item) and not allValues1.include?(item)
505
+ res = PodfileDep.checkUnuseInMain(item, main_path)
506
+ if res
507
+ puts "可能未使用的组件: " + item
508
+ end
509
+ end
510
+ }
511
+ end
512
+
513
+ def PodfileDep.checkUnuseInMain(item, main_path)
514
+ unless File.exist?(main_path)then
515
+ return true
516
+ end
517
+ lineArr = IO.readlines(main_path)
518
+ lineArr.each_with_index { |line, index|
519
+ if line.start_with?("#import <#{item}")
520
+ return false
521
+ end
522
+ }
523
+
524
+ return true
525
+ end
526
+
527
+ end
528
+
529
+ module ImportCheck
530
+ class Module
531
+ attr_reader :moduleName, :modulePath, :fileNameArray, :filePathArray
532
+ def initialize(moduleName, modulePath, fileNameArray, filePathArray)
533
+ @moduleName = moduleName
534
+ @modulePath = modulePath
535
+ @fileNameArray = fileNameArray
536
+ @filePathArray = filePathArray
537
+ end
538
+ end
539
+
540
+ class Import
541
+ attr_reader :content, :importName, :moduleItem, :fileName, :lineIndex, :pod
542
+ def initialize(content, importName, moduleItem, fileName, lineIndex, pod)
543
+ @content = content
544
+ @importName = importName
545
+ @moduleItem = moduleItem
546
+ @fileName = fileName
547
+ @lineIndex = lineIndex
548
+ @pod = pod
549
+ end
550
+ def setPod=(pod)
551
+ @pod = pod
552
+ end
553
+ end
554
+
555
+ def ImportCheck.check(check)
556
+ unless check
557
+ puts "未开启import规范检查(开启方式podfile文件中PodfileDep.setup的第二个参数)"
558
+ return
559
+ end
560
+ puts "import规范检查中..."
561
+ start = (Time.now.to_f * 1000).to_i
562
+
563
+ # 需要检查的模块
564
+ checkModules = []
565
+ ImportCheck.findCheckModules(checkModules, $podfile_module)
566
+ ImportCheck.findCheckModules(checkModules, $podfile_local)
567
+
568
+ # 白名单
569
+ whiteListName = "importCheckWhite.txt"
570
+ whiteList = ImportCheck.WhiteList(whiteListName)
571
+
572
+ # 有问题的import
573
+ badImportArray = []
574
+
575
+ # 计数
576
+ checkCount = 0
577
+ checkModules.each { |moduleItem|
578
+ modulePath = moduleItem.modulePath
579
+
580
+ # 需要检查的文件
581
+ filePathArray = []
582
+ fileNameArray = []
583
+ ImportCheck.findCodeFile(modulePath, filePathArray, fileNameArray, false)
584
+
585
+ filePathArray.each { |filePath|
586
+ ImportCheck.findBadQuoteImport(filePath, fileNameArray, badImportArray, moduleItem, whiteList)
587
+ }
588
+ checkCount += fileNameArray.size
589
+ }
590
+
591
+ allModuleArray = ImportCheck.findModules()
592
+ allModuleArray = allModuleArray + checkModules
593
+
594
+ tiplog = false
595
+ badImportArray.collect { |import|
596
+ moduleName = ImportCheck.findPodModule(allModuleArray, import.importName)
597
+ import.setPod = moduleName
598
+ result = moduleName ? "#import <#{moduleName}/#{import.importName}>" : "<>形式导入"
599
+ puts "⚠️ <#{import.moduleItem.moduleName}> #{import.fileName} #{import.lineIndex}行 #{import.content} => #{result}"
600
+ tiplog = true
601
+ }
602
+
603
+ # 生成白名单文件
604
+ ImportCheck.generateWhite(whiteListName)
605
+
606
+ if tiplog then
607
+ puts "\nimport规范检查白名单文件: #{whiteListName}"
608
+ end
609
+
610
+ duration = ((Time.now.to_f * 1000).to_i - start)*0.001
611
+ puts "import规范检查完毕! 共检查#{checkCount}个文件 耗时:#{duration.round(2)}秒"
612
+ end
613
+
614
+ def ImportCheck.WhiteList(whiteListName)
615
+ unless File.exist?(whiteListName) then
616
+ return []
617
+ end
618
+
619
+ array = []
620
+ lineArr = IO.readlines(whiteListName)
621
+ lineArr.each { |line|
622
+ unless line.start_with?("#import \"")
623
+ next
624
+ end
625
+ array << line
626
+ }
627
+ return array
628
+ end
629
+
630
+ def ImportCheck.generateWhite(whiteListName)
631
+ if File.exist?(whiteListName) then
632
+ return
633
+ end
634
+
635
+ content = "import不规范检查, 这里配置白名单, 每个一行(加入白名单的不会被检查是否规范)。 示例
636
+ #import \"libxx.h\"
637
+ #import \"libxxx.h\"
638
+ -----------请在下边按示例加白名单---------
639
+ "
640
+ File.open(whiteListName, 'w') { |file|
641
+ file.write(content)
642
+ }
643
+ end
644
+
645
+ def ImportCheck.findPodModule(moduleArray, importName)
646
+ moduleArray.each { |item|
647
+ item.fileNameArray.each { |fileName|
648
+ if fileName == importName
649
+ return item.moduleName
650
+ end
651
+ }
652
+ }
653
+ return nil
654
+ end
655
+
656
+ def ImportCheck.findModules()
657
+ pods_dir = FileUtils.pwd() + "/Pods"
658
+
659
+ moduleArray = []
660
+
661
+ Dir.foreach(pods_dir) { |moduleName|
662
+ if moduleName.include?(".") or moduleName == "Target Support Files" or moduleName == "Headers"
663
+ next
664
+ end
665
+ modulePath = pods_dir + "/" + moduleName
666
+ filePathArray = []
667
+ fileNameArray = []
668
+ ImportCheck.findCodeFile(modulePath, filePathArray, fileNameArray, true)
669
+ moduleArray << Module.new(moduleName, modulePath, fileNameArray, filePathArray)
670
+ }
671
+
672
+ return moduleArray
673
+ end
674
+
675
+ # 根据路径获取所有的代码文件
676
+ def ImportCheck.findCodeFile(des_path, filePathArray, fileNameArray, onlyDotH)
677
+
678
+ if not File.directory?(des_path)
679
+ puts "非文件夹, 请检查: #{des_path}"
680
+ return
681
+ end
682
+
683
+ Dir.foreach(des_path) { |fileName|
684
+ sub_path = des_path + "/" + fileName
685
+ if fileName.start_with?(".")
686
+ next
687
+ end
688
+ if File.directory?(sub_path)
689
+ ImportCheck.findCodeFile(sub_path, filePathArray, fileNameArray, onlyDotH)
690
+ else
691
+
692
+ onlyDotHCheck = (fileName.end_with?(".h") or fileName.end_with?(".pch"))
693
+ notOnlyDotHCheck = (fileName.end_with?(".h") or
694
+ fileName.end_with?(".m") or
695
+ fileName.end_with?(".pch") or
696
+ fileName.end_with?(".mm") or
697
+ fileName.end_with?(".hpp") or
698
+ fileName.end_with?(".cpp") or
699
+ fileName.end_with?(".c") or
700
+ fileName.end_with?(".cc"))
701
+ isCodeFile = onlyDotH ? onlyDotHCheck : notOnlyDotHCheck
702
+ if isCodeFile
703
+ filePath = des_path + "/" + fileName
704
+ filePathArray << filePath
705
+ fileNameArray << fileName
706
+ end
707
+ end
708
+ }
709
+ end
710
+
711
+ # 查找不在当前模块内的 #import "xx"
712
+ def ImportCheck.findBadQuoteImport(filePath, fileNameArray, badImportArray, moduleItem, whiteList)
713
+ lineArr = IO.readlines(filePath)
714
+ lineArr.each_with_index { |line, index|
715
+ unless line.start_with?("#import \"")
716
+ next
717
+ end
718
+
719
+ lineSplitArr = line.split("\"")
720
+ if lineSplitArr.size < 2
721
+ next
722
+ end
723
+
724
+ content = line.gsub("\n", "")
725
+ importName = lineSplitArr.size >=2 ? lineSplitArr[1].gsub("\n", "") : content
726
+
727
+ if ImportCheck.importInWihte(importName, whiteList)
728
+ next
729
+ end
730
+
731
+ if fileNameArray.include?(importName)
732
+ next
733
+ end
734
+
735
+ fileName = File.basename(filePath)
736
+ lineIndex = index+1
737
+ pod = nil
738
+
739
+ badImportArray << Import.new(content, importName, moduleItem, fileName, lineIndex, pod)
740
+ }
741
+ end
742
+
743
+ def ImportCheck.importInWihte(importName, whiteList)
744
+ whiteList.each {|whiteItem|
745
+ if whiteItem.include?(importName)
746
+ return true
747
+ end
748
+ }
749
+ return false
750
+ end
751
+
752
+ def ImportCheck.findCheckModules(checkModules, yaml_module)
753
+
754
+ unless File.exist?(yaml_module)
755
+ return
756
+ end
757
+
758
+ # 内容读取
759
+ dependencies_local = YAML.load_file(yaml_module)
760
+
761
+ unless dependencies_local.class == Hash
762
+ return
763
+ end
764
+
765
+ dependencies = dependencies_local['PODS']
766
+ unless dependencies
767
+ return
768
+ end
769
+
770
+ dependencies.each { |dependency|
771
+ dependencyPath = dependency["path"]
772
+ if dependencyPath and dependencyPath != "null" and dependencyPath.gsub(" ", "").length>0 then
773
+ moduleName = dependency["pod"]
774
+ modulePath = PathUtil.expandPath(dependencyPath)
775
+ fileNameArray = []
776
+ filePathArray = []
777
+ ImportCheck.findCodeFile(modulePath, filePathArray, fileNameArray, true)
778
+ checkModules << Module.new(moduleName, modulePath, fileNameArray, filePathArray)
779
+ end
780
+ }
781
+
782
+ end
783
+
784
+ end
785
+
786
+ class PathUtil
787
+
788
+ def PathUtil.expandPath(des_path)
789
+ return File.expand_path(des_path).gsub("\n", "")
790
+ end
791
+
792
+ end
793
+
794
+ END {
795
+ ImportCheck.check($openImportCheck)
796
+ PodfileDep.logIndirectDependencies()
797
+ PodfileDep.logUnusedDependencies()
798
+ }
@@ -0,0 +1,41 @@
1
+
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "podfileDep/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "podfileDep"
8
+ spec.version = PodfileDep::VERSION
9
+ spec.authors = ["wangshuaipeng"]
10
+ spec.email = ["wsp810@163.com"]
11
+
12
+ spec.summary = %q{podfile文件解析.}
13
+ spec.description = %q{podfile文件解析.}
14
+ spec.homepage = "https://toscode.gitee.com/sourceiOS/podfileDep"
15
+ spec.license = "MIT"
16
+
17
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
18
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
19
+ if spec.respond_to?(:metadata)
20
+ # spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
21
+
22
+ spec.metadata["homepage_uri"] = spec.homepage
23
+ spec.metadata["source_code_uri"] = "https://toscode.gitee.com/sourceiOS/podfileDep.git"
24
+ spec.metadata["changelog_uri"] = "https://toscode.gitee.com/sourceiOS/podfileDep"
25
+ else
26
+ raise "RubyGems 2.0 or newer is required to protect against " \
27
+ "public gem pushes."
28
+ end
29
+
30
+ # Specify which files should be added to the gem when it is released.
31
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
32
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
33
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
34
+ end
35
+ spec.bindir = "exe"
36
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
37
+ spec.require_paths = ["lib"]
38
+
39
+ spec.add_development_dependency "bundler", "~> 1.17"
40
+ spec.add_development_dependency "rake", "~> 10.0"
41
+ end
metadata ADDED
@@ -0,0 +1,85 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: podfileDep
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - wangshuaipeng
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2023-01-16 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.17'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.17'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ description: podfile文件解析.
42
+ email:
43
+ - wsp810@163.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - ".gitignore"
49
+ - CODE_OF_CONDUCT.md
50
+ - Gemfile
51
+ - LICENSE.txt
52
+ - README.md
53
+ - Rakefile
54
+ - bin/console
55
+ - bin/setup
56
+ - lib/podfileDep.rb
57
+ - lib/podfileDep/version.rb
58
+ - podfileDep.gemspec
59
+ homepage: https://toscode.gitee.com/sourceiOS/podfileDep
60
+ licenses:
61
+ - MIT
62
+ metadata:
63
+ homepage_uri: https://toscode.gitee.com/sourceiOS/podfileDep
64
+ source_code_uri: https://toscode.gitee.com/sourceiOS/podfileDep.git
65
+ changelog_uri: https://toscode.gitee.com/sourceiOS/podfileDep
66
+ post_install_message:
67
+ rdoc_options: []
68
+ require_paths:
69
+ - lib
70
+ required_ruby_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ required_rubygems_version: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: '0'
80
+ requirements: []
81
+ rubygems_version: 3.0.3
82
+ signing_key:
83
+ specification_version: 4
84
+ summary: podfile文件解析.
85
+ test_files: []