podfileDep 2.3.0 → 2.3.1
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 +4 -4
- data/CHANGELOG.md +3 -1
- data/lib/podfileDep/version.rb +1 -1
- data/lib/podfileDep.rb +2 -0
- metadata +1 -3
- data/lib/old/podfileDep.rb +0 -1408
- data/lib/podfileDep/reference/uninstall.rb +0 -129
data/lib/old/podfileDep.rb
DELETED
@@ -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
|
-
}
|