podfileDep 1.0.0

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 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: []