cocoapods-nexus 0.0.3 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8e790c8479f071d8bc80761fb28c74c72c93fef2403a68cb4f9009f25a398432
4
- data.tar.gz: 2a0394806a1121888688c43cebf35f1d4f3a2bcac18bead95b93b96570147d64
3
+ metadata.gz: 6ac4a898f34bf416710c9a860d1277a2b31e4724aa4227778db75a8a2fd66a50
4
+ data.tar.gz: 20eb9b143367130deb7da98ff04249773e5ca4ee92ef624b40ff79eb62a2416a
5
5
  SHA512:
6
- metadata.gz: 2d438fe47a93ec9f8221cc77f24afc6e9724474aadf0e985bfa33cd325a1d6799f0dac65ca2f130dba241a4584ec9e9bf483d7719b0731a0f2c924fbbac213df
7
- data.tar.gz: 5f482b8c5d309d61f93fcb4e5e0f8da5500f164b6c8398e85aa8269eb286bb0e9e9361bcf124b476deacd0bd567afff4e232e3e3dd73b289eb420db910c19563
6
+ metadata.gz: 23514cadd69f45a3892775c5efb738a4173c4ee0e0edf5b7081a51a11cc7f141f611dbc1f56d3b914afd45852aea8729769c319cbfd46b88a3d332d313cb7040
7
+ data.tar.gz: 33d55877147c3bc40b7de688d3833d571cf324850ada1ef23c89f1712a1ca52c2fb1c2f29299f1a42d4fce15c6b7e0829a2ac60670eab6d3e3e381ad729b17fc
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:host
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:host --repo=ios_release --artifact=~/demo.zip
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:host",
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和host,后续的mount地址默认为nexus,暂时不支持修改。
80
+ 插件关于nexus的相关操作只需要配置ip和port,后续的mount地址默认为nexus,暂时不支持修改。
81
81
 
82
82
  ## 致谢
83
83
 
@@ -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 = "0.0.3"
7
+ spec.version = '0.0.8'
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 'versionomy', '~> 0.5.0'
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
- upload_files << podspec unless podspec.nil?
19
- upload_files << artifact unless artifact.nil?
20
- upload_files | files unless files.nil?
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"] = File.extname(upload_files[index]).delete(".")
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 = "#{@hostname}/nexus/service/rest/#{api_version}/#{endpoint}"
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,
@@ -5,7 +5,7 @@ module Pod
5
5
  class Command
6
6
  class Nexus
7
7
  class List < Nexus
8
- self.summary = 'Add a nexus repo.'
8
+ self.summary = 'List a nexus repo.'
9
9
 
10
10
  self.description = <<-DESC
11
11
  添加一个nexus的repo
@@ -16,9 +16,10 @@ module Pod
16
16
 
17
17
  def self.options
18
18
  [
19
- ['--url=url', 'a nexus hostname'],
20
- ['--repo=repo', 'a nexus repo'],
21
- ['--artifact=artifact', 'a nexus artifact']
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
- UI.section("开始发布 #{File.basename(@podspec)} -> #{@url}/nexus/#browse/browse:#{@repo}") do
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
- files: [])
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]}.#{'podspec'.to_sym}"
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 '#{Http.user_agent_string}'"
35
+ "-A cocoapods-nexus"
36
36
  end
37
37
  end
38
38
  end
39
- end
39
+ end
@@ -1,2 +1 @@
1
- require 'cocoapods-nexus/hook/analyzer'
2
1
  require 'cocoapods-nexus/hook/manager'
@@ -4,8 +4,9 @@ require 'cocoapods-nexus/nexus_source'
4
4
  module Pod
5
5
  class Source
6
6
  class Manager
7
- alias orgin_source_from_path source_from_path
8
7
 
8
+ alias orgin_source_from_path source_from_path
9
+ # 根据nexus配置文件加载source
9
10
  def source_from_path(path)
10
11
  @new_sources_by_path ||= Hash.new do |hash, key|
11
12
  nexus_file_path = File.join(key, ".nexus")
