cocoapods-binary-gcp 0.0.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.
@@ -0,0 +1,3 @@
1
+ module CocoapodsBinary
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,101 @@
1
+ require_relative '../tool/tool'
2
+ require_relative 'prebuild_sandbox'
3
+
4
+ module Pod
5
+
6
+ # a flag that indicate stages
7
+ class_attr_accessor :is_prebuild_stage
8
+
9
+
10
+ # a switch for the `pod` DSL to make it only valid for ':binary => true'
11
+ class Podfile
12
+ module DSL
13
+
14
+ @@enable_prebuild_patch = false
15
+
16
+ # when enable, `pod` function will skip all pods without 'prebuild => true'
17
+ def self.enable_prebuild_patch(value)
18
+ @@enable_prebuild_patch = value
19
+ end
20
+
21
+ # --- patch ---
22
+ old_method = instance_method(:pod)
23
+
24
+ define_method(:pod) do |name, *args|
25
+ if !@@enable_prebuild_patch
26
+ old_method.bind(self).(name, *args)
27
+ return
28
+ end
29
+
30
+ # patched content
31
+ should_prebuild = Pod::Podfile::DSL.prebuild_all
32
+ local = false
33
+
34
+ options = args.last
35
+ if options.is_a?(Hash) and options[Pod::Prebuild.keyword] != nil
36
+ should_prebuild = options[Pod::Prebuild.keyword]
37
+ local = (options[:path] != nil)
38
+ end
39
+
40
+ if not Pod::Podfile::DSL.except_binary_list.nil?
41
+ should_prebuild = !Pod::Podfile::DSL.except_binary_list.include?(name)
42
+ end
43
+
44
+ if should_prebuild and (not local)
45
+ old_method.bind(self).(name, *args)
46
+ end
47
+ end
48
+ end
49
+ end
50
+
51
+
52
+ # a force disable option for integral
53
+ class Installer
54
+ def self.force_disable_integration(value)
55
+ @@force_disable_integration = value
56
+ end
57
+
58
+ old_method = instance_method(:integrate_user_project)
59
+ define_method(:integrate_user_project) do
60
+ if @@force_disable_integration
61
+ return
62
+ end
63
+ old_method.bind(self).()
64
+ end
65
+ end
66
+
67
+ # a option to disable install complete message
68
+ class Installer
69
+ def self.disable_install_complete_message(value)
70
+ @@disable_install_complete_message = value
71
+ end
72
+
73
+ old_method = instance_method(:print_post_install_message)
74
+ define_method(:print_post_install_message) do
75
+ if @@disable_install_complete_message
76
+ return
77
+ end
78
+ old_method.bind(self).()
79
+ end
80
+ end
81
+
82
+ # option to disable write lockfiles
83
+ class Config
84
+
85
+ @@force_disable_write_lockfile = false
86
+ def self.force_disable_write_lockfile(value)
87
+ @@force_disable_write_lockfile = value
88
+ end
89
+
90
+ old_method = instance_method(:lockfile_path)
91
+ define_method(:lockfile_path) do
92
+ if @@force_disable_write_lockfile
93
+ # As config is a singleton, sandbox_root refer to the standard sandbox.
94
+ return PrebuildSandbox.from_standard_sanbox_path(sandbox_root).root + 'Manifest.lock.tmp'
95
+ else
96
+ return old_method.bind(self).()
97
+ end
98
+ end
99
+ end
100
+
101
+ end
@@ -0,0 +1,78 @@
1
+ # ABOUT NAMES
2
+ #
3
+ # There are many kinds of name in cocoapods. Two main names are widely used in this plugin.
4
+ # - root_spec.name (spec.root_name, targe.pod_name):
5
+ # aka "pod_name"
6
+ # the name we use in podfile. the concept.
7
+ #
8
+ # - target.name:
9
+ # aka "target_name"
10
+ # the name of the final target in xcode project. the final real thing.
11
+ #
12
+ # One pod may have multiple targets in xcode project, due to one pod can be used in mutiple
13
+ # platform simultaneously. So one `root_spec.name` may have multiple coresponding `target.name`s.
14
+ # Therefore, map a spec to/from targets is a little complecated. It's one to many.
15
+ #
16
+
17
+ # Tool to transform Pod_name to target efficiently
18
+ module Pod
19
+ def self.fast_get_targets_for_pod_name(pod_name, targets, cache)
20
+ pod_name_to_targets_hash = nil
21
+ if cache.empty?
22
+ pod_name_to_targets_hash = targets.reduce({}) do |sum, target|
23
+ array = sum[target.pod_name] || []
24
+ array << target
25
+ sum[target.pod_name] = array
26
+ sum
27
+ end
28
+ cache << pod_name_to_targets_hash
29
+ else
30
+ pod_name_to_targets_hash = cache.first
31
+ end
32
+
33
+ pod_name_to_targets_hash[pod_name] || []
34
+ end
35
+ end
36
+
37
+
38
+
39
+
40
+
41
+
42
+ # Target:
43
+
44
+ # def pod_name
45
+ # root_spec.name
46
+ # end
47
+
48
+ # def name
49
+ # pod_name + #{scope_suffix}
50
+ # end
51
+
52
+ # def product_module_name
53
+ # root_spec.module_name
54
+ # end
55
+
56
+ # def framework_name
57
+ # "#{product_module_name}.framework"
58
+ # end
59
+
60
+ # def product_name
61
+ # if requires_frameworks?
62
+ # framework_name
63
+ # else
64
+ # static_library_name
65
+ # end
66
+ # end
67
+
68
+ # def product_basename
69
+ # if requires_frameworks?
70
+ # product_module_name
71
+ # else
72
+ # label
73
+ # end
74
+ # end
75
+
76
+ # def framework_name
77
+ # "#{product_module_name}.framework"
78
+ # end
@@ -0,0 +1,41 @@
1
+ require_relative '../tool/tool'
2
+
3
+ module Pod
4
+ class Prebuild
5
+
6
+ # Pass the data between the 2 steps
7
+ #
8
+ # At step 2, the normal pod install, it needs some info of the
9
+ # prebuilt step. So we store it here.
10
+ #
11
+ class Passer
12
+
13
+ # indicate the add/remove/update of prebuit pods
14
+ # @return [Analyzer::SpecsState]
15
+ #
16
+ class_attr_accessor :prebuild_pods_changes
17
+
18
+
19
+ # represent the path of resurces to copy
20
+ class ResourcePath
21
+ attr_accessor :real_file_path
22
+ attr_accessor :target_file_path
23
+ end
24
+ # Save the resoures for static framework, and used when installing the prebuild framework
25
+ # static framework needs copy the resurces mannully
26
+ #
27
+ # @return [Hash<String, [Passer::ResourcePath]>]
28
+ class_attr_accessor :resources_to_copy_for_static_framework
29
+ self.resources_to_copy_for_static_framework = {}
30
+
31
+ # Some pod won't be build in prebuild stage even if it have `binary=>true`.
32
+ # The targets of this pods have `oshould_build? == true`.
33
+ # We should skip integration (patch spec) for this pods
34
+ #
35
+ # @return [Array<String>]
36
+ class_attr_accessor :target_names_to_skip_integration_framework
37
+ self.target_names_to_skip_integration_framework = []
38
+
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,133 @@
1
+ module Pod
2
+
3
+ class Prebuild
4
+ def self.keyword
5
+ :binary
6
+ end
7
+ end
8
+
9
+ class Podfile
10
+ class TargetDefinition
11
+
12
+ ## --- option for setting using prebuild framework ---
13
+ def parse_prebuild_framework(name, requirements)
14
+ should_prebuild = Pod::Podfile::DSL.prebuild_all
15
+
16
+ options = requirements.last
17
+ if options.is_a?(Hash) && options[Pod::Prebuild.keyword] != nil
18
+ should_prebuild = options.delete(Pod::Prebuild.keyword)
19
+ requirements.pop if options.empty?
20
+ end
21
+
22
+ pod_name = Specification.root_name(name)
23
+ set_prebuild_for_pod(pod_name, should_prebuild)
24
+ end
25
+
26
+ def set_prebuild_for_pod(pod_name, should_prebuild)
27
+
28
+ if should_prebuild == true
29
+ @prebuild_framework_pod_names ||= []
30
+ @prebuild_framework_pod_names.push pod_name
31
+ else
32
+ @should_not_prebuild_framework_pod_names ||= []
33
+ @should_not_prebuild_framework_pod_names.push pod_name
34
+ end
35
+ end
36
+
37
+ def prebuild_framework_pod_names
38
+ names = @prebuild_framework_pod_names || []
39
+ if parent != nil and parent.kind_of? TargetDefinition
40
+ names += parent.prebuild_framework_pod_names
41
+ end
42
+ names
43
+ end
44
+ def should_not_prebuild_framework_pod_names
45
+ names = @should_not_prebuild_framework_pod_names || []
46
+ if parent != nil and parent.kind_of? TargetDefinition
47
+ names += parent.should_not_prebuild_framework_pod_names
48
+ end
49
+ names
50
+ end
51
+
52
+ # ---- patch method ----
53
+ # We want modify `store_pod` method, but it's hard to insert a line in the
54
+ # implementation. So we patch a method called in `store_pod`.
55
+ old_method = instance_method(:parse_inhibit_warnings)
56
+
57
+ define_method(:parse_inhibit_warnings) do |name, requirements|
58
+ parse_prebuild_framework(name, requirements)
59
+ old_method.bind(self).(name, requirements)
60
+ end
61
+
62
+ end
63
+ end
64
+ end
65
+
66
+
67
+ module Pod
68
+ class Installer
69
+
70
+ def prebuild_pod_targets
71
+ @prebuild_pod_targets ||= (
72
+ all = []
73
+
74
+ aggregate_targets = self.aggregate_targets
75
+ aggregate_targets.each do |aggregate_target|
76
+ target_definition = aggregate_target.target_definition
77
+ targets = aggregate_target.pod_targets || []
78
+
79
+ # filter prebuild
80
+ prebuild_names = target_definition.prebuild_framework_pod_names
81
+ if not Podfile::DSL.prebuild_all
82
+ targets = targets.select { |pod_target| prebuild_names.include?(pod_target.pod_name) }
83
+ end
84
+ dependency_targets = targets.map {|t| t.recursive_dependent_targets }.flatten.uniq || []
85
+ targets = (targets + dependency_targets).uniq
86
+
87
+ # filter should not prebuild
88
+ explict_should_not_names = target_definition.should_not_prebuild_framework_pod_names
89
+ targets = targets.reject { |pod_target| explict_should_not_names.include?(pod_target.pod_name) }
90
+
91
+ if not Pod::Podfile::DSL.except_binary_list.nil?
92
+ targets = targets.reject { |pod_target| Pod::Podfile::DSL.except_binary_list.include?(pod_target.pod_name) }
93
+ end
94
+
95
+ all += targets
96
+ end
97
+
98
+ all = all.reject {|pod_target| sandbox.local?(pod_target.pod_name) }
99
+ all.uniq
100
+ )
101
+ end
102
+
103
+ # the root names who needs prebuild, including dependency pods.
104
+ def prebuild_pod_names
105
+ @prebuild_pod_names ||= self.prebuild_pod_targets.map(&:pod_name)
106
+ end
107
+
108
+
109
+ def validate_every_pod_only_have_one_form
110
+
111
+ multi_targets_pods = self.pod_targets.group_by do |t|
112
+ t.pod_name
113
+ end.select do |k, v|
114
+ v.map{|t| t.platform.name }.count > 1
115
+ end
116
+
117
+ multi_targets_pods = multi_targets_pods.reject do |name, targets|
118
+ contained = targets.map{|t| self.prebuild_pod_targets.include? t }
119
+ contained.uniq.count == 1 # all equal
120
+ end
121
+
122
+ return if multi_targets_pods.empty?
123
+
124
+ warnings = "One pod can only be prebuilt or not prebuilt. These pod have different forms in multiple targets:\n"
125
+ warnings += multi_targets_pods.map{|name, targets| " #{name}: #{targets.map{|t|t.platform.name}}"}.join("\n")
126
+ raise Informative, warnings
127
+ end
128
+
129
+ end
130
+ end
131
+
132
+
133
+
@@ -0,0 +1,73 @@
1
+ require_relative "names"
2
+
3
+ module Pod
4
+ class PrebuildSandbox < Sandbox
5
+
6
+ # [String] standard_sandbox_path
7
+ def self.from_standard_sanbox_path(path)
8
+ prebuild_sandbox_path = Pathname.new(path).realpath + "_Prebuild"
9
+ self.new(prebuild_sandbox_path)
10
+ end
11
+
12
+ def self.from_standard_sandbox(sandbox)
13
+ self.from_standard_sanbox_path(sandbox.root)
14
+ end
15
+
16
+ def standard_sanbox_path
17
+ self.root.parent
18
+ end
19
+
20
+ def generate_framework_path
21
+ self.root + "GeneratedFrameworks"
22
+ end
23
+
24
+ # @param name [String] pass the target.name (may containing platform suffix)
25
+ # @return [Pathname] the folder containing the framework file.
26
+ def framework_folder_path_for_target_name(name)
27
+ self.generate_framework_path + name
28
+ end
29
+
30
+
31
+ def exsited_framework_target_names
32
+ exsited_framework_name_pairs.map {|pair| pair[0]}.uniq
33
+ end
34
+ def exsited_framework_pod_names
35
+ exsited_framework_name_pairs.map {|pair| pair[1]}.uniq
36
+ end
37
+ def existed_target_names_for_pod_name(pod_name)
38
+ exsited_framework_name_pairs.select {|pair| pair[1] == pod_name }.map { |pair| pair[0]}
39
+ end
40
+
41
+
42
+
43
+ def save_pod_name_for_target(target)
44
+ folder = framework_folder_path_for_target_name(target.name)
45
+ return unless folder.exist?
46
+ flag_file_path = folder + "#{target.pod_name}.pod_name"
47
+ File.write(flag_file_path.to_s, "")
48
+ end
49
+
50
+
51
+ private
52
+
53
+ def pod_name_for_target_folder(target_folder_path)
54
+ name = Pathname.new(target_folder_path).children.find do |child|
55
+ child.to_s.end_with? ".pod_name"
56
+ end
57
+ name = name.basename(".pod_name").to_s unless name.nil?
58
+ name ||= Pathname.new(target_folder_path).basename.to_s # for compatibility with older version
59
+ end
60
+
61
+ # Array<[target_name, pod_name]>
62
+ def exsited_framework_name_pairs
63
+ return [] unless generate_framework_path.exist?
64
+ generate_framework_path.children().map do |framework_path|
65
+ if framework_path.directory? && (not framework_path.children.empty?)
66
+ [framework_path.basename.to_s, pod_name_for_target_folder(framework_path)]
67
+ else
68
+ nil
69
+ end
70
+ end.reject(&:nil?).uniq
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,133 @@
1
+ require 'digest'
2
+ require_relative '../tool/tool'
3
+ require "google/cloud/storage"
4
+ require 'zip'
5
+
6
+ module Pod
7
+ class Prebuild
8
+ class SharedCache
9
+ extend Config::Mixin
10
+
11
+ # `true` if there is cache for the target
12
+ # `false` otherwise
13
+ #
14
+ # @return [Boolean]
15
+ def self.has?(target, options)
16
+ if Podfile::DSL.shared_cache_enabled
17
+ path = framework_cache_path_for(target, options)
18
+ if path.exist?
19
+ Pod::UI.puts "Local cache for #{target.name} found"
20
+ true
21
+ else
22
+ Pod::UI.puts "Local cache for #{target.name} not found"
23
+ if Podfile::DSL.shared_gcp_cache_enabled
24
+ cloud_path = cloud_framework_path_for(target, options)
25
+ storage = Google::Cloud::Storage.new
26
+ bucket = storage.bucket(Podfile::DSL.gcp_options[:bucket])
27
+ file = bucket.file "#{cloud_path}"
28
+ if not file.nil?
29
+ Pod::UI.puts "GCP cache for #{target.name} found, downloading..."
30
+ Dir.mktmpdir {|dir|
31
+ file.download "#{dir}/framework.zip"
32
+ unzip("#{dir}/framework.zip", path)
33
+ }
34
+ true
35
+ else
36
+ Pod::UI.puts "GCP cache for #{target.name} not found"
37
+ false
38
+ end
39
+ else
40
+ false
41
+ end
42
+ end
43
+ else
44
+ false
45
+ end
46
+ end
47
+
48
+ # Copies input_path to target's cache
49
+ def self.cache(target, input_path, options)
50
+ if not Podfile::DSL.shared_cache_enabled
51
+ return
52
+ end
53
+ cache_path = framework_cache_path_for(target, options)
54
+ cache_path.mkpath unless cache_path.exist?
55
+ FileUtils.cp_r "#{input_path}/.", cache_path
56
+
57
+ if Podfile::DSL.shared_gcp_cache_enabled
58
+ cloud_path = cloud_framework_path_for(target, options)
59
+ storage = Google::Cloud::Storage.new
60
+ bucket = storage.bucket(Podfile::DSL.gcp_options[:bucket])
61
+
62
+ Pod::UI.puts "Save to remote cache"
63
+ Dir.mktmpdir {|dir|
64
+ zip(cache_path, "#{dir}/framework.zip")
65
+ bucket.create_file "#{dir}/framework.zip",
66
+ "#{cloud_path}"
67
+ }
68
+ end
69
+ end
70
+
71
+ # Path of the target's cache
72
+ #
73
+ # @return [Pathname]
74
+ def self.framework_cache_path_for(target, options)
75
+ framework_cache_path = cache_root + xcode_version
76
+ framework_cache_path = framework_cache_path + target.name
77
+ framework_cache_path = framework_cache_path + target.version
78
+ options_with_platform = options + [target.platform.name]
79
+ framework_cache_path = framework_cache_path + Digest::MD5.hexdigest(options_with_platform.to_s).to_s
80
+ end
81
+
82
+ def self.cloud_framework_path_for(target, options)
83
+ cloud_cache_path = Pathname.new('').to_s + xcode_version
84
+ cloud_cache_path = cloud_cache_path + target.name
85
+ cloud_cache_path = cloud_cache_path + target.version
86
+ options_with_platform = options + [target.platform.name]
87
+ cloud_cache_path = cloud_cache_path + Digest::MD5.hexdigest(options_with_platform.to_s).to_s
88
+ end
89
+
90
+ def self.zip(dir, zip_dir)
91
+ Zip::File.open(zip_dir, Zip::File::CREATE)do |zipfile|
92
+ Find.find(dir) do |path|
93
+ Find.prune if File.basename(path)[0] == ?.
94
+ dest = /#{dir}\/(\w.*)/.match(path)
95
+ # Skip files if they exists
96
+ begin
97
+ zipfile.add(dest[1],path) if dest
98
+ rescue Zip::ZipEntryExistsError
99
+ end
100
+ end
101
+ end
102
+ end
103
+
104
+ def self.unzip(zip, unzip_dir, remove_after = false)
105
+ Zip::File.open(zip) do |zip_file|
106
+ zip_file.each do |f|
107
+ f_path=File.join(unzip_dir, f.name)
108
+ FileUtils.mkdir_p(File.dirname(f_path))
109
+ zip_file.extract(f, f_path) unless File.exist?(f_path)
110
+ end
111
+ end
112
+ FileUtils.rm(zip) if remove_after
113
+ end
114
+
115
+ # Current xcode version.
116
+ #
117
+ # @return [String]
118
+ private
119
+ class_attr_accessor :xcode_version
120
+ # Converts from "Xcode 10.2.1\nBuild version 10E1001\n" to "10.2.1".
121
+ self.xcode_version = `xcodebuild -version`.split("\n").first.split().last || "Unkwown"
122
+
123
+ # Path of the cache folder
124
+ # Reusing cache_root from cocoapods's config
125
+ # `~Library/Caches/CocoaPods` is default value
126
+ #
127
+ # @return [Pathname]
128
+ private
129
+ class_attr_accessor :cache_root
130
+ self.cache_root = config.cache_root + 'Prebuilt'
131
+ end
132
+ end
133
+ end