cocoapods-freezer 1.0.0
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 +6 -0
- data/Gemfile +13 -0
- data/LICENSE.txt +22 -0
- data/README.md +22 -0
- data/README_CH.md +46 -0
- data/Rakefile +13 -0
- data/cocoapods-freezer.gemspec +24 -0
- data/lib/cocoapods-freezer.rb +1 -0
- data/lib/cocoapods-freezer/command.rb +2 -0
- data/lib/cocoapods-freezer/command/freeze.rb +46 -0
- data/lib/cocoapods-freezer/command/install.rb +23 -0
- data/lib/cocoapods-freezer/command/options/use_freezer.rb +35 -0
- data/lib/cocoapods-freezer/config.rb +9 -0
- data/lib/cocoapods-freezer/dir.rb +16 -0
- data/lib/cocoapods-freezer/freezer.rb +237 -0
- data/lib/cocoapods-freezer/gem_version.rb +3 -0
- data/lib/cocoapods-freezer/installer.rb +128 -0
- data/lib/cocoapods-freezer/lipo.rb +22 -0
- data/lib/cocoapods-freezer/lockfile.rb +35 -0
- data/lib/cocoapods-freezer/sandbox.rb +7 -0
- data/lib/cocoapods-freezer/specification.rb +123 -0
- data/lib/cocoapods-freezer/xcodebuild.rb +60 -0
- data/lib/cocoapods_plugin.rb +11 -0
- data/spec/command/freeze_spec.rb +12 -0
- data/spec/spec_helper.rb +50 -0
- metadata +113 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 8bee456e3188be9d1c42048f880f2d08607f2111
|
4
|
+
data.tar.gz: 6d39185feedb5715ee7220ca8a664ca5938c82c2
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7d77376f93e7b74a9f33a89fad532007eb7ad1fe2ec928ec9f79fb92cc089fa3a96961b3ed03118d7577e8c4ca07d9534c109beb78b0bad293b235096b1a7c21
|
7
|
+
data.tar.gz: e20529d0dd900de550ddad5e699acc3e00a19cbc3d5bd80b18a644f5aefbbf8311fde45c5a9369eaa47b2f7e687349d4a82dc7d6f64d28fe4845cfb380b17962
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2018 <>
|
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,22 @@
|
|
1
|
+
# cocoapods-freezer
|
2
|
+
|
3
|
+
cocoapods-freezer is a plugin of cocoapods. It uses for cache of intergation!
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
``` shell
|
8
|
+
$ gem install cocoapods-freezer
|
9
|
+
```
|
10
|
+
|
11
|
+
## Usage
|
12
|
+
|
13
|
+
``` shell
|
14
|
+
$ pod install --user-freezer
|
15
|
+
|
16
|
+
```
|
17
|
+
|
18
|
+
## Principle
|
19
|
+
|
20
|
+
Versions of Pods maintain stability. And the same to the product of Pods. So cocoapods-freezer will cache the product when Pods pre-build. Then it use cache for integate.
|
21
|
+
|
22
|
+
Appreciate a 🌟 if you like it.
|
data/README_CH.md
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
# cocoapods-freezer
|
2
|
+
|
3
|
+
cocoapods-freezer是一款基于CocoaPods的集成缓存插件。
|
4
|
+
|
5
|
+
## 安装
|
6
|
+
|
7
|
+
``` shell
|
8
|
+
$ gem install cocoapods-freezer
|
9
|
+
```
|
10
|
+
|
11
|
+
## 使用
|
12
|
+
|
13
|
+
``` shell
|
14
|
+
$ pod install --user-freezer
|
15
|
+
|
16
|
+
```
|
17
|
+
|
18
|
+
## 原理
|
19
|
+
|
20
|
+
基于集成的Pod组件版本一般更新频率不高,其源码改动频率同样不高,因此这部分编译产物在一段时间内存在不变性,故通过对这其进行缓存,节省重复编译时间,最终达到提速效果。
|
21
|
+
|
22
|
+
## 能力
|
23
|
+
|
24
|
+
[x] 基于Podfile进行Pods缓存分析,配合'Pod install'进行缓存
|
25
|
+
[x] 目前仅支持static-library预打包处理(需屏蔽'use_framework!')
|
26
|
+
[x] 目前仅支持release打包配置
|
27
|
+
[x] 目前仅支持单iOS平台
|
28
|
+
[x] 支持增量打包
|
29
|
+
[x] 支持缓存复用
|
30
|
+
|
31
|
+
## 计划
|
32
|
+
|
33
|
+
- 缓存相关
|
34
|
+
[] 支持全平台(Platform)、全配置(Configuration)缓存
|
35
|
+
[] 支持Framework(Dynamic\Static)方式构建
|
36
|
+
[] 支持local类型
|
37
|
+
[] 支持swift类型
|
38
|
+
[] 缓存路径定制
|
39
|
+
[] 打包脚本定制?
|
40
|
+
[] Configuration定制?
|
41
|
+
|
42
|
+
- 命令相关
|
43
|
+
[] 支持'pod update'命令工作
|
44
|
+
[] 支持'pod freeze'命令的查询、缓存操作
|
45
|
+
|
46
|
+
如果你喜欢这个插件,请留下🌟!欢迎提出遇到的问题,以及希望增加的功能!
|
data/Rakefile
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'cocoapods-freezer/gem_version.rb'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'cocoapods-freezer'
|
8
|
+
spec.version = CocoapodsFreezer::VERSION
|
9
|
+
spec.authors = ['']
|
10
|
+
spec.email = ['']
|
11
|
+
spec.description = %q{A short description of cocoapods-freezer.}
|
12
|
+
spec.summary = %q{A longer description of cocoapods-freezer.}
|
13
|
+
spec.homepage = 'https://github.com/EXAMPLE/cocoapods-freezer'
|
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_dependency "cocoapods", '1.5.3'
|
22
|
+
spec.add_development_dependency 'bundler', '~> 1.3'
|
23
|
+
spec.add_development_dependency 'rake'
|
24
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'cocoapods-freezer/gem_version'
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Pod
|
2
|
+
class Command
|
3
|
+
# This is an example of a cocoapods plugin adding a top-level subcommand
|
4
|
+
# to the 'pod' command.
|
5
|
+
#
|
6
|
+
# You can also create subcommands of existing or new commands. Say you
|
7
|
+
# wanted to add a subcommand to `list` to show newly deprecated pods,
|
8
|
+
# (e.g. `pod list deprecated`), there are a few things that would need
|
9
|
+
# to change.
|
10
|
+
#
|
11
|
+
# - move this file to `lib/pod/command/list/deprecated.rb` and update
|
12
|
+
# the class to exist in the the Pod::Command::List namespace
|
13
|
+
# - change this class to extend from `List` instead of `Command`. This
|
14
|
+
# tells the plugin system that it is a subcommand of `list`.
|
15
|
+
# - edit `lib/cocoapods_plugins.rb` to require this file
|
16
|
+
#
|
17
|
+
# @todo Create a PR to add your plugin to CocoaPods/cocoapods.org
|
18
|
+
# in the `plugins.json` file, once your plugin is released.
|
19
|
+
#
|
20
|
+
|
21
|
+
# todo(ca1md0wn)
|
22
|
+
# class Freeze < Command
|
23
|
+
# self.summary = 'Short description of cocoapods-freezer.'
|
24
|
+
|
25
|
+
# self.description = <<-DESC
|
26
|
+
# Longer description of cocoapods-freezer.
|
27
|
+
# DESC
|
28
|
+
|
29
|
+
# self.arguments = 'NAME'
|
30
|
+
|
31
|
+
# def initialize(argv)
|
32
|
+
# @name = argv.shift_argument
|
33
|
+
# super
|
34
|
+
# end
|
35
|
+
|
36
|
+
# def validate!
|
37
|
+
# super
|
38
|
+
# help! 'A Pod name is required.' unless @name
|
39
|
+
# end
|
40
|
+
|
41
|
+
# def run
|
42
|
+
# UI.puts "Add your implementation for the cocoapods-freezer plugin in #{__FILE__}"
|
43
|
+
# end
|
44
|
+
# end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Pod
|
2
|
+
class Command
|
3
|
+
class Install < Command
|
4
|
+
require 'cocoapods-freezer/command/options/use_freezer'
|
5
|
+
include UseFreezer
|
6
|
+
|
7
|
+
define_method(:run) do
|
8
|
+
verify_podfile_exists!
|
9
|
+
|
10
|
+
if use_freezer?
|
11
|
+
Freezer::shared.freeze!
|
12
|
+
elsif Config.instance.sandbox.manifest && Config.instance.sandbox.manifest.freered?
|
13
|
+
Config.instance.sandbox.clear!
|
14
|
+
end
|
15
|
+
|
16
|
+
installer = installer_for_config
|
17
|
+
installer.repo_update = repo_update?(:default => false)
|
18
|
+
installer.update = false
|
19
|
+
installer.install!
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Pod
|
2
|
+
class Command
|
3
|
+
module Options
|
4
|
+
# Provides support for commands to skip updating the spec repositories.
|
5
|
+
#
|
6
|
+
module UseFreezer
|
7
|
+
|
8
|
+
module Options
|
9
|
+
def options
|
10
|
+
[
|
11
|
+
['--use-freezer', 'running cocoapods-freeze before install'],
|
12
|
+
].concat(super)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.included(base)
|
17
|
+
base.extend(Options)
|
18
|
+
end
|
19
|
+
|
20
|
+
def use_freezer?(default: false)
|
21
|
+
if @use_freezer.nil?
|
22
|
+
default
|
23
|
+
else
|
24
|
+
@use_freezer
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def initialize(argv)
|
29
|
+
@use_freezer = argv.flag?('use-freezer')
|
30
|
+
super
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class Dir
|
2
|
+
def self.randdir
|
3
|
+
path = nil
|
4
|
+
while (path == nil || path.exist?) do
|
5
|
+
path = Pathname.new(Dir.tmpdir + rand(999999).to_s) #todo(ca1md0wn)
|
6
|
+
end
|
7
|
+
|
8
|
+
path
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.mkranddir
|
12
|
+
path = randdir
|
13
|
+
path.mkpath
|
14
|
+
path
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,237 @@
|
|
1
|
+
require 'tmpdir'
|
2
|
+
|
3
|
+
module Pod
|
4
|
+
class Freezer
|
5
|
+
def self.shared
|
6
|
+
@shared ||= (Config.instance.podfile ? new(Config.instance.podfile) : nil)
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(podfile)
|
10
|
+
raise unless podfile
|
11
|
+
@podfile = podfile
|
12
|
+
@frozen_pods = []
|
13
|
+
@enable = false
|
14
|
+
end
|
15
|
+
|
16
|
+
def enable?
|
17
|
+
@enable
|
18
|
+
end
|
19
|
+
|
20
|
+
def exist?
|
21
|
+
root.exist?
|
22
|
+
end
|
23
|
+
|
24
|
+
def clear!
|
25
|
+
root.rmtree if root.exist?
|
26
|
+
end
|
27
|
+
|
28
|
+
# freeze!
|
29
|
+
# todo(ca1md0wn): if Dir of FrozenPods destoryed, should fix by itself!
|
30
|
+
def freeze!
|
31
|
+
@enable = true
|
32
|
+
|
33
|
+
Pod::UI.puts "Freezing Pods".green
|
34
|
+
|
35
|
+
unchange_spec_names = []
|
36
|
+
if manifest_path.exist?
|
37
|
+
lockfile = Pod::Lockfile.from_file(manifest_path)
|
38
|
+
unchange_spec_names = Pod::Installer::Analyzer::SpecsState.new(lockfile.detect_changes_with_podfile(@podfile)).unchanged.to_a
|
39
|
+
end
|
40
|
+
|
41
|
+
# prepare root dir
|
42
|
+
root.mkpath unless root.exist?
|
43
|
+
|
44
|
+
# prepare sandbox
|
45
|
+
sandbox = Pod::Sandbox.new(Dir.randdir)
|
46
|
+
|
47
|
+
# install!
|
48
|
+
installer = Pod::Installer.new(sandbox, @podfile , nil)
|
49
|
+
installer.repo_update = false # todo(ca1md0wn)
|
50
|
+
installer.update = false # todo(ca1md0wn)
|
51
|
+
installer.use_by_freezer = true
|
52
|
+
installer.install!
|
53
|
+
|
54
|
+
specs_for_freezing = installer.major_specs
|
55
|
+
|
56
|
+
# freeze!
|
57
|
+
specs_for_freezing.each do |spec|
|
58
|
+
|
59
|
+
# local not support;
|
60
|
+
if sandbox.local?(spec.name)
|
61
|
+
Pod::UI.puts "`#{spec.name}` can't freeze because it is local!".red
|
62
|
+
next
|
63
|
+
end
|
64
|
+
|
65
|
+
# fetch targets of pod in different platform,
|
66
|
+
pod_targets = installer.pod_targets.select do |target|
|
67
|
+
target.pod_name == spec.name
|
68
|
+
end || []
|
69
|
+
|
70
|
+
# multiplatform not support(just support ios now!)
|
71
|
+
# todo(ca1md0wn)
|
72
|
+
unless pod_targets.count > 0
|
73
|
+
Pod::UI.puts "`#{spec.name}` can't freeze because it is multiplatforms!".red
|
74
|
+
next
|
75
|
+
end
|
76
|
+
|
77
|
+
# swift not support;
|
78
|
+
# todo(ca1md0wn)
|
79
|
+
# build_as_framework not support;
|
80
|
+
# todo(ca1md0wn)
|
81
|
+
# should_not_build not support
|
82
|
+
not_support = false
|
83
|
+
pod_targets.each do |target|
|
84
|
+
if !target.should_build?
|
85
|
+
Pod::UI.puts "`#{spec.name}` can't freeze because it should not build!".red
|
86
|
+
not_support = true
|
87
|
+
break
|
88
|
+
end
|
89
|
+
|
90
|
+
if target.uses_swift?
|
91
|
+
Pod::UI.puts "`#{spec.name}` can't freeze because it use swift!".red
|
92
|
+
not_support = true
|
93
|
+
break
|
94
|
+
end
|
95
|
+
|
96
|
+
if target.requires_frameworks?
|
97
|
+
Pod::UI.puts "`#{spec.name}` don't support to freeze because it will build as framework!".red
|
98
|
+
not_support = true
|
99
|
+
break
|
100
|
+
end
|
101
|
+
end
|
102
|
+
next if not_support
|
103
|
+
|
104
|
+
frozen_pod = FrozenPod.new(spec.name)
|
105
|
+
|
106
|
+
# setup!
|
107
|
+
pod_targets.each do |target|
|
108
|
+
# target build when
|
109
|
+
# 1.spec change/add 2.product not exist
|
110
|
+
if !unchange_spec_names.include?(spec.name) || !(root + target.product_name).exist?
|
111
|
+
|
112
|
+
product_path = nil
|
113
|
+
case target.platform.name
|
114
|
+
when :ios then
|
115
|
+
# build iphonesimulator!
|
116
|
+
iphonesimulator_paths = Pod::Xcodebuild::build_iphonesimulator!(installer.sandbox.project_path.realdirpath, target.name, target.product_name)
|
117
|
+
if !iphonesimulator_paths || iphonesimulator_paths.count == 0
|
118
|
+
next
|
119
|
+
end
|
120
|
+
|
121
|
+
# build iphoneos!
|
122
|
+
iphoneos_paths = Pod::Xcodebuild::build_iphoneos!(installer.sandbox.project_path.realdirpath, target.name, target.product_name)
|
123
|
+
if !iphoneos_paths || iphoneos_paths.count == 0
|
124
|
+
next
|
125
|
+
end
|
126
|
+
|
127
|
+
# lipo!
|
128
|
+
product_path = Pod::Lipo::create!(iphoneos_paths + iphonesimulator_paths, target.product_name)
|
129
|
+
|
130
|
+
when :osx then
|
131
|
+
# todo
|
132
|
+
when :watchos then
|
133
|
+
# todo
|
134
|
+
when :tvos then
|
135
|
+
# todo
|
136
|
+
end
|
137
|
+
|
138
|
+
next unless product_path
|
139
|
+
|
140
|
+
FileUtils.cp_r(product_path, root + target.product_name, :remove_destination => true)
|
141
|
+
end
|
142
|
+
|
143
|
+
frozen_pod.mark!(target.product_name)
|
144
|
+
end
|
145
|
+
|
146
|
+
unless frozen_pod.empty?
|
147
|
+
@frozen_pods += [frozen_pod]
|
148
|
+
end
|
149
|
+
|
150
|
+
Pod::UI.puts "`#{spec.name}` freeze!".green
|
151
|
+
end
|
152
|
+
|
153
|
+
# save manifest file
|
154
|
+
if sandbox.manifest_path.exist?
|
155
|
+
FileUtils.cp_r(sandbox.manifest_path, manifest_path, :remove_destination => true)
|
156
|
+
end
|
157
|
+
|
158
|
+
Pod::UI.puts "Pods freeze complete!".green
|
159
|
+
end
|
160
|
+
|
161
|
+
def frozen_pod_names
|
162
|
+
pod_names = @frozen_pods.map do |frozen_pod|
|
163
|
+
frozen_pod.pod_name
|
164
|
+
end
|
165
|
+
|
166
|
+
pod_names || []
|
167
|
+
end
|
168
|
+
|
169
|
+
def freezed_pod?(pod_name)
|
170
|
+
@frozen_pods.each do |frozen_pod|
|
171
|
+
if frozen_pod.pod_name == pod_name
|
172
|
+
return true
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
return false
|
177
|
+
end
|
178
|
+
|
179
|
+
def freezed_product?(product_name)
|
180
|
+
@frozen_pods.each do |frozen_pod|
|
181
|
+
frozen_pod.product_names.each do |name|
|
182
|
+
if name == product_name
|
183
|
+
return true
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
return false
|
189
|
+
end
|
190
|
+
|
191
|
+
def export!(product_name, path)
|
192
|
+
if !path || !freezed_product?(product_name)
|
193
|
+
return
|
194
|
+
end
|
195
|
+
|
196
|
+
FileUtils.cp_r(root + product_name, path.to_s, :remove_destination => true)
|
197
|
+
end
|
198
|
+
|
199
|
+
private
|
200
|
+
|
201
|
+
class FrozenPod
|
202
|
+
# String
|
203
|
+
attr_reader :pod_name
|
204
|
+
|
205
|
+
# Array<String>
|
206
|
+
attr_reader :product_names
|
207
|
+
|
208
|
+
def initialize(pod_name)
|
209
|
+
@pod_name = pod_name
|
210
|
+
@product_names = []
|
211
|
+
end
|
212
|
+
|
213
|
+
def mark!(product_name)
|
214
|
+
@product_names += [product_name]
|
215
|
+
end
|
216
|
+
|
217
|
+
def empty?
|
218
|
+
if @product_names.count > 0
|
219
|
+
return false
|
220
|
+
end
|
221
|
+
|
222
|
+
return true
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
# Array<FrozenPod>
|
227
|
+
@frozen_pods
|
228
|
+
|
229
|
+
def root
|
230
|
+
Pathname.new(@podfile.defined_in_file.dirname) + 'FrozenPods'
|
231
|
+
end
|
232
|
+
|
233
|
+
def manifest_path
|
234
|
+
root + 'Manifest.lock'
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
module Pod
|
2
|
+
class Installer
|
3
|
+
|
4
|
+
def major_specs
|
5
|
+
root_specs
|
6
|
+
end
|
7
|
+
|
8
|
+
def clean_pods_about_freezed
|
9
|
+
Pod::Freezer.shared.frozen_pod_names.each do |pod_name|
|
10
|
+
sandbox.clean_pod(pod_name)
|
11
|
+
end
|
12
|
+
|
13
|
+
if sandbox.manifest && sandbox.manifest.frozen_pod_names
|
14
|
+
sandbox.manifest.frozen_pod_names.select do |pod_name|
|
15
|
+
!Pod::Freezer.shared.frozen_pod_names.include?(pod_name)
|
16
|
+
end.each do |pod_name|
|
17
|
+
sandbox.clean_pod(pod_name)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def resolve_dependencies_about_freezed
|
23
|
+
analysis_result.specifications.each do |spec|
|
24
|
+
next unless Pod::Freezer.shared.freezed_pod?(spec.root.name)
|
25
|
+
|
26
|
+
targets = pod_targets.select do |target|
|
27
|
+
target.pod_name == spec.root.name
|
28
|
+
end
|
29
|
+
|
30
|
+
if !targets || targets.count == 0
|
31
|
+
next
|
32
|
+
end
|
33
|
+
|
34
|
+
targets.each do |target|
|
35
|
+
spec.prepare_to_store_freezed(target.platform.name.to_s)
|
36
|
+
if Pod::Freezer.shared.freezed_product?(target.product_name)
|
37
|
+
spec.store_freezed(target.platform.name.to_s, target.product_name, target.product_type)
|
38
|
+
else # not freezed product in platform
|
39
|
+
spec.store_freezed_none(target.platform.name.to_s)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
spec.done_for_store_freezed
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def install_source_of_pod_about_freezed(pod_name)
|
48
|
+
if Pod::Freezer.shared.freezed_pod?(pod_name)
|
49
|
+
pod_targets.select do |target|
|
50
|
+
target.pod_name == pod_name
|
51
|
+
end.map do |target|
|
52
|
+
target.product_name
|
53
|
+
end.each do |product_name|
|
54
|
+
Pod::Freezer.shared.export!(product_name, self.sandbox.pod_dir(pod_name) + product_name)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
attr_accessor :use_by_freezer
|
60
|
+
@use_by_freezer
|
61
|
+
|
62
|
+
# hook integrate_user_project
|
63
|
+
hook_integrate_user_project = instance_method(:integrate_user_project)
|
64
|
+
define_method(:integrate_user_project) do
|
65
|
+
# ignore when install by freezer
|
66
|
+
if @use_by_freezer
|
67
|
+
return
|
68
|
+
end
|
69
|
+
|
70
|
+
hook_integrate_user_project.bind(self).()
|
71
|
+
end
|
72
|
+
|
73
|
+
# hook resolve_dependecies
|
74
|
+
hook_resolve_dependecies = instance_method(:resolve_dependencies)
|
75
|
+
define_method(:resolve_dependencies) do
|
76
|
+
|
77
|
+
# no hook when install by freezer
|
78
|
+
if @use_by_freezer || !Pod::Freezer.shared.enable?
|
79
|
+
hook_resolve_dependecies.bind(self).()
|
80
|
+
else
|
81
|
+
clean_pods_about_freezed
|
82
|
+
hook_resolve_dependecies.bind(self).()
|
83
|
+
resolve_dependencies_about_freezed
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# hook install_source_of_pod
|
88
|
+
|
89
|
+
hook_install_source_of_pod = instance_method(:install_source_of_pod)
|
90
|
+
define_method(:install_source_of_pod) do |pod_name|
|
91
|
+
# no hook when install by freezer
|
92
|
+
if @use_by_freezer || !Pod::Freezer.shared.enable?
|
93
|
+
hook_install_source_of_pod.bind(self).(pod_name)
|
94
|
+
return
|
95
|
+
end
|
96
|
+
|
97
|
+
pod_installer = create_pod_installer(pod_name)
|
98
|
+
pod_installer.install!
|
99
|
+
install_source_of_pod_about_freezed(pod_name)
|
100
|
+
@installed_specs.concat(pod_installer.specs_by_platform.values.flatten.uniq)
|
101
|
+
end
|
102
|
+
|
103
|
+
# hook write_lockfiles
|
104
|
+
|
105
|
+
hook_write_lockfiles = instance_method(:write_lockfiles)
|
106
|
+
define_method(:write_lockfiles) do
|
107
|
+
# no hook when install by freezer
|
108
|
+
if @use_by_freezer || !Pod::Freezer.shared.enable?
|
109
|
+
hook_write_lockfiles.bind(self).()
|
110
|
+
return
|
111
|
+
end
|
112
|
+
|
113
|
+
external_source_pods = analysis_result.podfile_dependency_cache.podfile_dependencies.select(&:external_source).map(&:root_name).uniq
|
114
|
+
checkout_options = sandbox.checkout_sources.select { |root_name, _| external_source_pods.include? root_name }
|
115
|
+
|
116
|
+
@lockfile = Lockfile.generrate_by_freezer(podfile, analysis_result.specifications, checkout_options, analysis_result.specs_by_source, Pod::Freezer.shared.frozen_pod_names)
|
117
|
+
UI.message "- Writing Lockfile in #{UI.path config.lockfile_path}" do
|
118
|
+
@lockfile.write_to_disk(config.lockfile_path)
|
119
|
+
end
|
120
|
+
|
121
|
+
UI.message "- Writing Manifest in #{UI.path sandbox.manifest_path}" do
|
122
|
+
sandbox.manifest_path.open('w') do |f|
|
123
|
+
f.write config.lockfile_path.read
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Pod
|
2
|
+
module Lipo
|
3
|
+
def self.create!(paths, product_name)
|
4
|
+
output_path = Dir.mkranddir + product_name
|
5
|
+
|
6
|
+
begin
|
7
|
+
command = "lipo -create"
|
8
|
+
paths.each do |pathname|
|
9
|
+
command += " " + pathname.to_s
|
10
|
+
end
|
11
|
+
|
12
|
+
command += " -output #{output_path}"
|
13
|
+
`#{command}`
|
14
|
+
# Pod::UI.puts "lipo succeed!"
|
15
|
+
rescue => e
|
16
|
+
# Pod::UI.puts "lipo failed! #{e}"
|
17
|
+
end
|
18
|
+
|
19
|
+
output_path
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Pod
|
2
|
+
class Lockfile
|
3
|
+
|
4
|
+
def freered?
|
5
|
+
frozen_pods = @internal_data['FROZENPODS']
|
6
|
+
if !frozen_pods || frozen_pods.count == 0
|
7
|
+
return false
|
8
|
+
end
|
9
|
+
|
10
|
+
return true
|
11
|
+
end
|
12
|
+
|
13
|
+
def frozen_pod_names
|
14
|
+
@internal_data['FROZENPODS'] || []
|
15
|
+
end
|
16
|
+
|
17
|
+
class << self
|
18
|
+
public
|
19
|
+
def generrate_by_freezer(podfile, specs, checkout_options, spec_repos = {}, frozen_pods=[])
|
20
|
+
hash = {
|
21
|
+
'PODS' => generate_pods_data(specs),
|
22
|
+
'DEPENDENCIES' => generate_dependencies_data(podfile),
|
23
|
+
'SPEC REPOS' => generate_spec_repos(spec_repos),
|
24
|
+
'EXTERNAL SOURCES' => generate_external_sources_data(podfile),
|
25
|
+
'CHECKOUT OPTIONS' => checkout_options,
|
26
|
+
'SPEC CHECKSUMS' => generate_checksums(specs),
|
27
|
+
'PODFILE CHECKSUM' => podfile.checksum,
|
28
|
+
'COCOAPODS' => CORE_VERSION,
|
29
|
+
'FROZENPODS' => frozen_pods,
|
30
|
+
}
|
31
|
+
Lockfile.new(hash)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
class Array
|
2
|
+
def self.from_attributes(attributes)
|
3
|
+
if attributes == nil
|
4
|
+
return []
|
5
|
+
elsif attributes.is_a?(String) || attributes.is_a?(Pathname)
|
6
|
+
return [attributes]
|
7
|
+
elsif attributes.is_a?(Array)
|
8
|
+
return attributes
|
9
|
+
else
|
10
|
+
raise
|
11
|
+
end
|
12
|
+
|
13
|
+
[]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
module Pod
|
18
|
+
|
19
|
+
class Specification
|
20
|
+
def done_for_store_freezed
|
21
|
+
attributes_hash["source_files"] = []
|
22
|
+
|
23
|
+
available_platforms.map do |spec_platform|
|
24
|
+
platform_name = spec_platform.to_sym
|
25
|
+
@consumers[platform_name] = Consumer.new(self, platform_name)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def prepare_to_store_freezed(platform_name)
|
30
|
+
(attributes_hash[platform_name] = {}) unless attributes_hash[platform_name]
|
31
|
+
end
|
32
|
+
|
33
|
+
def store_freezed_none(platform_name)
|
34
|
+
raise unless platform_name && platform_name.is_a?(String)
|
35
|
+
attributes_hash[platform_name]["source_files"] = all_source_files(platform_name)
|
36
|
+
end
|
37
|
+
|
38
|
+
def store_freezed(platform_name, product_name, product_type)
|
39
|
+
raise unless platform_name && platform_name.is_a?(String)
|
40
|
+
raise unless product_name && product_name.is_a?(String)
|
41
|
+
raise unless product_type
|
42
|
+
|
43
|
+
case product_type
|
44
|
+
when :framework then
|
45
|
+
attributes_hash[platform_name]["source_files"] = []
|
46
|
+
vendors = Array.from_attributes(attributes_hash[platform_name]["vendored_frameworks"])
|
47
|
+
vendors += [product_name]
|
48
|
+
attributes_hash[platform_name]["vendored_frameworks"] = vendors
|
49
|
+
when :static_library then
|
50
|
+
attributes_hash[platform_name]["source_files"] = header_files_in_all_sources_files(platform_name)
|
51
|
+
vendors = Array.from_attributes(attributes_hash[platform_name]["vendored_frameworks"])
|
52
|
+
vendors += [product_name]
|
53
|
+
attributes_hash[platform_name]["vendored_libraries"] = vendors
|
54
|
+
else
|
55
|
+
attributes_hash[platform_name]["source_files"] = all_source_files(platform_name)
|
56
|
+
return
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def all_source_files_paths(platform_name=nil)
|
63
|
+
files = Array.from_attributes(attributes_hash["source_files"])
|
64
|
+
|
65
|
+
if platform_name && attributes_hash[platform_name]
|
66
|
+
files += Array.from_attributes(attributes_hash[platform_name]["source_files"])
|
67
|
+
end
|
68
|
+
|
69
|
+
paths = files.map do |file|
|
70
|
+
real_file = file
|
71
|
+
if real_file.is_a?(String)
|
72
|
+
real_file = Pathname.new(real_file)
|
73
|
+
end
|
74
|
+
|
75
|
+
real_file
|
76
|
+
end
|
77
|
+
|
78
|
+
paths
|
79
|
+
end
|
80
|
+
|
81
|
+
def all_source_files(platform_name=nil)
|
82
|
+
all_source_files_paths(platform_name).map do |path|
|
83
|
+
path_s = path
|
84
|
+
if !path.is_a?(String)
|
85
|
+
path_s = path.to_s
|
86
|
+
end
|
87
|
+
|
88
|
+
path_s
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def header_files_paths_in_all_sources_files(platform_name=nil)
|
93
|
+
files = all_source_files_paths(platform_name)
|
94
|
+
files = files.select do |file|
|
95
|
+
file.extname == nil || file.extname.length == 0 || file.extname.to_s.include?("h")
|
96
|
+
end.map do |file|
|
97
|
+
real_file = file
|
98
|
+
if file.extname && file.extname.length > 0
|
99
|
+
real_file = real_file.sub_ext(".{h,hpp}")
|
100
|
+
elsif file.to_s.end_with?('*')
|
101
|
+
real_file = real_file.sub_ext(".{h,hpp}")
|
102
|
+
else # 'file' may be a folder!
|
103
|
+
real_file = (real_file + "*").sub_ext(".{h,hpp}")
|
104
|
+
end
|
105
|
+
|
106
|
+
real_file
|
107
|
+
end
|
108
|
+
|
109
|
+
files
|
110
|
+
end
|
111
|
+
|
112
|
+
def header_files_in_all_sources_files(platform_name=nil)
|
113
|
+
header_files_paths_in_all_sources_files(platform_name).map do |path|
|
114
|
+
path_s = path
|
115
|
+
if !path.is_a?(String)
|
116
|
+
path_s = path.to_s
|
117
|
+
end
|
118
|
+
|
119
|
+
path_s
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Pod
|
2
|
+
module Xcodebuild
|
3
|
+
def self.build_iphonesimulator!(project, scheme, product_name)
|
4
|
+
output_paths = []
|
5
|
+
sdk = 'iphonesimulator'
|
6
|
+
archs = %w(i386 x86_64)
|
7
|
+
archs.each do |arch|
|
8
|
+
output_path = build!(project, sdk, arch, scheme)
|
9
|
+
if !output_path
|
10
|
+
return []
|
11
|
+
end
|
12
|
+
|
13
|
+
output_paths += [output_path + product_name]
|
14
|
+
end
|
15
|
+
|
16
|
+
output_paths
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.build_iphoneos!(project, scheme, product_name)
|
20
|
+
output_paths = []
|
21
|
+
sdk = 'iphoneos'
|
22
|
+
archs = %w(arm64 armv7 armv7s)
|
23
|
+
archs.each do |arch|
|
24
|
+
output_path = build!(project, sdk, arch, scheme)
|
25
|
+
if !output_path
|
26
|
+
return []
|
27
|
+
end
|
28
|
+
|
29
|
+
output_paths += [output_path + product_name]
|
30
|
+
end
|
31
|
+
|
32
|
+
output_paths
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.build_macos!
|
36
|
+
# todo
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.build_tvos!
|
40
|
+
# todo
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.build_watchos!
|
44
|
+
# todo
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.build!(project, sdk, arch, scheme)
|
48
|
+
begin
|
49
|
+
output_path = Dir.randdir
|
50
|
+
args = %W(-project #{project.to_s} -scheme #{scheme} -configuration Release CONFIGURATION_BUILD_DIR=#{output_path.to_s} -sdk #{sdk} -derivedDataPath #{Dir.randdir.to_s} -arch #{arch} clean build)
|
51
|
+
Pod::Executable.execute_command("xcodebuild", args, true)
|
52
|
+
# Pod::UI.puts "#{scheme} #{sdk} #{arch} xcodebuild succeed!"
|
53
|
+
return output_path
|
54
|
+
rescue => e
|
55
|
+
# Pod::UI.puts "#{scheme} #{sdk} #{arch} xcodebuild failed! #{e}"
|
56
|
+
return nil
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'cocoapods-freezer/freezer'
|
2
|
+
require 'cocoapods-freezer/dir'
|
3
|
+
require 'cocoapods-freezer/config'
|
4
|
+
require 'cocoapods-freezer/installer'
|
5
|
+
require 'cocoapods-freezer/xcodebuild'
|
6
|
+
require 'cocoapods-freezer/lipo'
|
7
|
+
require 'cocoapods-freezer/specification'
|
8
|
+
require 'cocoapods-freezer/sandbox'
|
9
|
+
require 'cocoapods-freezer/lockfile'
|
10
|
+
require 'cocoapods-freezer/command'
|
11
|
+
|
data/spec/spec_helper.rb
ADDED
@@ -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,113 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cocoapods-freezer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- ''
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-01-08 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: cocoapods
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.5.3
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 1.5.3
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.3'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.3'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: A short description of cocoapods-freezer.
|
56
|
+
email:
|
57
|
+
- ''
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- ".gitignore"
|
63
|
+
- Gemfile
|
64
|
+
- LICENSE.txt
|
65
|
+
- README.md
|
66
|
+
- README_CH.md
|
67
|
+
- Rakefile
|
68
|
+
- cocoapods-freezer.gemspec
|
69
|
+
- lib/cocoapods-freezer.rb
|
70
|
+
- lib/cocoapods-freezer/command.rb
|
71
|
+
- lib/cocoapods-freezer/command/freeze.rb
|
72
|
+
- lib/cocoapods-freezer/command/install.rb
|
73
|
+
- lib/cocoapods-freezer/command/options/use_freezer.rb
|
74
|
+
- lib/cocoapods-freezer/config.rb
|
75
|
+
- lib/cocoapods-freezer/dir.rb
|
76
|
+
- lib/cocoapods-freezer/freezer.rb
|
77
|
+
- lib/cocoapods-freezer/gem_version.rb
|
78
|
+
- lib/cocoapods-freezer/installer.rb
|
79
|
+
- lib/cocoapods-freezer/lipo.rb
|
80
|
+
- lib/cocoapods-freezer/lockfile.rb
|
81
|
+
- lib/cocoapods-freezer/sandbox.rb
|
82
|
+
- lib/cocoapods-freezer/specification.rb
|
83
|
+
- lib/cocoapods-freezer/xcodebuild.rb
|
84
|
+
- lib/cocoapods_plugin.rb
|
85
|
+
- spec/command/freeze_spec.rb
|
86
|
+
- spec/spec_helper.rb
|
87
|
+
homepage: https://github.com/EXAMPLE/cocoapods-freezer
|
88
|
+
licenses:
|
89
|
+
- MIT
|
90
|
+
metadata: {}
|
91
|
+
post_install_message:
|
92
|
+
rdoc_options: []
|
93
|
+
require_paths:
|
94
|
+
- lib
|
95
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - ">="
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '0'
|
100
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - ">="
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '0'
|
105
|
+
requirements: []
|
106
|
+
rubyforge_project:
|
107
|
+
rubygems_version: 2.5.2.3
|
108
|
+
signing_key:
|
109
|
+
specification_version: 4
|
110
|
+
summary: A longer description of cocoapods-freezer.
|
111
|
+
test_files:
|
112
|
+
- spec/command/freeze_spec.rb
|
113
|
+
- spec/spec_helper.rb
|