podfileDep 2.3.6 → 2.4.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,143 +1,10 @@
1
1
  require 'pathname'
2
2
  require 'colored2'
3
+ require_relative 'util'
4
+ require_relative 'item'
3
5
 
4
6
  module Xcodeproj
5
7
 
6
- class ImportItem
7
- attr_accessor :import_name
8
- attr_accessor :module_name
9
- attr_accessor :file_path
10
- attr_accessor :import_file_name
11
- attr_accessor :line_index
12
- def initialize
13
- @import_name = nil
14
- @module_name = nil
15
- @file_path = nil
16
- @import_file_name = nil
17
- @line_index = nil
18
- end
19
-
20
- end
21
-
22
- class ModuleItem
23
-
24
- public
25
- # 组名名
26
- attr_accessor :module_name
27
-
28
- # 组件路径
29
- attr_accessor :module_path
30
-
31
- # podspec路径
32
- attr_accessor :podspec_path
33
-
34
- # 组件目录的所有被引用的文件数组
35
- attr_accessor :header_files
36
-
37
- # 组件目录的所有被引用的文件数组
38
- attr_accessor :source_files
39
-
40
- # 是否是开发模块
41
- attr_reader :is_development_module
42
-
43
- # [Hash{String => ImportItem}]
44
- attr_accessor :import_items
45
-
46
- def initialize(module_name)
47
- @module_name = module_name
48
- @module_path = nil
49
- @podspec_path = nil
50
- @header_files = {}
51
- @source_files = {}
52
- @import_items = []
53
- end
54
-
55
- # 是否是开发模块
56
- # @return bool
57
- def is_development_module
58
- !!(podspec_path)
59
- end
60
-
61
- # 生成 import "XXX.h"的信息
62
- def init_import_info
63
- source_files.each_value do |source_file_path|
64
- if File.directory?(source_file_path)
65
- next
66
- end
67
-
68
- line_array = IO.readlines(source_file_path)
69
- line_array.each_with_index { |line, line_index|
70
- line = line.gsub(" ", "")
71
-
72
- unless line.start_with?("#import")
73
- next
74
- end
75
-
76
- if line.start_with?("@implementation")
77
- break
78
- end
79
-
80
- # 前一行的内容
81
- pre_index = line_index-1 < 0 ? 0 : line_index-1
82
- pre_line = line_array[pre_index]
83
-
84
- if line.start_with?("#import\"") #本组件
85
- import_item = own_module_import(line, source_file_path, line_index, @module_name, pre_line)
86
- if import_item
87
- import_items << import_item
88
- end
89
- elsif line.start_with?("#import<") #其他组件
90
-
91
- end
92
-
93
- }
94
- end
95
-
96
- import_items
97
- end
98
-
99
- private
100
- # 生成自己模块的import item
101
- # @param line 以 import" 开头
102
- def own_module_import(line, file_path, line_index, module_name, pre_line)
103
- line_split_array = line.split("\"")
104
- if line_split_array.size <= 1
105
- return nil
106
- end
107
-
108
- import_content = "#{line_split_array[0]}\"#{line_split_array[1]}\"" # import"XXX.h" 或import"XXX.AAA.h" 防止后边有其他内容
109
-
110
- # 特殊处理
111
- if import_content == "#import\"NBSAppAgent.h\""
112
- return nil
113
- end
114
-
115
- pre_line = pre_line.gsub(" ", "").gsub("\n", "")
116
- if pre_line.start_with?("#if") or pre_line == "#else"
117
- return nil
118
- end
119
-
120
- import_file_name = import_content
121
- import_file_name = import_file_name.gsub("#import\"", "")
122
- import_file_name = import_file_name.gsub("\"", "") # 变成 XX.h
123
-
124
-
125
- import_item = ImportItem.new # (import_name, module_name, file_name, line_index, podfile)
126
- import_item.import_name = import_content.gsub("#import\"", "#import \"")
127
- import_item.module_name = module_name
128
- import_item.file_path = file_path
129
- import_item.import_file_name = import_file_name
130
- import_item.line_index = line_index + 1
131
-
132
- import_item
133
- end
134
-
135
-
136
- def other_module_import(line)
137
-
138
- end
139
- end
140
-
141
8
  class XCodeProject
142
9
 
143
10
  # 壳工程xcodeproj对象
@@ -151,6 +18,8 @@ module Xcodeproj
151
18
  # @return [Hash{String => ModuleItem}]
152
19
  attr_accessor :module_items
153
20
 
21
+ # @return [Hash]
22
+ attr_accessor :lock_content
154
23
 
