cocoapods-nexus 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/.github/workflows/main.yml +13 -0
- data/.gitignore +56 -0
- data/Gemfile +10 -0
- data/LICENSE +22 -0
- data/README.md +11 -0
- data/Rakefile +13 -0
- data/cocoapods-nexus.gemspec +26 -0
- data/lib/cocoapods-nexus.rb +3 -0
- data/lib/cocoapods-nexus/api.rb +16 -0
- data/lib/cocoapods-nexus/api/components.rb +29 -0
- data/lib/cocoapods-nexus/api/connection.rb +158 -0
- data/lib/cocoapods-nexus/command.rb +1 -0
- data/lib/cocoapods-nexus/command/nexus.rb +24 -0
- data/lib/cocoapods-nexus/command/nexus/add.rb +58 -0
- data/lib/cocoapods-nexus/command/nexus/list.rb +34 -0
- data/lib/cocoapods-nexus/command/nexus/push.rb +71 -0
- data/lib/cocoapods-nexus/downloader.rb +39 -0
- data/lib/cocoapods-nexus/hook.rb +2 -0
- data/lib/cocoapods-nexus/hook/analyzer.rb +29 -0
- data/lib/cocoapods-nexus/hook/installer.rb +49 -0
- data/lib/cocoapods-nexus/hook/manager.rb +22 -0
- data/lib/cocoapods-nexus/nexus_source.rb +103 -0
- data/lib/cocoapods_plugin.rb +29 -0
- data/spec/command/nexus_spec.rb +12 -0
- data/spec/spec_helper.rb +50 -0
- metadata +126 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: a7a9541ba6b2cab7847ca881391c0531d200a5ea17903d9688a3f5305685da3c
|
4
|
+
data.tar.gz: fe6507a84828877934b74c77e4935888b32c851a0af134e280c38dee879e79c7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 530ea1d9c6eff91257c46d3dc52d9981841d147a728f22cfbd8b62b9ccb9e5258a80cb1a1c17511f9286836ba9652f149004a4f95bc92175436ea588133aa2ff
|
7
|
+
data.tar.gz: c36596c0e6471a86456178e8df7acdb98dd2c5103184fd2e9fcf9ea0edb6289b3a35a9396d029b2a9fa1086a08cceb26af31febe0093fe938ddc743e4fe34319
|
data/.gitignore
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
/.config
|
4
|
+
/coverage/
|
5
|
+
/InstalledFiles
|
6
|
+
/pkg/
|
7
|
+
/spec/reports/
|
8
|
+
/spec/examples.txt
|
9
|
+
/test/tmp/
|
10
|
+
/test/version_tmp/
|
11
|
+
/tmp/
|
12
|
+
|
13
|
+
# Used by dotenv library to load environment variables.
|
14
|
+
# .env
|
15
|
+
|
16
|
+
# Ignore Byebug command history file.
|
17
|
+
.byebug_history
|
18
|
+
|
19
|
+
## Specific to RubyMotion:
|
20
|
+
.dat*
|
21
|
+
.repl_history
|
22
|
+
build/
|
23
|
+
*.bridgesupport
|
24
|
+
build-iPhoneOS/
|
25
|
+
build-iPhoneSimulator/
|
26
|
+
|
27
|
+
## Specific to RubyMotion (use of CocoaPods):
|
28
|
+
#
|
29
|
+
# We recommend against adding the Pods directory to your .gitignore. However
|
30
|
+
# you should judge for yourself, the pros and cons are mentioned at:
|
31
|
+
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
|
32
|
+
#
|
33
|
+
# vendor/Pods/
|
34
|
+
|
35
|
+
## Documentation cache and generated files:
|
36
|
+
/.yardoc/
|
37
|
+
/_yardoc/
|
38
|
+
/doc/
|
39
|
+
/rdoc/
|
40
|
+
|
41
|
+
## Environment normalization:
|
42
|
+
/.bundle/
|
43
|
+
/vendor/bundle
|
44
|
+
/lib/bundler/man/
|
45
|
+
|
46
|
+
# for a library or gem, you might want to ignore these files since the code is
|
47
|
+
# intended to run in multiple environments; otherwise, check them in:
|
48
|
+
# Gemfile.lock
|
49
|
+
# .ruby-version
|
50
|
+
# .ruby-gemset
|
51
|
+
|
52
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
53
|
+
.rvmrc
|
54
|
+
|
55
|
+
# Used by RuboCop. Remote config files pulled in from inherit_from directive.
|
56
|
+
# .rubocop-https?--*
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2020 mrdaios <mrdaios@gmail.com>
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = 'cocoapods-nexus'
|
7
|
+
spec.version = "0.0.1"
|
8
|
+
spec.authors = ['mrdaios']
|
9
|
+
spec.email = ['mrdaios@gmail.com']
|
10
|
+
spec.description = 'a cocoapods plugin for nexus.'
|
11
|
+
spec.summary = '运行时修改spec的source为nexus中的预编译的zip.'
|
12
|
+
spec.homepage = 'https://github.com/mrdaios/cocoapods-nexus'
|
13
|
+
spec.license = 'MIT'
|
14
|
+
|
15
|
+
spec.files = `git ls-files`.split($/)
|
16
|
+
# spec.files = Dir['lib/**/*']
|
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_runtime_dependency 'cocoapods', '>= 1.9.3'
|
22
|
+
spec.add_runtime_dependency 'rest-client', '~> 2.1.0'
|
23
|
+
|
24
|
+
spec.add_development_dependency 'bundler', '~> 1.3'
|
25
|
+
spec.add_development_dependency 'rake', '~> 13.0'
|
26
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'cocoapods-nexus/api/connection'
|
2
|
+
require 'cocoapods-nexus/api/components'
|
3
|
+
|
4
|
+
module CocoapodsNexus
|
5
|
+
# https://github.com/Cisco-AMP/nexus_api
|
6
|
+
class API
|
7
|
+
attr_accessor :connection
|
8
|
+
attr_accessor :repo
|
9
|
+
|
10
|
+
# 用于管理nexus服务器
|
11
|
+
def initialize(hostname:, repo:)
|
12
|
+
@connection = CocoapodsNexus::API::NexusConnection.new(hostname: hostname)
|
13
|
+
@repo = repo
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module CocoapodsNexus
|
2
|
+
class API
|
3
|
+
# 搜索组件
|
4
|
+
def search_maven_component(artifact_id:)
|
5
|
+
@connection.get_response(endpoint: "search?repository=#{@repo}&name=#{artifact_id}")
|
6
|
+
end
|
7
|
+
|
8
|
+
# 上传组件
|
9
|
+
def upload_maven_component(artifact_id:, version:, group_id:, podspec:, artifact:, files:)
|
10
|
+
parameters = {
|
11
|
+
'maven2.artifactId' => artifact_id,
|
12
|
+
'maven2.version' => version,
|
13
|
+
'maven2.groupId' => group_id,
|
14
|
+
'maven2.generate-pom' => true,
|
15
|
+
'maven2.packaging' => artifact.nil? ? 'podspec' : File.extname(artifact).delete(".")
|
16
|
+
}
|
17
|
+
upload_files = []
|
18
|
+
upload_files << podspec unless podspec.nil?
|
19
|
+
upload_files << artifact unless artifact.nil?
|
20
|
+
upload_files | files unless files.nil?
|
21
|
+
|
22
|
+
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(".")
|
25
|
+
end
|
26
|
+
@connection.post(endpoint: "components?repository=#{@repo}", parameters: parameters, headers: {})
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,158 @@
|
|
1
|
+
require 'base64'
|
2
|
+
require 'json'
|
3
|
+
require 'rest-client'
|
4
|
+
require 'uri'
|
5
|
+
|
6
|
+
module CocoapodsNexus
|
7
|
+
class API
|
8
|
+
class NexusConnection
|
9
|
+
VALID_RESPONSE_CODES = [200, 201, 204].freeze
|
10
|
+
|
11
|
+
attr_accessor :continuation_token
|
12
|
+
|
13
|
+
def initialize(hostname:)
|
14
|
+
@hostname = hostname
|
15
|
+
end
|
16
|
+
|
17
|
+
def get_response(endpoint:, paginate: false, headers: {'Content-Type' => 'application/json'}, api_version: 'v1')
|
18
|
+
response = send_get(endpoint, paginate, headers, api_version)
|
19
|
+
response.nil? ? {} : jsonize(response)
|
20
|
+
end
|
21
|
+
|
22
|
+
def get(endpoint:, paginate: false, headers: {'Content-Type' => 'application/json'}, api_version: 'v1')
|
23
|
+
valid?(send_get(endpoint, paginate, headers, api_version))
|
24
|
+
end
|
25
|
+
|
26
|
+
def post(endpoint:, parameters: '', headers: {'Content-Type' => 'application/json'}, api_version: 'v1')
|
27
|
+
response = send_request(
|
28
|
+
:post,
|
29
|
+
endpoint,
|
30
|
+
parameters: parameters,
|
31
|
+
headers: headers,
|
32
|
+
api_version: api_version
|
33
|
+
)
|
34
|
+
valid?(response)
|
35
|
+
end
|
36
|
+
|
37
|
+
def put(endpoint:, parameters: '', headers: {'Content-Type' => 'application/json'}, api_version: 'v1')
|
38
|
+
response = send_request(
|
39
|
+
:put,
|
40
|
+
endpoint,
|
41
|
+
parameters: parameters,
|
42
|
+
headers: headers,
|
43
|
+
api_version: api_version
|
44
|
+
)
|
45
|
+
valid?(response)
|
46
|
+
end
|
47
|
+
|
48
|
+
def delete(endpoint:, headers: {'Content-Type' => 'application/json'}, api_version: 'v1')
|
49
|
+
response = send_request(
|
50
|
+
:delete,
|
51
|
+
endpoint,
|
52
|
+
headers: headers,
|
53
|
+
api_version: api_version
|
54
|
+
)
|
55
|
+
valid?(response)
|
56
|
+
end
|
57
|
+
|
58
|
+
def head(asset_url:)
|
59
|
+
catch_connection_error do
|
60
|
+
RestClient.head(URI.escape(asset_url))
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def content_length(asset_url:)
|
65
|
+
response = head(asset_url: asset_url)
|
66
|
+
return -1 unless response.respond_to?(:headers)
|
67
|
+
response.headers[:content_length]
|
68
|
+
end
|
69
|
+
|
70
|
+
def download(url:)
|
71
|
+
catch_connection_error do
|
72
|
+
RestClient.get(URI.escape(url), authorization_header)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def paginate?
|
77
|
+
!@continuation_token.nil?
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
def valid?(response)
|
84
|
+
return false if response.nil?
|
85
|
+
VALID_RESPONSE_CODES.include?(response.code) ? true : false
|
86
|
+
end
|
87
|
+
|
88
|
+
def handle(error)
|
89
|
+
puts 'ERROR: Request failed'
|
90
|
+
puts error
|
91
|
+
end
|
92
|
+
|
93
|
+
def catch_connection_error
|
94
|
+
begin
|
95
|
+
yield
|
96
|
+
rescue SocketError => error
|
97
|
+
return handle(error)
|
98
|
+
rescue RestClient::Unauthorized => error
|
99
|
+
return handle(error)
|
100
|
+
rescue RestClient::Exceptions::ReadTimeout => error
|
101
|
+
return handle(error)
|
102
|
+
rescue RestClient::ExceptionWithResponse => error
|
103
|
+
return handle(error.response)
|
104
|
+
rescue StandardError => error
|
105
|
+
return handle(error)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def authorization_header
|
110
|
+
{}
|
111
|
+
end
|
112
|
+
|
113
|
+
def send_request(connection_method, endpoint, parameters: '', headers: {}, api_version: 'v1')
|
114
|
+
parameters = parameters.to_json if headers['Content-Type'] == 'application/json'
|
115
|
+
url = "#{@hostname}/nexus/service/rest/#{api_version}/#{endpoint}"
|
116
|
+
catch_connection_error do
|
117
|
+
RestClient::Request.execute(
|
118
|
+
method: connection_method,
|
119
|
+
url: URI.escape(url),
|
120
|
+
payload: parameters,
|
121
|
+
headers: authorization_header.merge(headers)
|
122
|
+
)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def send_get(endpoint, paginate, headers, api_version)
|
127
|
+
url_marker = endpoint.include?('?') ? '&' : '?'
|
128
|
+
# paginate answers is the user requesting pagination, paginate? answers does a continuation token exist
|
129
|
+
# if an empty continuation token is included in the request we'll get an ArrayIndexOutOfBoundsException
|
130
|
+
endpoint += "#{url_marker}continuationToken=#{@continuation_token}" if paginate && paginate?
|
131
|
+
send_request(
|
132
|
+
:get,
|
133
|
+
endpoint,
|
134
|
+
headers: headers,
|
135
|
+
api_version: api_version
|
136
|
+
)
|
137
|
+
end
|
138
|
+
|
139
|
+
# That's right, nexus has inconsistent null values for its api
|
140
|
+
def continuation_token_for(json)
|
141
|
+
return nil if json['continuationToken'].nil?
|
142
|
+
return nil if json['continuationToken'] == 'nil'
|
143
|
+
json['continuationToken']
|
144
|
+
end
|
145
|
+
|
146
|
+
def jsonize(response)
|
147
|
+
json = JSON.parse(response.body)
|
148
|
+
if json.class == Hash
|
149
|
+
@continuation_token = continuation_token_for(json)
|
150
|
+
json = json['items'] if json['items']
|
151
|
+
end
|
152
|
+
json
|
153
|
+
rescue JSON::ParserError
|
154
|
+
response.body
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'cocoapods-nexus/command/nexus'
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'cocoapods-nexus/nexus_source'
|
2
|
+
|
3
|
+
module Pod
|
4
|
+
class Command
|
5
|
+
class Nexus < Command
|
6
|
+
require 'cocoapods-nexus/command/nexus/add'
|
7
|
+
require 'cocoapods-nexus/command/nexus/list'
|
8
|
+
require 'cocoapods-nexus/command/nexus/push'
|
9
|
+
|
10
|
+
self.abstract_command = true
|
11
|
+
|
12
|
+
self.summary = 'a cocoapods plugin for nexus'
|
13
|
+
|
14
|
+
self.description = <<-DESC
|
15
|
+
a cocoapods plugin for nexus.
|
16
|
+
DESC
|
17
|
+
|
18
|
+
def initialize(argv)
|
19
|
+
@repos_nexus_dir = Pod::Config.instance.repos_dir
|
20
|
+
super
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module Pod
|
4
|
+
class Command
|
5
|
+
class Nexus
|
6
|
+
class Add < Nexus
|
7
|
+
self.summary = 'Add a nexus repo.'
|
8
|
+
|
9
|
+
self.description = <<-DESC
|
10
|
+
添加一个nexus的repo
|
11
|
+
DESC
|
12
|
+
|
13
|
+
self.arguments = [
|
14
|
+
CLAide::Argument.new('NAME', true),
|
15
|
+
CLAide::Argument.new('URL', true)
|
16
|
+
]
|
17
|
+
|
18
|
+
def initialize(argv)
|
19
|
+
@name = argv.shift_argument
|
20
|
+
@url = argv.shift_argument
|
21
|
+
@silent = argv.flag?('silent', false)
|
22
|
+
@silent = false
|
23
|
+
super
|
24
|
+
end
|
25
|
+
|
26
|
+
def validate!
|
27
|
+
super
|
28
|
+
help! '需要配置`NAME`和`URL`.' unless @name && @url
|
29
|
+
end
|
30
|
+
|
31
|
+
def run
|
32
|
+
UI.section("从#{@url}添加#{@name}仓库") do
|
33
|
+
repos_path = File.join(@repos_nexus_dir, @name)
|
34
|
+
raise Pod::Informative.exception "#{repos_path}已经存在. 请删除或者执行'pod nexus add #{@name} #{@url}'" if File.exist?(repos_path) && !@silent
|
35
|
+
repo_dir_root = "#{@repos_nexus_dir}/#{@name}"
|
36
|
+
|
37
|
+
FileUtils.mkdir_p repo_dir_root
|
38
|
+
|
39
|
+
begin
|
40
|
+
nexus_path = create_nexus_file(repo_dir_root)
|
41
|
+
rescue StandardError => e
|
42
|
+
raise Informative, "Cannot create file '#{nexus_path}' because : #{e.message}."
|
43
|
+
end
|
44
|
+
UI.puts "Successfully added repo #{@name}".green unless @silent
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def create_nexus_file(repo_dir_root)
|
49
|
+
nexus_path = "#{repo_dir_root}/.nexus"
|
50
|
+
nexus_path = File.new(nexus_path, 'wb')
|
51
|
+
nexus_path << @url
|
52
|
+
nexus_path.close
|
53
|
+
nexus_path
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'cocoapods-nexus/nexus_source'
|
3
|
+
|
4
|
+
module Pod
|
5
|
+
class Command
|
6
|
+
class Nexus
|
7
|
+
class List < Nexus
|
8
|
+
self.summary = 'Add a nexus repo.'
|
9
|
+
|
10
|
+
self.description = <<-DESC
|
11
|
+
添加一个nexus的repo
|
12
|
+
DESC
|
13
|
+
|
14
|
+
def run
|
15
|
+
repos_dir = Pod::Config.instance.repos_dir
|
16
|
+
dirs = Dir.glob "#{repos_dir}/*/"
|
17
|
+
repos = []
|
18
|
+
dirs.each do |dir|
|
19
|
+
next unless File.exist?("#{dir}/.nexus")
|
20
|
+
url = File.read("#{dir}/.nexus")
|
21
|
+
repos.push Pod::NexusSource.new(dir, url) if url
|
22
|
+
end
|
23
|
+
|
24
|
+
repos.each { |repo|
|
25
|
+
UI.title repo.name do
|
26
|
+
UI.puts "- URL: #{repo.url}"
|
27
|
+
UI.puts "- Path: #{repo.repo}"
|
28
|
+
end
|
29
|
+
}
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'cocoapods-nexus/api'
|
2
|
+
|
3
|
+
module Pod
|
4
|
+
class Command
|
5
|
+
class Nexus
|
6
|
+
class Push < Nexus
|
7
|
+
self.summary = 'Push a podspec.'
|
8
|
+
|
9
|
+
self.description = <<-DESC
|
10
|
+
Push a podspec to nexus.
|
11
|
+
DESC
|
12
|
+
|
13
|
+
self.arguments = [
|
14
|
+
CLAide::Argument.new('NAME.podspec', true)
|
15
|
+
]
|
16
|
+
|
17
|
+
def self.options
|
18
|
+
[
|
19
|
+
['--url=url', 'a nexus hostname'],
|
20
|
+
['--repo=repo', 'a nexus repo'],
|
21
|
+
['--artifact=artifact', 'a nexus artifact']
|
22
|
+
].concat(super)
|
23
|
+
end
|
24
|
+
|
25
|
+
def initialize(argv)
|
26
|
+
@podspec = argv.shift_argument
|
27
|
+
@url = argv.option('url')
|
28
|
+
@repo = argv.option('repo')
|
29
|
+
@artifact = argv.option('artifact')
|
30
|
+
super
|
31
|
+
end
|
32
|
+
|
33
|
+
def validate!
|
34
|
+
super
|
35
|
+
help! 'A podspec is required.' unless @podspec && File.exist?(File.expand_path(@podspec))
|
36
|
+
help! 'A url is required.' unless @url
|
37
|
+
help! 'A repo is required.' unless @repo
|
38
|
+
end
|
39
|
+
|
40
|
+
def run
|
41
|
+
podspec_path = File.expand_path(@podspec)
|
42
|
+
artifact_path = File.expand_path(@artifact) unless @artifact.nil?
|
43
|
+
|
44
|
+
UI.section("开始发布 #{File.basename(@podspec)} -> #{@url}/nexus/#browse/browse:#{@repo}") do
|
45
|
+
spec = Specification.from_file(podspec_path)
|
46
|
+
artifact_id = spec.attributes_hash['name']
|
47
|
+
version = spec.attributes_hash['version']
|
48
|
+
group_id = 'Specs'
|
49
|
+
|
50
|
+
if nexus_api.upload_maven_component(artifact_id: artifact_id,
|
51
|
+
version: version,
|
52
|
+
group_id: group_id,
|
53
|
+
podspec: podspec_path,
|
54
|
+
artifact: artifact_path,
|
55
|
+
files: [])
|
56
|
+
UI.puts "成功发布 #{artifact_id}(#{version})"
|
57
|
+
else
|
58
|
+
raise Informative, "发布失败 #{artifact_id}(#{version}),请检查~/.netrc文件或#{@repo}类型"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
def nexus_api
|
66
|
+
@nexus_api ||= CocoapodsNexus::API.new(hostname: @url, repo: @repo)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'cocoapods-downloader/remote_file'
|
2
|
+
|
3
|
+
module Pod
|
4
|
+
module Downloader
|
5
|
+
class NexusHttp < RemoteFile
|
6
|
+
def self.options
|
7
|
+
[:type, :name]
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
executable :curl
|
13
|
+
|
14
|
+
def download!
|
15
|
+
@filename = "#{options[:name]}.#{'podspec'.to_sym}"
|
16
|
+
@download_path = @target_path + @filename
|
17
|
+
download_file(@download_path)
|
18
|
+
end
|
19
|
+
|
20
|
+
def download_file(full_filename)
|
21
|
+
parameters = ['-f', '-L', '-o', full_filename, url, '--create-dirs', '--netrc-optional', '--retry', '2']
|
22
|
+
parameters << user_agent_argument if headers.nil? ||
|
23
|
+
headers.none? { |header| header.casecmp(USER_AGENT_HEADER).zero? }
|
24
|
+
unless headers.nil?
|
25
|
+
headers.each do |h|
|
26
|
+
parameters << '-H'
|
27
|
+
parameters << h
|
28
|
+
end
|
29
|
+
end
|
30
|
+
# 通过curl下载文件
|
31
|
+
curl! parameters
|
32
|
+
end
|
33
|
+
|
34
|
+
def user_agent_argument
|
35
|
+
"-A '#{Http.user_agent_string}'"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# require 'cocoapods'
|
2
|
+
# require 'cocoapods-nexus/nexus_source'
|
3
|
+
#
|
4
|
+
# module Pod
|
5
|
+
# class Installer
|
6
|
+
# class Analyzer
|
7
|
+
# alias orig_sources sources
|
8
|
+
#
|
9
|
+
# # 修改pod的sources,用于注入cocoapods-nexus
|
10
|
+
# def sources
|
11
|
+
# value = orig_sources
|
12
|
+
# if podfile.sources.empty? && podfile.plugins.key?('cocoapods-nexus')
|
13
|
+
# sources = []
|
14
|
+
# plugin_config = podfile.plugins['cocoapods-nexus']
|
15
|
+
# # all sources declared in the plugin clause
|
16
|
+
# plugin_config['sources'].uniq.map do |config|
|
17
|
+
# name = config['name']
|
18
|
+
# url = config['url']
|
19
|
+
#
|
20
|
+
# sources.push(Pod::NexusSource.new("nexus_#{name}", url))
|
21
|
+
# end
|
22
|
+
# @sources = sources
|
23
|
+
# else
|
24
|
+
# orig_sources
|
25
|
+
# end
|
26
|
+
# end
|
27
|
+
# end
|
28
|
+
# end
|
29
|
+
# end
|
@@ -0,0 +1,49 @@
|
|
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
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'cocoapods'
|
2
|
+
require 'cocoapods-nexus/nexus_source'
|
3
|
+
|
4
|
+
module Pod
|
5
|
+
class Source
|
6
|
+
class Manager
|
7
|
+
alias orgin_source_from_path source_from_path
|
8
|
+
|
9
|
+
def source_from_path(path)
|
10
|
+
@new_sources_by_path ||= Hash.new do |hash, key|
|
11
|
+
nexus_file_path = File.join(key, ".nexus")
|
12
|
+
hash[key] = if File.exist?(nexus_file_path)
|
13
|
+
Pod::NexusSource.new(key, File.read(nexus_file_path))
|
14
|
+
else
|
15
|
+
orgin_source_from_path(key)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
@new_sources_by_path[path]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require 'cocoapods-nexus/api'
|
2
|
+
require 'cocoapods-nexus/downloader'
|
3
|
+
|
4
|
+
module Pod
|
5
|
+
class NexusSource < Source
|
6
|
+
def initialize(repo, url)
|
7
|
+
@source_url = url
|
8
|
+
super(repo)
|
9
|
+
end
|
10
|
+
|
11
|
+
def url
|
12
|
+
if @source_url
|
13
|
+
@source_url.to_s
|
14
|
+
else
|
15
|
+
# after super(repo) repo is now the path to the repo
|
16
|
+
File.read("#{repo}/.nexus") if File.exist?("#{repo}/.nexus")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def git?
|
21
|
+
false
|
22
|
+
end
|
23
|
+
|
24
|
+
def type
|
25
|
+
'nexus'
|
26
|
+
end
|
27
|
+
|
28
|
+
# 从nexus查询依赖
|
29
|
+
# @param [Object] query
|
30
|
+
def search(query)
|
31
|
+
unless File.exist?("#{repo}/.nexus")
|
32
|
+
raise Informative, "Unable to find a source named: `#{name}`"
|
33
|
+
end
|
34
|
+
|
35
|
+
found = find_local_podspec(query)
|
36
|
+
# 本地没查询到,则从nexus服务查询
|
37
|
+
if found == []
|
38
|
+
# 暂时这样处理
|
39
|
+
spec_version = query.requirement.requirements.last.last.to_s
|
40
|
+
artifacte = nexus_find_artifacte(spec_name: query.root_name, spec_version: spec_version)
|
41
|
+
if artifacte
|
42
|
+
download_url = parse_artifacte_asset_url(artifacte, 'podspec')
|
43
|
+
if download_url
|
44
|
+
target_path = "#{@repo}/#{query.root_name}/#{spec_version}"
|
45
|
+
downloader = Pod::Downloader::NexusHttp.new(target_path, download_url, {:type => 'podspec', :name => query.root_name})
|
46
|
+
downloader.download
|
47
|
+
|
48
|
+
found = find_local_podspec(query)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
if found == [query.root_name]
|
54
|
+
set = set(query.root_name)
|
55
|
+
set if set.specification_name == query.root_name
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def specification(name, version)
|
60
|
+
specification = super
|
61
|
+
version = version.version if version.is_a?(Pod::Version)
|
62
|
+
artifacte = nexus_find_artifacte(spec_name: name, spec_version: version)
|
63
|
+
download_url = parse_artifacte_asset_url(artifacte, 'zip')
|
64
|
+
if download_url
|
65
|
+
specification.attributes_hash['source'] = {
|
66
|
+
'http' => download_url
|
67
|
+
}
|
68
|
+
specification.attributes_hash['vendored_frameworks'] = "#{name}.framework"
|
69
|
+
end
|
70
|
+
specification
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
# 从本地repo查询spec
|
76
|
+
def find_local_podspec(query)
|
77
|
+
query = query.root_name if query.is_a?(Dependency)
|
78
|
+
found = []
|
79
|
+
Pathname.glob(pod_path(query)) do |path|
|
80
|
+
next unless Dir.foreach(path).any? { |child| child != '.' && child != '..' }
|
81
|
+
found << path.basename.to_s
|
82
|
+
end
|
83
|
+
found
|
84
|
+
end
|
85
|
+
|
86
|
+
# 解析附件downloadUrl
|
87
|
+
def parse_artifacte_asset_url(artifacte, asset_type)
|
88
|
+
asset = artifacte['assets'].select { |asset| asset['path'].end_with?(asset_type) }.first
|
89
|
+
asset['downloadUrl'] unless asset['downloadUrl'].nil?
|
90
|
+
end
|
91
|
+
|
92
|
+
def nexus_find_artifacte(spec_name:, spec_version:)
|
93
|
+
artifactes = nexus_api.search_maven_component(artifact_id: spec_name)
|
94
|
+
artifacte = artifactes.select { |artifacte| artifacte['version'].start_with?(spec_version) }.sort_by { |artifacte| artifacte['version'].downcase }.last
|
95
|
+
artifacte
|
96
|
+
end
|
97
|
+
|
98
|
+
def nexus_api
|
99
|
+
repo_name = File.basename(@repo).gsub('nexus_', '')
|
100
|
+
@nexus_api ||= CocoapodsNexus::API.new(hostname: url, repo: repo_name)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'cocoapods'
|
2
|
+
require 'cocoapods-nexus'
|
3
|
+
|
4
|
+
Pod::HooksManager.register('cocoapods-nexus', :source_provider) do |context, options|
|
5
|
+
Pod::UI.message 'cocoapods-nexus received source_provider hook'
|
6
|
+
unless (sources = options['sources'])
|
7
|
+
raise Pod::Informative.exception 'cocoapods-nexus插件需要配置sources参数.'
|
8
|
+
end
|
9
|
+
|
10
|
+
sources.each do |source_config|
|
11
|
+
name = source_config['name']
|
12
|
+
url = source_config['url']
|
13
|
+
source = Pod::NexusSource.new(File.join(Pod::Config.instance.repos_dir, name), url)
|
14
|
+
update_or_add_source(source)
|
15
|
+
context.add_source(source)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def update_or_add_source(source)
|
20
|
+
name = source.name
|
21
|
+
url = source.url
|
22
|
+
dir = source.repo
|
23
|
+
|
24
|
+
unless dir.exist?
|
25
|
+
argv = CLAide::ARGV.new([name, url])
|
26
|
+
cmd = Pod::Command::Nexus::Add.new(argv)
|
27
|
+
cmd.run
|
28
|
+
end
|
29
|
+
end
|
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,126 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cocoapods-nexus
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- mrdaios
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-09-04 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.9.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.9.3
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rest-client
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 2.1.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 2.1.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: bundler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.3'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.3'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '13.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '13.0'
|
69
|
+
description: a cocoapods plugin for nexus.
|
70
|
+
email:
|
71
|
+
- mrdaios@gmail.com
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- ".github/workflows/main.yml"
|
77
|
+
- ".gitignore"
|
78
|
+
- Gemfile
|
79
|
+
- LICENSE
|
80
|
+
- README.md
|
81
|
+
- Rakefile
|
82
|
+
- cocoapods-nexus.gemspec
|
83
|
+
- lib/cocoapods-nexus.rb
|
84
|
+
- lib/cocoapods-nexus/api.rb
|
85
|
+
- lib/cocoapods-nexus/api/components.rb
|
86
|
+
- lib/cocoapods-nexus/api/connection.rb
|
87
|
+
- lib/cocoapods-nexus/command.rb
|
88
|
+
- lib/cocoapods-nexus/command/nexus.rb
|
89
|
+
- lib/cocoapods-nexus/command/nexus/add.rb
|
90
|
+
- lib/cocoapods-nexus/command/nexus/list.rb
|
91
|
+
- lib/cocoapods-nexus/command/nexus/push.rb
|
92
|
+
- lib/cocoapods-nexus/downloader.rb
|
93
|
+
- lib/cocoapods-nexus/hook.rb
|
94
|
+
- lib/cocoapods-nexus/hook/analyzer.rb
|
95
|
+
- lib/cocoapods-nexus/hook/installer.rb
|
96
|
+
- lib/cocoapods-nexus/hook/manager.rb
|
97
|
+
- lib/cocoapods-nexus/nexus_source.rb
|
98
|
+
- lib/cocoapods_plugin.rb
|
99
|
+
- spec/command/nexus_spec.rb
|
100
|
+
- spec/spec_helper.rb
|
101
|
+
homepage: https://github.com/mrdaios/cocoapods-nexus
|
102
|
+
licenses:
|
103
|
+
- MIT
|
104
|
+
metadata: {}
|
105
|
+
post_install_message:
|
106
|
+
rdoc_options: []
|
107
|
+
require_paths:
|
108
|
+
- lib
|
109
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
110
|
+
requirements:
|
111
|
+
- - ">="
|
112
|
+
- !ruby/object:Gem::Version
|
113
|
+
version: '0'
|
114
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
115
|
+
requirements:
|
116
|
+
- - ">="
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
version: '0'
|
119
|
+
requirements: []
|
120
|
+
rubygems_version: 3.0.3
|
121
|
+
signing_key:
|
122
|
+
specification_version: 4
|
123
|
+
summary: 运行时修改spec的source为nexus中的预编译的zip.
|
124
|
+
test_files:
|
125
|
+
- spec/command/nexus_spec.rb
|
126
|
+
- spec/spec_helper.rb
|