podfileDep 2.3.6 → 2.4.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.
@@ -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 {}