155
24
  def initialize
156
25
  @shell_project = nil
@@ -158,9 +27,12 @@ module Xcodeproj
158
27
  @module_items = {}
159
28
  init_shell_project
160
29
  init_pod_project
30
+ init_lockfile
161
31
  expand_module
32
+ init_vendor_frameworks
162
33
  end
163
34
 
35
+ @private
164
36
  def init_shell_project
165
37
  xcodeproj_file = nil
166
38
  Dir.foreach(Dir.pwd) do |file|
@@ -187,6 +59,16 @@ module Xcodeproj
187
59
  @pod_project = Xcodeproj::Project.open(xcodeproj_path)
188
60
  end
189
61
 
62
+ def init_lockfile
63
+ lockfile_path = MyConstants::PODFILE_LOCK
64
+
65
+ unless File.exist?(lockfile_path)
66
+ return
67
+ end
68
+
69
+ @lock_content = YAML.load_file(lockfile_path)
70
+ end
71
+
190
72
  # 展开模块
191
73
  def expand_module
192
74
  self.expand_with_module(pod_project.main_group, nil)
@@ -208,6 +90,7 @@ module Xcodeproj
208
90
  source_file_item = @module_items[module_name]
209
91
  if module_name and not source_file_item
210
92
  source_file_item = ModuleItem.new(module_name)
93
+ source_file_item.podspec_path = get_podspec_path(module_name)
211
94
  @module_items[module_name] = source_file_item
212
95
  end
213
96
 
@@ -251,6 +134,7 @@ module Xcodeproj
251
134
  extend_name = child.real_path.basename.extname
252
135
  if extend_name == ".podspec" or extend_name == ".podspec.json"
253
136
  source_file_item.podspec_path = child.real_path
137
+ source_file_item.is_development_module = true
254
138
  elsif source_file_extension.include?(extend_name)
255
139
  source_file_item.source_files[child.real_path.basename.to_s] = child.real_path
256
140
  if header_file_extension.include?(extend_name)
@@ -267,65 +151,94 @@ module Xcodeproj
267
151
 
268
152
  end
269
153
 
270
- # 检查import规范
271
- def check_import
272
- puts "import检查中..."
273
- start = (Time.now.to_f * 1000).to_i
274
- module_count = 0
275
- file_count = 0
154
+ # 读取某个模块的podspec路径
155
+ def get_podspec_path(module_name)
156
+ lock_content = @lock_content
157
+ local_spec = lock_content["EXTERNAL SOURCES"]
158
+ if local_spec and local_spec[module_name]
159
+ path = local_spec[module_name][:path]
160
+ return Pathname(path).expand_path
161
+ end
162
+
163
+ remote_dependencies = lock_content["DEPENDENCIES"]
164
+ version_map = {}
165
+ remote_dependencies.each do |dependency|
166
+ temp = dependency.split("(")
167
+ name = temp[0].split("/")[0] # UMCShare/Social/ReducedWeChat
168
+ name = name.gsub(" ", "").gsub(")", "")
169
+ version = temp[1].gsub("= ", "").gsub(")", "")
170
+ version_map[name] = version
171
+ end
172
+ version = version_map[module_name]
276
173
 
277
- module_items.each do |module_name, module_item|
278
- unless module_item.is_development_module
279
- next
280
- end
281
- module_count += 1
174
+ remote_spec = lock_content["SPEC CHECKSUMS"]
175
+ md5_to5 = ""
176
+ if remote_spec and remote_spec[module_name]
177
+ md5 = remote_spec[module_name]
178
+ md5_to5 = md5.slice(0,5)
179
+ end
180
+ # 4.0.1-24ee2.podspec.json
181
+ podspec_json_name = "#{version}-#{md5_to5}.podspec.json"
182
+ path = "~/Library/Caches/CocoaPods/Pods/Specs/Release/#{module_name}/#{podspec_json_name}"
183
+ Pathname(path).expand_path
184
+ end
282
185
 
283
- messages = []
284
186
 
285
- did_check_imports = {}
286
- module_item.init_import_info
187
+ # 初始化模块的vendor_frameworks
188
+ def init_vendor_frameworks
189
+ @module_items.each_value do |module_item|
190
+ module_item.frameworks << module_item.module_name
191
+ podspec_content = Util.get_podspec_content(module_item.podspec_path)
287
192
 
