cocoapods-binary-matchup 0.0.26 → 0.0.28
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
- metadata +3 -29
- data/.gitignore +0 -32
- data/.travis.yml +0 -23
- data/Gemfile +0 -13
- data/Gemfile.lock +0 -161
- data/LICENSE.txt +0 -22
- data/README.md +0 -83
- data/Rakefile +0 -13
- data/cocoapods-binary-matchup.gemspec +0 -27
- data/lib/cocoapods-binary-matchup/Integration.rb +0 -287
- data/lib/cocoapods-binary-matchup/Integration_cache.rb +0 -320
- data/lib/cocoapods-binary-matchup/Main.rb +0 -385
- data/lib/cocoapods-binary-matchup/Prebuild.rb +0 -249
- data/lib/cocoapods-binary-matchup/gem_version.rb +0 -3
- data/lib/cocoapods-binary-matchup/helper/feature_switches.rb +0 -109
- data/lib/cocoapods-binary-matchup/helper/passer.rb +0 -41
- data/lib/cocoapods-binary-matchup/helper/podfile_options.rb +0 -122
- data/lib/cocoapods-binary-matchup/helper/prebuild_sandbox.rb +0 -53
- data/lib/cocoapods-binary-matchup/helper/target_checker.rb +0 -49
- data/lib/cocoapods-binary-matchup/rome/build_framework.rb +0 -315
- data/lib/cocoapods-binary-matchup/tool/tool.rb +0 -12
- data/lib/cocoapods-binary.rb +0 -1
- data/lib/cocoapods_plugin.rb +0 -2
- data/spec/plugin_spec.rb +0 -43
- data/spec/spec_helper.rb +0 -50
|
@@ -1,287 +0,0 @@
|
|
|
1
|
-
require_relative 'helper/podfile_options'
|
|
2
|
-
require_relative 'helper/feature_switches'
|
|
3
|
-
require_relative 'helper/prebuild_sandbox'
|
|
4
|
-
require_relative 'helper/passer'
|
|
5
|
-
require_relative 'helper/target_checker'
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
# NOTE:
|
|
9
|
-
# This file will only be loaded on normal pod install step
|
|
10
|
-
# so there's no need to check is_prebuild_stage
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
# Provide a special "download" process for prebuilded pods.
|
|
15
|
-
#
|
|
16
|
-
# As the frameworks is already exsited in local folder. We
|
|
17
|
-
# just create a symlink to the original target folder.
|
|
18
|
-
#
|
|
19
|
-
require_relative 'Integration_cache'
|
|
20
|
-
|
|
21
|
-
module Pod
|
|
22
|
-
class Installer
|
|
23
|
-
class PodSourceInstaller
|
|
24
|
-
|
|
25
|
-
def install_for_prebuild!(standard_sanbox)
|
|
26
|
-
return if standard_sanbox.local? self.name
|
|
27
|
-
UI.puts "install_for_prebuild! start: #{self.name}"
|
|
28
|
-
|
|
29
|
-
# 获取pod版本信息
|
|
30
|
-
prebuild_sandbox = Pod::PrebuildSandbox.from_standard_sandbox(standard_sanbox)
|
|
31
|
-
|
|
32
|
-
target_folder = standard_sanbox.pod_dir(self.name)
|
|
33
|
-
target_folder.rmtree if target_folder.exist?
|
|
34
|
-
|
|
35
|
-
real_file_folder = prebuild_sandbox.framework_folder_path_for_pod_name(self.name)
|
|
36
|
-
|
|
37
|
-
if real_file_folder.exist?
|
|
38
|
-
# 拷贝到pods目录
|
|
39
|
-
FileUtils.cp_r(real_file_folder, target_folder, :remove_destination => true)
|
|
40
|
-
UI.puts "📦 Copied prebuilt files for #{self.name}: #{real_file_folder} -> #{target_folder}"
|
|
41
|
-
|
|
42
|
-
# 3. 同时保存到缓存(如果缓存不存在)
|
|
43
|
-
Pod::PrebuildCache::Cache.save_to_cache(self.name, target_folder.to_s)
|
|
44
|
-
else
|
|
45
|
-
UI.puts "⚠️ Warning: Prebuilt files not found for #{self.name} at #{real_file_folder}"
|
|
46
|
-
# 如果预构建文件不存在,创建空目录避免错误
|
|
47
|
-
target_folder.mkpath
|
|
48
|
-
end
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
# Let cocoapods use the prebuild framework files in install process.
|
|
57
|
-
#
|
|
58
|
-
# the code only effect the second pod install process.
|
|
59
|
-
#
|
|
60
|
-
module Pod
|
|
61
|
-
class Installer
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
# Remove the old target files if prebuild frameworks changed
|
|
65
|
-
def remove_target_files_if_needed
|
|
66
|
-
|
|
67
|
-
changes = Pod::Prebuild::Passer.prebuild_pods_changes
|
|
68
|
-
updated_names = []
|
|
69
|
-
if changes == nil
|
|
70
|
-
updated_names = PrebuildSandbox.from_standard_sandbox(self.sandbox).exsited_framework_names
|
|
71
|
-
else
|
|
72
|
-
added = changes.added
|
|
73
|
-
changed = changes.changed
|
|
74
|
-
deleted = changes.deleted
|
|
75
|
-
updated_names = added + changed + deleted
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
updated_names.each do |name|
|
|
79
|
-
root_name = Specification.root_name(name)
|
|
80
|
-
next if self.sandbox.local?(root_name)
|
|
81
|
-
# 只有当不是预构建的pod时才删除,避免删除刚拷贝的预构建文件
|
|
82
|
-
next if self.prebuild_pod_names.include?(root_name)
|
|
83
|
-
|
|
84
|
-
# delete the cached files,include all cached files in the target
|
|
85
|
-
target_path = self.sandbox.pod_dir(root_name)
|
|
86
|
-
target_path.rmtree if target_path.exist?
|
|
87
|
-
|
|
88
|
-
support_path = sandbox.target_support_files_dir(root_name)
|
|
89
|
-
support_path.rmtree if support_path.exist?
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
# Modify specification to use only the prebuild framework after analyzing
|
|
96
|
-
old_method2 = instance_method(:resolve_dependencies)
|
|
97
|
-
define_method(:resolve_dependencies) do
|
|
98
|
-
|
|
99
|
-
# Remove the old target files, else it will not notice file changes
|
|
100
|
-
self.remove_target_files_if_needed
|
|
101
|
-
|
|
102
|
-
# call original
|
|
103
|
-
old_method2.bind(self).()
|
|
104
|
-
|
|
105
|
-
# check the pods
|
|
106
|
-
# Although we have did it in prebuild stage, it's not sufficient.
|
|
107
|
-
# Same pod may appear in another target in form of source code.
|
|
108
|
-
Prebuild.check_one_pod_should_have_only_one_target(self.prebuild_pod_targets)
|
|
109
|
-
UI.puts "🔍 prebuild_pod_names (cached): #{self.prebuild_pod_names}"
|
|
110
|
-
|
|
111
|
-
# FIXED: 在主安装阶段强制重新计算 prebuild_pod_names
|
|
112
|
-
# 避免使用过期的缓存(可能在 aggregate_targets 初始化前被缓存为空)
|
|
113
|
-
fresh_prebuild_pod_names = self.refresh_prebuild_pod_names!
|
|
114
|
-
UI.puts "🔍 prebuild_pod_names (fresh): #{fresh_prebuild_pod_names}"
|
|
115
|
-
|
|
116
|
-
#
|
|
117
|
-
specs = self.analysis_result.specifications
|
|
118
|
-
# 只保留podspec中prebuild的pod,这里本质过滤了所有非prebuild的pod
|
|
119
|
-
prebuilt_specs = (specs.select do |spec|
|
|
120
|
-
self.prebuild_pod_names.include? spec.root.name
|
|
121
|
-
end)
|
|
122
|
-
|
|
123
|
-
# make sturcture to fast get target by name
|
|
124
|
-
name_to_target_hash = self.pod_targets.reduce({}) do |sum, target|
|
|
125
|
-
sum[target.name] = target
|
|
126
|
-
sum
|
|
127
|
-
end
|
|
128
|
-
|
|
129
|
-
prebuilt_specs.each do |spec|
|
|
130
|
-
# `spec` may be a subspec, so we use the root's name
|
|
131
|
-
root_name = spec.root.name
|
|
132
|
-
|
|
133
|
-
target = name_to_target_hash[root_name]
|
|
134
|
-
# 如果是非源码编译成的pod(如本身是动态库和静态库依赖),则跳过集成,使用pod本身的配置
|
|
135
|
-
next if Prebuild::Passer.target_names_to_skip_integration_framework.include? target.pod_name
|
|
136
|
-
|
|
137
|
-
# use the prebuilt framework
|
|
138
|
-
original_vendored_frameworks = spec.attributes_hash["vendored_frameworks"] || []
|
|
139
|
-
if original_vendored_frameworks.kind_of?(String)
|
|
140
|
-
original_vendored_frameworks = [original_vendored_frameworks]
|
|
141
|
-
end
|
|
142
|
-
framework_name = target.framework_name
|
|
143
|
-
if framework_name.kind_of?(Array)
|
|
144
|
-
original_vendored_frameworks += framework_name
|
|
145
|
-
else
|
|
146
|
-
# 始终使用Build目录下的路径,因为我们的install_for_prebuild!会复制framework到Build目录
|
|
147
|
-
original_vendored_frameworks += [framework_name]
|
|
148
|
-
end
|
|
149
|
-
spec.attributes_hash["vendored_frameworks"] = original_vendored_frameworks
|
|
150
|
-
|
|
151
|
-
# 对于静态库类型的pod,需要保留头文件,不能完全清空source_files
|
|
152
|
-
# 检查是否有vendored_libraries(静态库)
|
|
153
|
-
vendored_libraries = spec.attributes_hash["vendored_libraries"] || []
|
|
154
|
-
if vendored_libraries.kind_of?(String)
|
|
155
|
-
vendored_libraries = [vendored_libraries]
|
|
156
|
-
end
|
|
157
|
-
|
|
158
|
-
# 不管是静态库还是动态框架,都需要智能处理source_files
|
|
159
|
-
# 保留头文件和重要文件,清空.m/.swift等源码文件
|
|
160
|
-
current_source_files = spec.attributes_hash["source_files"] || []
|
|
161
|
-
if current_source_files.kind_of?(String)
|
|
162
|
-
current_source_files = [current_source_files]
|
|
163
|
-
end
|
|
164
|
-
|
|
165
|
-
if current_source_files.empty?
|
|
166
|
-
# 如果原来就没有source_files,不做处理
|
|
167
|
-
spec.attributes_hash["source_files"] = []
|
|
168
|
-
else
|
|
169
|
-
# 智能处理source_files:保留头文件相关模式,清空源码文件模式
|
|
170
|
-
header_files = current_source_files.select { |file_pattern|
|
|
171
|
-
pattern = file_pattern.to_s
|
|
172
|
-
# 检查是否是头文件相关的模式,使用更精确的正则表达式
|
|
173
|
-
pattern.match?(/\*+\.h$/) || # 匹配 "*.h", "**/*.h" 等
|
|
174
|
-
pattern.match?(/\*+\.hpp$/) || # 匹配 "*.hpp", "**/*.hpp" 等
|
|
175
|
-
pattern.match?(/\*+\.hh$/) || # 匹配 "*.hh", "**/*.hh" 等
|
|
176
|
-
pattern.match?(/\*+\.modulemap$/) || # 匹配 "*.modulemap"
|
|
177
|
-
pattern.match?(/\/\*\.h$/) || # 匹配 "Sources/*.h" 等
|
|
178
|
-
pattern.match?(/\/\*\.hpp$/) || # 匹配 "Sources/*.hpp" 等
|
|
179
|
-
pattern.match?(/\/\*\.hh$/) || # 匹配 "Sources/*.hh" 等
|
|
180
|
-
pattern.match?(/\/\*\.modulemap$/) || # 匹配 "Sources/*.modulemap"
|
|
181
|
-
pattern.end_with?('.h', '.hpp', '.hh', '.modulemap') || # 直接的头文件路径
|
|
182
|
-
pattern.match?(/\*\*?\/\*$/) # 通用通配符保留,如 "Sources/*", "**/*"
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
# 如果没有找到明确的头文件模式,保留原有的source_files
|
|
186
|
-
# 这样可以避免意外删除重要的头文件
|
|
187
|
-
if header_files.empty?
|
|
188
|
-
spec.attributes_hash["source_files"] = current_source_files
|
|
189
|
-
else
|
|
190
|
-
UI.puts "📋 #{spec.root.name} header_files: #{header_files}"
|
|
191
|
-
spec.attributes_hash["source_files"] = header_files
|
|
192
|
-
end
|
|
193
|
-
end
|
|
194
|
-
|
|
195
|
-
# to remove the resurce bundle target.
|
|
196
|
-
# When specify the "resource_bundles" in podspec, xcode will generate a bundle
|
|
197
|
-
# target after pod install. But the bundle have already built when the prebuit
|
|
198
|
-
# phase and saved in the framework folder. We will treat it as a normal resource
|
|
199
|
-
# file.
|
|
200
|
-
# https://github.com/leavez/cocoapods-binary/issues/29
|
|
201
|
-
if spec.attributes_hash["resource_bundles"]
|
|
202
|
-
bundle_names = spec.attributes_hash["resource_bundles"].keys
|
|
203
|
-
spec.attributes_hash["resource_bundles"] = nil
|
|
204
|
-
current_resources = spec.attributes_hash["resources"] || []
|
|
205
|
-
|
|
206
|
-
if current_resources.kind_of?(String)
|
|
207
|
-
current_resources = [current_resources]
|
|
208
|
-
end
|
|
209
|
-
|
|
210
|
-
current_resources += bundle_names.map{|n| n+".bundle"}
|
|
211
|
-
spec.attributes_hash["resources"] = current_resources
|
|
212
|
-
end
|
|
213
|
-
|
|
214
|
-
# to avoid the warning of missing license
|
|
215
|
-
spec.attributes_hash["license"] = {}
|
|
216
|
-
end
|
|
217
|
-
|
|
218
|
-
end
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
# Override the download step to skip download and prepare file in target folder
|
|
222
|
-
old_method = instance_method(:install_source_of_pod)
|
|
223
|
-
define_method(:install_source_of_pod) do |pod_name|
|
|
224
|
-
|
|
225
|
-
# copy from original,创建一个单pod的安装器
|
|
226
|
-
pod_installer = create_pod_installer(pod_name)
|
|
227
|
-
# \copy from original
|
|
228
|
-
|
|
229
|
-
if self.prebuild_pod_names.include? pod_name
|
|
230
|
-
UI.puts "📦 [#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}] Installing prebuild pod: #{pod_name}"
|
|
231
|
-
pod_installer.install_for_prebuild!(self.sandbox)
|
|
232
|
-
UI.puts "📦 [#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}] Installing prebuild pod: #{pod_name}"
|
|
233
|
-
else
|
|
234
|
-
UI.puts "📥 [#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}] Installing source pod: #{pod_name}"
|
|
235
|
-
pod_installer.install!
|
|
236
|
-
UI.puts "📥 [#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}] Installing source pod: #{pod_name}"
|
|
237
|
-
end
|
|
238
|
-
|
|
239
|
-
# copy from original
|
|
240
|
-
@installed_specs.concat(pod_installer.specs_by_platform.values.flatten.uniq)
|
|
241
|
-
# \copy from original
|
|
242
|
-
end
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
end
|
|
246
|
-
end
|
|
247
|
-
|
|
248
|
-
# A fix in embeded frameworks script.
|
|
249
|
-
#
|
|
250
|
-
# The framework file in pod target folder is a symblink. The EmbedFrameworksScript use `readlink`
|
|
251
|
-
# to read the read path. As the symlink is a relative symlink, readlink cannot handle it well. So
|
|
252
|
-
# we override the `readlink` to a fixed version.
|
|
253
|
-
#
|
|
254
|
-
module Pod
|
|
255
|
-
module Generator
|
|
256
|
-
class EmbedFrameworksScript
|
|
257
|
-
|
|
258
|
-
old_method = instance_method(:script)
|
|
259
|
-
define_method(:script) do
|
|
260
|
-
|
|
261
|
-
script = old_method.bind(self).()
|
|
262
|
-
patch = <<-SH.strip_heredoc
|
|
263
|
-
#!/bin/sh
|
|
264
|
-
|
|
265
|
-
# ---- this is added by cocoapods-binary ---
|
|
266
|
-
# Readlink cannot handle relative symlink well, so we override it to a new one
|
|
267
|
-
# If the path isn't an absolute path, we add a realtive prefix.
|
|
268
|
-
old_read_link=`which readlink`
|
|
269
|
-
readlink () {
|
|
270
|
-
path=`$old_read_link $1`;
|
|
271
|
-
if [ $(echo "$path" | cut -c 1-1) = '/' ]; then
|
|
272
|
-
echo $path;
|
|
273
|
-
else
|
|
274
|
-
echo "`dirname $1`/$path";
|
|
275
|
-
fi
|
|
276
|
-
}
|
|
277
|
-
# ---
|
|
278
|
-
SH
|
|
279
|
-
|
|
280
|
-
# patch the rsync for copy dSYM symlink
|
|
281
|
-
script = script.gsub "rsync --delete", "rsync --copy-links --delete"
|
|
282
|
-
|
|
283
|
-
patch + script
|
|
284
|
-
end
|
|
285
|
-
end
|
|
286
|
-
end
|
|
287
|
-
end
|
|
@@ -1,320 +0,0 @@
|
|
|
1
|
-
require 'fileutils'
|
|
2
|
-
require 'digest'
|
|
3
|
-
require 'set'
|
|
4
|
-
|
|
5
|
-
module Pod
|
|
6
|
-
|
|
7
|
-
class_attr_accessor :main_deployment_target_name
|
|
8
|
-
|
|
9
|
-
module PrebuildCache
|
|
10
|
-
|
|
11
|
-
class Cache
|
|
12
|
-
|
|
13
|
-
# 类变量用于跟踪依赖关系和失效的pod
|
|
14
|
-
@@dependency_graph = {}
|
|
15
|
-
|
|
16
|
-
# 获取缓存根目录
|
|
17
|
-
def self.cache_root_dir
|
|
18
|
-
cache_dir = File.expand_path("~/.PodCache/#{Pod.main_deployment_target_name}")
|
|
19
|
-
FileUtils.mkdir_p(cache_dir) unless Dir.exist?(cache_dir)
|
|
20
|
-
cache_dir
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
# 获取manifest.lock缓存路径
|
|
24
|
-
def self.cached_manifest_path
|
|
25
|
-
File.join(cache_root_dir, 'Manifest.lock')
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
# 获取特定pod的缓存目录
|
|
29
|
-
def self.cache_dir_for_pod(pod_name)
|
|
30
|
-
File.join(cache_root_dir, pod_name)
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
# 获取pod的版本信息,优先使用commit hash
|
|
34
|
-
def self.get_pod_version(sandbox, pod_name)
|
|
35
|
-
UI.puts "🔍 starting get pod version: #{pod_name}"
|
|
36
|
-
UI.puts "🔍 get_pod_version sandbox: #{sandbox.manifest_path}"
|
|
37
|
-
checkout_options = sandbox.manifest.checkout_options_for_pod_named(pod_name)
|
|
38
|
-
# 优先使用checkout_options中的检出来源
|
|
39
|
-
if checkout_options
|
|
40
|
-
UI.puts "🔍 get pod checkout version: #{pod_name}"
|
|
41
|
-
if checkout_options[:tag]
|
|
42
|
-
UI.puts "🔍 get pod checkout version tag: #{pod_name}# - #{checkout_options[:tag]}"
|
|
43
|
-
return checkout_options[:tag]
|
|
44
|
-
end
|
|
45
|
-
if checkout_options[:branch]
|
|
46
|
-
UI.puts "🔍 get pod checkout version branch: #{pod_name}# - #{checkout_options[:branch]}"
|
|
47
|
-
return checkout_options[:branch]
|
|
48
|
-
end
|
|
49
|
-
if checkout_options[:commit]
|
|
50
|
-
UI.puts "🔍 get pod checkout version commit: #{pod_name}# - #{checkout_options[:commit]}"
|
|
51
|
-
return checkout_options[:commit]
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
# 如果checkout_options中没有版本信息,则使用dependency中的版本信息
|
|
56
|
-
dependency = sandbox.manifest.dependencies.find { |d| d.name == pod_name }
|
|
57
|
-
if dependency
|
|
58
|
-
UI.puts "🔍 get pod dependency version: #{pod_name}"
|
|
59
|
-
external_source = dependency.external_source
|
|
60
|
-
if external_source
|
|
61
|
-
UI.puts "🔍 get pod dependency version podspec: #{external_source}"
|
|
62
|
-
if external_source[:commit]
|
|
63
|
-
UI.puts "🔍 get pod dependency version commit: #{pod_name}# - #{external_source[:commit]}"
|
|
64
|
-
return external_source[:commit]
|
|
65
|
-
end
|
|
66
|
-
if external_source[:branch]
|
|
67
|
-
UI.puts "🔍 get pod dependency version branch: #{pod_name}# - #{external_source[:branch]}"
|
|
68
|
-
return external_source[:branch]
|
|
69
|
-
end
|
|
70
|
-
end
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
# 如果checkout_options和dependency中没有版本信息,则使用podspec中的version
|
|
74
|
-
UI.puts "🔍 get pod spec version: #{pod_name}"
|
|
75
|
-
version = sandbox.manifest.version(pod_name).version
|
|
76
|
-
if version
|
|
77
|
-
UI.puts "🔍 get pod spec version: #{pod_name}# - #{version}"
|
|
78
|
-
return version
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
# 如果以上都失败,则返回unknown,理论上只要是正常的podfile.lock或者manifest.lock,都不会走到这里
|
|
82
|
-
UI.puts "🔍 get pod version failed: #{pod_name}"
|
|
83
|
-
return "unknown"
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
# 检查缓存是否存在
|
|
87
|
-
def self.cache_exists?(pod_name)
|
|
88
|
-
cache_dir = cache_dir_for_pod(pod_name)
|
|
89
|
-
Pod::UI.puts "🔍 cache_exists? #{cache_dir}"
|
|
90
|
-
Dir.exist?(cache_dir) && !Dir.empty?(cache_dir)
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
# 保存到缓存(如果缓存不存在的话)
|
|
94
|
-
def self.save_to_cache(pod_name, source_dir)
|
|
95
|
-
return unless Dir.exist?(source_dir)
|
|
96
|
-
|
|
97
|
-
# 检查缓存是否已经存在,如果存在则不覆盖
|
|
98
|
-
if cache_exists?(pod_name)
|
|
99
|
-
Pod::UI.puts "📦 Cache already exists for #{pod_name}, skipping save"
|
|
100
|
-
return true
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
cache_dir = cache_dir_for_pod(pod_name)
|
|
104
|
-
|
|
105
|
-
begin
|
|
106
|
-
# 创建缓存目录
|
|
107
|
-
FileUtils.mkdir_p(File.dirname(cache_dir))
|
|
108
|
-
|
|
109
|
-
# 删除旧缓存(如果存在)
|
|
110
|
-
FileUtils.rm_rf(cache_dir) if Dir.exist?(cache_dir)
|
|
111
|
-
|
|
112
|
-
# 拷贝到缓存
|
|
113
|
-
FileUtils.cp_r(source_dir, cache_dir, :remove_destination => true)
|
|
114
|
-
return true
|
|
115
|
-
rescue => e
|
|
116
|
-
Pod::UI.puts "❌ Failed to save #{pod_name} to cache: #{e.message}"
|
|
117
|
-
return false
|
|
118
|
-
end
|
|
119
|
-
end
|
|
120
|
-
|
|
121
|
-
# 保存当前manifest.lock到缓存目录
|
|
122
|
-
def self.save_manifest_to_cache(sandbox)
|
|
123
|
-
begin
|
|
124
|
-
# 查找_Prebuild目录中的manifest.lock
|
|
125
|
-
prebuild_manifest = sandbox.root + 'Manifest.lock'
|
|
126
|
-
# 如果存在,复制到缓存目录
|
|
127
|
-
if prebuild_manifest.exist?
|
|
128
|
-
cached_path = cached_manifest_path
|
|
129
|
-
FileUtils.cp(prebuild_manifest, cached_path)
|
|
130
|
-
Pod::UI.puts "💾 save_manifest_to_cache Manifest.lock to cache: #{cached_path}"
|
|
131
|
-
return true
|
|
132
|
-
else
|
|
133
|
-
Pod::UI.puts "⚠️ save_manifest_to_cache Manifest.lock not found in _Prebuild directory"
|
|
134
|
-
return false
|
|
135
|
-
end
|
|
136
|
-
rescue => e
|
|
137
|
-
Pod::UI.puts "❌ save_manifest_to_cache save Manifest.lock to cache failed: #{e.message}"
|
|
138
|
-
return false
|
|
139
|
-
end
|
|
140
|
-
end
|
|
141
|
-
|
|
142
|
-
# 清空所有缓存
|
|
143
|
-
def self.clear_all_caches
|
|
144
|
-
begin
|
|
145
|
-
cache_dir = cache_root_dir
|
|
146
|
-
|
|
147
|
-
# 删除除了cached_manifest.lock之外的所有缓存
|
|
148
|
-
Dir.glob("#{cache_dir}/*").each do |path|
|
|
149
|
-
next if File.basename(path) == 'Manifest.lock'
|
|
150
|
-
|
|
151
|
-
if Dir.exist?(path)
|
|
152
|
-
FileUtils.rm_rf(path)
|
|
153
|
-
Pod::UI.puts "🗑️ Cleared cache directory: #{File.basename(path)}"
|
|
154
|
-
end
|
|
155
|
-
end
|
|
156
|
-
|
|
157
|
-
Pod::UI.puts "✅ All pod caches cleared due to dependency changes"
|
|
158
|
-
|
|
159
|
-
rescue => e
|
|
160
|
-
Pod::UI.puts "❌ Error clearing caches: #{e.message}"
|
|
161
|
-
end
|
|
162
|
-
end
|
|
163
|
-
|
|
164
|
-
# 验证pod版本一致性(与缓存时的manifest对比)
|
|
165
|
-
def self.validate_pod_version_consistency(pod_name, current_version)
|
|
166
|
-
begin
|
|
167
|
-
manifest_path = cached_manifest_path
|
|
168
|
-
Pod::UI.puts "🔍 validate_pod_version_consistency pod_name: #{pod_name} manifest_path: #{manifest_path}"
|
|
169
|
-
# 如果没有缓存的manifest,认为一致(首次构建)
|
|
170
|
-
unless File.exist?(manifest_path)
|
|
171
|
-
return true
|
|
172
|
-
end
|
|
173
|
-
|
|
174
|
-
# 创建基于缓存manifest的临时sandbox来获取缓存版本
|
|
175
|
-
cached_version = get_cached_pod_version(pod_name, cached_manifest_path)
|
|
176
|
-
|
|
177
|
-
# 对比版本
|
|
178
|
-
if current_version == cached_version
|
|
179
|
-
return true
|
|
180
|
-
else
|
|
181
|
-
Pod::UI.puts "🔄 #{pod_name} version changed: #{cached_version} → #{current_version}"
|
|
182
|
-
return false
|
|
183
|
-
end
|
|
184
|
-
|
|
185
|
-
rescue => e
|
|
186
|
-
Pod::UI.puts "⚠️ Error validating version consistency for #{pod_name}: #{e.message}"
|
|
187
|
-
return false
|
|
188
|
-
end
|
|
189
|
-
end
|
|
190
|
-
|
|
191
|
-
# 从缓存的manifest中获取pod版本(复用get_pod_version的逻辑)
|
|
192
|
-
def self.get_cached_pod_version(pod_name, cached_manifest_path)
|
|
193
|
-
begin
|
|
194
|
-
# 使用缓存目录作为根目录创建PrebuildSandbox
|
|
195
|
-
# 因为Manifest.lock就在cache_root_dir下,可以直接使用
|
|
196
|
-
cache_dir = File.dirname(cached_manifest_path)
|
|
197
|
-
temp_sandbox = Pod::PrebuildSandbox.new(cache_dir)
|
|
198
|
-
|
|
199
|
-
# 复用现有的get_pod_version逻辑
|
|
200
|
-
return get_pod_version(temp_sandbox, pod_name)
|
|
201
|
-
|
|
202
|
-
rescue => e
|
|
203
|
-
Pod::UI.puts "⚠️ Error reading cached version for #{pod_name}: #{e.message}"
|
|
204
|
-
return "unknown"
|
|
205
|
-
end
|
|
206
|
-
end
|
|
207
|
-
|
|
208
|
-
# 获取指定target的反向依赖(哪些targets依赖于它)
|
|
209
|
-
def self.find_reverse_dependencies(target_to_find, all_pod_targets)
|
|
210
|
-
reverse_deps = all_pod_targets.select do |pod_target|
|
|
211
|
-
# 跳过自己
|
|
212
|
-
next false if pod_target.pod_name == target_to_find.pod_name
|
|
213
|
-
# 检查当前pod_target的正向递归依赖中是否包含目标target
|
|
214
|
-
pod_target.recursive_dependent_targets.include?(target_to_find)
|
|
215
|
-
end
|
|
216
|
-
|
|
217
|
-
reverse_deps.map { |item| item.pod_name }
|
|
218
|
-
end
|
|
219
|
-
|
|
220
|
-
# 构建简单的依赖关系图(从targets获取)
|
|
221
|
-
def self.build_simple_dependency_graph(target, total_targets)
|
|
222
|
-
return if total_targets.nil? || total_targets.empty?
|
|
223
|
-
|
|
224
|
-
Pod::UI.puts "🔍 Building reverse dependency graph for cache validation..."
|
|
225
|
-
begin
|
|
226
|
-
pod_name = target.pod_name
|
|
227
|
-
@@dependency_graph[pod_name] = []
|
|
228
|
-
dependencies = []
|
|
229
|
-
temp_dependencies = find_reverse_dependencies(target, total_targets)
|
|
230
|
-
if !temp_dependencies.nil?
|
|
231
|
-
dependencies = temp_dependencies
|
|
232
|
-
end
|
|
233
|
-
|
|
234
|
-
@@dependency_graph[pod_name] = dependencies
|
|
235
|
-
rescue => e
|
|
236
|
-
Pod::UI.puts "⚠️ Warning: Error processing target #{target}: #{e.message}"
|
|
237
|
-
end
|
|
238
|
-
end
|
|
239
|
-
|
|
240
|
-
# 删除pod的缓存
|
|
241
|
-
def self.invalidate_pod_cache(pod_name)
|
|
242
|
-
cache_dir = cache_dir_for_pod(pod_name)
|
|
243
|
-
Pod::UI.puts "🗑️ start Removed invalid cache for #{pod_name}"
|
|
244
|
-
if Dir.exist?(cache_dir)
|
|
245
|
-
FileUtils.rm_rf(cache_dir)
|
|
246
|
-
Pod::UI.puts "🗑️ end Removed invalid cache for #{pod_name}"
|
|
247
|
-
end
|
|
248
|
-
end
|
|
249
|
-
|
|
250
|
-
def self.remove_all_invalid_cache(sandbox, all_targets)
|
|
251
|
-
all_targets.each do |target|
|
|
252
|
-
build_simple_dependency_graph(target, all_targets)
|
|
253
|
-
current_version = get_pod_version(sandbox, target.pod_name)
|
|
254
|
-
if validate_pod_version_consistency(target.pod_name, current_version)
|
|
255
|
-
Pod::UI.puts "🔍 validate_pod_version_consistency #{target.pod_name} #{current_version}"
|
|
256
|
-
else
|
|
257
|
-
cascade_invalidate_dependents(target.pod_name)
|
|
258
|
-
Pod::UI.puts "❌ validate_pod_version_consistency #{target.pod_name} #{current_version}"
|
|
259
|
-
end
|
|
260
|
-
end
|
|
261
|
-
Pod::UI.puts "📊 Dependency graph: #{@@dependency_graph}"
|
|
262
|
-
end
|
|
263
|
-
|
|
264
|
-
# 级联失效依赖当前pod的其他pod
|
|
265
|
-
def self.cascade_invalidate_dependents(invalidated_pod)
|
|
266
|
-
# 查找所有依赖invalidated_pod的pod
|
|
267
|
-
invalidate_pod_cache(invalidated_pod)
|
|
268
|
-
dependenciess = @@dependency_graph[invalidated_pod]
|
|
269
|
-
return if dependenciess.nil? || !dependenciess.any?
|
|
270
|
-
dependenciess.each do |dependent_pod|
|
|
271
|
-
invalidate_pod_cache(dependent_pod)
|
|
272
|
-
end
|
|
273
|
-
end
|
|
274
|
-
|
|
275
|
-
# 重置依赖验证状态并检查manifest一致性
|
|
276
|
-
def self.reset_dependency_validation(sandbox = nil)
|
|
277
|
-
@@dependency_graph.clear
|
|
278
|
-
Pod::UI.puts "🔄 Reset dependency validation state"
|
|
279
|
-
end
|
|
280
|
-
|
|
281
|
-
# 从 ~/.PodCache 恢复缓存到 _prebuild 目录(版本感知版)
|
|
282
|
-
def self.restore_from_pod_cache(pod_name, prebuild_sandbox)
|
|
283
|
-
begin
|
|
284
|
-
Pod::UI.puts "🔍 Checking cache for #{pod_name}"
|
|
285
|
-
|
|
286
|
-
# 获取pod版本信息
|
|
287
|
-
pod_version = get_pod_version(prebuild_sandbox, pod_name)
|
|
288
|
-
|
|
289
|
-
# 检查缓存是否存在
|
|
290
|
-
unless cache_exists?(pod_name)
|
|
291
|
-
Pod::UI.puts "⚠️ No cache found for #{pod_name}"
|
|
292
|
-
return false
|
|
293
|
-
end
|
|
294
|
-
|
|
295
|
-
# 所有验证通过,从缓存恢复
|
|
296
|
-
cache_dir = cache_dir_for_pod(pod_name)
|
|
297
|
-
target_dir = prebuild_sandbox.framework_folder_path_for_pod_name(pod_name)
|
|
298
|
-
|
|
299
|
-
# 确保目标目录存在
|
|
300
|
-
target_dir.parent.mkpath unless target_dir.parent.exist?
|
|
301
|
-
|
|
302
|
-
# 复制缓存到_prebuild
|
|
303
|
-
FileUtils.cp_r(cache_dir, target_dir, :remove_destination => true)
|
|
304
|
-
|
|
305
|
-
# 删除缓存标记文件
|
|
306
|
-
hash_file = target_dir + '.cache_hash'
|
|
307
|
-
hash_file.delete if hash_file.exist?
|
|
308
|
-
|
|
309
|
-
Pod::UI.puts "📦 Successfully restored #{pod_name} (#{pod_version}) from cache"
|
|
310
|
-
return true
|
|
311
|
-
|
|
312
|
-
rescue => e
|
|
313
|
-
Pod::UI.puts "❌ Error restoring from cache: #{e.message}"
|
|
314
|
-
# 出错时也标记为失效
|
|
315
|
-
return false
|
|
316
|
-
end
|
|
317
|
-
end
|
|
318
|
-
end
|
|
319
|
-
end
|
|
320
|
-
end
|