cocoapods-nexus 0.0.2 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +4 -4
- data/cocoapods-nexus.gemspec +3 -2
- data/lib/cocoapods-nexus/api/components.rb +34 -7
- data/lib/cocoapods-nexus/api/connection.rb +1 -1
- data/lib/cocoapods-nexus/command/nexus/list.rb +1 -1
- data/lib/cocoapods-nexus/command/nexus/push.rb +10 -5
- data/lib/cocoapods-nexus/downloader.rb +3 -3
- data/lib/cocoapods-nexus/hook/specification.rb +19 -0
- data/lib/cocoapods-nexus/nexus_source.rb +253 -25
- metadata +20 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 96b8c8d75508a36b5121b69dadb1c71acec0edae13eff2b779d97793fcfbd33b
|
4
|
+
data.tar.gz: 05db6f85c0611aae05420f65e487221692e0c08cf50c5bab656584e7a14fe78a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 32e7ac7b9fd22c4f41f7f30b25d96c2178b4122447c69fb7e58023c85f8d9286bb2795364e0e2b00ccf76d68f621b0f643e9d7b98cd71dfef551ab364ef5c066
|
7
|
+
data.tar.gz: 269c7f2054d40ec71345698aab553e5aa421d8738d21f2227f7e7ca773b522dfac13ad23e5605291d7085e8302888bf83eb64ec4930c7ecf71f8a2414790fe40
|
data/README.md
CHANGED
@@ -26,7 +26,7 @@ $ gem install cocoapods-nexus
|
|
26
26
|
```shell
|
27
27
|
$ pod nexus add RepoName NexusHostUrl
|
28
28
|
# 例如:
|
29
|
-
# pod nexus add ios_release http://ip:
|
29
|
+
# pod nexus add ios_release http://ip:port
|
30
30
|
```
|
31
31
|
|
32
32
|
#### List
|
@@ -45,7 +45,7 @@ $ pod nexus list
|
|
45
45
|
$ pod nexus push path/to/podspec --url=NexusHostUrl --repo=RepoName --artifact=path/to/预编译文件
|
46
46
|
|
47
47
|
# 例如:
|
48
|
-
# pod nexus push ~/demo.podspec --url=http://ip:
|
48
|
+
# pod nexus push ~/demo.podspec --url=http://ip:port --repo=ios_release --artifact=~/demo.zip
|
49
49
|
```
|
50
50
|
|
51
51
|
### Podfile配置
|
@@ -55,7 +55,7 @@ $ pod nexus push path/to/podspec --url=NexusHostUrl --repo=RepoName --artifact=p
|
|
55
55
|
plugin 'cocoapods-nexus', :sources => [
|
56
56
|
{
|
57
57
|
:name => "ios",
|
58
|
-
:url => "http://ip:
|
58
|
+
:url => "http://ip:port",
|
59
59
|
}
|
60
60
|
]
|
61
61
|
|
@@ -77,7 +77,7 @@ password nexus_password
|
|
77
77
|
|
78
78
|
### 2.服务器地址
|
79
79
|
|
80
|
-
插件关于nexus的相关操作只需要配置ip和
|
80
|
+
插件关于nexus的相关操作只需要配置ip和port,后续的mount地址默认为nexus,暂时不支持修改。
|
81
81
|
|
82
82
|
## 致谢
|
83
83
|
|
data/cocoapods-nexus.gemspec
CHANGED
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
4
|
|
5
5
|
Gem::Specification.new do |spec|
|
6
6
|
spec.name = 'cocoapods-nexus'
|
7
|
-
spec.version =
|
7
|
+
spec.version = '0.0.7'
|
8
8
|
spec.authors = ['mrdaios']
|
9
9
|
spec.email = ['mrdaios@gmail.com']
|
10
10
|
spec.description = 'a cocoapods plugin for nexus.'
|
@@ -19,8 +19,9 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.require_paths = ['lib']
|
20
20
|
|
21
21
|
spec.add_runtime_dependency 'cocoapods', '>= 1.9.3'
|
22
|
+
spec.add_runtime_dependency 'concurrent-ruby', '~> 1.1'
|
22
23
|
spec.add_runtime_dependency 'rest-client', '~> 2.1.0'
|
23
|
-
spec.add_runtime_dependency '
|
24
|
+
spec.add_runtime_dependency 'typhoeus', '~> 1.0'
|
24
25
|
|
25
26
|
spec.add_development_dependency 'bundler', '~> 1.3'
|
26
27
|
spec.add_development_dependency 'rake', '~> 13.0'
|
@@ -6,22 +6,49 @@ module CocoapodsNexus
|
|
6
6
|
end
|
7
7
|
|
8
8
|
# 上传组件
|
9
|
-
def upload_maven_component(artifact_id:, version:, group_id:, podspec:, artifact:, files:)
|
9
|
+
def upload_maven_component(artifact_id:, version:, group_id:, podspec:, artifact:, podspec_hook:, files:)
|
10
10
|
parameters = {
|
11
11
|
'maven2.artifactId' => artifact_id,
|
12
12
|
'maven2.version' => version,
|
13
13
|
'maven2.groupId' => group_id,
|
14
14
|
'maven2.generate-pom' => true,
|
15
|
-
'maven2.packaging' => artifact.nil? ? 'podspec' : File.extname(artifact).delete(
|
15
|
+
'maven2.packaging' => artifact.nil? ? 'podspec' : File.extname(artifact).delete('.')
|
16
16
|
}
|
17
17
|
upload_files = []
|
18
|
-
|
19
|
-
|
20
|
-
|
18
|
+
unless podspec.nil?
|
19
|
+
upload_files << {
|
20
|
+
'file' => podspec,
|
21
|
+
'extension' => 'podspec',
|
22
|
+
# 'classifier' => 'podspec'
|
23
|
+
}
|
24
|
+
end
|
25
|
+
unless artifact.nil?
|
26
|
+
upload_files << {
|
27
|
+
'file' => artifact,
|
28
|
+
'extension' => File.extname(artifact).delete('.')
|
29
|
+
}
|
30
|
+
end
|
31
|
+
unless podspec_hook.nil?
|
32
|
+
upload_files << {
|
33
|
+
'file' => podspec_hook,
|
34
|
+
'extension' => 'rb',
|
35
|
+
'classifier' => 'podspec_hook'
|
36
|
+
}
|
37
|
+
end
|
38
|
+
|
39
|
+
unless files.nil?
|
40
|
+
upload_files |= files.map do |file|
|
41
|
+
{
|
42
|
+
'file' => file,
|
43
|
+
'extension' => File.extname(file).delete('.'),
|
44
|
+
}
|
45
|
+
end
|
46
|
+
end
|
21
47
|
|
22
48
|
upload_files.each_index do |index|
|
23
|
-
parameters["maven2.asset#{index + 1}"] = File.open(upload_files[index], 'r:utf-8')
|
24
|
-
parameters["maven2.asset#{index + 1}.extension"] =
|
49
|
+
parameters["maven2.asset#{index + 1}"] = File.open(upload_files[index]['file'], 'r:utf-8')
|
50
|
+
parameters["maven2.asset#{index + 1}.extension"] = upload_files[index]['extension'] unless upload_files[index]['extension'].nil?
|
51
|
+
parameters["maven2.asset#{index + 1}.classifier"] = upload_files[index]['classifier'] unless upload_files[index]['classifier'].nil?
|
25
52
|
end
|
26
53
|
@connection.post(endpoint: "components?repository=#{@repo}", parameters: parameters, headers: {})
|
27
54
|
end
|
@@ -112,7 +112,7 @@ module CocoapodsNexus
|
|
112
112
|
|
113
113
|
def send_request(connection_method, endpoint, parameters: '', headers: {}, api_version: 'v1')
|
114
114
|
parameters = parameters.to_json if headers['Content-Type'] == 'application/json'
|
115
|
-
url =
|
115
|
+
url = File.join(@hostname,"/nexus/service/rest/#{api_version}/#{endpoint}")
|
116
116
|
catch_connection_error do
|
117
117
|
RestClient::Request.execute(
|
118
118
|
method: connection_method,
|
@@ -16,9 +16,10 @@ module Pod
|
|
16
16
|
|
17
17
|
def self.options
|
18
18
|
[
|
19
|
-
[
|
20
|
-
[
|
21
|
-
[
|
19
|
+
%w[--url=url nexus服务器地址(http://ip:port)],
|
20
|
+
%w[--repo=repo nexus的仓库名称],
|
21
|
+
%w[--artifact=artifact 制品文件],
|
22
|
+
%w[--podspec_hook=podspec_hook. podspec动态修改脚本文件]
|
22
23
|
].concat(super)
|
23
24
|
end
|
24
25
|
|
@@ -27,6 +28,7 @@ module Pod
|
|
27
28
|
@url = argv.option('url')
|
28
29
|
@repo = argv.option('repo')
|
29
30
|
@artifact = argv.option('artifact')
|
31
|
+
@podspec_hook = argv.option('podspec_hook')
|
30
32
|
super
|
31
33
|
end
|
32
34
|
|
@@ -40,8 +42,10 @@ module Pod
|
|
40
42
|
def run
|
41
43
|
podspec_path = File.expand_path(@podspec)
|
42
44
|
artifact_path = File.expand_path(@artifact) unless @artifact.nil?
|
45
|
+
podspec_hook_path = File.expand_path(@podspec_hook) unless @podspec_hook.nil?
|
43
46
|
|
44
|
-
|
47
|
+
|
48
|
+
UI.section("开始发布 #{File.basename(@podspec)} -> #{File.join(@url,"/nexus/#browse/browse:",@repo)}") do
|
45
49
|
spec = Specification.from_file(podspec_path)
|
46
50
|
artifact_id = spec.attributes_hash['name']
|
47
51
|
version = spec.attributes_hash['version']
|
@@ -52,7 +56,8 @@ module Pod
|
|
52
56
|
group_id: group_id,
|
53
57
|
podspec: podspec_path,
|
54
58
|
artifact: artifact_path,
|
55
|
-
|
59
|
+
podspec_hook: podspec_hook_path,
|
60
|
+
files: nil)
|
56
61
|
UI.puts "成功发布 #{artifact_id}(#{version})"
|
57
62
|
else
|
58
63
|
raise Informative, "发布失败 #{artifact_id}(#{version}),请检查~/.netrc文件或#{@repo}类型"
|
@@ -12,7 +12,7 @@ module Pod
|
|
12
12
|
executable :curl
|
13
13
|
|
14
14
|
def download!
|
15
|
-
@filename = "#{options[:name]}.#{
|
15
|
+
@filename = "#{options[:name]}.#{options[:type]}"
|
16
16
|
@download_path = @target_path + @filename
|
17
17
|
download_file(@download_path)
|
18
18
|
end
|
@@ -32,8 +32,8 @@ module Pod
|
|
32
32
|
end
|
33
33
|
|
34
34
|
def user_agent_argument
|
35
|
-
"-A
|
35
|
+
"-A cocoapods-nexus"
|
36
36
|
end
|
37
37
|
end
|
38
38
|
end
|
39
|
-
end
|
39
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'cocoapods-core'
|
2
|
+
|
3
|
+
module Pod
|
4
|
+
class Specification
|
5
|
+
class << Specification
|
6
|
+
def _eval_nexus_podspec(nexus_podspec, parent_podspec)
|
7
|
+
podspec_string = nexus_podspec.gsub('Pod::Spec.new', 'Pod::Spec.nexus(parent_podspec)')
|
8
|
+
.gsub('Pod::Specification.new', 'Pod::Spec.nexus(parent_podspec)')
|
9
|
+
# rubocop:disable Eval
|
10
|
+
eval(podspec_string, binding)
|
11
|
+
# rubocop:enable Eval
|
12
|
+
end
|
13
|
+
|
14
|
+
def nexus(parent_podspec)
|
15
|
+
yield parent_podspec if block_given?
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -1,9 +1,14 @@
|
|
1
|
+
require 'concurrent'
|
2
|
+
require 'typhoeus'
|
1
3
|
require 'cocoapods-nexus/api'
|
2
4
|
require 'cocoapods-nexus/downloader'
|
3
|
-
require '
|
5
|
+
require 'cocoapods-nexus/hook/specification'
|
4
6
|
|
5
7
|
module Pod
|
6
8
|
class NexusSource < Source
|
9
|
+
include Concurrent
|
10
|
+
HYDRA_EXECUTOR = Concurrent::SingleThreadExecutor.new
|
11
|
+
|
7
12
|
def initialize(repo, url)
|
8
13
|
@source_url = url
|
9
14
|
super(repo)
|
@@ -26,34 +31,87 @@ module Pod
|
|
26
31
|
'nexus'
|
27
32
|
end
|
28
33
|
|
34
|
+
# @return [Array<Version>] all the available versions for the Pod, sorted
|
35
|
+
# from highest to lowest.
|
36
|
+
#
|
37
|
+
# @param [String] name
|
38
|
+
# the name of the Pod.
|
39
|
+
#
|
40
|
+
def versions(name)
|
41
|
+
return nil unless specs_dir
|
42
|
+
raise ArgumentError, 'No name' unless name
|
43
|
+
|
44
|
+
return @versions_by_name[name] unless @versions_by_name[name].nil?
|
45
|
+
|
46
|
+
pod_path_actual = pod_path(name)
|
47
|
+
pod_path_relative = pod_path(name).relative_path_from(repo)
|
48
|
+
|
49
|
+
concurrent_requests_catching_errors do
|
50
|
+
loaders = []
|
51
|
+
components = nexus_api.search_maven_component(artifact_id: name)
|
52
|
+
if !components.nil? && components.count > 0
|
53
|
+
# 从服务器获取version
|
54
|
+
@versions_by_name[name] ||= components.map do |component|
|
55
|
+
# Optimization: ensure all the podspec files at least exist. The correct one will get refreshed
|
56
|
+
# in #specification_path regardless.
|
57
|
+
podspec_version_path_relative = Pathname.new(component["version"]).join("#{name}.podspec")
|
58
|
+
|
59
|
+
unless pod_path_actual.join(podspec_version_path_relative).exist?
|
60
|
+
remote_url = parse_artifacte_asset_url(component, 'podspec')
|
61
|
+
# Queue all podspec download tasks first
|
62
|
+
loaders << download_file_async(pod_path_relative.join(podspec_version_path_relative).to_s, remote_url)
|
63
|
+
end
|
64
|
+
|
65
|
+
begin
|
66
|
+
Version.new(component["version"]) if component["version"][0, 1] != '.'
|
67
|
+
rescue ArgumentError
|
68
|
+
raise Informative, 'An unexpected version directory ' \
|
69
|
+
"`#{component["version"]}` was encountered for the " \
|
70
|
+
"`#{pod_path_actual}` Pod in the `#{name}` repository."
|
71
|
+
end
|
72
|
+
end.compact.sort.reverse
|
73
|
+
end
|
74
|
+
# Block and wait for all to complete running on Hydra
|
75
|
+
Promises.zip_futures_on(HYDRA_EXECUTOR, *loaders).wait!
|
76
|
+
end
|
77
|
+
@versions_by_name[name]
|
78
|
+
end
|
79
|
+
|
29
80
|
# 从nexus查询依赖
|
30
81
|
# @param [Object] query
|
31
82
|
def search(query)
|
32
83
|
unless File.exist?("#{repo}/.nexus")
|
33
84
|
raise Informative, "Unable to find a source named: `#{name}`"
|
34
85
|
end
|
35
|
-
|
36
|
-
|
37
|
-
# 本地没查询到,则从nexus服务查询
|
38
|
-
if found == []
|
39
|
-
# 暂时这样处理
|
40
|
-
spec_version = query.requirement.requirements.last.last.to_s
|
41
|
-
artifacte = nexus_find_artifacte(spec_name: query.root_name, spec_version: spec_version)
|
42
|
-
if artifacte
|
43
|
-
download_url = parse_artifacte_asset_url(artifacte, 'podspec')
|
44
|
-
if download_url
|
45
|
-
target_path = "#{@repo}/#{query.root_name}/#{spec_version}"
|
46
|
-
downloader = Pod::Downloader::NexusHttp.new(target_path, download_url, {:type => 'podspec', :name => query.root_name})
|
47
|
-
downloader.download
|
48
|
-
|
49
|
-
found = find_local_podspec(query)
|
50
|
-
end
|
51
|
-
end
|
86
|
+
if query.is_a?(Dependency)
|
87
|
+
query = query.root_name
|
52
88
|
end
|
53
89
|
|
54
|
-
|
55
|
-
|
56
|
-
|
90
|
+
# found = find_local_podspec(query)
|
91
|
+
# # 本地没查询到,则从nexus服务查询
|
92
|
+
# if found == []
|
93
|
+
# # 暂时这样处理
|
94
|
+
# spec_version = query.requirement.requirements.last.last.to_s
|
95
|
+
# artifacte = nexus_find_artifacte(spec_name: query.root_name, spec_version: spec_version)
|
96
|
+
# if artifacte
|
97
|
+
# download_url = parse_artifacte_asset_url(artifacte, 'podspec')
|
98
|
+
# if download_url
|
99
|
+
# target_path = "#{@repo}/#{query.root_name}/#{spec_version}"
|
100
|
+
# downloader = Pod::Downloader::NexusHttp.new(target_path, download_url, {:type => 'podspec', :name => query.root_name})
|
101
|
+
# downloader.download
|
102
|
+
#
|
103
|
+
# found = find_local_podspec(query)
|
104
|
+
# end
|
105
|
+
# end
|
106
|
+
# end
|
107
|
+
|
108
|
+
# version信息暂时不缓存到本地
|
109
|
+
components = nexus_api.search_maven_component(artifact_id: query)
|
110
|
+
found = !components.nil? && components.count > 0 ? query : nil
|
111
|
+
|
112
|
+
if found
|
113
|
+
set = set(query)
|
114
|
+
set if set.specification_name == query
|
57
115
|
end
|
58
116
|
end
|
59
117
|
|
@@ -66,7 +124,24 @@ module Pod
|
|
66
124
|
specification.attributes_hash['source'] = {
|
67
125
|
'http' => download_url
|
68
126
|
}
|
69
|
-
|
127
|
+
|
128
|
+
# 执行自定义脚本
|
129
|
+
podspec_rb_url = parse_artifacte_asset_url(artifacte, 'podspec_hook.rb')
|
130
|
+
if podspec_rb_url
|
131
|
+
tmpdir = Dir.tmpdir
|
132
|
+
downloader = Pod::Downloader::NexusHttp.new(tmpdir, podspec_rb_url, {:type => 'rb', :name => name})
|
133
|
+
downloader.download
|
134
|
+
|
135
|
+
path = File.join(tmpdir, "#{name}.rb")
|
136
|
+
if File.exist?(path)
|
137
|
+
string = File.open(path, 'r:utf-8', &:read)
|
138
|
+
if string
|
139
|
+
Pod::Specification._eval_nexus_podspec(string, specification)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
else
|
143
|
+
specification.attributes_hash['vendored_frameworks'] = "#{name}.framework"
|
144
|
+
end
|
70
145
|
end
|
71
146
|
specification
|
72
147
|
end
|
@@ -87,12 +162,14 @@ module Pod
|
|
87
162
|
# 解析附件downloadUrl
|
88
163
|
def parse_artifacte_asset_url(artifacte, asset_type)
|
89
164
|
asset = artifacte['assets'].select { |asset| asset['path'].end_with?(asset_type) }.first
|
90
|
-
asset['downloadUrl'] if asset && asset['downloadUrl']
|
91
|
-
end
|
165
|
+
asset['downloadUrl'] if asset && asset['downloadUrl']
|
166
|
+
end
|
92
167
|
|
93
168
|
def nexus_find_artifacte(spec_name:, spec_version:)
|
94
169
|
artifactes = nexus_api.search_maven_component(artifact_id: spec_name)
|
95
|
-
artifacte = artifactes.select { |artifacte| artifacte['version'].start_with?(spec_version) }.sort_by { |artifacte| Versionomy.parse(artifacte['version'])}.last
|
170
|
+
# artifacte = artifactes.select { |artifacte| artifacte['version'].start_with?(spec_version) }.sort_by { |artifacte| Versionomy.parse(artifacte['version'])}.last
|
171
|
+
# 暂时只支持查询指定版本
|
172
|
+
artifacte = artifactes.select { |artifacte| artifacte['version'] == spec_version }.last
|
96
173
|
artifacte
|
97
174
|
end
|
98
175
|
|
@@ -100,5 +177,156 @@ module Pod
|
|
100
177
|
repo_name = File.basename(@repo).gsub('nexus_', '')
|
101
178
|
@nexus_api ||= CocoapodsNexus::API.new(hostname: url, repo: repo_name)
|
102
179
|
end
|
180
|
+
|
181
|
+
def concurrent_requests_catching_errors
|
182
|
+
yield
|
183
|
+
rescue MultipleErrors => e
|
184
|
+
# aggregated error message from `Concurrent`
|
185
|
+
errors = e.errors
|
186
|
+
raise Informative, "CDN: #{name} Repo update failed - #{e.errors.size} error(s):\n#{errors.join("\n")}"
|
187
|
+
end
|
188
|
+
|
189
|
+
def download_file_async(partial_url, remote_url)
|
190
|
+
file_remote_url = URI.encode(remote_url)
|
191
|
+
path = repo + partial_url
|
192
|
+
|
193
|
+
# file_okay = local_file_okay?(partial_url)
|
194
|
+
# if file_okay
|
195
|
+
# if @startup_time < File.mtime(path)
|
196
|
+
# debug "CDN: #{name} Relative path: #{partial_url} modified during this run! Returning local"
|
197
|
+
# return Promises.fulfilled_future(partial_url, HYDRA_EXECUTOR)
|
198
|
+
# end
|
199
|
+
#
|
200
|
+
# unless @check_existing_files_for_update
|
201
|
+
# debug "CDN: #{name} Relative path: #{partial_url} exists! Returning local because checking is only perfomed in repo update"
|
202
|
+
# return Promises.fulfilled_future(partial_url, HYDRA_EXECUTOR)
|
203
|
+
# end
|
204
|
+
# end
|
205
|
+
|
206
|
+
path.dirname.mkpath
|
207
|
+
|
208
|
+
# etag_path = path.sub_ext(path.extname + '.etag')
|
209
|
+
|
210
|
+
# etag = File.read(etag_path) if file_okay && File.exist?(etag_path)
|
211
|
+
# debug "CDN: #{name} Relative path: #{partial_url}, has ETag? #{etag}" unless etag.nil?
|
212
|
+
|
213
|
+
download_and_save_with_retries_async(partial_url, file_remote_url)
|
214
|
+
end
|
215
|
+
|
216
|
+
def download_and_save_with_retries_async(partial_url, file_remote_url, retries = 5)
|
217
|
+
path = repo + partial_url
|
218
|
+
# etag_path = path.sub_ext(path.extname + '.etag')
|
219
|
+
|
220
|
+
download_task = download_typhoeus_impl_async(file_remote_url, nil).then do |response|
|
221
|
+
case response.response_code
|
222
|
+
when 301
|
223
|
+
redirect_location = response.headers['location']
|
224
|
+
# debug "CDN: #{name} Redirecting from #{file_remote_url} to #{redirect_location}"
|
225
|
+
download_and_save_with_retries_async(partial_url, redirect_location, nil )
|
226
|
+
when 304
|
227
|
+
# debug "CDN: #{name} Relative path not modified: #{partial_url}"
|
228
|
+
# We need to update the file modification date, as it is later used for freshness
|
229
|
+
# optimization. See #initialize for more information.
|
230
|
+
FileUtils.touch path
|
231
|
+
partial_url
|
232
|
+
when 200
|
233
|
+
File.open(path, 'w') { |f| f.write(response.response_body.force_encoding('UTF-8')) }
|
234
|
+
|
235
|
+
# etag_new = response.headers['etag'] unless response.headers.nil?
|
236
|
+
# debug "CDN: #{name} Relative path downloaded: #{partial_url}, save ETag: #{etag_new}"
|
237
|
+
# File.open(etag_path, 'w') { |f| f.write(etag_new) } unless etag_new.nil?
|
238
|
+
partial_url
|
239
|
+
when 404
|
240
|
+
# debug "CDN: #{name} Relative path couldn't be downloaded: #{partial_url} Response: #{response.response_code}"
|
241
|
+
nil
|
242
|
+
when 502, 503, 504
|
243
|
+
# Retryable HTTP errors, usually related to server overloading
|
244
|
+
if retries <= 1
|
245
|
+
# raise Informative, "CDN: #{name} URL couldn't be downloaded: #{file_remote_url} Response: #{response.response_code} #{response.response_body}"
|
246
|
+
else
|
247
|
+
# debug "CDN: #{name} URL couldn't be downloaded: #{file_remote_url} Response: #{response.response_code} #{response.response_body}, retries: #{retries - 1}"
|
248
|
+
exponential_backoff_async(retries).then do
|
249
|
+
download_and_save_with_retries_async(partial_url, file_remote_url, nil , retries - 1)
|
250
|
+
end
|
251
|
+
end
|
252
|
+
when 0
|
253
|
+
# Non-HTTP errors, usually network layer
|
254
|
+
if retries <= 1
|
255
|
+
raise Informative, "CDN: #{name} URL couldn't be downloaded: #{file_remote_url} Response: #{response.return_message}"
|
256
|
+
else
|
257
|
+
debug "CDN: #{name} URL couldn't be downloaded: #{file_remote_url} Response: #{response.return_message}, retries: #{retries - 1}"
|
258
|
+
exponential_backoff_async(retries).then do
|
259
|
+
download_and_save_with_retries_async(partial_url, file_remote_url, etag, retries - 1)
|
260
|
+
end
|
261
|
+
end
|
262
|
+
else
|
263
|
+
raise Informative, "CDN: #{name} URL couldn't be downloaded: #{file_remote_url} Response: #{response.response_code} #{response.response_body}"
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
# Calling `Future#run` flattens the chained futures created by retries or redirects
|
268
|
+
#
|
269
|
+
# Does not, in fact, run the task - that is already happening in Hydra at this point
|
270
|
+
download_task.run
|
271
|
+
end
|
272
|
+
|
273
|
+
def exponential_backoff_async(retries)
|
274
|
+
sleep_async(backoff_time(retries))
|
275
|
+
end
|
276
|
+
|
277
|
+
def backoff_time(retries)
|
278
|
+
current_retry = MAX_NUMBER_OF_RETRIES - retries
|
279
|
+
4 * 2**current_retry
|
280
|
+
end
|
281
|
+
|
282
|
+
def sleep_async(seconds)
|
283
|
+
# Async sleep to avoid blocking either the main or the Hydra thread
|
284
|
+
Promises.schedule_on(HYDRA_EXECUTOR, seconds)
|
285
|
+
end
|
286
|
+
|
287
|
+
def download_typhoeus_impl_async(file_remote_url, etag)
|
288
|
+
# Create a prefereably HTTP/2 request - the protocol is ultimately responsible for picking
|
289
|
+
# the maximum supported protocol
|
290
|
+
# When debugging with proxy, use the following extra options:
|
291
|
+
# :proxy => 'http://localhost:8888',
|
292
|
+
# :ssl_verifypeer => false,
|
293
|
+
# :ssl_verifyhost => 0,
|
294
|
+
request = Typhoeus::Request.new(
|
295
|
+
file_remote_url,
|
296
|
+
:method => :get,
|
297
|
+
:http_version => :httpv2_0,
|
298
|
+
:timeout => 10,
|
299
|
+
:connecttimeout => 10,
|
300
|
+
:accept_encoding => 'gzip',
|
301
|
+
:netrc => :optional,
|
302
|
+
:netrc_file => Netrc.default_path,
|
303
|
+
:headers => etag.nil? ? {} : { 'If-None-Match' => etag },
|
304
|
+
)
|
305
|
+
|
306
|
+
future = Promises.resolvable_future_on(Concurrent::SingleThreadExecutor.new)
|
307
|
+
queue_request(request)
|
308
|
+
request.on_complete do |response|
|
309
|
+
future.fulfill(response)
|
310
|
+
end
|
311
|
+
|
312
|
+
# This `Future` should never reject, network errors are exposed on `Typhoeus::Response`
|
313
|
+
future
|
314
|
+
end
|
315
|
+
|
316
|
+
def queue_request(request)
|
317
|
+
@hydra ||= Typhoeus::Hydra.new
|
318
|
+
|
319
|
+
# Queue the request into the Hydra (libcurl reactor).
|
320
|
+
@hydra.queue(request)
|
321
|
+
|
322
|
+
# Cycle the reactor on a separate thread
|
323
|
+
#
|
324
|
+
# The way it works is that if more requests are queued while Hydra is in the `#run`
|
325
|
+
# method, it will keep executing them
|
326
|
+
#
|
327
|
+
# The upcoming calls to `#run` will simply run empty.
|
328
|
+
HYDRA_EXECUTOR.post(@hydra, &:run)
|
329
|
+
end
|
330
|
+
|
103
331
|
end
|
104
332
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cocoapods-nexus
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- mrdaios
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-09-
|
11
|
+
date: 2020-09-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: cocoapods
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 1.9.3
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: concurrent-ruby
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.1'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.1'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: rest-client
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -39,19 +53,19 @@ dependencies:
|
|
39
53
|
- !ruby/object:Gem::Version
|
40
54
|
version: 2.1.0
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
56
|
+
name: typhoeus
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
44
58
|
requirements:
|
45
59
|
- - "~>"
|
46
60
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
61
|
+
version: '1.0'
|
48
62
|
type: :runtime
|
49
63
|
prerelease: false
|
50
64
|
version_requirements: !ruby/object:Gem::Requirement
|
51
65
|
requirements:
|
52
66
|
- - "~>"
|
53
67
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
68
|
+
version: '1.0'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: bundler
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -108,6 +122,7 @@ files:
|
|
108
122
|
- lib/cocoapods-nexus/hook/analyzer.rb
|
109
123
|
- lib/cocoapods-nexus/hook/installer.rb
|
110
124
|
- lib/cocoapods-nexus/hook/manager.rb
|
125
|
+
- lib/cocoapods-nexus/hook/specification.rb
|
111
126
|
- lib/cocoapods-nexus/nexus_source.rb
|
112
127
|
- lib/cocoapods_plugin.rb
|
113
128
|
- spec/command/nexus_spec.rb
|