288
- module_item.import_items.each do |import_item|
289
- file_count += 1
290
- did_check_import = did_check_imports[import_item.import_file_name]
291
- if did_check_import
292
- next
293
- end
294
- need_module_item = module_items[import_item.module_name]
295
- real_path = need_module_item.header_files[import_item.import_file_name]
296
- did_check_imports[import_item.import_file_name] = !!(real_path)
297
- unless real_path
298
- # 去查找所属模块
299
- expect_module_name = find_module_with_header_file(import_item.import_file_name)
300
- if expect_module_name
301
- messages << "#{import_item.file_path.basename} 第#{import_item.line_index}行 #{import_item.import_name} => #import <#{expect_module_name}/#{import_item.import_file_name}>"
302
- end
303
- end
193
+ unless podspec_content
194
+ next
304
195
  end
305
196
 
306
- if messages.size >0
307
- puts "组件#{module_item.module_name}存在以下情况, 请检查:".yellow
308
- puts messages
309
- puts "\n"
310
- end
197
+ update_dep_frameworks(module_item.frameworks, podspec_content)
311
198
 
199
+ subspec_content = podspec_content["subspecs"]
200
+ if subspec_content and subspec_content.class == Array
201
+ subspec_content.each { |json_content|
202
+ update_dep_frameworks(module_item.frameworks, json_content)
203
+ }
204
+ end
312
205
  end
313
206
 
314
- duration = ((Time.now.to_f * 1000).to_i - start)*0.001
315
- puts "import检查完毕! 共检查#{module_count}个组件(#{file_count}个import) 耗时:#{duration.round(2)}秒"
316
207
  end
317
208
 
318
- private
319
- # 根据头文件名查找所属组件
320
- # @return [String, nil]
321
- def find_module_with_header_file(header_file_name)
322
- module_items.each do |module_name, module_item|
323
- file_path = module_item.header_files[header_file_name]
324
- if file_path
325
- return module_item.module_name
209
+ def update_dep_frameworks(item_frameworks, json_content)
210
+ vendor_frameworks = json_content["vendored_frameworks"]
211
+ unless vendor_frameworks
212
+ ios = json_content["ios"]
213
+ if ios and ios.class == Hash
214
+ vendor_frameworks = ios["vendored_frameworks"]
215
+ end
216
+ end
217
+
218
+ if vendor_frameworks
219
+ if vendor_frameworks.class == Array
220
+ vendor_frameworks.each do |framework|
221
+ frameworks = deal_frameworks(vendor_frameworks)
222
+ if frameworks != "*"
223
+ item_frameworks << frameworks
224
+ end
225
+ end
226
+ elsif vendor_frameworks.class == String
227
+ frameworks = deal_frameworks(vendor_frameworks)
228
+ if frameworks != "*"
229
+ item_frameworks << frameworks
230
+ end
326
231
  end
327
232
  end
328
- nil
233
+ end
234
+
235
+ def deal_frameworks(frameworks)
236
+ # "frameworks/WCDB/WCDB.framework",
237
+ # "openssl.xcframework"
238
+ temp_array = frameworks.split("/")
239
+ result = temp_array.last
240
+ result = result.gsub(".xcframework","")
241
+ result.gsub(".framework", "")
329
242
  end
330
243
 
331
244
  end
@@ -0,0 +1,38 @@
1
+ module Xcodeproj
2
+ class Util
3
+ #读取podspec内容
4
+ # @return [Hash]
5
+ # @param podspec_path::[Pathname]
6
+ def self.get_podspec_content(podspec_path)
7
+
8
+ podspec_json_path = podspec_path.to_s.end_with?(".podspec.json") ? podspec_path : nil
9
+
10
+ podspec_content = nil
11
+ if podspec_json_path and File.exist?(podspec_json_path)
12
+ json = File.read(podspec_json_path)
13
+ podspec_content = JSON.parse(json)
14
+ elsif podspec_path and File.exist?(podspec_path)
15
+ json = get_podspec_file_content(podspec_path)
16
+ podspec_content = JSON.parse(json)
17
+ end
18
+ podspec_content
19
+ end
20
+
21
+ @private
22
+ # 根据podspec路径把podspec转为json
23
+ def self.get_podspec_file_content(podspec_path)
24
+
25
+ spec_contents = File.open(podspec_path, 'r:utf-8', &:read)
26
+
27
+ if spec_contents.respond_to?(:encoding) && spec_contents.encoding.name != 'UTF-8'
28
+ spec_contents.encode!('UTF-8')
29
+ end
30
+
31
+ path = Pathname.new(podspec_path)
32
+
33
+ spec = ::Pod._eval_podspec(spec_contents, path)
34
+
35
+ spec.to_json
36
+ end
37
+ end
38
+ end
@@ -2,38 +2,6 @@ require 'xcodeproj'
2
2
  require 'pathname'
