cocoapods-podfile_patch 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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9754afa9090b5b5b1ee61171e615a45607974f51
4
+ data.tar.gz: 76ad7be9d5dc18fe4b5e252cce3b2798af59e073
5
+ SHA512:
6
+ metadata.gz: 9ec67eea259cc5c40b20335efd4a766182ed785dd1aa70f43b2ed2ca4beb2aa9b7de9ee79402cc79e1663367d50e39b0c1b0c01b7f9c4713f69a3b93c4babdbf
7
+ data.tar.gz: 8686e788b26ea2e89d84bd5b8d450cb1024ad13175915968f434f6f31f193ba6f8e5482cae6b9ec441d04c96ee94dac1965daa08d90615aa5d74eebcdbbc9def
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ .DS_Store
2
+ pkg
3
+ .idea/
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in cocoapods-podfile_patch.gemspec
4
+ gemspec
5
+
6
+ group :development do
7
+ gem 'cocoapods'
8
+
9
+ gem 'mocha'
10
+ gem 'bacon'
11
+ gem 'mocha-on-bacon'
12
+ gem 'prettybacon'
13
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2019 Gao <gaoji@bytedance.com>
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,44 @@
1
+ # cocoapods-podfile_patch
2
+
3
+ This plugin provide the ability to override podfile in another file.
4
+
5
+ Place a `Podfile.patch` at the same directory with Podfile. Configurate the pods
6
+ in patchfile just like in Podfile. It will append to original podfile, and override
7
+ the settings in podfile if duplicated.
8
+
9
+ For example:
10
+
11
+ Podfile:
12
+ ```
13
+ use_patch_file!
14
+ target EVA do
15
+ pod "A", "1.5.3", :inhibit_warning => true
16
+ pod "B", :path => "some/path"
17
+ end
18
+ ```
19
+
20
+ Podfile.patch
21
+ ```
22
+ target EVA do
23
+ pod "A", :path => "path/to/local/A"
24
+ end
25
+ ```
26
+
27
+ The final result equal to
28
+ ```
29
+ target EVA do
30
+ pod "A", :path => "path/to/local/A"
31
+ pod "B", :path => "some/path"
32
+ end
33
+ ```
34
+
35
+ This function is base on the parsed result of podfile. It means you could do ANYTHING
36
+ you do in podfile, i.e. your custom pod function or other plugins.
37
+
38
+ ## Installation
39
+
40
+ $ gem install cocoapods-podfile_patch
41
+
42
+ ## Usage
43
+
44
+ Just add `use_patch_file!` in podfile, and make your own `Podfile.patch`
data/Rakefile ADDED
@@ -0,0 +1,13 @@
1
+ require 'bundler/gem_tasks'
2
+
3
+ def specs(dir)
4
+ FileList["spec/#{dir}/*_spec.rb"].shuffle.join(' ')
5
+ end
6
+
7
+ desc 'Runs all the specs'
8
+ task :specs do
9
+ sh "bundle exec bacon #{specs('**')}"
10
+ end
11
+
12
+ task :default => :specs
13
+
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'cocoapods-podfile_patch/gem_version.rb'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'cocoapods-podfile_patch'
8
+ spec.version = CocoapodsPodfile_patch::VERSION
9
+ spec.authors = ['Gao']
10
+ spec.email = ['gaoji@bytedance.com']
11
+ spec.description = %q{A short description of cocoapods-podfile_patch.}
12
+ spec.summary = %q{A longer description of cocoapods-podfile_patch.}
13
+ spec.homepage = 'https://github.com/EXAMPLE/cocoapods-podfile_patch'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_development_dependency 'bundler', '~> 1.3'
22
+ spec.add_development_dependency 'rake'
23
+ end
@@ -0,0 +1,3 @@
1
+ module CocoapodsPodfile_patch
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,232 @@
1
+
2
+ require 'cocoapods-core/specification'
3
+ require 'cocoapods-core/podfile'
4
+ require 'pathname'
5
+ require 'set'
6
+
7
+
8
+ class PodfilePatch
9
+
10
+ def main(podfile)
11
+
12
+ podfile_root_path = Pathname.new(podfile.defined_in_file).dirname
13
+ patch_file_path = self.patchfile_filepath(podfile_root_path)
14
+ if not patch_file_path.file?
15
+ Pod::UI.info "Podfile patch feature is enabled. (No patch file now.)"
16
+ return
17
+ end
18
+
19
+ patchfile = self.patchfile(patch_file_path)
20
+ self.patch(podfile: podfile, with_podfile: patchfile)
21
+
22
+ Pod::UI.titled_section "Podfile patch feature is enabled" do
23
+ next unless Pod::UI.config.verbose?
24
+ Pod::UI.section "Patchfile Info" do
25
+ self.print_podfile_raw_dependencies patchfile
26
+ end
27
+ Pod::UI.section "Modified Podfile Info" do
28
+ self.print_podfile_raw_dependencies podfile
29
+ end
30
+ end
31
+ end
32
+
33
+ def patchfile_filepath(podfile_root) # [Pathname]
34
+ Pathname.new(podfile_root) + "Podfile.patch"
35
+ end
36
+
37
+ def patchfile(patch_file_path) # [Podfile]
38
+ Pod::Podfile.from_ruby(patch_file_path)
39
+ end
40
+
41
+ def patch(podfile:, with_podfile: )
42
+ original = podfile
43
+ patch = with_podfile
44
+
45
+ merge_target_definitions_dependency(
46
+ podfile.root_target_definitions[0],
47
+ patch.root_target_definitions[0]
48
+ )
49
+ end
50
+
51
+ def merge_target_definitions_dependency(targetdef, patch_targetdef)
52
+ # Demo Data
53
+ # Original Target
54
+ # ```
55
+ # TargetDefination 'Pods':
56
+ # [{"BDWebImage"=>["1.0.1.1-binary"]}]
57
+ #
58
+ # TargetDefination 'Pods-FrameworkDemos_Tests':
59
+ # ["BDWebImage/SDAdapter", "BDWebImage/Download", {"TTNetworkManager"=>["2.2.8.46-rc.18"]}, {"AFNetworking"=>[{:path=>"/Users/lea/Downloads/AFNetworking"}]}]
60
+ #
61
+ # TargetDefination 'Pods-FrameworkDemos_Example':
62
+ # ["BDWebImage", {"TTNetworkManager"=>["2.2.8.46-rc.18"]}]
63
+ # ```
64
+ #
65
+ # Patch Target
66
+ # ```
67
+ # TargetDefination 'Pods':
68
+ # [{"AFNetworking"=>["2.3"]}]
69
+ # ```
70
+
71
+ # 1. find all dependency patch_targetdef: patched_dependencies
72
+ # 2. modify targetdef's depedencies recursively:
73
+ # - replace the requirement to the one in patched_dependencies
74
+ # - add to target if not contained
75
+
76
+
77
+ def get_raw_dependencies(target_defination)
78
+ (target_defination.send :get_hash_value, 'dependencies') || []
79
+ end
80
+
81
+ all_dependencies_in_patch = begin
82
+ def all_dependencies(target_defination)
83
+ d = get_raw_dependencies(target_defination)
84
+ d += (target_defination.children.map do |subtarget|
85
+ all_dependencies(subtarget)
86
+ end.flatten || [])
87
+ d
88
+ end
89
+ all_dependencies(patch_targetdef)
90
+ end
91
+
92
+ def transform_target_dependency_to_dict(dependencies)
93
+ dict = {}
94
+ dependencies.each do |name_or_hash|
95
+ if name_or_hash.is_a?(Hash)
96
+ name = name_or_hash.keys.first
97
+ requirements = name_or_hash.values.first
98
+ dict[name] = requirements
99
+ else
100
+ dict[name_or_hash] = {}
101
+ end
102
+ end
103
+ dict
104
+ end
105
+
106
+ dependencies_dict_in_patch = transform_target_dependency_to_dict(all_dependencies_in_patch)
107
+
108
+ def modify_target_defination_recursively(target_defination, &block)
109
+ block.call(target_defination)
110
+ target_defination.children.each { |t| modify_target_defination_recursively(t, &block) }
111
+ end
112
+
113
+ patch_file_all_targets_dict = begin
114
+ targets = {}
115
+ modify_target_defination_recursively(patch_targetdef) do |t|
116
+ targets[t.name] = t
117
+ end
118
+ targets
119
+ end
120
+
121
+ patch_file_target_to_dependency_dict = begin
122
+ dict = {}
123
+ modify_target_defination_recursively(patch_targetdef) do |t|
124
+ deps = get_raw_dependencies(t)
125
+ dict[t.name] = transform_target_dependency_to_dict(deps)
126
+ end
127
+ dict
128
+ end
129
+
130
+ modified_dependencies_names = {} # pod name => target name
131
+
132
+ modify_target_defination_recursively(targetdef) do |t|
133
+ deps = get_raw_dependencies(t)
134
+ new_deps = []
135
+ deps_set = Set.new
136
+
137
+ # modify origianl dependency
138
+ deps.each do |name_or_hash|
139
+ name = nil
140
+ if name_or_hash.is_a?(Hash)
141
+ name = name_or_hash.keys.first
142
+ else
143
+ name = name_or_hash
144
+ end
145
+ if dependencies_dict_in_patch.key? name
146
+ new_deps << {name => dependencies_dict_in_patch[name]}
147
+ modified_dependencies_names[name] = t
148
+ else
149
+ new_deps << name_or_hash
150
+ end
151
+ deps_set.add(name)
152
+ end
153
+ # add new dependency
154
+ patching_deps = patch_file_target_to_dependency_dict[t.name]
155
+ if not patching_deps.blank?
156
+ patching_deps.each do |name, requirements|
157
+ if not deps_set.include? name
158
+ new_deps << (requirements.empty? ? name : {name => requirements})
159
+ modified_dependencies_names[name] = t
160
+ end
161
+ end
162
+ end
163
+
164
+ t.send :set_hash_value, "dependencies", new_deps
165
+ end
166
+
167
+ # handle MODULAR_HEADERS & INHIBIT_WARNING
168
+ [ :raw_inhibit_warnings_hash,
169
+ :raw_use_modular_headers_hash].each do |method|
170
+ modify_target_defination_recursively(targetdef) do |t|
171
+ original_inhibit_warning_dict = t.send method
172
+ original_inhibit_warning_dict.each do |key, value|
173
+ # the key is "for_pods" or "not_for_pods" or "all"
174
+ # Clear if patchfile have modified the pod
175
+ next unless value.kind_of? Array
176
+ value.reject! { |name| modified_dependencies_names.include? name}
177
+ end
178
+
179
+ patch_target = patch_file_all_targets_dict[t.name]
180
+ next if patch_target.nil?
181
+ patch_inhibit_warning_dict = patch_target.send method
182
+ patch_inhibit_warning_dict.each do |key, value|
183
+ if value.kind_of? Array
184
+ original = original_inhibit_warning_dict[key] || []
185
+ original.concat(value).uniq!
186
+ original_inhibit_warning_dict[key] = original
187
+ elsif [true, false].include? value # "all"
188
+ original_inhibit_warning_dict[key] = value
189
+ end
190
+ end
191
+ end
192
+ end
193
+
194
+ # handle CONFIGURATION_WHITELIST
195
+ modify_target_defination_recursively(targetdef) do |t|
196
+ original = t.send :raw_configuration_pod_whitelist
197
+ original.each do |config_name, pods|
198
+ # Clear if patchfile have modified the pod
199
+ next unless pods.kind_of? Array
200
+ pods.reject! { |name| modified_dependencies_names.include? name}
201
+ end
202
+
203
+ patch_target = patch_file_all_targets_dict[t.name]
204
+ next if patch_target.nil?
205
+ patched = patch_target.send :raw_configuration_pod_whitelist
206
+ patched.each do |config_name, pods|
207
+ next unless pods.kind_of? Array
208
+ original_pods = original[config_name] || []
209
+ original_pods.concat(pods).uniq!
210
+ original[config_name] = original_pods
211
+ end
212
+ end
213
+ end
214
+
215
+ def print_podfile_raw_dependencies(podfile)
216
+
217
+ def print_target_def_and_its_dependencies(target_def, intend = "")
218
+ puts "|\n"
219
+ puts "| #{intend}TARGET_DEFINITION: #{target_def}"
220
+ puts "| #{intend}INHIBIT_WARNING: #{target_def.send :raw_inhibit_warnings_hash}"
221
+ puts "| #{intend}DEPS: #{target_def.send :get_hash_value, 'dependencies'}"
222
+ target_def.children.each do |target_def|
223
+ print_target_def_and_its_dependencies(target_def, intend + " ")
224
+ end
225
+ end
226
+ podfile.root_target_definitions.each do |target_def|
227
+ print_target_def_and_its_dependencies(target_def)
228
+ end
229
+ end
230
+ end
231
+
232
+
@@ -0,0 +1 @@
1
+ require 'cocoapods-podfile_patch/gem_version'
@@ -0,0 +1,64 @@
1
+ module Pod
2
+ class Podfile
3
+ module DSL
4
+ # Enable Podfile Patch feature.
5
+ #
6
+ # Thid feature provide the ability to override podfile in another file.
7
+ #
8
+ # Place a `Podfile.patch` at the same directory with Podfile. Configurate the pods
9
+ # in patchfile just like in Podfile. It will append to original podfile, and override
10
+ # the settings in podfile if duplicated.
11
+ #
12
+ # For example:
13
+ #
14
+ # Podfile:
15
+ # ```
16
+ # target EVA do
17
+ # pod "A", "1.5.3", :inhibit_warning => true
18
+ # pod "B", :path => "some/path"
19
+ # end
20
+ # ```
21
+ #
22
+ # Podfile.patch
23
+ # ```
24
+ # target EVA do
25
+ # pod "A", :path => "path/to/local/A"
26
+ # end
27
+ # ```
28
+ #
29
+ # The final result equal to
30
+ # ```
31
+ # target EVA do
32
+ # pod "A", :path => "path/to/local/A"
33
+ # pod "B", :path => "some/path"
34
+ # end
35
+ # ```
36
+ #
37
+ # This function is base on the parsed result of podfile. It means you could do ANYTHING
38
+ # you do in podfile, i.e. your custom pod function or other plugins.
39
+ #
40
+ def use_patch_file!(enabled = true)
41
+ @enable_patch = enabled
42
+ if self.defined_in_file.basename.to_s.downcase == "podfile.patch"
43
+ raise "Cannot call `#{__method__}` in Podfile.patch"
44
+ end
45
+ end
46
+
47
+ end
48
+ end
49
+ end
50
+
51
+ module Pod
52
+ class Podfile
53
+ old_initialize_function = instance_method(:initialize)
54
+ define_method(:initialize) do |defined_in_file = nil, internal_hash = {}, &block|
55
+ old_initialize_function.bind(self).(defined_in_file, internal_hash, &block)
56
+
57
+ if @enable_patch
58
+ require 'cocoapods-podfile_patch/podfile_patch'
59
+ patcher = PodfilePatch.new
60
+ patcher.main(self)
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,12 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+
3
+ module Pod
4
+ describe Command::Podfile_patch do
5
+ describe 'CLAide' do
6
+ it 'registers it self' do
7
+ Command.parse(%w{ podfile_patch }).should.be.instance_of Command::Podfile_patch
8
+ end
9
+ end
10
+ end
11
+ end
12
+
@@ -0,0 +1,50 @@
1
+ require 'pathname'
2
+ ROOT = Pathname.new(File.expand_path('../../', __FILE__))
3
+ $:.unshift((ROOT + 'lib').to_s)
4
+ $:.unshift((ROOT + 'spec').to_s)
5
+
6
+ require 'bundler/setup'
7
+ require 'bacon'
8
+ require 'mocha-on-bacon'
9
+ require 'pretty_bacon'
10
+ require 'pathname'
11
+ require 'cocoapods'
12
+
13
+ Mocha::Configuration.prevent(:stubbing_non_existent_method)
14
+
15
+ require 'cocoapods_plugin'
16
+
17
+ #-----------------------------------------------------------------------------#
18
+
19
+ module Pod
20
+
21
+ # Disable the wrapping so the output is deterministic in the tests.
22
+ #
23
+ UI.disable_wrap = true
24
+
25
+ # Redirects the messages to an internal store.
26
+ #
27
+ module UI
28
+ @output = ''
29
+ @warnings = ''
30
+
31
+ class << self
32
+ attr_accessor :output
33
+ attr_accessor :warnings
34
+
35
+ def puts(message = '')
36
+ @output << "#{message}\n"
37
+ end
38
+
39
+ def warn(message = '', actions = [])
40
+ @warnings << "#{message}\n"
41
+ end
42
+
43
+ def print(message)
44
+ @output << message
45
+ end
46
+ end
47
+ end
48
+ end
49
+
50
+ #-----------------------------------------------------------------------------#
metadata ADDED
@@ -0,0 +1,86 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cocoapods-podfile_patch
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Gao
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-02-26 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: A short description of cocoapods-podfile_patch.
42
+ email:
43
+ - gaoji@bytedance.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - ".gitignore"
49
+ - Gemfile
50
+ - LICENSE.txt
51
+ - README.md
52
+ - Rakefile
53
+ - cocoapods-podfile_patch.gemspec
54
+ - lib/cocoapods-podfile_patch.rb
55
+ - lib/cocoapods-podfile_patch/gem_version.rb
56
+ - lib/cocoapods-podfile_patch/podfile_patch.rb
57
+ - lib/cocoapods_plugin.rb
58
+ - spec/command/podfile_patch_spec.rb
59
+ - spec/spec_helper.rb
60
+ homepage: https://github.com/EXAMPLE/cocoapods-podfile_patch
61
+ licenses:
62
+ - MIT
63
+ metadata: {}
64
+ post_install_message:
65
+ rdoc_options: []
66
+ require_paths:
67
+ - lib
68
+ required_ruby_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: '0'
73
+ required_rubygems_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ requirements: []
79
+ rubyforge_project:
80
+ rubygems_version: 2.5.2.3
81
+ signing_key:
82
+ specification_version: 4
83
+ summary: A longer description of cocoapods-podfile_patch.
84
+ test_files:
85
+ - spec/command/podfile_patch_spec.rb
86
+ - spec/spec_helper.rb