podfileDep 2.3.0 → 2.3.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,1408 +0,0 @@
1
- require 'pathname'
2
- require 'yaml'
3
- require 'cocoapods'
4
- require 'xcodeproj'
5
- autoload :CheckDep, "check_dep"
6
-
7
- module PodfileDep
8
-
9
- $libLibarys = ["time","removefile","AppleTextureEncoder","standards","AvailabilityMacros","semaphore","SystemHealthClient","dns_sd","ftw","checkint","pwd","bitstring","utime","err","CommonCrypto","inttypes","resolv","c++","_ctermid","stdlib","sysdir","unwind","fts","vis","AvailabilityVersions","membership","libxml2","ulimit","_stdio","ntsid","net","notify_keys","CMakeLists.txt","AssertMacros","float","aio","libxml","ConditionalMacros","locale","fmtmsg","unicode","_wctype","cpio","langinfo","xlocale","limits","Endian","unwind_itanium","_types","db","bank","_ctype","unistd","stddef","dispatch","wctype","fcntl","mach_debug","Availability","stringlist","tar","readpassphrase","_locale","ttyent","bzlib","cache","signal","dirent","mpool","libDER","unwind_arm_ehabi","spawn","crt_externs","simd","regex","AvailabilityInternal","arpa","syslog","bsm","netinet","libunwind","libgen","corpses","rpcsvc","monetary","compression","expat_external","setjmp","tgmath","notify","getopt","_regex","dlfcn","strings","TargetConditionals","fnmatch","pthread","xlocale","execinfo","networkext","printf","architecture","alloca","sys","iconv","fenv","expat","grp","secure","ctype","fstab","pthread_spis","machine","SystemHealthManager","voucher","wordexp","zlib","nl_types","paths","AppleEXR","wchar","sqlite3","util","gethostuuid","sched","sqlite3ext","iso646","Block","netdb","pthread","math","memory","asl","__wctype","mach","errno","device","termios","copyfile","os","xattr_flags","poll","_xlocale","stdio","mach-o","malloc","string_x86","arm","Spatial","__libunwind_config","nameser","dns","_types","rpc","netinet6","pthread_impl","objc","MacTypes","libkern","uuid","search","assert","AppleArchive","cache_callbacks","dns_util","glob","ifaddrs","utmpx","sandbox","arm64","stdint","complex","runetype","zconf","ucontext","sysexits","string","ndbm"]
10
- $frameworks = ["MetricKit","Network","GameKit","AddressBookUI","CreateML","Speech","SafariServices","ProximityReader","Metal","AppClip","QuartzCore","CoreGraphics","StoreKit","GSS","CoreML","WatchConnectivity","UserNotificationsUI","ARKit","CoreLocationUI","MetalPerformanceShaders","AutomaticAssessmentConfiguration","ExternalAccessory","MediaPlayer","LinkPresentation","IdentityLookupUI","MediaToolbox","UIKit","MessageUI","MetalFX","CoreNFC","HomeKit","CryptoKit","ScreenTime","NewsstandKit","MLCompute","NaturalLanguage","CoreVideo","MetalKit","OSLog","PDFKit","CoreText","UniformTypeIdentifiers","IOKit","ManagedSettings","AVFoundation","Accelerate","DeviceCheck","ImageIO","BackgroundTasks","FamilyControls","ClockKit","CoreBluetooth","ThreadNetwork","SensorKit","Security","Contacts","CarPlay","ExtensionFoundation","RealityKit","PhotosUI","RoomPlan","ReplayKit","IOSurface","SpriteKit","MobileCoreServices","IntentsUI","QuickLookThumbnailing","CoreMedia","BusinessChat","Intents","ColorSync","VideoSubscriberAccount","PencilKit","ManagedSettingsUI","CoreServices","HealthKit","MultipeerConnectivity","BackgroundAssets","WebKit","NotificationCenter","SystemConfiguration","GameController","CoreTelephony","ActivityKit","AVFAudio","AssetsLibrary","AudioUnit","FileProvider","DeviceActivity","Social","IdentityLookup","Matter","CoreImage","CoreAudio","MusicKit","DeviceDiscoveryExtension","MediaSetup","AutomatedDeviceEnrollment","CoreAudioKit","ExposureNotification","ClassKit","VisionKit","SwiftUI","Combine","ModelIO","PHASE","SharedWithYou","OpenGLES","MetalPerformanceShadersGraph","CreateMLComponents","Accounts","FileProviderUI","ShazamKit","CarKey","RealityFoundation","QuickLook","AppIntents","AuthenticationServices","WeatherKit","DataDetection","AudioToolbox","NearbyInteraction","ContactsUI","CoreSpotlight","LocalAuthentication","MatterSupport","Foundation","AdSupport","LocalAuthenticationEmbeddedUI","Accessibility","HealthKitUI","PushKit","Vision","CoreAudioTypes","NetworkExtension","ExtensionKit","OpenAL","EventKit","MediaAccessibility","Charts","iAd","MapKit","AppTrackingTransparency","CoreHaptics","CallKit","CoreFoundation","TabularData","CoreMotion","AVRouting","WidgetKit","AVKit","AddressBook","SoundAnalysis","GroupActivities","CoreLocation","CloudKit","SharedWithYouCore","CFNetwork","Photos","JavaScriptCore","GameplayKit","PushToTalk","CoreMIDI","Twitter","PassKit","ImageCaptureCore","CoreData","GLKit","AdServices","Messages","CryptoTokenKit","VideoToolbox","SafetyKit","UserNotifications","DeveloperToolsSupport","CoreTransferable","EventKitUI","SceneKit"]
11
-
12
- $podfile_thirdParty = 'PodfileThirdParty.yaml'
13
- $podfile_module = 'PodfileModule.yaml'
14
- $podfile_local = 'PodfileLocal.yaml'
15
- $podfile_lock = 'Podfile.lock'
16
-
17
-
18
- class PodDependency
19
- attr_reader :pod, :version, :git, :tag, :branch, :podspec, :configurations, :path, :inhibit_warnings, :source, :binary
20
- def initialize(module_name, pod, version, git, tag, branch, podspec, configurations, path, inhibit_warnings, source, binary)
21
- @module_name = module_name
22
- @pod = pod
23
- @version = version
24
- @git = git
25
- @tag = tag
26
- @branch = branch
27
- @podspec = podspec
28
- @configurations = configurations
29
- @path = path
30
- @inhibit_warnings = inhibit_warnings
31
- @source = source
32
- @binary = binary
33
- end
34
- end
35
-
36
- def PodfileDep.setup(targets)
37
-
38
- PodfileDep.checkFile()
39
- PodfileDep.checkParam(targets)
40
-
41
- PodfileDep.generateLocal()
42
- PodfileDep.generateModule($podfile_module, "企业内部组件", "TestPodName")
43
- PodfileDep.generateModule($podfile_thirdParty, "第三方组件", "Masonry")
44
-
45
- all_dependencies = {}
46
- PodfileDep.readYamlDep(all_dependencies, $podfile_thirdParty, false)
47
- PodfileDep.readYamlDep(all_dependencies, $podfile_module, false)
48
- PodfileDep.readYamlDep(all_dependencies, $podfile_local, true)
49
-
50
- PodfileDep.logDeps(all_dependencies)
51
-
52
- result = PodfileDep.generateTargetsDep(targets, all_dependencies)
53
-
54
- # 读取依赖
55
- lock_dependencies = PodfileDep.lockDeps()
56
- PodfileDep.logChangedDep(all_dependencies, lock_dependencies)
57
-
58
- return result
59
- end
60
-
61
- def PodfileDep.checkFile()
62
- unless File.exist?("Podfile") then
63
- puts "本脚本文件必须和Podfile文件同级目录"
64
- exit!
65
- end
66
- end
67
-
68
- def PodfileDep.checkParam(targets)
69
- msg = "❌ setup里参数需要填写target名字, 参数类型是字符串格式的数组。例如[\"test1\", \"test2\"]"
70
- unless targets.class == Array
71
- puts msg
72
- exit!
73
- end
74
-
75
- targets.each { |target|
76
- unless target.class == String
77
- puts msg
78
- exit!
79
- end
80
- }
81
- end
82
-
83
- def PodfileDep.lockDeps()
84
- result = {}
85
-
86
- unless File.exist?($podfile_lock)
87
- return result
88
- end
89
-
90
- dependencies_yaml = YAML.load_file($podfile_lock)
91
- if dependencies_yaml.key?('DEPENDENCIES')
92
- temp_dependencies = dependencies_yaml['DEPENDENCIES']
93
- temp_dependencies.each { |item|
94
- old_dependency = item.split(' (')
95
- result[old_dependency[0]] = old_dependency[1]
96
- }
97
- end
98
- return result
99
- end
100
-
101
- def PodfileDep.generateLocal()
102
- if File.exist?($podfile_local) then
103
- return
104
- end
105
- content = "
106
- # 1、本依赖配置文件优先级最高, 用来覆盖其他两个依赖的yaml文件中的组件。 尝试打开以下注释, 修改对应字段, 然后执行pod install
107
- # 2、PODS下边的配置是数组形式, 如果有多个就写多个
108
- # 3、请将本文件加入到忽略文件中
109
-
110
- PODS:
111
-
112
- # - module: Masonry
113
- # pod: Masonry
114
- # path: ~/CodePath
115
-
116
- "
117
- File.open($podfile_local, 'w') { |file|
118
- file.write(content)
119
- }
120
- end
121
-
122
- def PodfileDep.generateModule(yaml_module, prefix, pod_name)
123
- if File.exist?(yaml_module) then
124
- return
125
- end
126
-
127
- content = "
128
- # #{prefix}
129
- # 1、优先级:path > podspec > version > tag > branch (git字段是tag字段或branch字段不为空时用到, source字段是version不为空时用到, path字段就是直接从对应的路径读取依赖)
130
- # 2、为方便查看, 建议将本文件拖入壳工程引用
131
-
132
- # 如果 source = null && binary = false 则source默认使用这个
133
- SOURCE: 这里替换成源码的source
134
-
135
- # 如果 source = null && binary = true 则source默认使用这个
136
- BINARY_SOURCE: 这里替换成二进制的source
137
-
138
- PODS:
139
-
140
- # - module: #{pod_name}
141
- # pod: #{pod_name}
142
- # podspec: null
143
- # version: 1.1.0
144
- # git: null
145
- # tag: null
146
- # branch: null
147
- # configurations: null
148
- # inhibit_warnings: true
149
- # source: null
150
- # binary: true
151
- "
152
- File.open(yaml_module, 'w') { |file|
153
- file.write(content)
154
- }
155
- end
156
-
157
- def PodfileDep.readYamlDep(all_dependencies, yamlName, canCover)
158
- unless File.exist?(yamlName)
159
- puts "文件不存在:"+yamlName
160
- return
161
- end
162
-
163
- begin
164
- dependencies_yaml = YAML.load_file(yamlName)
165
- rescue Exception => e
166
- puts e
167
- puts yamlName+'文件解析异常, 请检查 ⬆️'
168
- exit!
169
- end
170
-
171
- prefix_message = "解析:"+yamlName + "=> "
172
- unless dependencies_yaml.class == Hash
173
- puts "#{prefix_message}共0个依赖(文件不是keyValue形式)"
174
- return
175
- end
176
-
177
- unless dependencies_yaml.key?('PODS')
178
- puts "#{prefix_message}共0个依赖(文件内的key[PODS]不存在)"
179
- return
180
- end
181
-
182
- unless dependencies_yaml['PODS'].class == Array
183
- puts "#{prefix_message}共0个依赖(文件配置的依赖PODS下边不是数组或数组为空)"
184
- return
185
- end
186
-
187
- # 读取默认源码source
188
- default_source = nil
189
- if dependencies_yaml.key?('SOURCE') and dependencies_yaml['SOURCE'].class == String
190
- default_source = dependencies_yaml['SOURCE']
191
- end
192
-
193
- # 读取默认二进制source
194
- default_binary_source = nil
195
- if dependencies_yaml.key?('BINARY_SOURCE') and dependencies_yaml['BINARY_SOURCE'].class == String
196
- default_binary_source = dependencies_yaml['BINARY_SOURCE']
197
- end
198
-
199
- dependencies = dependencies_yaml['PODS']
200
- puts "#{prefix_message}共"+dependencies.size.to_s + "个依赖"
201
-
202
- covers = []
203
- repeats = []
204
- # 遍历依赖库列表
205
- dependencies.each { |dependency|
206
-
207
- # 不能覆盖,有重复依赖
208
- if all_dependencies.key?(dependency['pod'])
209
- # 能被覆盖
210
- if canCover
211
- covers << dependency['pod']
212
- else
213
- repeats << dependency['pod']
214
- end
215
- end
216
-
217
- # 如果source不存在, 则使用默认的
218
- unless dependency['source']
219
- dependency['source'] = dependency['binary'] ? default_binary_source : default_source
220
- end
221
-
222
- # 校验
223
- if not dependency['path'] and not dependency['podspec'] and not dependency['source'] and dependency['version']
224
- puts '❌ 请为组件'+dependency['pod']+'配置source字段或在'+ yamlName+'顶层设置默认source(字段:SOURCE和BINARY_SOURCE)'
225
- exit!
226
- end
227
-
228
- # 警告
229
- if dependency['path'] and not canCover
230
- puts '⚠️ 组件'+dependency['pod']+'使用path依赖方式应该写在'+ $podfile_local
231
- end
232
-
233
- if dependency['podspec'] and not canCover
234
- puts '⚠️ 组件'+dependency['pod']+'使用podspec依赖方式应该写在'+ $podfile_local
235
- end
236
-
237
- # 生成依赖对象
238
- module_name = dependency['module']
239
- pod = dependency['pod']
240
- version = dependency['version']
241
- git = dependency['git']
242
- tag = dependency['tag']
243
- branch = dependency['branch']
244
- podspec = dependency['podspec']
245
- configurations = dependency['configurations']
246
- path = dependency['path']
247
- inhibit_warnings = dependency['inhibit_warnings'] ? dependency['inhibit_warnings'] : false
248
- source = dependency['source']
249
- binary = dependency['binary']
250
-
251
- unless pod then
252
- puts yamlName + ': pod 字段(pod组件名字)必须存在,请检查'
253
- exit!
254
- end
255
-
256
- unless path or podspec or version or git or tag or branch then
257
- puts yamlName + ': path/podspec/version/git/tag/branch 字段需至少有一个存在,请检查'
258
- exit!
259
- end
260
-
261
- pod_dependency = PodDependency.new(module_name, pod, version, git, tag, branch, podspec, configurations, path, inhibit_warnings, source, binary);
262
-
263
- # 加入全部的依赖map中
264
- all_dependencies[dependency['pod']] = pod_dependency
265
- }
266
-
267
- if covers.size > 0
268
- puts "✅ 被#{yamlName}中同名组件覆盖的组件如下:"
269
- puts covers
270
- end
271
-
272
- if repeats.size > 0
273
- puts "❌ 发现重复组件如下,请检查并删除重复依赖:"
274
- puts repeats
275
- exit!
276
- end
277
- end
278
-
279
- def PodfileDep.logDeps(all_dependencies)
280
- puts "\n➡️ 解析依赖总数共计:#{all_dependencies.size}个"
281
- puts '⬇️ 按照 Podfile 格式打印一遍'
282
- all_dependencies.each_value { |dependency|
283
-
284
- # 执行打印
285
- if dependency.path #路径引用
286
- puts_result = 'pod \'' + dependency.pod + '\''
287
- puts_result += ', :path => \'' + dependency.path + '\''
288
- if dependency.configurations
289
- puts_result += ', :configurations => [\'' + dependency.configurations.join('\', \'') + '\']'
290
- end
291
- if dependency.inhibit_warnings
292
- puts_result += ', :inhibit_warnings => true'
293
- end
294
- puts puts_result
295
- elsif dependency.podspec #podspec引用
296
- puts_result = 'pod \'' + dependency.pod + '\''
297
- if dependency.podspec
298
- puts_result += ', :podspec => \'' + dependency.podspec + '\''
299
- end
300
- if dependency.configurations
301
- puts_result += ', :configurations => [\'' + dependency.configurations.join('\', \'') + '\']'
302
- end
303
- if dependency.inhibit_warnings
304
- puts_result += ', :inhibit_warnings => true'
305
- end
306
- puts puts_result
307
- elsif dependency.version #版本号引用
308
- puts_result = 'pod \'' + dependency.pod + '\', \'' + dependency.version.to_s + '\''
309
- if dependency.configurations
310
- puts_result += ', :configurations => [\'' + dependency.configurations.join('\', \'') + '\']'
311
- end
312
- if dependency.inhibit_warnings
313
- puts_result += ', :inhibit_warnings => true'
314
- end
315
- if dependency.source
316
- puts_result += ', :source => \'' + dependency.source + '\''
317
- end
318
- puts puts_result
319
- elsif dependency.git #git仓库引用
320
- puts_result = 'pod \'' + dependency.pod + '\''
321
- if dependency.git
322
- puts_result += ', :git => \'' + dependency.git + '\''
323
- end
324
- if dependency.tag
325
- puts_result += ', :tag => \'' + dependency.tag + '\''
326
- elsif dependency.branch
327
- puts_result += ', :branch => \'' + dependency.branch + '\''
328
- end
329
- if dependency.configurations
330
- puts_result += ', :configurations => [\'' + dependency.configurations.join('\', \'') + '\']'
331
- end
332
- if dependency.inhibit_warnings
333
- puts_result += ', :inhibit_warnings => true'
334
- end
335
- puts puts_result
336
- else # 路径 版本号 git地址 podspec 均未指定 去指定的source中找(source不会为空)
337
- puts_result = 'pod \'' + dependency.pod + '\''
338
- if dependency.configurations
339
- puts_result += ', :configurations => [\'' + dependency.configurations.join('\', \'') + '\']'
340
- end
341
- if dependency.inhibit_warnings
342
- puts_result += ', :inhibit_warnings => true'
343
- end
344
- if dependency.source
345
- puts_result += ', :source => \'' + dependency.source + '\''
346
- end
347
- puts puts_result
348
- end
349
- }
350
- puts '⬆️ 打印完毕'
351
- end
352
-
353
- def PodfileDep.generateTargetsDep(targets, all_dependencies)
354
-
355
- tempArray = []
356
- all_dependencies.each_value { |value|
357
- tempArray << value
358
- }
359
-
360
- result = {}
361
- targets.each { |target|
362
- result[target] = tempArray
363
- }
364
- return result
365
- end
366
-
367
- def PodfileDep.logNewDependency(lock_dependencies, new_dependency)
368
- new_add = true
369
- lock_dependencies.each_key { |old_dependency|
370
- if old_dependency == new_dependency
371
- new_add = false
372
- break
373
- end
374
- }
375
-
376
- if new_add == true
377
- puts '🈶 新增依赖: ' + new_dependency
378
- end
379
- end
380
-
381
- def PodfileDep.logRemoveDependency(new_dependencies, old_dependency)
382
-
383
- old_remove = true
384
- new_dependencies.each { |new_dependency|
385
- if old_dependency == new_dependency
386
- old_remove = false
387
- break
388
- end
389
- }
390
-
391
- if old_remove == true
392
- puts '🈚️ 删除依赖: ' + old_dependency
393
- end
394
- end
395
-
396
- def PodfileDep.podfilePod()
397
- work_dir = FileUtils.pwd()
398
- podfile_path = work_dir + '/Podfile'
399
- res = Array.new()
400
- unless File.exist?(podfile_path) then
401
- return res
402
- end
403
- lineArr = IO.readlines(podfile_path)
404
- lineArr.each { |line|
405
- line = line.gsub(" ", "")
406
- if line.start_with?("pod\'")
407
- arr = line.split("\'")
408
- if arr.size>1 then
409
- res << arr[1]
410
- end
411
- end
412
- }
413
- return res
414
- end
415
-
416
- def PodfileDep.logChangedDep(all_dependencies, lock_dependencies)
417
- new_dependencies = PodfileDep.podfilePod()
418
-
419
- all_dependencies.each_key { |key|
420
- new_dependencies << key
421
- }
422
-
423
- new_dependencies.each { |item|
424
- PodfileDep.logNewDependency(lock_dependencies, item)
425
- }
426
-
427
- lock_dependencies.each_key { |old_dependency|
428
- PodfileDep.logRemoveDependency(new_dependencies, old_dependency)
429
- }
430
- end
431
-
432
- def PodfileDep.logIndirectDependencies()
433
-
434
- # 判断yaml文件是否存在
435
- unless File.exist?($podfile_lock)
436
- return
437
- end
438
-
439
- # 内容读取
440
- dependencies_lock = YAML.load_file($podfile_lock)
441
-
442
- dependencies = dependencies_lock['DEPENDENCIES']
443
- unless dependencies
444
- return
445
- end
446
-
447
- check_sums = dependencies_lock['SPEC CHECKSUMS']
448
- unless check_sums
449
- return
450
- end
451
-
452
- # 数组处理
453
- checkValues = dependencies.collect! {|item|
454
- item.split(' (')[0]
455
- }
456
- checkValues = dependencies.collect! {|item|
457
- item.split('/')[0]
458
- }
459
-
460
- puts ''
461
- check_sums.each{ |array|
462
- beCheckValue = array[0]
463
- unless checkValues.include?(beCheckValue)
464
- puts '↪️ 间接依赖: '+ beCheckValue
465
- end
466
- }
467
- end
468
-
469
- def PodfileDep.logUnusedDependencies()
470
-
471
- # 判断yaml文件是否存在
472
- unless File.exist?($podfile_lock)
473
- return
474
- end
475
-
476
- # 内容读取
477
- dependencies_lock = YAML.load_file($podfile_lock)
478
-
479
- dependencies = dependencies_lock['PODS']
480
- unless dependencies
481
- return
482
- end
483
-
484
- # 数组处理
485
- checkValues = Array.new
486
- allValues = Array.new
487
- dependencies.each {|item|
488
- if item.class == Hash then
489
- item.each { |key, value|
490
- item = key
491
- allValues.concat(value)
492
- }
493
- end
494
- item.split(' (')[0]
495
- checkValues << item
496
- }
497
-
498
- # 数组处理
499
- checkValues.collect! { |value|
500
- value.split(' (')[0]
501
- }
502
- allValues.collect! { |value|
503
- value.split(' (')[0]
504
- }
505
-
506
- # 处理有的只依赖了子仓库
507
- allValues1 = allValues + []
508
- allValues1.collect! { |value|
509
- value.split('/')[0]
510
- }
511
-
512
-
513
- # 壳工程中的文件 只查找main.m 因为有的文件可能没有使用到
514
- main_path = %x(find . -name "main.m")
515
- main_path = PathUtil.expandPath(main_path)
516
-
517
- checkValues.each { |item|
518
- if not allValues.include?(item) and not allValues1.include?(item)
519
- res = PodfileDep.checkUnuseInMain(item, main_path)
520
- if res
521
- puts "可能未使用的组件: " + item
522
- end
523
- end
524
- }
525
- end
526
-
527
- def PodfileDep.checkUnuseInMain(item, main_path)
528
- unless File.exist?(main_path)then
529
- return true
530
- end
531
- lineArr = IO.readlines(main_path)
532
- lineArr.each_with_index { |line, index|
533
- if line.start_with?("#import <#{item}")
534
- return false
535
- end
536
- }
537
-
538
- return true
539
- end
540
-
541
- end
542
-
543
- module ModuleCheck
544
- class ModuleItem
545
- attr_reader :moduleName, :modulePath
546
- def initialize(moduleName, modulePath)
547
- @moduleName = moduleName
548
- @modulePath = modulePath
549
- end
550
- end
551
-
552
- class ImportItem
553
- attr_reader :importName, :moduleItem, :fileName, :lineIndex, :pod
554
-
555
- def initialize(importName, moduleItem, fileName, lineIndex, pod)
556
- @importName = importName
557
- @moduleItem = moduleItem
558
- @fileName = fileName
559
- @lineIndex = lineIndex
560
- @pod = pod
561
- end
562
-
563
- end
564
-
565
- # 检查import规范
566
- def ModuleCheck.checkImport()
567
- puts "\nimport规范检查中..."
568
- start = (Time.now.to_f * 1000).to_i
569
-
570
- # podfile.lock的内容
571
- lockContent = YAML.load_file($podfile_lock)
572
-
573
- # 获取需要检查的模块名和路径
574
- modules = ModuleCheck.getCheckModules(lockContent)
575
-
576
- # podfile.lock里的所有组件依赖
577
- lock_dependencies = lockContent["PODS"]
578
-
579
- # 获取Pods和本地依赖库的 组件名和包含的头文件列表
580
- module_headers = ModuleCheck.getModuleHeaders(modules)
581
-
582
- # 白名单
583
- importWhiteList = ModuleCheck.getImportWhiteList()
584
-
585
- # 计数
586
- checkCount = 0
587
-
588
- # 遍历需要被检查的模块
589
- modules.each { |moduleItem|
590
-
591
- # 获取某个模块的podspec里写的依赖库和源码文件路径
592
- moduleInfo = ModuleCheck.getDepdencyInModule(moduleItem, lockContent, shouldGetDependencies = false)
593
- source_files_array = moduleInfo["source_files"]
594
-
595
-
596
- # 某个模块从代码文件里读取的双引号依赖库 #import "XX/XX.h"
597
- checkDirectory = false
598
- importItemMap = {}
599
- headerFileNames = [] #头文件的文件名
600
- source_files_array.each {|source_files|
601
- source_files_path = "#{moduleItem.modulePath}/#{source_files}"
602
- Dir[source_files_path].select{|filePath|
603
- headerFileName = File.basename(filePath)
604
- if headerFileName.end_with?(".h") or headerFileName.end_with?(".hpp") or headerFileName.end_with?(".pch")
605
- headerFileNames << headerFileName
606
- end
607
- ModuleCheck.updateImportDotItemMap(filePath, moduleItem, importItemMap)
608
- checkCount += 1
609
- if File.directory?(filePath)
610
- checkDirectory = true
611
- end
612
- }
613
- }
614
-
615
- # 检测到文件夹
616
- if checkDirectory
617
- # puts "⚠️ #{moduleItem.moduleName}解析到文件夹, 请检查s.source_files的写法(注意加文件后缀,例如*.{h,m})"
618
- end
619
-
620
- if importItemMap.size == 0 and headerFileNames.size == 0
621
- next
622
- end
623
-
624
- messages = []
625
- importItemMap.each {|key, value|
626
-
627
- # 当前仓库的文件已包含
628
- if headerFileNames.include?(key)
629
- next
630
- end
631
-
632
- # 白名单
633
- if importWhiteList.include?(value.importName)
634
- next
635
- end
636
-
637
- # 是否是导入的系统lib
638
- if ModuleCheck.checkNameInLig(key)
639
- next
640
- end
641
-
642
- moduleName = module_headers[value.pod]
643
- result = moduleName ? "#import <#{moduleName}/#{value.pod}>" : "<>形式导入"
644
- message = "#{value.fileName} 第#{value.lineIndex}行 #{value.importName} => #{result}"
645
- messages << message
646
-
647
- }
648
-
649
- if messages.size >0
650
- puts "⚠️ 组件#{moduleItem.moduleName}import存在以下情况, 请检查:"
651
- puts messages
652
- puts "\n"
653
- end
654
-
655
- }
656
-
657
- duration = ((Time.now.to_f * 1000).to_i - start)*0.001
658
- puts "import规范检查完毕! 共检查#{modules.size.to_s}个组件 #{checkCount}个文件 耗时:#{duration.round(2)}秒"
659
- end
660
-
661
-
662
- # 检查缺少的或着多的依赖
663
- def ModuleCheck.checkModuleDep()
664
- puts "\n依赖库检查中..."
665
- start = (Time.now.to_f * 1000).to_i
666
-
667
- # podfile.lock的内容
668
- lockContent = YAML.load_file($podfile_lock)
669
-
670
- # 获取需要检查的模块名和路径
671
- modules = ModuleCheck.getCheckModules(lockContent)
672
-
673
- # podfile.lock里的所有组件依赖
674
- lock_dependencies = lockContent["PODS"]
675
-
676
- # 获取所有已安装的依赖库
677
- installedDeps = ModuleCheck.getInstalledDeps(lockContent)
678
-
679
- # 计数
680
- checkCount = 0
681
-
682
- # 遍历需要被检查的模块
683
- modules.each { |moduleItem|
684
-
685
- # 获取某个模块的podspec里写的依赖库和源码文件路径
686
- moduleInfo = ModuleCheck.getDepdencyInModule(moduleItem, lockContent, shouldGetDependencies = true)
687
- dependencies = moduleInfo["dependencies"]
688
- source_files_array = moduleInfo["source_files"]
689
- podspec_dependencies = moduleInfo["podspec_dependencies"]
690
-
691
- # 某个模块从代码文件里读取的真实需要的依赖库 #import <XX/XX.h>
692
- checkDirectory = false
693
- importItemMap = {}
694
- source_files_array.each {|source_files|
695
- source_files_path = "#{moduleItem.modulePath}/#{source_files}"
696
- Dir[source_files_path].select{|filePath|
697
- ModuleCheck.updateImportItemMap(filePath, moduleItem, importItemMap)
698
- checkCount += 1
699
- if File.directory?(filePath)
700
- checkDirectory = true
701
- end
702
- }
703
- }
704
-
705
- # 检测到文件夹
706
- if checkDirectory
707
- puts "⚠️ #{moduleItem.moduleName}解析到文件夹, 请检查s.source_files的写法(注意加文件后缀,例如*.{h,m})"
708
- end
709
-
710
- if importItemMap.size == 0 and dependencies.size == 0
711
- next
712
- end
713
-
714
- loss = []
715
-
716
- # dependencies指的是根据组件podspec的写法 解析出来的依赖库
717
- # importItemMap指的是根据代码文件解析出来的依赖库
718
- importItemMap.each_key {|key|
719
- if installedDeps.include?(key) and key != moduleItem.moduleName
720
- didLoss = true
721
- dependencies.each { |dep|
722
- if dep.include?("/") #处理子仓库的形式
723
- didLoss = dep.start_with?(key) ? false : true
724
- else
725
- didLoss = dep == key ? false : true
726
- end
727
- if !didLoss #没有丢失 就结束
728
- break
729
- end
730
- }
731
-
732
- if didLoss
733
- loss << "s.dependency '#{key}'"
734
- end
735
-
736
- end
737
- }
738
-
739
- if loss.size >0
740
- puts "⚠️ [#{moduleItem.moduleName}] 请到#{moduleItem.moduleName}.podspec文件中添加缺少的依赖库, 如下:"
741
- puts loss
742
- puts "\n"
743
- end
744
-
745
- unuse = []
746
- dependencies.each {|dep|
747
- if not importItemMap.keys.include?(dep) and podspec_dependencies.include?(dep)
748
- unuse << "# s.dependency '#{dep}'"
749
- end
750
- }
751
- if unuse.size >0
752
- puts "⚠️ [#{moduleItem.moduleName}] 请到#{moduleItem.moduleName}.podspec文件中移除未使用的依赖库, 如下:"
753
- puts unuse
754
- puts "\n"
755
- end
756
- }
757
-
758
- duration = ((Time.now.to_f * 1000).to_i - start)*0.001
759
- puts "依赖库检查完毕! 共检查#{modules.size.to_s}个组件 #{checkCount}个文件 耗时:#{duration.round(2)}秒"
760
- end
761
-
762
- # 获取某个文件内对应类型的import "XXX.h"
763
- def ModuleCheck.updateImportDotItemMap(filePath, moduleItem, importItemMap)
764
- if File.directory?(filePath)
765
- return
766
- end
767
-
768
- resut = []
769
- lineArr = IO.readlines(filePath)
770
- lineArr.each_with_index { |line, index|
771
- unless line.start_with?("#import \"")
772
- next
773
- end
774
-
775
- lineSplitArr = line.split("\"")
776
- if lineSplitArr.size <= 1
777
- next
778
- end
779
-
780
- importName = "#{lineSplitArr[0]}\"#{lineSplitArr[1]}\"" # import "XXX.h" 或import "XXX.AAA.h" 防止后边有其他内容
781
-
782
- podFile = importName
783
- podFile = podFile.gsub("#import \"", "")
784
- podFile = podFile.gsub("\"", "") # 变成 XX.h
785
-
786
- # 已经包含
787
- if importItemMap[podFile]
788
- next
789
- end
790
-
791
- podFile_temp = podFile
792
- podFile_temp = podFile_temp.gsub(".h", "")
793
- podFile_temp = podFile_temp.gsub(".h", "") # 变成 XX
794
-
795
- fileName = File.basename(filePath)
796
- lineIndex = index+1
797
-
798
- importItemMap[podFile] = ImportItem.new(importName, moduleItem, fileName, lineIndex, podFile)
799
-
800
- }
801
- end
802
-
803
- # 获取某个文件内对应类型的import <XX/XX>
804
- def ModuleCheck.updateImportItemMap(filePath, moduleItem, importItemMap)
805
- if File.directory?(filePath)
806
- return
807
- end
808
-
809
- resut = []
810
- lineArr = IO.readlines(filePath)
811
- lineArr.each_with_index { |line, index|
812
- unless line.start_with?("#import <")
813
- next
814
- end
815
-
816
- lineSplitArr = line.split(">")
817
- if lineSplitArr.size == 0
818
- next
819
- end
820
-
821
- importName = lineSplitArr[0]+">" # #import <XX/XX.h> 或者 #import <XX.h> 防止后边有其他的内容
822
- importArr = importName.split("/")
823
- if lineSplitArr.size == 0
824
- next
825
- end
826
-
827
- pod = importArr[0].gsub("#import <", "")
828
- pod = pod.gsub(".h>", "")
829
- pod = pod.gsub(".H>", "")
830
-
831
- # 已经包含
832
- if importItemMap[pod]
833
- next
834
- end
835
-
836
- # 系统级依赖库
837
- systemDeps = ModuleCheck.systemDeps()
838
- if systemDeps.include?(pod)
839
- next
840
- end
841
-
842
- fileName = File.basename(filePath)
843
- lineIndex = index+1
844
-
845
- importItemMap[pod] = ImportItem.new(importName, moduleItem, fileName, lineIndex, pod)
846
-
847
- }
848
- end
849
-
850
- # 获取Pods和本地依赖库的 组件名和包含的头文件列表
851
- def ModuleCheck.getModuleHeaders(modules)
852
- resMap = {}
853
-
854
- # Pods文件夹下的
855
- pods_dir = FileUtils.pwd() + "/Pods"
856
- Dir.foreach(pods_dir) { |dirName|
857
- if dirName.include?(".") or dirName == "Target Support Files" or dirName == "Local Podspecs" or dirName == "Headers"
858
- next
859
- end
860
-
861
- moduleName = File.basename(dirName)
862
- modulePath = pods_dir + "/" + moduleName
863
-
864
- res = ModuleCheck.getModuleOnHeader(modulePath, moduleName)
865
- res.each {|key, value|
866
- resMap[key] = value
867
- }
868
- }
869
-
870
- # 本地路径下的
871
- modules.each { |moduleItem|
872
- res = ModuleCheck.getModuleOnHeader(moduleItem.modulePath, moduleItem.moduleName)
873
- res.each {|key, value|
874
- resMap[key] = value
875
- }
876
- }
877
-
878
- return resMap
879
- end
880
-
881
- # 找出某个路径下所有的.h .hpp文件
882
- def ModuleCheck.getModuleOnHeader(path, moduleName)
883
- res = {}
884
- path = path + +"/**/*.{h,hpp}"
885
- fineNameArray = []
886
- Dir[path].select{|filePath|
887
- res[File.basename(filePath)] = moduleName
888
- }
889
-
890
- return res
891
- end
892
-
893
- # 系统级的依赖库
894
- def ModuleCheck.checkNameInLig(name)
895
- name = name.gsub(".h", "")
896
- return $libLibarys.include?(name)
897
- end
898
-
899
- # 系统级的依赖库
900
- def ModuleCheck.systemDeps()
901
- return $libLibarys + $frameworks
902
- end
903
-
904
- # 获取已安装的依赖库
905
- def ModuleCheck.getInstalledDeps(lock_dependencies)
906
- installedDeps = lock_dependencies["SPEC CHECKSUMS"] ? lock_dependencies["SPEC CHECKSUMS"].keys : {}
907
- return installedDeps
908
- end
909
-
910
- # 获取某个库的所有依赖和源码文件路径
911
- def ModuleCheck.getDepdencyInModule(moduleItem, lockContent, shouldGetDependencies)
912
-
913
- podspecName = "#{moduleItem.moduleName}.podspec"
914
- podspecPath = File.expand_path("#{moduleItem.modulePath}/#{podspecName}")
915
-
916
- podspecJsonName = "#{podspecName}.json"
917
- podspecJsonPath = File.expand_path("#{moduleItem.modulePath}/#{podspecJsonName}")
918
-
919
- podspec_content = nil
920
-
921
- if File.exist?(podspecJsonPath)
922
- json = File.read(podspecJsonPath)
923
- podspec_content = JSON.parse(json)
924
- elsif File.exist?(podspecPath)
925
- json = ModuleCheck.getPodspecContent(podspecPath)
926
- podspec_content = JSON.parse(json)
927
- end
928
-
929
- source_files = []
930
- if podspec_content["subspecs"]
931
- subspecs = podspec_content["subspecs"]
932
- subspecs.each {|subspec|
933
- subModuleName = "#{moduleItem.moduleName}/#{subspec["name"]}"
934
- subModuleIsUse = ModuleCheck.getSubModuleIsUse(subModuleName, lockContent)
935
- # puts "#{subModuleName}是否被依赖#{subModuleIsUse.to_s}"
936
- subspecs_source_files = subspec["source_files"]
937
- if subModuleIsUse and subspecs_source_files
938
- source_files << subspecs_source_files
939
- end
940
- }
941
- end
942
- if podspec_content["source_files"]
943
- source_files << podspec_content["source_files"]
944
- end
945
-
946
- # puts "source_files: #{source_files}"
947
-
948
- podspec_dependencies = podspec_content["dependencies"] ? podspec_content["dependencies"].keys : {}
949
- dependencies = Array.new
950
-
951
- if shouldGetDependencies #耗时操作 依赖库越多越耗时
952
- lock_dependencies = lockContent["PODS"]
953
- ModuleCheck.getDep(lock_dependencies, moduleItem.moduleName, dependencies) #此处依赖库越多 越是耗时操作
954
- end
955
-
956
- return {"dependencies" => dependencies, "source_files" => source_files, "podspec_dependencies" => podspec_dependencies}
957
- end
958
-
959
- # 根据podspec路径把podspec转为json
960
- def ModuleCheck.getPodspecContent(podspecPath)
961
-
962
- spec_contents = File.open(podspecPath, 'r:utf-8', &:read)
963
- if spec_contents.respond_to?(:encoding) && spec_contents.encoding.name != 'UTF-8'
964
- spec_contents.encode!('UTF-8')
965
- end
966
-
967
- path = Pathname.new(podspecPath)
968
-
969
- spec = nil
970
- Dir.chdir(path.parent.directory? ? path.parent : Dir.pwd) do
971
- spec = ::Pod._eval_podspec(spec_contents, path)
972
- end
973
- return spec.to_json
974
- end
975
-
976
- # 根据podflie.lock里内容递归获取某个库的依赖库
977
- def ModuleCheck.getDep(dependencies, pod_name, allDeps)
978
-
979
- dependencies.each { |item|
980
- unless item.class == Hash then
981
- next
982
- end
983
-
984
- item.each {|key, value|
985
- item = key.split(" (")[0]
986
- item = item.split("/")[0] #解决子仓库的问题
987
- if item == pod_name then
988
- value.each { |dep|
989
- dep = dep.split(" (")[0]
990
-
991
- if pod_name != dep and not allDeps.include? (dep) then
992
- allDeps << dep
993
- end
994
- ModuleCheck.getDep(dependencies, dep, allDeps)
995
- }
996
- end
997
- }
998
- }
999
- return allDeps
1000
- end
1001
-
1002
- # 获取子模块是否被依赖, 子模块格式 XXX/AAA
1003
- def ModuleCheck.getSubModuleIsUse(subModuleName, lockContent)
1004
- use = false
1005
- dependencies = lockContent['PODS']
1006
-
1007
- dependencies.each { |item|
1008
- dependency = item
1009
- if item.class == Hash and item.keys.size > 0
1010
- dependency = item.keys[0]
1011
- end
1012
-
1013
- if not dependency.include?("/")
1014
- next
1015
- end
1016
- if dependency.start_with?(subModuleName)
1017
- use = true
1018
- end
1019
- }
1020
-
1021
- return use
1022
- end
1023
-
1024
- # 获取podfile.lock里所有的本地依赖
1025
- def ModuleCheck.getCheckModules(lockContent)
1026
- result = []
1027
- local_dependencies = lockContent['EXTERNAL SOURCES']
1028
- unless local_dependencies then
1029
- return result
1030
- end
1031
-
1032
- local_dependencies.each { |item|
1033
- if item.size >=2
1034
- moduleName = item[0]
1035
- modulePath = item[1]
1036
- item[1].each_value {|obj|
1037
- modulePath = obj
1038
- break
1039
- }
1040
- modulePath = File.expand_path(modulePath)
1041
- result << ModuleItem.new(moduleName, modulePath)
1042
- end
1043
- }
1044
- return result
1045
- end
1046
-
1047
- # 获取 白名单检查的import
1048
- def ModuleCheck.getImportWhiteList()
1049
- whiteListName = "importCheckWhite.txt"
1050
-
1051
- unless File.exist?(whiteListName) then
1052
- ModuleCheck.generateWhiteImportList(whiteListName)
1053
- puts "\n⛔️⛔️⛔️ import规范检查白名单文件: #{whiteListName}"
1054
- return []
1055
- end
1056
-
1057
- array = []
1058
- lineArr = IO.readlines(whiteListName)
1059
- lineArr.each { |line|
1060
- unless line.start_with?("#import \"")
1061
- next
1062
- end
1063
- array << line.gsub("\n","")
1064
- }
1065
- return array
1066
- end
1067
-
1068
- def ModuleCheck.generateWhiteImportList(whiteListName)
1069
-
1070
- content = "import不规范检查, 这里配置白名单, 每个一行(加入白名单的不会被检查是否规范)。 示例
1071
- #import \"libxx.h\"
1072
- #import \"libxxx.h\"
1073
- -----------请在下边按示例加白名单---------
1074
- "
1075
- File.open(whiteListName, 'w') { |file|
1076
- file.write(content)
1077
- }
1078
- end
1079
-
1080
- # 读取podfile.lock内功
1081
- def ModuleCheck.getPodfileLock()
1082
- YAML.load_file($podfile_lock)
1083
- end
1084
- end
1085
-
1086
- module ImportCheck
1087
- class Module
1088
- attr_reader :moduleName, :modulePath, :fileNameArray, :filePathArray
1089
- def initialize(moduleName, modulePath, fileNameArray, filePathArray)
1090
- @moduleName = moduleName
1091
- @modulePath = modulePath
1092
- @fileNameArray = fileNameArray
1093
- @filePathArray = filePathArray
1094
- end
1095
- end
1096
-
1097
- class Import
1098
- attr_reader :content, :importName, :moduleItem, :fileName, :lineIndex, :pod
1099
- def initialize(content, importName, moduleItem, fileName, lineIndex, pod)
1100
- @content = content
1101
- @importName = importName
1102
- @moduleItem = moduleItem
1103
- @fileName = fileName
1104
- @lineIndex = lineIndex
1105
- @pod = pod
1106
- end
1107
- def setPod=(pod)
1108
- @pod = pod
1109
- end
1110
- end
1111
-
1112
-
1113
-
1114
- def ImportCheck.check()
1115
- puts "import规范检查中..."
1116
- start = (Time.now.to_f * 1000).to_i
1117
-
1118
- # 需要检查的模块
1119
- checkModules = []
1120
- ImportCheck.findCheckModules(checkModules, $podfile_module)
1121
- ImportCheck.findCheckModules(checkModules, $podfile_local)
1122
-
1123
- # 白名单
1124
- whiteListName = "importCheckWhite.txt"
1125
- whiteList = ImportCheck.WhiteList(whiteListName)
1126
-
1127
- # 有问题的import
1128
- badImportArray = []
1129
-
1130
- # 计数
1131
- checkCount = 0
1132
- checkModules.each { |moduleItem|
1133
- modulePath = moduleItem.modulePath
1134
-
1135
- # 需要检查的文件
1136
- filePathArray = []
1137
- fileNameArray = []
1138
- ImportCheck.findCodeFile(modulePath, filePathArray, fileNameArray, false)
1139
-
1140
- filePathArray.each { |filePath|
1141
- ImportCheck.findBadQuoteImport(filePath, fileNameArray, badImportArray, moduleItem, whiteList)
1142
- }
1143
- checkCount += fileNameArray.size
1144
- }
1145
-
1146
- allModuleArray = ImportCheck.findModules()
1147
- allModuleArray = allModuleArray + checkModules
1148
-
1149
- tiplog = false
1150
- badImportArray.collect { |import|
1151
- moduleName = ImportCheck.findPodModule(allModuleArray, import.importName)
1152
- import.setPod = moduleName
1153
- result = moduleName ? "#import <#{moduleName}/#{import.importName}>" : "<>形式导入"
1154
- puts "⚠️ <#{import.moduleItem.moduleName}> #{import.fileName} #{import.lineIndex}行 #{import.content} => #{result}"
1155
- tiplog = true
1156
- }
1157
-
1158
- # 生成白名单文件
1159
- ImportCheck.generateWhite(whiteListName)
1160
-
1161
- if tiplog then
1162
- puts "\nimport规范检查白名单文件: #{whiteListName}"
1163
- end
1164
-
1165
- duration = ((Time.now.to_f * 1000).to_i - start)*0.001
1166
- puts "import规范检查完毕! 共检查#{checkModules.size.to_s}个组件 #{checkCount}个文件 耗时:#{duration.round(2)}秒"
1167
- end
1168
-
1169
- def ImportCheck.WhiteList(whiteListName)
1170
- unless File.exist?(whiteListName) then
1171
- return []
1172
- end
1173
-
1174
- array = []
1175
- lineArr = IO.readlines(whiteListName)
1176
- lineArr.each { |line|
1177
- unless line.start_with?("#import \"")
1178
- next
1179
- end
1180
- array << line
1181
- }
1182
- return array
1183
- end
1184
-
1185
- def ImportCheck.generateWhite(whiteListName)
1186
- if File.exist?(whiteListName) then
1187
- return
1188
- end
1189
-
1190
- content = "import不规范检查, 这里配置白名单, 每个一行(加入白名单的不会被检查是否规范)。 示例
1191
- #import \"libxx.h\"
1192
- #import \"libxxx.h\"
1193
- -----------请在下边按示例加白名单---------
1194
- "
1195
- File.open(whiteListName, 'w') { |file|
1196
- file.write(content)
1197
- }
1198
- end
1199
-
1200
- def ImportCheck.findPodModule(moduleArray, importName)
1201
- moduleArray.each { |item|
1202
- item.fileNameArray.each { |fileName|
1203
- if fileName == importName
1204
- return item.moduleName
1205
- end
1206
- }
1207
- }
1208
- return nil
1209
- end
1210
-
1211
- def ImportCheck.findModules()
1212
- pods_dir = FileUtils.pwd() + "/Pods"
1213
-
1214
- moduleArray = []
1215
-
1216
- Dir.foreach(pods_dir) { |moduleName|
1217
- if moduleName.include?(".") or moduleName == "Target Support Files" or moduleName == "Local Podspecs" or moduleName == "Headers"
1218
- next
1219
- end
1220
- modulePath = pods_dir + "/" + moduleName
1221
- filePathArray = []
1222
- fileNameArray = []
1223
- ImportCheck.findCodeFile(modulePath, filePathArray, fileNameArray, true)
1224
- moduleArray << Module.new(moduleName, modulePath, fileNameArray, filePathArray)
1225
- }
1226
-
1227
- return moduleArray
1228
- end
1229
-
1230
- # 根据路径获取所有的代码文件
1231
- def ImportCheck.findCodeFile(des_path, filePathArray, fileNameArray, onlyDotH)
1232
-
1233
- if not File.directory?(des_path)
1234
- puts "非文件夹, 请检查: #{des_path}"
1235
- return
1236
- end
1237
-
1238
- Dir.foreach(des_path) { |fileName|
1239
- sub_path = des_path + "/" + fileName
1240
- if fileName.start_with?(".")
1241
- next
1242
- end
1243
- if File.directory?(sub_path)
1244
- ImportCheck.findCodeFile(sub_path, filePathArray, fileNameArray, onlyDotH)
1245
- else
1246
-
1247
- onlyDotHCheck = (fileName.end_with?(".h") or fileName.end_with?(".pch"))
1248
- notOnlyDotHCheck = (fileName.end_with?(".h") or
1249
- fileName.end_with?(".m") or
1250
- fileName.end_with?(".pch") or
1251
- fileName.end_with?(".mm") or
1252
- fileName.end_with?(".hpp") or
1253
- fileName.end_with?(".cpp") or
1254
- fileName.end_with?(".c") or
1255
- fileName.end_with?(".cc"))
1256
- isCodeFile = onlyDotH ? onlyDotHCheck : notOnlyDotHCheck
1257
- if isCodeFile
1258
- filePath = des_path + "/" + fileName
1259
- filePathArray << filePath
1260
- fileNameArray << fileName
1261
- end
1262
- end
1263
- }
1264
- end
1265
-
1266
- # 查找不在当前模块内的 #import "xx"
1267
- def ImportCheck.findBadQuoteImport(filePath, fileNameArray, badImportArray, moduleItem, whiteList)
1268
- lineArr = IO.readlines(filePath)
1269
- lineArr.each_with_index { |line, index|
1270
- unless line.start_with?("#import \"")
1271
- next
1272
- end
1273
-
1274
- lineSplitArr = line.split("\"")
1275
- if lineSplitArr.size < 2
1276
- next
1277
- end
1278
-
1279
- content = line.gsub("\n", "")
1280
- importName = lineSplitArr.size >=2 ? lineSplitArr[1].gsub("\n", "") : content
1281
-
1282
- if ImportCheck.importInWihte(importName, whiteList)
1283
- next
1284
- end
1285
-
1286
- if fileNameArray.include?(importName)
1287
- next
1288
- end
1289
-
1290
- fileName = File.basename(filePath)
1291
- lineIndex = index+1
1292
- pod = nil
1293
-
1294
- badImportArray << Import.new(content, importName, moduleItem, fileName, lineIndex, pod)
1295
- }
1296
- end
1297
-
1298
- def ImportCheck.importInWihte(importName, whiteList)
1299
- whiteList.each {|whiteItem|
1300
- if whiteItem.include?(importName)
1301
- return true
1302
- end
1303
- }
1304
- return false
1305
- end
1306
-
1307
- def ImportCheck.findCheckModules(checkModules, yaml_module)
1308
-
1309
- unless File.exist?(yaml_module)
1310
- return
1311
- end
1312
-
1313
- # 内容读取
1314
- dependencies_local = YAML.load_file(yaml_module)
1315
-
1316
- unless dependencies_local.class == Hash
1317
- return
1318
- end
1319
-
1320
- dependencies = dependencies_local['PODS']
1321
- unless dependencies
1322
- return
1323
- end
1324
-
1325
- dependencies.each { |dependency|
1326
- dependencyPath = dependency["path"]
1327
- if dependencyPath and dependencyPath != "null" and dependencyPath.gsub(" ", "").length>0 then
1328
- moduleName = dependency["pod"]
1329
- modulePath = PathUtil.expandPath(dependencyPath)
1330
- fileNameArray = []
1331
- filePathArray = []
1332
- ImportCheck.findCodeFile(modulePath, filePathArray, fileNameArray, true)
1333
- checkModules << Module.new(moduleName, modulePath, fileNameArray, filePathArray)
1334
- end
1335
- }
1336
-
1337
- end
1338
-
1339
- end
1340
-
1341
- class PathUtil
1342
-
1343
- def PathUtil.expandPath(des_path)
1344
- return File.expand_path(des_path).gsub("\n", "")
1345
- end
1346
-
1347
- def PathUtil.replaceStr(file_path, findstr, replacestr)
1348
- unless File.exist?(file_path)
1349
- return
1350
- end
1351
-
1352
- FileUtils.chmod("+w", file_path)
1353
- text = File.read(file_path)
1354
- replace = text.gsub(findstr, replacestr)
1355
- if text != replace
1356
- File.open(file_path, "w") { |file| file.puts replace }
1357
- STDOUT.flush
1358
- file_name = File.basename(file_path)
1359
- puts "代码替换: #{file_name} (#{findstr} => #{replacestr})"
1360
- end
1361
- end
1362
-
1363
- end
1364
-
1365
- module SpecialDeal
1366
- def SpecialDeal.FBRetainCycleDetector()
1367
- PathUtil.replaceStr("Pods/FBRetainCycleDetector/FBRetainCycleDetector/Layout/Classes/FBClassStrongLayout.mm", "layoutCache[currentClass] = ivars;", "layoutCache[(id<NSCopying>)currentClass] = ivars;")
1368
- PathUtil.replaceStr("Pods/FBRetainCycleDetector/fishhook/fishhook.c", "indirect_symbol_bindings[i] = cur->rebindings[j].replacement;", "if(i < (sizeof(indirect_symbol_bindings) /sizeof(indirect_symbol_bindings[0]))) {indirect_symbol_bindings[i]=cur->rebindings[j].replacement;}")
1369
-
1370
- newStr = "#import <objc/runtime.h>
1371
- #import <malloc/malloc.h>"
1372
- PathUtil.replaceStr("Pods/FBRetainCycleDetector/FBRetainCycleDetector/Graph/FBObjectiveCGraphElement.mm", "#import <objc/runtime.h>", newStr)
1373
-
1374
- newStr = "malloc_zone_t *zone = malloc_zone_from_ptr((__bridge void *)object); if (zone) { Class aCls=object_getClass(object);"
1375
- PathUtil.replaceStr("Pods/FBRetainCycleDetector/FBRetainCycleDetector/Graph/FBObjectiveCGraphElement.mm", "Class aCls = object_getClass(object);", newStr)
1376
-
1377
- newStr = "}
1378
- # endif"
1379
- PathUtil.replaceStr("Pods/FBRetainCycleDetector/FBRetainCycleDetector/Graph/FBObjectiveCGraphElement.mm", "#endif", newStr)
1380
-
1381
- end
1382
-
1383
- def SpecialDeal.test
1384
- res = CheckDep::Dep.check
1385
- puts res
1386
-
1387
- path = "/Users/wangshuaipeng/BSCode/podfileDepDemo/Pods/Pods.xcodeproj"
1388
- project = Xcodeproj::Project.open(path)
1389
- project.groups.each { |group|
1390
- if group.name != "Development Pods"
1391
- next
1392
- end
1393
- group.children.each {|child|
1394
- puts child.children
1395
- }
1396
- }
1397
- end
1398
-
1399
- end
1400
-
1401
- END {
1402
- # SpecialDeal.test
1403
- # SpecialDeal.FBRetainCycleDetector()
1404
- # ModuleCheck.checkModuleDep()
1405
- ModuleCheck.checkImport()
1406
- # PodfileDep.logIndirectDependencies()
1407
- # PodfileDep.logUnusedDependencies()
1408
- }