cocoapods-nexus-downloader 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 +7 -0
- data/lib/cocoapods-nexus-downloader/command/nexus.rb +44 -0
- data/lib/cocoapods-nexus-downloader/command.rb +1 -0
- data/lib/cocoapods-nexus-downloader/gem_version.rb +3 -0
- data/lib/cocoapods-nexus-downloader/hook-cocoapods-downloader.rb +18 -0
- data/lib/cocoapods-nexus-downloader/nexus-downloader.rb +256 -0
- data/lib/cocoapods-nexus-downloader/pre-install.rb +23 -0
- data/lib/cocoapods-nexus-downloader.rb +3 -0
- data/lib/cocoapods_plugin.rb +1 -0
- metadata +80 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 3c8c852aa349b236b4cf219847aff4876ab6540ba4951ad91be9c22b74992962
|
4
|
+
data.tar.gz: a6d6d9dcad0fc4979ca7f62f115b373a7e8cbdfe6c94940a0935b78ac69d17ec
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 3524e18e04501317d01dac4b987213ffcd8ae78b4f4c61e612f282db11ccb076abcf5357929cc7823e890ea457c136aeb4fc5ad59f1bfb1efc1a74edbf65a83c
|
7
|
+
data.tar.gz: f126a15e3b06df0fda848ecdbd7bac822bb6be55c86985d0d2b79392f8fc447544a795761aadf9fdc54fc877ae4111e4ff46c542a9189c177d73d922562c1dfb
|
@@ -0,0 +1,44 @@
|
|
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
|
+
class Nexus < Command
|
21
|
+
self.summary = 'Short description of cocoapods-nexus.'
|
22
|
+
|
23
|
+
self.description = <<-DESC
|
24
|
+
Longer description of cocoapods-Nexus.
|
25
|
+
DESC
|
26
|
+
|
27
|
+
self.arguments = 'NAME'
|
28
|
+
|
29
|
+
def initialize(argv)
|
30
|
+
@name = argv.shift_argument
|
31
|
+
super
|
32
|
+
end
|
33
|
+
|
34
|
+
def validate!
|
35
|
+
super
|
36
|
+
help! 'A Pod name is required.' unless @name
|
37
|
+
end
|
38
|
+
|
39
|
+
def run
|
40
|
+
UI.puts "Add your implementation for the cocoapods-nexus plugin in #{__FILE__}"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'cocoapods-nexus-downloader/command/nexus'
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'cocoapods-downloader'
|
2
|
+
require 'cocoapods-nexus-downloader/nexus-downloader'
|
3
|
+
|
4
|
+
module Pod
|
5
|
+
module Downloader
|
6
|
+
class <<self
|
7
|
+
alias_method :real_downloader_class_by_key, :downloader_class_by_key
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.downloader_class_by_key
|
11
|
+
original = self.real_downloader_class_by_key
|
12
|
+
original[:nexus] = NexusDownloader
|
13
|
+
original
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
@@ -0,0 +1,256 @@
|
|
1
|
+
# require 'addressable'
|
2
|
+
require 'cocoapods-downloader'
|
3
|
+
require 'uri'
|
4
|
+
require 'net/http'
|
5
|
+
require 'json'
|
6
|
+
|
7
|
+
module Pod
|
8
|
+
module Downloader
|
9
|
+
|
10
|
+
class NexusDownloader < Base
|
11
|
+
def self.options
|
12
|
+
[:repo, :group, :artifact, :version, :type, :md5, :sha1,]
|
13
|
+
end
|
14
|
+
|
15
|
+
USER_AGENT_HEADER = 'User-Agent'.freeze
|
16
|
+
|
17
|
+
class UnsupportedFileTypeError < StandardError; end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
executable :curl
|
22
|
+
# executable :mvn
|
23
|
+
executable :unzip
|
24
|
+
executable :tar
|
25
|
+
executable :hdiutil
|
26
|
+
# @return [String] the url of the remote source.
|
27
|
+
#
|
28
|
+
attr_accessor :filename, :download_path
|
29
|
+
|
30
|
+
def self.preprocess_options(options)
|
31
|
+
|
32
|
+
debug_puts "preprocess_options: #{options}"
|
33
|
+
artifact_item = self.request_artifact(options[:nexus], options)
|
34
|
+
debug_puts artifact_item
|
35
|
+
md5Val = artifact_item.checksum.md5
|
36
|
+
|
37
|
+
if options.key?(:md5)
|
38
|
+
raise "md5 value is not matched with remote file" unless options[:md5] == md5Val
|
39
|
+
else
|
40
|
+
options[:md5] = md5Val
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
# TODO: also check sha1
|
45
|
+
options
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.request_artifact(url, options)
|
49
|
+
|
50
|
+
# https://stackoverflow.com/a/70596332/11884593
|
51
|
+
# http://192.168.138.192:8081/#admin/system/api
|
52
|
+
uri = URI("#{url}/service/rest/v1/search/assets")
|
53
|
+
params = {
|
54
|
+
'sort' => 'version',
|
55
|
+
'repository' => options[:repo],
|
56
|
+
'maven.groupId' => options[:group],
|
57
|
+
'maven.artifactId' => options[:artifact],
|
58
|
+
# maven don't allow '/' in version, so we replace it with '_' automatically
|
59
|
+
'maven.baseVersion' => options[:version].gsub('/', '_'),
|
60
|
+
'maven.extension' => options[:type],
|
61
|
+
'prerelease' => false
|
62
|
+
}
|
63
|
+
uri.query = URI.encode_www_form(params)
|
64
|
+
|
65
|
+
debug_puts("uri: #{uri}")
|
66
|
+
res = Net::HTTP.get_response(uri)
|
67
|
+
raise DownloaderError, 'Search failed!' if res.is_a?(Net::HTTPError) || res.body.to_s.empty?
|
68
|
+
debug_puts "res.body: #{res.body.to_s}"
|
69
|
+
|
70
|
+
parsed_model = JSON.parse(res.body, object_class: OpenStruct)
|
71
|
+
raise DownloaderError, "Can't find matched artifact!" if parsed_model.items.empty?
|
72
|
+
debug_puts "aaa3: #{parsed_model.items.first}"
|
73
|
+
parsed_model.items.to_a.first
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
def download!
|
78
|
+
@filename = filename_with_type(type)
|
79
|
+
@download_path = target_path + @filename
|
80
|
+
download_file(@download_path)
|
81
|
+
verify_checksum(@download_path)
|
82
|
+
extract_with_type(@download_path, type)
|
83
|
+
end
|
84
|
+
|
85
|
+
def type
|
86
|
+
if options[:type]
|
87
|
+
options[:type].to_sym
|
88
|
+
else
|
89
|
+
type_with_url(url)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def headers
|
94
|
+
options[:headers]
|
95
|
+
end
|
96
|
+
|
97
|
+
# @note The archive is flattened if it contains only one folder and its
|
98
|
+
# extension is either `tgz`, `tar`, `tbz` or the options specify
|
99
|
+
# it.
|
100
|
+
#
|
101
|
+
# @return [Bool] Whether the archive should be flattened if it contains
|
102
|
+
# only one folder.
|
103
|
+
#
|
104
|
+
def should_flatten?
|
105
|
+
if options.key?(:flatten)
|
106
|
+
options[:flatten]
|
107
|
+
elsif %i[tgz tar tbz txz].include?(type)
|
108
|
+
true # those archives flatten by default
|
109
|
+
else
|
110
|
+
false # all others (actually only .zip) default not to flatten
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def type_with_url(url)
|
115
|
+
case URI.parse(url).path
|
116
|
+
when /\.zip$/
|
117
|
+
:zip
|
118
|
+
when /\.(tgz|tar\.gz)$/
|
119
|
+
:tgz
|
120
|
+
when /\.tar$/
|
121
|
+
:tar
|
122
|
+
when /\.(tbz|tar\.bz2)$/
|
123
|
+
:tbz
|
124
|
+
when /\.(txz|tar\.xz)$/
|
125
|
+
:txz
|
126
|
+
when /\.dmg$/
|
127
|
+
:dmg
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def filename_with_type(type = :zip)
|
132
|
+
case type
|
133
|
+
when :zip, :tgz, :tar, :tbz, :txz, :dmg
|
134
|
+
"file.#{type}"
|
135
|
+
else
|
136
|
+
raise UnsupportedFileTypeError, "Unsupported file type: #{type}"
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def extract_with_type(full_filename, type = :zip)
|
141
|
+
unpack_from = full_filename
|
142
|
+
unpack_to = @target_path
|
143
|
+
|
144
|
+
case type
|
145
|
+
when :zip
|
146
|
+
unzip! unpack_from, '-d', unpack_to
|
147
|
+
when :tar, :tgz, :tbz, :txz
|
148
|
+
tar! 'xf', unpack_from, '-C', unpack_to
|
149
|
+
when :dmg
|
150
|
+
extract_dmg(unpack_from, unpack_to)
|
151
|
+
else
|
152
|
+
raise UnsupportedFileTypeError, "Unsupported file type: #{type}"
|
153
|
+
end
|
154
|
+
|
155
|
+
# If the archive is a tarball and it only contained a folder, move its
|
156
|
+
# contents to the target (#727)
|
157
|
+
#
|
158
|
+
if should_flatten?
|
159
|
+
contents = target_path.children
|
160
|
+
contents.delete(target_path + @filename)
|
161
|
+
entry = contents.first
|
162
|
+
if contents.count == 1 && entry.directory?
|
163
|
+
tmp_entry = entry.sub_ext("#{entry.extname}.tmp")
|
164
|
+
begin
|
165
|
+
FileUtils.move(entry, tmp_entry)
|
166
|
+
FileUtils.move(tmp_entry.children, target_path)
|
167
|
+
ensure
|
168
|
+
FileUtils.remove_entry(tmp_entry)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
FileUtils.rm(unpack_from) if File.exist?(unpack_from)
|
174
|
+
end
|
175
|
+
|
176
|
+
def extract_dmg(unpack_from, unpack_to)
|
177
|
+
require 'rexml/document'
|
178
|
+
plist_s = hdiutil! 'attach', '-plist', '-nobrowse', unpack_from, '-mountrandom', unpack_to
|
179
|
+
plist = REXML::Document.new plist_s
|
180
|
+
xpath = '//key[.="mount-point"]/following-sibling::string'
|
181
|
+
mount_point = REXML::XPath.first(plist, xpath).text
|
182
|
+
FileUtils.cp_r(Dir.glob(mount_point + '/*'), unpack_to)
|
183
|
+
hdiutil! 'detach', mount_point
|
184
|
+
end
|
185
|
+
|
186
|
+
def compare_hash(filename, hasher, hash)
|
187
|
+
incremental_hash = hasher.new
|
188
|
+
|
189
|
+
File.open(filename, 'rb') do |file|
|
190
|
+
buf = ''
|
191
|
+
incremental_hash << buf while file.read(1024, buf)
|
192
|
+
end
|
193
|
+
|
194
|
+
computed_hash = incremental_hash.hexdigest
|
195
|
+
|
196
|
+
return unless computed_hash != hash
|
197
|
+
|
198
|
+
raise DownloaderError, 'Verification checksum was incorrect, ' \
|
199
|
+
"expected #{hash}, got #{computed_hash}"
|
200
|
+
end
|
201
|
+
|
202
|
+
# Verify that the downloaded file matches a sha1 hash
|
203
|
+
#
|
204
|
+
def verify_sha1_hash(filename, hash)
|
205
|
+
require 'digest/sha1'
|
206
|
+
compare_hash(filename, Digest::SHA1, hash)
|
207
|
+
end
|
208
|
+
|
209
|
+
# Verify that the downloaded file matches a sha256 hash
|
210
|
+
#
|
211
|
+
def verify_sha256_hash(filename, hash)
|
212
|
+
require 'digest/sha2'
|
213
|
+
compare_hash(filename, Digest::SHA2, hash)
|
214
|
+
end
|
215
|
+
|
216
|
+
# Verify that the downloaded file matches the hash if set
|
217
|
+
#
|
218
|
+
def verify_checksum(filename)
|
219
|
+
if options[:sha256]
|
220
|
+
verify_sha256_hash(filename, options[:sha256])
|
221
|
+
elsif options[:sha1]
|
222
|
+
verify_sha1_hash(filename, options[:sha1])
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
def download_file(download_path)
|
227
|
+
debug_puts "hl: download_file: #{download_path}"
|
228
|
+
artifact_item = NexusDownloader.request_artifact(url, options)
|
229
|
+
source_url = artifact_item.downloadUrl
|
230
|
+
parameters = ['-f', '-L', '-o', download_path, source_url, '--create-dirs', '--netrc-optional', '--retry', '2']
|
231
|
+
parameters << user_agent_argument if headers.nil? ||
|
232
|
+
headers.none? { |header| header.casecmp(USER_AGENT_HEADER).zero? }
|
233
|
+
|
234
|
+
unless headers.nil?
|
235
|
+
headers.each do |h|
|
236
|
+
parameters << '-H'
|
237
|
+
parameters << h
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
debug_puts "curl parameters: #{parameters}"
|
242
|
+
curl! parameters
|
243
|
+
end
|
244
|
+
|
245
|
+
# Returns a cURL command flag to add the CocoaPods User-Agent.
|
246
|
+
#
|
247
|
+
# @return [String] cURL command -A flag and User-Agent.
|
248
|
+
#
|
249
|
+
def user_agent_argument
|
250
|
+
debug_puts "1"
|
251
|
+
"-A '#{Http.user_agent_string}'"
|
252
|
+
end
|
253
|
+
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
def debug_puts(content)
|
2
|
+
return unless CocoapodsNexusDownloader.debug
|
3
|
+
|
4
|
+
puts content
|
5
|
+
end
|
6
|
+
|
7
|
+
module CocoapodsNexusDownloader
|
8
|
+
class << self
|
9
|
+
# @return [Bool] the url of the remote source.
|
10
|
+
#
|
11
|
+
attr_accessor :debug
|
12
|
+
|
13
|
+
Pod::HooksManager.register('cocoapods-nexus-downloader', :pre_install) do |_context, options|
|
14
|
+
CocoapodsNexusDownloader.pre_install(options)
|
15
|
+
end
|
16
|
+
|
17
|
+
def pre_install(options)
|
18
|
+
debug_puts "pre_install hook: #{options}"
|
19
|
+
# Now we can configure the downloader to use the Azure CLI for downloading pods from the given hosts
|
20
|
+
@debug = options.fetch(:debug, false)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'cocoapods-nexus-downloader'
|
metadata
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cocoapods-nexus-downloader
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Hanley Lee
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-01-23 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: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
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: Host the pod's framework file on Nexus and download it using ':nexus'.
|
42
|
+
email:
|
43
|
+
- hanley.lei@gmail.com
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- lib/cocoapods-nexus-downloader.rb
|
49
|
+
- lib/cocoapods-nexus-downloader/command.rb
|
50
|
+
- lib/cocoapods-nexus-downloader/command/nexus.rb
|
51
|
+
- lib/cocoapods-nexus-downloader/gem_version.rb
|
52
|
+
- lib/cocoapods-nexus-downloader/hook-cocoapods-downloader.rb
|
53
|
+
- lib/cocoapods-nexus-downloader/nexus-downloader.rb
|
54
|
+
- lib/cocoapods-nexus-downloader/pre-install.rb
|
55
|
+
- lib/cocoapods_plugin.rb
|
56
|
+
homepage: https://github.com/hanleylee/cocoapods-nexus-downloader
|
57
|
+
licenses:
|
58
|
+
- MIT
|
59
|
+
metadata: {}
|
60
|
+
post_install_message:
|
61
|
+
rdoc_options: []
|
62
|
+
require_paths:
|
63
|
+
- lib
|
64
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '0'
|
74
|
+
requirements: []
|
75
|
+
rubygems_version: 3.4.10
|
76
|
+
signing_key:
|
77
|
+
specification_version: 4
|
78
|
+
summary: A CocoaPods plugin that enables referencing a pod using ':nexus' and downloading
|
79
|
+
it from Nexus in maven type.
|
80
|
+
test_files: []
|