3
3
 
4
4
  module XCProject
5
- class ModuleItem
6
-
7
-
8
- def initialize(module_name, module_path)
9
- @module_name = module_name
10
- @module_path = module_path
11
- @podspec_path = nil
12
- @source_files = []
13
- end
14
-
15
- # 组件名
16
- attr_reader :module_name
17
-
18
- # 组件路径
19
- attr_reader :module_path
20
-
21
- # 组件目录的所有被引用的文件数组
22
- attr_reader :source_files
23
-
24
- # podspec路径
25
- attr_reader :podspec_path
26
-
27
- # 添加一个文件路径进去
28
- def add_source_file(source_file)
29
- self.source_files << source_file
30
- end
31
-
32
- def update_podspec_path(podspec_path)
33
- @podspec_path = podspec_path
34
- end
35
-
36
- end
37
5
 
38
6
  class XcodeprojManager
39
7
 
@@ -99,57 +67,6 @@ module XCProject
99
67
  results
100
68
  end
101
69
 
102
- # 获取壳工程的引用的文件列表
103
- # @return Hash
104
- def get_shell_module
105
- project = self.get_shell_project
106
-
107
- result_map = {}
108
- self.reference_shell_code_file(project.root_object.main_group, result_map)
109
- result_map
110
- end
111
-
112
- # 根据一个group获取其对应的引用代码文件和路径- 仅限壳工程
113
- @private
114
- def reference_shell_code_file(group, result_map)
115
- # 文件引用
116
- file_reference = Xcodeproj::Project::Object::PBXFileReference
117
-
118
- group.children.each {|child|
119
-
120
- if child.class != file_reference
121
- self.reference_shell_code_file(child, result_map)
122
- next
123
- end
124
-
125
- file_name = child.real_path.basename
126
- extend_name = file_name.extname
127
- if not extend_name == ".h" and
128
- not extend_name == ".m" and
129
- not extend_name == ".mm" and
130
- not extend_name == ".pch" and
131
- not extend_name == ".c" and
132
- not extend_name == ".cc" and
133
- not extend_name == ".hpp" and
134
- not extend_name == ".cpp"
135
- next
136
- end
137
-
138
- # 引用关系路径
139
- hierarchy_path_array = child.hierarchy_path.split("/")
140
- if hierarchy_path_array.size < 2
141
- next
142
- end
143
-
144
- module_name = hierarchy_path_array[1]
145
- module_item = result_map[module_name] ? result_map[module_name] : ModuleItem.new(module_name, child.real_path)
146
- module_item.add_source_file(child.real_path)
147
-
148
- result_map[module_name] = module_item
149
- }
150
- end
151
-
152
-
153
70
  # 获取Pods下project对象
154
71
  def get_pods_project
155
72
 
@@ -162,160 +79,5 @@ module XCProject
162
79
 
163
80
  end
164
81
 