@@ -17,6 +18,12 @@ module Pod
17
18
  end
18
19
  @new_sources_by_path[path]
19
20
  end
21
+
22
+ alias orgin_source_with_url source_with_url
23
+ # 让nexus支持多repo
24
+ def source_with_url(url)
25
+ nil
26
+ end
20
27
  end
21
28
  end
22
29
  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 'versionomy'
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
- found = find_local_podspec(query)
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
- if found == [query.root_name]
55
- set = set(query.root_name)
56
- set if set.specification_name == query.root_name
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
- specification.attributes_hash['vendored_frameworks'] = "#{name}.framework"
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
@@ -88,11 +163,13 @@ module Pod
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
165
  asset['downloadUrl'] if asset && asset['downloadUrl']
91
- end
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.3
4
+ version: 0.0.8
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-05 00:00:00.000000000 Z
11
+ date: 2020-09-16 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: versionomy
56
+ name: typhoeus
43
57
  requirement: !ruby/object:Gem::Requirement
44
58
  requirements:
45
59
  - - "~>"
46
60
  - !ruby/object:Gem::Version
47
- version: 0.5.0
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: 0.5.0
68
+ version: '1.0'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: bundler
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -106,8 +120,8 @@ files:
106
120
  - lib/cocoapods-nexus/downloader.rb
107
121
  - lib/cocoapods-nexus/hook.rb
108
122
  - lib/cocoapods-nexus/hook/analyzer.rb
109
- - lib/cocoapods-nexus/hook/installer.rb
110
123
  - lib/cocoapods-nexus/hook/manager.rb
124
+ - lib/cocoapods-nexus/hook/specification.rb
111
125
  - lib/cocoapods-nexus/nexus_source.rb
112
126
  - lib/cocoapods_plugin.rb
113
127
  - spec/command/nexus_spec.rb
@@ -1,49 +0,0 @@
1
- # require 'cocoapods-core'
2
- # require 'cocoapods-nexus/api'
3
-
4
- # module Pod
5
- # class Installer
6
- # alias_method :old_root_specs, :root_specs
7
- # def root_specs
8
- # # 通过修改specs的source到nexus下载zip(不完美的解决方案)
9
- # specs = old_root_specs
10
- # specs = specs.map{|spec| modify_spec_if_find_last_version(spec)}
11
- # specs
12
- # end
13
-
14
- # private
15
-
16
- # def modify_spec_if_find_last_version(spec)
17
- # attributes_hash = spec.attributes_hash
18
- # spec_name = attributes_hash['name']
19
- # spec_version = attributes_hash['version']
20
- # artifacte = nexus_find_artifacte(spec_name: spec_name, spec_version: spec_version)
21
- # if artifacte != nil
22
- # asset_zip = artifacte['assets'].select{ |asset| asset['path'].end_with?('zip') }.first
23
- # if asset_zip != nil
24
- # attributes_hash['source'] = {
25
- # 'http' => asset_zip['downloadUrl']
26
- # }
27
- # puts "Downloading #{spec_name}(#{spec_version})from nexus(#{asset_zip['downloadUrl']})"
28
- # spec.attributes_hash = attributes_hash
29
- # end
30
- # end
31
- # spec
32
- # end
33
-
34
- # def nexus_find_artifacte(spec_name:, spec_version:)
35
- # artifacte = {}
36
- # api.each do |api|
37
- # artifactes = api.search_maven_component(artifact_id: spec_name)
38
- # artifacte = artifactes.select{ |artifacte| artifacte['version'].start_with?(spec_version) }.sort_by{ |artifacte| artifacte['version'].downcase }.last
39
- # break if artifacte != nil
40
- # end
41
- # artifacte
42
- # end
43
-
44
- # def api
45
- # nexus_options = Pod::Config.instance.podfile.get_options || []
46
- # @apis = @apis || nexus_options.map{|nexus| CocoapodsNexus::API.new(hostname: nexus['endpoint'], repo: nexus['repo'])}
47
- # end
48
- # end
49
- # end