pod-builder-y 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 +7 -0
- data/.gitignore +19 -0
- data/Gemfile +8 -0
- data/LICENSE.txt +13 -0
- data/README.md +385 -0
- data/Rakefile +2 -0
- data/bin/console +16 -0
- data/bin/setup +8 -0
- data/exe/pod_builder_y +406 -0
- data/lib/core_ext/string.rb +5 -0
- data/lib/pod_builder/analyze.rb +59 -0
- data/lib/pod_builder/analyzer.rb +16 -0
- data/lib/pod_builder/command.rb +14 -0
- data/lib/pod_builder/command/build.rb +228 -0
- data/lib/pod_builder/command/build_all.rb +15 -0
- data/lib/pod_builder/command/clean.rb +75 -0
- data/lib/pod_builder/command/deintegrate.rb +101 -0
- data/lib/pod_builder/command/generate_lldbinit.rb +128 -0
- data/lib/pod_builder/command/generate_podspec.rb +22 -0
- data/lib/pod_builder/command/info.rb +18 -0
- data/lib/pod_builder/command/init.rb +148 -0
- data/lib/pod_builder/command/install_sources.rb +79 -0
- data/lib/pod_builder/command/none.rb +16 -0
- data/lib/pod_builder/command/restore_all.rb +33 -0
- data/lib/pod_builder/command/switch.rb +224 -0
- data/lib/pod_builder/command/sync_podfile.rb +34 -0
- data/lib/pod_builder/command/update.rb +43 -0
- data/lib/pod_builder/configuration.rb +300 -0
- data/lib/pod_builder/core.rb +222 -0
- data/lib/pod_builder/info.rb +90 -0
- data/lib/pod_builder/install.rb +505 -0
- data/lib/pod_builder/licenses.rb +73 -0
- data/lib/pod_builder/podfile.rb +700 -0
- data/lib/pod_builder/podfile/pre_actions_swizzles.rb +84 -0
- data/lib/pod_builder/podfile_cp.rb +99 -0
- data/lib/pod_builder/podfile_item.rb +530 -0
- data/lib/pod_builder/podspec.rb +269 -0
- data/lib/pod_builder/rome/post_install.rb +446 -0
- data/lib/pod_builder/rome/pre_install.rb +6 -0
- data/lib/pod_builder/templates/build_podfile.template +70 -0
- data/lib/pod_builder/templates/build_podspec.template +19 -0
- data/lib/pod_builder/version.rb +4 -0
- data/pod-builder.gemspec +37 -0
- metadata +240 -0
@@ -0,0 +1,73 @@
|
|
1
|
+
module PodBuilder
|
2
|
+
class Licenses
|
3
|
+
def self.write(licenses, all_buildable_items)
|
4
|
+
puts "Writing licenses".yellow
|
5
|
+
license_file_path = PodBuilder::project_path(Configuration.license_filename) + ".plist"
|
6
|
+
|
7
|
+
current_licenses = []
|
8
|
+
if File.exist?(license_file_path)
|
9
|
+
plist = CFPropertyList::List.new(:file => license_file_path)
|
10
|
+
dict = CFPropertyList.native_types(plist.value)
|
11
|
+
current_licenses = dict["PreferenceSpecifiers"]
|
12
|
+
|
13
|
+
if current_licenses.count > 0
|
14
|
+
licenses_header = current_licenses.shift
|
15
|
+
raise "\n\nUnexpected license found in header".red if licenses_header.has_key?("License")
|
16
|
+
end
|
17
|
+
if current_licenses.count > 0
|
18
|
+
license_footer = current_licenses.pop
|
19
|
+
raise "\n\nUnexpected license found in footer".red if license_footer.has_key?("License")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
if licenses.count > 0
|
24
|
+
licenses_header = licenses.shift
|
25
|
+
raise "\n\nUnexpected license found in header".red if licenses_header.has_key?("License")
|
26
|
+
license_footer = licenses.pop
|
27
|
+
raise "\n\nUnexpected license found in footer".red if license_footer.has_key?("License")
|
28
|
+
|
29
|
+
lincenses_titles = licenses.map { |x| x["Title"] }
|
30
|
+
current_licenses.select! { |x| !lincenses_titles.include?(x["Title"]) }
|
31
|
+
end
|
32
|
+
|
33
|
+
licenses += current_licenses # merge with existing license
|
34
|
+
licenses.uniq! { |x| x["Title"] }
|
35
|
+
licenses.sort_by! { |x| x["Title"] }
|
36
|
+
licenses.select! { |x| !Configuration.skip_licenses.include?(x["Title"]) }
|
37
|
+
licenses.select! { |x| all_buildable_items.map(&:root_name).include?(x["Title"]) } # Remove items that are no longer included
|
38
|
+
|
39
|
+
license_dict = {}
|
40
|
+
license_dict["PreferenceSpecifiers"] = [licenses_header, licenses, license_footer].compact.flatten
|
41
|
+
license_dict["StringsTable"] = "Acknowledgements"
|
42
|
+
license_dict["Title"] = license_dict["StringsTable"]
|
43
|
+
|
44
|
+
plist = CFPropertyList::List.new
|
45
|
+
plist.value = CFPropertyList.guess(license_dict)
|
46
|
+
plist.save(license_file_path, CFPropertyList::List::FORMAT_BINARY)
|
47
|
+
|
48
|
+
if licenses.count > 0
|
49
|
+
write_markdown(license_file_path)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def self.write_markdown(plist_path)
|
56
|
+
plist = CFPropertyList::List.new(:file => plist_path)
|
57
|
+
dict = CFPropertyList.native_types(plist.value)
|
58
|
+
licenses = dict["PreferenceSpecifiers"]
|
59
|
+
|
60
|
+
header = licenses.shift
|
61
|
+
|
62
|
+
markdown = []
|
63
|
+
markdown += ["# #{header["Title"]}", header["FooterText"], ""]
|
64
|
+
markdown += licenses.map { |x| ["## #{x["Title"]}", x["FooterText"], ""] }
|
65
|
+
|
66
|
+
markdown.flatten!
|
67
|
+
|
68
|
+
markdown_path = plist_path.chomp(File.extname(plist_path)) + ".md"
|
69
|
+
|
70
|
+
File.write(markdown_path, markdown.join("\n"))
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,700 @@
|
|
1
|
+
require 'json'
|
2
|
+
module PodBuilder
|
3
|
+
class Podfile
|
4
|
+
PODBUILDER_LOCK_ACTION = ["raise \"\\n🚨 Do not launch 'pod install' manually, use `pod_builder` instead!\\n\" if !File.exist?('pod_builder.lock')"].freeze
|
5
|
+
|
6
|
+
PRE_INSTALL_ACTIONS = ["Pod::Installer::Xcode::TargetValidator.send(:define_method, :verify_no_duplicate_framework_and_library_names) {}", "require 'pod_builder/podfile/pre_actions_swizzles'"].freeze
|
7
|
+
|
8
|
+
def self.from_podfile_items(items, analyzer, build_configuration, install_using_frameworks, build_catalyst, build_xcframeworks)
|
9
|
+
raise "\n\nno items".red unless items.count > 0
|
10
|
+
|
11
|
+
sources = analyzer.sources
|
12
|
+
|
13
|
+
cwd = File.dirname(File.expand_path(__FILE__))
|
14
|
+
podfile = File.read("#{cwd}/templates/build_podfile.template")
|
15
|
+
|
16
|
+
platform = analyzer.instance_variable_get("@result").targets.first.platform
|
17
|
+
|
18
|
+
podfile.sub!("%%%use_frameworks%%%", install_using_frameworks ? "use_frameworks!" : "")
|
19
|
+
podfile.sub!("%%%uses_frameworks%%%", install_using_frameworks ? "true" : "false")
|
20
|
+
podfile.sub!("%%%build_xcframeworks%%%", build_xcframeworks ? "true" : "false")
|
21
|
+
podfile.sub!("%%%build_catalyst%%%", build_catalyst ? "true" : "false")
|
22
|
+
|
23
|
+
podfile.sub!("%%%platform_name%%%", platform.name.to_s)
|
24
|
+
podfile.sub!("%%%deployment_version%%%", platform.deployment_target.version)
|
25
|
+
|
26
|
+
podfile.sub!("%%%sources%%%", sources.map { |x| "source '#{x.url}'" }.join("\n"))
|
27
|
+
|
28
|
+
podfile.sub!("%%%build_configuration%%%", build_configuration.capitalize)
|
29
|
+
|
30
|
+
podfile_build_settings = ""
|
31
|
+
|
32
|
+
pod_dependencies = {}
|
33
|
+
|
34
|
+
items.each do |item|
|
35
|
+
build_settings = Configuration.build_settings.dup
|
36
|
+
|
37
|
+
item_build_settings = Configuration.build_settings_overrides[item.name] || {}
|
38
|
+
|
39
|
+
# These settings need to be set as is to properly build frameworks
|
40
|
+
build_settings["SWIFT_COMPILATION_MODE"] = "wholemodule"
|
41
|
+
build_settings["ONLY_ACTIVE_ARCH"] = "NO"
|
42
|
+
build_settings["DEBUG_INFORMATION_FORMAT"] = "dwarf-with-dsym"
|
43
|
+
|
44
|
+
# https://thi.imhttps://thi.im/posts/swift-serialize-debugging-options/
|
45
|
+
build_settings["SWIFT_SERIALIZE_DEBUGGING_OPTIONS"] = "NO"
|
46
|
+
|
47
|
+
build_settings["IPHONEOS_DEPLOYMENT_TARGET"] = platform.deployment_target.version # Fix compilation warnings on Xcode 12
|
48
|
+
|
49
|
+
# Don't store .pcm info in binary, see https://forums.swift.org/t/swift-behavior-of-gmodules-and-dsyms/23211/3
|
50
|
+
build_settings["CLANG_ENABLE_MODULE_DEBUGGING"] = "NO"
|
51
|
+
build_settings["OTHER_SWIFT_FLAGS"] = "$(inherited) -Xfrontend -no-clang-module-breadcrumbs"
|
52
|
+
|
53
|
+
# Ignore deprecation warnings
|
54
|
+
build_settings["GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS"] = "NO"
|
55
|
+
|
56
|
+
# Improve compile speed
|
57
|
+
build_settings["COMPILER_INDEX_STORE_ENABLE"] = "NO"
|
58
|
+
build_settings["SWIFT_INDEX_STORE_ENABLE"] = "NO"
|
59
|
+
build_settings["MTL_ENABLE_INDEX_STORE"] = "NO"
|
60
|
+
|
61
|
+
if Configuration.build_system == "Legacy"
|
62
|
+
build_settings["BUILD_LIBRARY_FOR_DISTRIBUTION"] = "NO"
|
63
|
+
raise "\n\nCan't enable library evolution support with legacy build system!".red if Configuration.library_evolution_support
|
64
|
+
elsif Configuration.library_evolution_support
|
65
|
+
build_settings["BUILD_LIBRARY_FOR_DISTRIBUTION"] = "YES"
|
66
|
+
end
|
67
|
+
if Configuration.build_xcframeworks
|
68
|
+
build_settings["BUILD_LIBRARY_FOR_DISTRIBUTION"] = "YES"
|
69
|
+
end
|
70
|
+
|
71
|
+
build_settings["SWIFT_VERSION"] = item_build_settings["SWIFT_VERSION"] || item.swift_version || project_swift_version(analyzer)
|
72
|
+
|
73
|
+
if build_settings["ENABLE_BITCODE"] == "YES"
|
74
|
+
build_settings["BITCODE_GENERATION_MODE"] = "bitcode"
|
75
|
+
end
|
76
|
+
|
77
|
+
item_build_settings.each do |k, v|
|
78
|
+
build_settings[k] = v
|
79
|
+
end
|
80
|
+
|
81
|
+
podfile_build_settings += "set_build_settings(\"#{item.root_name}\", #{build_settings.to_s}, installer)\n "
|
82
|
+
|
83
|
+
dependency_names = item.dependency_names.map { |x|
|
84
|
+
if x.split("/").first == item.root_name
|
85
|
+
next nil # remove dependency to parent spec
|
86
|
+
end
|
87
|
+
if overridded_module_name = Configuration.spec_overrides.fetch(x, {})["module_name"] # this might no longer be needed after
|
88
|
+
next overridded_module_name
|
89
|
+
end
|
90
|
+
}.compact
|
91
|
+
|
92
|
+
if dependency_names.count > 0
|
93
|
+
pod_dependencies[item.root_name] = dependency_names
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
podfile.sub!("%%%build_settings%%%", podfile_build_settings)
|
98
|
+
|
99
|
+
podfile.sub!("%%%build_system%%%", Configuration.build_system)
|
100
|
+
|
101
|
+
podfile.sub!("%%%pods%%%", "\"#{items.map(&:name).join('", "')}\"")
|
102
|
+
|
103
|
+
podfile.sub!("%%%pods_dependencies%%%", pod_dependencies.to_s)
|
104
|
+
|
105
|
+
podfile.sub!("%%%targets%%%", items.map(&:entry).join("\n "))
|
106
|
+
|
107
|
+
return podfile
|
108
|
+
end
|
109
|
+
|
110
|
+
def self.write_restorable(updated_pods, podfile_items, analyzer)
|
111
|
+
unless Configuration.restore_enabled && (podfile_items.count + updated_pods.count) > 0
|
112
|
+
return
|
113
|
+
end
|
114
|
+
|
115
|
+
puts "Writing Restore Podfile".yellow
|
116
|
+
|
117
|
+
podfile_items = podfile_items.dup
|
118
|
+
podfile_restore_path = PodBuilder::basepath("Podfile.restore")
|
119
|
+
podfile_path = PodBuilder::basepath("Podfile")
|
120
|
+
|
121
|
+
if File.exist?(podfile_restore_path)
|
122
|
+
restore_podfile_items = podfile_items_at(podfile_restore_path, include_prebuilt = true)
|
123
|
+
|
124
|
+
podfile_items.map! { |podfile_item|
|
125
|
+
if updated_pod = updated_pods.detect { |x| x.name == podfile_item.name } then
|
126
|
+
updated_pod
|
127
|
+
elsif updated_pods.any? { |x| podfile_item.root_name == x.root_name } == false && # podfile_item shouldn't be among those being updated (including root specification)
|
128
|
+
restored_pod = restore_podfile_items.detect { |x| x.name == podfile_item.name }
|
129
|
+
restored_pod
|
130
|
+
else
|
131
|
+
podfile_item
|
132
|
+
end
|
133
|
+
}
|
134
|
+
end
|
135
|
+
|
136
|
+
result_targets = analyzer.instance_variable_get("@result").targets.map(&:name)
|
137
|
+
podfile_content = ["# Autogenerated by PodBuilder (https://github.com/Subito-it/PodBuilder)", "# Please don't modify this file", "\n"]
|
138
|
+
podfile_content += analyzer.podfile.sources.map { |x| "source '#{x}'" }
|
139
|
+
podfile_content += ["", "use_frameworks!", ""]
|
140
|
+
|
141
|
+
# multiple platforms not (yet) supported
|
142
|
+
# https://github.com/CocoaPods/Rome/issues/37
|
143
|
+
platform = analyzer.instance_variable_get("@result").targets.first.platform
|
144
|
+
podfile_content += ["platform :#{platform.name}, '#{platform.deployment_target.version}'", ""]
|
145
|
+
|
146
|
+
analyzer.instance_variable_get("@result").specs_by_target.each do |target, specifications|
|
147
|
+
target_name = target.name.to_s
|
148
|
+
|
149
|
+
unless result_targets.select { |x| x.end_with?(target_name) }.count > 0
|
150
|
+
next
|
151
|
+
end
|
152
|
+
|
153
|
+
podfile_content.push("target '#{target_name}' do")
|
154
|
+
|
155
|
+
if project_path = target.user_project_path
|
156
|
+
podfile_content.push("\tproject '#{project_path}'")
|
157
|
+
end
|
158
|
+
|
159
|
+
specifications.each do |spec|
|
160
|
+
item = podfile_items.detect { |x| x.name == spec.name }
|
161
|
+
if podfile_items.map(&:name).include?(spec.name)
|
162
|
+
podfile_content.push("\t#{item.entry}")
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
podfile_content.push("end\n")
|
167
|
+
end
|
168
|
+
|
169
|
+
File.write(podfile_restore_path, podfile_content.join("\n"))
|
170
|
+
end
|
171
|
+
|
172
|
+
def self.write_prebuilt(all_buildable_items, analyzer)
|
173
|
+
if Configuration.react_native_project
|
174
|
+
return write_prebuilt_react_native(all_buildable_items, analyzer)
|
175
|
+
end
|
176
|
+
|
177
|
+
puts "Updating Application Podfile".yellow
|
178
|
+
|
179
|
+
explicit_deps = analyzer.explicit_pods()
|
180
|
+
explicit_deps.map! { |t| all_buildable_items.detect { |x| x.name == t.name } }
|
181
|
+
explicit_deps.uniq!
|
182
|
+
podbuilder_podfile_path = PodBuilder::basepath("Podfile")
|
183
|
+
rel_path = Pathname.new(podbuilder_podfile_path).relative_path_from(Pathname.new(PodBuilder::project_path)).to_s
|
184
|
+
|
185
|
+
podfile_content = File.read(podbuilder_podfile_path)
|
186
|
+
|
187
|
+
exclude_lines = Podfile::PODBUILDER_LOCK_ACTION.map { |x| strip_line(x) }
|
188
|
+
|
189
|
+
prebuilt_lines = ["# Autogenerated by PodBuilder (https://github.com/Subito-it/PodBuilder)\n", "# Any change to this file should be done on #{rel_path}\n", "\n"]
|
190
|
+
podfile_content.each_line do |line|
|
191
|
+
stripped_line = strip_line(line)
|
192
|
+
if exclude_lines.include?(stripped_line)
|
193
|
+
next
|
194
|
+
end
|
195
|
+
|
196
|
+
if pod_name = pod_definition_in(line, true)
|
197
|
+
if podfile_item = all_buildable_items.detect { |x| x.name == pod_name }
|
198
|
+
marker = podfile_item.prebuilt_marker()
|
199
|
+
|
200
|
+
non_explicit_dependencies = podfile_item.recursive_dependencies(all_buildable_items) - explicit_deps
|
201
|
+
non_explicit_dependencies_root_names = non_explicit_dependencies.map(&:root_name).uniq.filter { |t| t != podfile_item.root_name }
|
202
|
+
non_explicit_dependencies = non_explicit_dependencies_root_names.map { |x|
|
203
|
+
if item = all_buildable_items.detect { |t| x == t.name }
|
204
|
+
item
|
205
|
+
else
|
206
|
+
item = all_buildable_items.detect { |t| x == t.root_name }
|
207
|
+
end
|
208
|
+
}.compact
|
209
|
+
|
210
|
+
non_explicit_dependencies.each do |dep|
|
211
|
+
dep_item = all_buildable_items.detect { |x| x.name == dep.name }
|
212
|
+
|
213
|
+
if File.exist?(dep_item.prebuilt_podspec_path) && !dep_item.is_prebuilt
|
214
|
+
pod_name = dep_item.prebuilt_entry(false, false)
|
215
|
+
prebuilt_lines.push("#{line.detect_indentation}#{pod_name}#{marker}\n")
|
216
|
+
end
|
217
|
+
|
218
|
+
explicit_deps.push(dep)
|
219
|
+
end
|
220
|
+
|
221
|
+
if File.exist?(podfile_item.prebuilt_podspec_path) && !podfile_item.is_prebuilt
|
222
|
+
prebuilt_lines.push("#{line.detect_indentation}#{podfile_item.prebuilt_entry}\n")
|
223
|
+
next
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
prebuilt_lines.push(line)
|
229
|
+
end
|
230
|
+
|
231
|
+
podfile_content = prebuilt_lines.join
|
232
|
+
|
233
|
+
podfile_content = Podfile.update_path_entries(podfile_content, Podfile.method(:podfile_path_transform))
|
234
|
+
podfile_content = Podfile.update_project_entries(podfile_content, Podfile.method(:podfile_path_transform))
|
235
|
+
podfile_content = Podfile.update_require_entries(podfile_content, Podfile.method(:podfile_path_transform))
|
236
|
+
|
237
|
+
podfile_content = add_pre_install_actions(podfile_content)
|
238
|
+
|
239
|
+
project_podfile_path = PodBuilder::project_path("Podfile")
|
240
|
+
File.write(project_podfile_path, podfile_content)
|
241
|
+
end
|
242
|
+
|
243
|
+
def self.write_prebuilt_react_native(all_buildable_items, analyzer)
|
244
|
+
puts "Updating Application Podfile".yellow
|
245
|
+
|
246
|
+
podbuilder_podfile_path = PodBuilder::basepath("Podfile")
|
247
|
+
rel_path = Pathname.new(podbuilder_podfile_path).relative_path_from(Pathname.new(PodBuilder::project_path)).to_s
|
248
|
+
|
249
|
+
podfile_content = ["# Autogenerated by PodBuilder (https://github.com/Subito-it/PodBuilder)\n", "# Any change to this file should be done on #{rel_path}\n", "\n"].join
|
250
|
+
podfile_content += analyzer.podfile.pb_to_s(all_buildable_items)
|
251
|
+
|
252
|
+
podfile_content = Podfile.update_path_entries(podfile_content, PodfileCP.method(:podfile_path_transform))
|
253
|
+
podfile_content = Podfile.update_project_entries(podfile_content, Podfile.method(:podfile_path_transform))
|
254
|
+
podfile_content = Podfile.update_require_entries(podfile_content, Podfile.method(:podfile_path_transform))
|
255
|
+
|
256
|
+
podfile_content = add_pre_install_actions(podfile_content)
|
257
|
+
|
258
|
+
project_podfile_path = PodBuilder::project_path("Podfile")
|
259
|
+
File.write(project_podfile_path, podfile_content)
|
260
|
+
end
|
261
|
+
|
262
|
+
def self.install
|
263
|
+
puts "Running pod install".yellow
|
264
|
+
|
265
|
+
Dir.chdir(PodBuilder::project_path) do
|
266
|
+
bundler_prefix = Configuration.use_bundler ? "bundle exec " : ""
|
267
|
+
system("#{bundler_prefix}pod install;")
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
def self.strip_line(line)
|
272
|
+
stripped_line = line.strip
|
273
|
+
return stripped_line.gsub("\"", "'").gsub(" ", "").gsub("\t", "").gsub("\n", "")
|
274
|
+
end
|
275
|
+
|
276
|
+
def self.pod_definition_in(line, include_commented)
|
277
|
+
stripped_line = strip_line(line)
|
278
|
+
matches = stripped_line.match(/(^pod')(.*?)(')/)
|
279
|
+
|
280
|
+
if matches&.size == 4 && (include_commented || !stripped_line.start_with?("#"))
|
281
|
+
return matches[2]
|
282
|
+
else
|
283
|
+
return nil
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
def self.restore_podfile_clean(pod_items)
|
288
|
+
unless Configuration.restore_enabled
|
289
|
+
return
|
290
|
+
end
|
291
|
+
|
292
|
+
# remove pods that are no longer listed in pod_items
|
293
|
+
podfile_restore_path = PodBuilder::basepath("Podfile.restore")
|
294
|
+
unless File.exist?(podfile_restore_path)
|
295
|
+
return
|
296
|
+
end
|
297
|
+
|
298
|
+
restore_content = File.read(podfile_restore_path)
|
299
|
+
|
300
|
+
cleaned_lines = []
|
301
|
+
restore_content.each_line do |line|
|
302
|
+
if pod_name = pod_definition_in(line, false)
|
303
|
+
if pod_items.map(&:name).include?(pod_name)
|
304
|
+
cleaned_lines.push(line)
|
305
|
+
end
|
306
|
+
else
|
307
|
+
cleaned_lines.push(line)
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
File.write(podfile_restore_path, cleaned_lines.join)
|
312
|
+
end
|
313
|
+
|
314
|
+
def self.restore_file_sanity_check
|
315
|
+
unless Configuration.restore_enabled
|
316
|
+
return nil
|
317
|
+
end
|
318
|
+
|
319
|
+
puts "Checking Podfile.restore".yellow
|
320
|
+
|
321
|
+
podfile_restore_path = PodBuilder::basepath("Podfile.restore")
|
322
|
+
unless File.exist?(podfile_restore_path)
|
323
|
+
return
|
324
|
+
end
|
325
|
+
|
326
|
+
error = nil
|
327
|
+
|
328
|
+
begin
|
329
|
+
File.rename(PodBuilder::basepath("Podfile"), PodBuilder::basepath("Podfile.tmp2"))
|
330
|
+
File.rename(podfile_restore_path, PodBuilder::basepath("Podfile"))
|
331
|
+
|
332
|
+
Analyze.installer_at(PodBuilder::basepath, false)
|
333
|
+
rescue Exception => e
|
334
|
+
error = e.to_s
|
335
|
+
ensure
|
336
|
+
File.rename(PodBuilder::basepath("Podfile"), podfile_restore_path)
|
337
|
+
File.rename(PodBuilder::basepath("Podfile.tmp2"), PodBuilder::basepath("Podfile"))
|
338
|
+
end
|
339
|
+
|
340
|
+
if !error.nil?
|
341
|
+
FileUtils.rm(podfile_restore_path)
|
342
|
+
end
|
343
|
+
|
344
|
+
return error
|
345
|
+
end
|
346
|
+
|
347
|
+
def self.sanity_check
|
348
|
+
podfile_path = PodBuilder::basepath("Podfile")
|
349
|
+
unless File.exist?(podfile_path)
|
350
|
+
return
|
351
|
+
end
|
352
|
+
|
353
|
+
File.read(podfile_path).each_line do |line|
|
354
|
+
stripped_line = strip_line(line)
|
355
|
+
unless !stripped_line.start_with?("#")
|
356
|
+
next
|
357
|
+
end
|
358
|
+
|
359
|
+
if stripped_line.match(/(pod')(.*?)(')/) != nil
|
360
|
+
starting_def_found = stripped_line.start_with?("def") && (line.match("\s*def\s") != nil)
|
361
|
+
raise "\n\nUnsupported single line def/pod. `def` and `pod` shouldn't be on the same line, please modify the following line:\n#{line}".red if starting_def_found
|
362
|
+
end
|
363
|
+
end
|
364
|
+
end
|
365
|
+
|
366
|
+
def self.resolve_pod_names(names, all_buildable_items)
|
367
|
+
resolved_names = []
|
368
|
+
|
369
|
+
names.each do |name|
|
370
|
+
if item = all_buildable_items.detect { |t| t.root_name.downcase == name.downcase }
|
371
|
+
resolved_names.push(item.root_name)
|
372
|
+
end
|
373
|
+
end
|
374
|
+
|
375
|
+
return resolved_names.uniq
|
376
|
+
end
|
377
|
+
|
378
|
+
def self.resolve_pod_names_from_podfile(names)
|
379
|
+
resolved_names = []
|
380
|
+
|
381
|
+
# resolve potentially wrong pod name case
|
382
|
+
podfile_path = PodBuilder::basepath("Podfile")
|
383
|
+
content = File.read(podfile_path)
|
384
|
+
|
385
|
+
current_section = ""
|
386
|
+
content.each_line do |line|
|
387
|
+
matches = line.gsub("\"", "'").match(/pod '(.*?)'/)
|
388
|
+
if matches&.size == 2
|
389
|
+
if resolved_name = names.detect { |t| matches[1].split("/").first.downcase == t.downcase }
|
390
|
+
resolved_names.push(matches[1].split("/").first)
|
391
|
+
end
|
392
|
+
end
|
393
|
+
end
|
394
|
+
|
395
|
+
resolved_names.uniq
|
396
|
+
end
|
397
|
+
|
398
|
+
def self.install_using_frameworks(analyzer)
|
399
|
+
target_settings = analyzer.podfile.target_definition_list.map(&:uses_frameworks?).uniq
|
400
|
+
if target_settings.count == 1
|
401
|
+
return target_settings.first
|
402
|
+
elsif target_settings.count > 1
|
403
|
+
raise "\n\n'use_frameworks!' should be declared only once at Podfile root level (not nested in targets)".red
|
404
|
+
else
|
405
|
+
raise "\n\nFailed detecting use_frameworks!"
|
406
|
+
end
|
407
|
+
|
408
|
+
return true
|
409
|
+
end
|
410
|
+
|
411
|
+
private
|
412
|
+
|
413
|
+
def self.podfile_path_transform(path)
|
414
|
+
use_absolute_paths = false
|
415
|
+
podfile_path = PodBuilder::project_path("Podfile")
|
416
|
+
original_basepath = PodBuilder::basepath
|
417
|
+
|
418
|
+
podfile_base_path = Pathname.new(File.dirname(podfile_path))
|
419
|
+
|
420
|
+
original_path = Pathname.new(File.join(original_basepath, path))
|
421
|
+
replace_path = original_path.relative_path_from(podfile_base_path)
|
422
|
+
if use_absolute_paths
|
423
|
+
replace_path = replace_path.expand_path(podfile_base_path)
|
424
|
+
end
|
425
|
+
|
426
|
+
return replace_path
|
427
|
+
end
|
428
|
+
|
429
|
+
def self.indentation_from_string(content)
|
430
|
+
lines = content.split("\n").select { |x| !x.empty? }
|
431
|
+
|
432
|
+
if lines.count > 2
|
433
|
+
lines[0..-2].each_with_index do |current_line, index|
|
434
|
+
next_line = lines[index + 1]
|
435
|
+
next_line_first_char = next_line.chars.first
|
436
|
+
current_doesnt_begin_with_whitespace = current_line[/\A\S*/] != nil
|
437
|
+
|
438
|
+
if current_doesnt_begin_with_whitespace && [" ", "\t"].include?(next_line_first_char)
|
439
|
+
return next_line[/\A\s*/]
|
440
|
+
end
|
441
|
+
end
|
442
|
+
end
|
443
|
+
|
444
|
+
return " "
|
445
|
+
end
|
446
|
+
|
447
|
+
def self.project_swift_version(analyzer)
|
448
|
+
swift_versions = analyzer.instance_variable_get("@result").targets.map { |x| x.target_definition.swift_version }.compact.uniq
|
449
|
+
|
450
|
+
raise "\n\nFound different Swift versions in targets. Expecting one, got `#{swift_versions}`".red if swift_versions.count > 1
|
451
|
+
|
452
|
+
return swift_versions.first || PodBuilder::system_swift_version
|
453
|
+
end
|
454
|
+
|
455
|
+
def self.podfile_items_at(podfile_path, include_prebuilt = false)
|
456
|
+
raise "\n\nExpecting basepath folder!".red if !File.exist?(PodBuilder::basepath("Podfile"))
|
457
|
+
|
458
|
+
if File.basename(podfile_path) != "Podfile"
|
459
|
+
File.rename(PodBuilder::basepath("Podfile"), PodBuilder::basepath("Podfile.tmp"))
|
460
|
+
FileUtils.cp(podfile_path, PodBuilder::basepath("Podfile"))
|
461
|
+
end
|
462
|
+
|
463
|
+
current_dir = Dir.pwd
|
464
|
+
Dir.chdir(File.dirname(podfile_path))
|
465
|
+
|
466
|
+
buildable_items = []
|
467
|
+
begin
|
468
|
+
installer, analyzer = Analyze.installer_at(PodBuilder::basepath)
|
469
|
+
|
470
|
+
podfile_items = Analyze.podfile_items(installer, analyzer)
|
471
|
+
buildable_items = podfile_items.select { |item| include_prebuilt || !item.is_prebuilt }
|
472
|
+
rescue Exception => e
|
473
|
+
raise e
|
474
|
+
ensure
|
475
|
+
Dir.chdir(current_dir)
|
476
|
+
|
477
|
+
if File.basename(podfile_path) != "Podfile"
|
478
|
+
File.rename(PodBuilder::basepath("Podfile.tmp"), PodBuilder::basepath("Podfile"))
|
479
|
+
end
|
480
|
+
end
|
481
|
+
|
482
|
+
return buildable_items
|
483
|
+
end
|
484
|
+
|
485
|
+
def self.add_install_block(podfile_content)
|
486
|
+
return add(PODBUILDER_LOCK_ACTION, "pre_install", podfile_content)
|
487
|
+
end
|
488
|
+
|
489
|
+
def self.add_pre_install_actions(podfile_content)
|
490
|
+
return add(PRE_INSTALL_ACTIONS + [" "], "pre_install", podfile_content)
|
491
|
+
end
|
492
|
+
|
493
|
+
def self.add(entries, marker, podfile_content)
|
494
|
+
file_indentation = indentation_from_string(podfile_content)
|
495
|
+
|
496
|
+
entries = entries.map { |x| "#{file_indentation}#{x}\n"}
|
497
|
+
|
498
|
+
marker_found = false
|
499
|
+
podfile_lines = []
|
500
|
+
podfile_content.each_line do |line|
|
501
|
+
stripped_line = strip_line(line)
|
502
|
+
|
503
|
+
podfile_lines.push(line)
|
504
|
+
if stripped_line.start_with?("#{marker}do|")
|
505
|
+
marker_found = true
|
506
|
+
podfile_lines.push(entries)
|
507
|
+
end
|
508
|
+
end
|
509
|
+
|
510
|
+
if !marker_found
|
511
|
+
if podfile_lines.last.strip.length > 0
|
512
|
+
podfile_lines.push("\n")
|
513
|
+
end
|
514
|
+
podfile_lines.push("\n#{marker} do |installer|\n")
|
515
|
+
podfile_lines.push(entries)
|
516
|
+
podfile_lines.push("end\n")
|
517
|
+
end
|
518
|
+
|
519
|
+
return podfile_lines.join
|
520
|
+
end
|
521
|
+
|
522
|
+
def self.update_path_entries(podfile_content, path_transform)
|
523
|
+
regex = "(\s*pod\s*['|\"])(.*?)(['|\"])(.*?):(path|podspec)(\s*=>\s*['|\"])(.*?)(['|\"])"
|
524
|
+
|
525
|
+
podfile_lines = []
|
526
|
+
podfile_content.each_line do |line|
|
527
|
+
stripped_line = strip_line(line)
|
528
|
+
matches = line.match(/#{regex}/)
|
529
|
+
|
530
|
+
if matches&.size == 9 && !stripped_line.start_with?("#")
|
531
|
+
pod_name = matches[2]
|
532
|
+
path = matches[7]
|
533
|
+
|
534
|
+
is_absolute = ["~", "/"].include?(path[0])
|
535
|
+
unless !PodBuilder::prebuiltpath.end_with?(path) && !is_absolute
|
536
|
+
podfile_lines.push(line)
|
537
|
+
next
|
538
|
+
end
|
539
|
+
|
540
|
+
replace_path = path_transform.call(path)
|
541
|
+
|
542
|
+
updated_path_line = line.gsub(/#{regex}/, '\1\2\3\4:\5\6' + replace_path.to_s + '\8\9')
|
543
|
+
podfile_lines.push(updated_path_line)
|
544
|
+
else
|
545
|
+
podfile_lines.push(line)
|
546
|
+
end
|
547
|
+
end
|
548
|
+
|
549
|
+
return podfile_lines.join
|
550
|
+
end
|
551
|
+
|
552
|
+
def self.update_project_entries(podfile_content, path_transform)
|
553
|
+
regex = "(\s*project\s*['|\"])(.*?)(['|\"])"
|
554
|
+
|
555
|
+
podfile_lines = []
|
556
|
+
podfile_content.each_line do |line|
|
557
|
+
stripped_line = strip_line(line)
|
558
|
+
matches = line.match(/#{regex}/)
|
559
|
+
|
560
|
+
if matches&.size == 4 && !stripped_line.start_with?("#")
|
561
|
+
path = matches[2]
|
562
|
+
|
563
|
+
is_absolute = ["~", "/"].include?(path[0])
|
564
|
+
unless !is_absolute
|
565
|
+
podfile_lines.push(line)
|
566
|
+
next
|
567
|
+
end
|
568
|
+
|
569
|
+
replace_path = path_transform.call(path)
|
570
|
+
|
571
|
+
updated_path_line = line.gsub(/#{regex}/, '\1' + replace_path.to_s + '\3\4')
|
572
|
+
podfile_lines.push(updated_path_line)
|
573
|
+
else
|
574
|
+
podfile_lines.push(line)
|
575
|
+
end
|
576
|
+
end
|
577
|
+
|
578
|
+
return podfile_lines.join
|
579
|
+
end
|
580
|
+
|
581
|
+
def self.update_require_entries(podfile_content, path_transform)
|
582
|
+
regex = "(\s*require_relative\s*['|\"])(.*?)(['|\"])"
|
583
|
+
|
584
|
+
podfile_lines = []
|
585
|
+
podfile_content.each_line do |line|
|
586
|
+
stripped_line = strip_line(line)
|
587
|
+
matches = line.match(/#{regex}/)
|
588
|
+
|
589
|
+
if matches&.size == 4 && !stripped_line.start_with?("#")
|
590
|
+
path = matches[2]
|
591
|
+
|
592
|
+
is_absolute = ["~", "/"].include?(path[0])
|
593
|
+
unless !is_absolute
|
594
|
+
podfile_lines.push(line)
|
595
|
+
next
|
596
|
+
end
|
597
|
+
|
598
|
+
replace_path = path_transform.call(path)
|
599
|
+
|
600
|
+
updated_path_line = line.gsub(/#{regex}/, '\1' + replace_path.to_s + '\3\4')
|
601
|
+
podfile_lines.push(updated_path_line)
|
602
|
+
else
|
603
|
+
podfile_lines.push(line)
|
604
|
+
end
|
605
|
+
end
|
606
|
+
|
607
|
+
return podfile_lines.join
|
608
|
+
end
|
609
|
+
|
610
|
+
def self.prepare_for_react_native_write_pb_configuration(podfile_content)
|
611
|
+
base = File.expand_path(File.join(PodBuilder::project_path, ".."))
|
612
|
+
bin_js = Dir.glob("#{base}/node_modules/@react-native-community/cli/build/bin.js")
|
613
|
+
|
614
|
+
raise "\n\nReact native cli bin_js not found! Did you run yarn install?".red unless bin_js.count == 1
|
615
|
+
bin_js = bin_js.first
|
616
|
+
|
617
|
+
config_dest_path = PodBuilder::basepath("rn_config.json")
|
618
|
+
|
619
|
+
raise "\n\nFailed generating react native configuration file".red unless system("node '#{bin_js}' config > #{config_dest_path}")
|
620
|
+
|
621
|
+
content = File.read(config_dest_path)
|
622
|
+
|
623
|
+
content.gsub!(PodBuilder::project_path, "..")
|
624
|
+
content.gsub!(File.expand_path(PodBuilder::project_path("..")), "../..")
|
625
|
+
|
626
|
+
json = JSON.parse(content)
|
627
|
+
begin
|
628
|
+
json["project"]["ios"]["sourceDir"] = "./"
|
629
|
+
json["project"]["ios"]["podfile"] = "./"
|
630
|
+
rescue => exception
|
631
|
+
raise "\n\nFailed updating react native configuration json".red
|
632
|
+
end
|
633
|
+
|
634
|
+
File.write(config_dest_path, JSON.pretty_generate(json))
|
635
|
+
|
636
|
+
return "rn_config = JSON.load(File.read(\"rn_config.json\")) # pb added\n\n" + podfile_content
|
637
|
+
end
|
638
|
+
|
639
|
+
def self.prepare_for_react_native_rn_pods_file(podfile_content)
|
640
|
+
lines = []
|
641
|
+
podfile_content.each_line do |line|
|
642
|
+
if line.include?("use_react_native!")
|
643
|
+
matches = line.match(/(\s*)/)
|
644
|
+
unless matches&.size == 2
|
645
|
+
return podfile_content
|
646
|
+
end
|
647
|
+
|
648
|
+
indentation = matches[1]
|
649
|
+
lines.push("#{indentation}use_react_native!(:path => rn_config[\"reactNativePath\"]) # pb added\n")
|
650
|
+
lines.push("#{indentation}# #{line.strip} # pb removed\n")
|
651
|
+
else
|
652
|
+
lines.push(line)
|
653
|
+
end
|
654
|
+
end
|
655
|
+
|
656
|
+
return lines.join
|
657
|
+
end
|
658
|
+
|
659
|
+
def self.prepare_for_react_native_native_modules_file(podfile_content)
|
660
|
+
lines = []
|
661
|
+
podfile_content.each_line do |line|
|
662
|
+
if line.include?("use_native_modules!")
|
663
|
+
matches = line.match(/(\s*)/)
|
664
|
+
unless matches&.size == 2
|
665
|
+
return podfile_content
|
666
|
+
end
|
667
|
+
|
668
|
+
indentation = matches[1]
|
669
|
+
lines.push("#{indentation}use_native_modules!(rn_config) # pb added\n")
|
670
|
+
lines.push("#{indentation}# #{line.strip} # pb removed\n")
|
671
|
+
else
|
672
|
+
lines.push(line)
|
673
|
+
end
|
674
|
+
end
|
675
|
+
|
676
|
+
return lines.join
|
677
|
+
end
|
678
|
+
|
679
|
+
def self.prepare_for_react_native(podfile_content)
|
680
|
+
original_podfile_content = podfile_content.dup
|
681
|
+
|
682
|
+
podfile_content = prepare_for_react_native_write_pb_configuration(podfile_content)
|
683
|
+
content = prepare_for_react_native_rn_pods_file(podfile_content)
|
684
|
+
if content == podfile_content
|
685
|
+
return original_podfile_content
|
686
|
+
end
|
687
|
+
podfile_content = content
|
688
|
+
content = prepare_for_react_native_native_modules_file(podfile_content)
|
689
|
+
if content == podfile_content
|
690
|
+
return original_podfile_content
|
691
|
+
end
|
692
|
+
podfile_content = content
|
693
|
+
|
694
|
+
Configuration.build_using_repo_paths = true
|
695
|
+
Configuration.react_native_project = true
|
696
|
+
|
697
|
+
return podfile_content
|
698
|
+
end
|
699
|
+
end
|
700
|
+
end
|