165
- # 根据一个组件名获取其内部所有的framework名字 如果没有则返回自己
166
- def frameworks_with_module_name(module_name)
167
- if self.module_frameworks[module_name]
168
- return self.module_frameworks[module_name]
169
- end
170
-
171
- module_path = self.real_path_with_module_name(module_name)
172
- frameworks = [module_name]
173
- self.get_framework(module_path, frameworks)
174
- self.module_frameworks[module_name] = frameworks
175
- frameworks
176
- end
177
-
178
- # 递归查找路径下的framework名字
179
- @private
180
- def get_framework(path, frameworks)
181
-
182
- if File.directory?(path)
183
- Dir.foreach(path) { |fileName|
184
- child_path = "#{path}/#{fileName}"
185
- if File.directory?(child_path) and not fileName.start_with?(".")
186
- if fileName.end_with?(".framework") or fileName.end_with?(".xcframework")
187
- framework_name = fileName.gsub(".xcframework","").gsub(".framework","")
188
- unless frameworks.include?(framework_name)
189
- frameworks << framework_name
190
- end
191
- else
192
- self.get_framework(child_path, frameworks)
193
- end
194
- end
195
- }
196
- end
197
- frameworks
198
- end
199
-
200
- # 根据一个组件的名字,获取其绝对路径
201
- def real_path_with_module_name(module_name)
202
- project = self.get_pods_project
203
- project.main_group.children.each {|child|
204
- if child.name != "Development Pods" and child.name != "Pods"
205
- next
206
- end
207
-
208
- child.children.each {|sun|
209
- if sun.name == module_name
210
- real_path = sun.real_path
211
- return real_path
212
- end
213
- }
214
- }
215
- nil
216
- end
217
-
218
- # 获取本地依赖库
219
- # @return 数组 [ModuleItem]
220
- def get_development_module
221
- project = self.get_pods_project
222
- result_map = {}
223
- self.reference_file(project.main_group, result_map)
224
- result_map
225
- end
226
-
227
- # 根据一个group获取 其对应的引用文件和路径
228
- @private
229
- def reference_file(group, result_map)
230
- # 文件引用
231
- file_reference = Xcodeproj::Project::Object::PBXFileReference
232
-
233
- group.children.each {|child|
234
- if child.class == file_reference and child.name != "Podfile"
235
-
236
- # 引用关系路径
237
- hierarchy_path_array = child.hierarchy_path.split("/")
238
- if hierarchy_path_array.size >= 3
239
- module_name = hierarchy_path_array[2]
240
-
241
- module_item = result_map[module_name] ? result_map[module_name] : ModuleItem.new(module_name, child.real_path)
242
-
243
- file_name = child.real_path.basename
244
- extend_name = file_name.extname
245
- if extend_name == ".podspec" or extend_name == ".podspec.json"
246
- module_item.update_podspec_path(child.real_path)
247
- elsif extend_name == ".h" or extend_name == ".m" or
248
- extend_name == ".mm" or extend_name == ".pch" or
249
- extend_name == ".c" or extend_name == ".cc" or
250
- extend_name == ".cpp" or extend_name == ".hpp"
251
- module_item.add_source_file(child.real_path)
252
- end
253
-
254
- result_map[module_name] = module_item
255
- end
256
- # 无论加或着不加 都跳过
257
- next
258
- end
259
-
260
- if child.name == "Podfile" or
261
- child.name == "Frameworks" or
262
- child.name == "Pods" or
263
- child.name == "Products" or
264
- child.name == "Targets Support Files" or
265
- child.name == "Support Files"
266
- next
267
- end
268
-
269
- self.reference_file(child, result_map)
270
- }
271
- end
272
-
273
- # 获取已引用的所有库,仅包含头文件
274
- def get_installed_headers_module
275
- project = self.get_pods_project
276
-
277
- result_map = {}
278
- self.reference_header_file(project.main_group, result_map)
279
- result_map
280
- end
281
-
282
- # 获取引用的头文件
283
- @private
284
- def reference_header_file(group, result_map)
285
- # 文件引用
286
- file_reference = Xcodeproj::Project::Object::PBXFileReference
287
-
288
- group.children.each {|child|
289
- if child.class == file_reference
290
-
291
- # 引用关系路径
292
- hierarchy_path_array = child.hierarchy_path.split("/")
293
- if hierarchy_path_array.size >= 3
294
- module_name = hierarchy_path_array[2]
295
-
296
- module_item = result_map[module_name] ? result_map[module_name] : ModuleItem.new(module_name, child.real_path)
297
-
298
- file_name = child.real_path.basename
299
- if file_name.to_s.end_with?(".h") or file_name.to_s.end_with?(".hpp") or file_name.to_s.end_with?(".pch")
300
- module_item.add_source_file(child.real_path)
301
- end
302
- result_map[module_name] = module_item
303
- end
304
- # 无论加或着不加 都跳过
305
- next
306
- end
307
-
308
- if child.name == "Podfile" or
309
- child.name == "Frameworks" or
310
- child.name == "Products" or
311
- child.name == "Targets Support Files" or
312
- child.name == "Support Files"
313
- next
314
- end
315
-
316
- self.reference_header_file(child, result_map)
317
- }
318
- end
319
-
320
82
  end
321
83
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
- module Constants
2
+ module MyConstants
3
3
 
4
4
  PODFILE_LOCAL_YAML = 'PodfileLocal.yaml'
5
5
  PODFILE_MODULE_YAML = 'PodfileModule.yaml'
@@ -1,11 +1,11 @@
1
- require_relative 'constants'
1
+ require_relative 'my_constants'
2
2
  require 'yaml'
3
3
 
4
4
  module PodfileLock
5
5
  class PodfileLockManager
6
6
  # 读取podfile.lock
7
7
  def self.podfile_lock_content
8
- podfile_lock = Constants::PODFILE_LOCK
8
+ podfile_lock = MyConstants::PODFILE_LOCK
9
9
 
10
10
  unless File.exist?(podfile_lock)
11
11
  return {}