nexus_cli 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/VERSION +1 -1
- data/features/nexus_oss.feature +57 -30
- data/features/step_definitions/cli_steps.rb +21 -4
- data/features/support/env.rb +4 -3
- data/lib/nexus_cli.rb +1 -0
- data/lib/nexus_cli/configuration.rb +1 -1
- data/lib/nexus_cli/errors.rb +46 -2
- data/lib/nexus_cli/n3_metadata.rb +88 -0
- data/lib/nexus_cli/nexus_oss_remote.rb +97 -28
- data/lib/nexus_cli/nexus_pro_remote.rb +115 -58
- data/lib/nexus_cli/nexus_remote_factory.rb +4 -4
- data/lib/nexus_cli/tasks.rb +57 -18
- data/nexus_cli.gemspec +1 -0
- data/pro/nexus_pro.feature +110 -0
- data/spec/pro_remote_spec.rb +43 -0
- metadata +24 -4
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.5.0
|
data/features/nexus_oss.feature
CHANGED
@@ -22,9 +22,9 @@ Feature: Use the Nexus CLI
|
|
22
22
|
Scenario: Pull an artifact
|
23
23
|
When I call the nexus "pull com.test:mytest:1.0.0:tgz" command
|
24
24
|
Then the output should contain:
|
25
|
-
|
26
|
-
|
27
|
-
|
25
|
+
"""
|
26
|
+
Artifact has been retrived and can be found at path:
|
27
|
+
"""
|
28
28
|
And the exit status should be 0
|
29
29
|
|
30
30
|
Scenario: Pull the LATEST of an artifact
|
@@ -40,18 +40,18 @@ Feature: Use the Nexus CLI
|
|
40
40
|
Scenario: Get an artifact's info
|
41
41
|
When I call the nexus "info com.test:mytest:1.0.0:tgz" command
|
42
42
|
Then the output should contain:
|
43
|
-
|
44
|
-
|
45
|
-
|
43
|
+
"""
|
44
|
+
<groupId>com.test</groupId>
|
45
|
+
"""
|
46
46
|
And the exit status should be 0
|
47
47
|
|
48
48
|
Scenario: Search for artifacts
|
49
49
|
When I call the nexus "search_for_artifacts com.test:mytest" command
|
50
50
|
Then the output should contain:
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
51
|
+
"""
|
52
|
+
Found Versions:
|
53
|
+
1.0.0: `nexus-cli pull com.test:mytest:1.0.0:tgz`
|
54
|
+
"""
|
55
55
|
And the exit status should be 0
|
56
56
|
|
57
57
|
@delete
|
@@ -59,18 +59,18 @@ Feature: Use the Nexus CLI
|
|
59
59
|
When I delete an artifact with the GAV of "com.test:mytest:1.0.0:tgz"
|
60
60
|
And I call the nexus "info com.test:mytest:1.0.0:tgz" command
|
61
61
|
Then the output should contain:
|
62
|
-
|
63
|
-
|
64
|
-
|
62
|
+
"""
|
63
|
+
The artifact you requested information for could not be found. Please ensure it exists inside the Nexus.
|
64
|
+
"""
|
65
65
|
And the exit status should be 101
|
66
66
|
|
67
67
|
Scenario: Get the current global settings of Nexus
|
68
68
|
When I call the nexus "get_global_settings" command
|
69
69
|
Then the output should contain:
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
And a file named "global_settings.json" should exist
|
70
|
+
"""
|
71
|
+
Your current Nexus global settings have been written to the file: ~/.nexus/global_settings.json
|
72
|
+
"""
|
73
|
+
And a file named "global_settings.json" should exist in my nexus folder
|
74
74
|
And the exit status should be 0
|
75
75
|
|
76
76
|
Scenario: Update the global settings of Nexus
|
@@ -78,25 +78,52 @@ Feature: Use the Nexus CLI
|
|
78
78
|
And I edit the "global_settings.json" files "forceBaseUrl" field to true
|
79
79
|
And I call the nexus "upload_global_settings" command
|
80
80
|
Then the output should contain:
|
81
|
-
|
82
|
-
|
83
|
-
|
81
|
+
"""
|
82
|
+
Your global_settings.json file has been uploaded to Nexus
|
83
|
+
"""
|
84
84
|
When I call the nexus "get_global_settings" command
|
85
|
-
Then the file "global_settings.json" should contain:
|
85
|
+
Then the file "global_settings.json" in my nexus folder should contain:
|
86
|
+
"""
|
87
|
+
"forceBaseUrl": true
|
88
|
+
"""
|
89
|
+
And the exit status should be 0
|
90
|
+
|
91
|
+
Scenario: Update the global settings of Nexus with a string
|
92
|
+
When I update global settings uiTimeout to 61 and upload the json string
|
93
|
+
And I call the nexus "get_global_settings" command
|
94
|
+
Then the file "global_settings.json" in my nexus folder should contain:
|
86
95
|
"""
|
87
|
-
"
|
96
|
+
"uiTimeout": 61
|
88
97
|
"""
|
89
98
|
And the exit status should be 0
|
90
99
|
|
91
100
|
Scenario: Reset the global settings of Nexus
|
92
101
|
When I call the nexus "reset_global_settings" command
|
93
102
|
Then the output should contain:
|
94
|
-
|
95
|
-
|
96
|
-
|
103
|
+
"""
|
104
|
+
Your Nexus global settings have been reset to their default values
|
105
|
+
"""
|
97
106
|
When I call the nexus "get_global_settings" command
|
98
|
-
Then the file "global_settings.json" should contain:
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
And the exit status should be 0
|
107
|
+
Then the file "global_settings.json" in my nexus folder should contain:
|
108
|
+
"""
|
109
|
+
"forceBaseUrl": false
|
110
|
+
"""
|
111
|
+
And the exit status should be 0
|
112
|
+
|
113
|
+
Scenario: Create a new repository in Nexus
|
114
|
+
When I call the nexus "create_repository Artifacts" command
|
115
|
+
Then the output should contain:
|
116
|
+
"""
|
117
|
+
A new Repository named Artifacts has been created.
|
118
|
+
"""
|
119
|
+
And the exit status should be 0
|
120
|
+
|
121
|
+
Scenario: Delete a repository in Nexus
|
122
|
+
When I call the nexus "delete_repository Artifacts" command
|
123
|
+
And I call the nexus "get_repository_info Artifacts" command
|
124
|
+
Then the output should contain:
|
125
|
+
"""
|
126
|
+
The repository you requested information could not be found. Please ensure the repository exists.
|
127
|
+
"""
|
128
|
+
And the exit status should be 114
|
129
|
+
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'aruba/api'
|
2
2
|
require 'json'
|
3
|
+
require 'jsonpath'
|
3
4
|
World(Aruba::Api)
|
4
5
|
|
5
6
|
When /^I call the nexus "(.*?)" command$/ do |command|
|
@@ -7,8 +8,8 @@ When /^I call the nexus "(.*?)" command$/ do |command|
|
|
7
8
|
end
|
8
9
|
|
9
10
|
When /^I push an artifact with the GAV of "(.*)"$/ do |gav|
|
10
|
-
groupId,
|
11
|
-
file = File.new(File.join(temp_dir, "#{
|
11
|
+
groupId, artifact_id, version, extension = gav.split(":")
|
12
|
+
file = File.new(File.join(temp_dir, "#{artifact_id}-#{version}.#{extension}"), 'w')
|
12
13
|
file.puts "some data"
|
13
14
|
file.close
|
14
15
|
step "I run `nexus-cli push #{gav} #{file.path} --overrides=#{get_overrides_string}`"
|
@@ -28,14 +29,30 @@ end
|
|
28
29
|
|
29
30
|
When /^I edit the "(.*?)" files "(.*?)" field to true$/ do |file, field|
|
30
31
|
Dir.chdir('tmp/aruba') do
|
31
|
-
json = JSON.parse(File.read(File.join(File.expand_path("
|
32
|
-
File.open(File.join(File.expand_path("
|
32
|
+
json = JSON.parse(File.read(File.join(File.expand_path("~/.nexus"), file)))
|
33
|
+
File.open(File.join(File.expand_path("~/.nexus"), file), "w+") do |opened|
|
33
34
|
json["data"]["globalRestApiSettings"][field] = true
|
34
35
|
opened.write(JSON.pretty_generate(json))
|
35
36
|
end
|
36
37
|
end
|
37
38
|
end
|
38
39
|
|
40
|
+
When /^I update global settings uiTimeout to (\d+) and upload the json string$/ do |value|
|
41
|
+
json = JSON.parse(nexus_remote.get_global_settings_json)
|
42
|
+
edited_json = JsonPath.for(json).gsub("$..uiTimeout") {|v| value.to_i}.to_hash
|
43
|
+
nexus_remote.upload_global_settings(JSON.dump(edited_json))
|
44
|
+
end
|
45
|
+
|
46
|
+
Then /^a file named "(.*?)" should exist in my nexus folder$/ do |file|
|
47
|
+
path = File.join(File.expand_path("~/.nexus"), file)
|
48
|
+
step "a file named \"#{path}\" should exist"
|
49
|
+
end
|
50
|
+
|
51
|
+
Then /^the file "(.*?)" in my nexus folder should contain:$/ do |file, partial_content|
|
52
|
+
path = File.join(File.expand_path("~/.nexus"), file)
|
53
|
+
check_file_content(path, partial_content, true)
|
54
|
+
end
|
55
|
+
|
39
56
|
Then /^the file "([^"]*)" should contain:$/ do |file, partial_content|
|
40
57
|
check_file_content(file, partial_content, true)
|
41
58
|
end
|
data/features/support/env.rb
CHANGED
@@ -17,14 +17,15 @@ end
|
|
17
17
|
World(ArubaOverrides)
|
18
18
|
|
19
19
|
Before do
|
20
|
-
@aruba_timeout_seconds =
|
20
|
+
@aruba_timeout_seconds = 10
|
21
21
|
end
|
22
|
+
|
22
23
|
def get_overrides_string
|
23
24
|
@overrides_string ||= "url:http://localhost:8081/nexus repository:releases username:admin password:admin123"
|
24
25
|
end
|
25
26
|
|
26
27
|
def get_overrides
|
27
|
-
@overrides ||= {'url' => 'http://localhost:8081/nexus', 'repository' => 'releases', 'username' => '
|
28
|
+
@overrides ||= {'url' => 'http://localhost:8081/nexus', 'repository' => 'releases', 'username' => 'admin', 'password' => 'admin123'}
|
28
29
|
end
|
29
30
|
|
30
31
|
def temp_dir
|
@@ -37,4 +38,4 @@ end
|
|
37
38
|
|
38
39
|
at_exit do
|
39
40
|
FileUtils.rm_rf(temp_dir)
|
40
|
-
end
|
41
|
+
end
|
data/lib/nexus_cli.rb
CHANGED
@@ -15,7 +15,7 @@ module NexusCli
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def validate_config(configuration)
|
18
|
-
["url", "repository", "username","password"].each do |key|
|
18
|
+
["url", "repository", "username", "password"].each do |key|
|
19
19
|
raise InvalidSettingsException.new(key) if configuration[key].blank?
|
20
20
|
end
|
21
21
|
end
|
data/lib/nexus_cli/errors.rb
CHANGED
@@ -81,7 +81,7 @@ This could mean several things:
|
|
81
81
|
|
82
82
|
class SearchParameterMalformedException < NexusCliError
|
83
83
|
def message
|
84
|
-
"Submit your search request specifying
|
84
|
+
"Submit your search request specifying one or more 3 colon-separated values: `key:type:value`. The available search types are `equal`, `matches`, `bounded`, and `notequal`."
|
85
85
|
end
|
86
86
|
status_code(109)
|
87
87
|
end
|
@@ -105,4 +105,48 @@ The output from the server was:
|
|
105
105
|
end
|
106
106
|
status_code(111)
|
107
107
|
end
|
108
|
-
|
108
|
+
|
109
|
+
class CreateRepsitoryException < NexusCliError
|
110
|
+
def initialize(body)
|
111
|
+
@server_response = JSON.pretty_generate(JSON.parse(body))
|
112
|
+
end
|
113
|
+
|
114
|
+
def message
|
115
|
+
%{Your create repository command failed due to the following:
|
116
|
+
#{@server_response}}
|
117
|
+
end
|
118
|
+
status_code(112)
|
119
|
+
end
|
120
|
+
|
121
|
+
class RepositoryDoesNotExistException < NexusCliError
|
122
|
+
def message
|
123
|
+
"The repository you are trying to delete does not exist."
|
124
|
+
end
|
125
|
+
status_code(113)
|
126
|
+
end
|
127
|
+
|
128
|
+
class RepositoryNotFoundException < NexusCliError
|
129
|
+
def message
|
130
|
+
"The repository you requested information could not be found. Please ensure the repository exists."
|
131
|
+
end
|
132
|
+
status_code(114)
|
133
|
+
end
|
134
|
+
|
135
|
+
class UnexpectedStatusCodeException < NexusCliError
|
136
|
+
def initialize(code)
|
137
|
+
@code = code
|
138
|
+
end
|
139
|
+
|
140
|
+
def message
|
141
|
+
"The server responded with a #{@code} status code which is unexpected. Please submit a bug."
|
142
|
+
end
|
143
|
+
status_code(115)
|
144
|
+
end
|
145
|
+
|
146
|
+
class N3ParameterMalformedException < NexusCliError
|
147
|
+
def message
|
148
|
+
"Submit your tag request specifying one or more 2 colon-separated values: `key:value`. The key can only consist of alphanumeric characters."
|
149
|
+
end
|
150
|
+
status_code(116)
|
151
|
+
end
|
152
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
|
3
|
+
module NexusCli
|
4
|
+
module N3Metadata
|
5
|
+
class << self
|
6
|
+
def generate_n3_path(group_id, artifact_id, version, extension, repository)
|
7
|
+
return "content/repositories/#{repository}/.meta/#{group_id.gsub(".", "/")}/#{artifact_id.gsub(".", "/")}/#{version}/#{artifact_id}-#{version}.#{extension}.n3"
|
8
|
+
end
|
9
|
+
|
10
|
+
def valid_n3_key?(element)
|
11
|
+
return !element.match(/^[a-zA-Z0-9]+$/).nil? ? true : false
|
12
|
+
end
|
13
|
+
|
14
|
+
def valid_n3_value?(element)
|
15
|
+
return !element.match(/^[^"'\\]*$/).nil? ? true : false
|
16
|
+
end
|
17
|
+
|
18
|
+
def valid_n3_search_type?(element)
|
19
|
+
return ["equal", "notequal", "matches", "bounded"].include?(element)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Generates the Nexus .n3 header for the tempfile that will be used to update an artifact's custom metadata.
|
23
|
+
def generate_n3_header(group_id, artifact_id, version, extension)
|
24
|
+
return "<urn:maven/artifact##{group_id}:#{artifact_id}:#{version}::#{extension}> a <urn:maven#artifact>"
|
25
|
+
end
|
26
|
+
|
27
|
+
# Generates a hash containing the Nexus .n3 contents for the tempfile that will be used to update an artifact's custom metadata.
|
28
|
+
# If a hash of n3 user urns is provided, the contents will override existing key/value pairs.
|
29
|
+
def generate_n3_urns_from_n3(contents, n3_user_urns={})
|
30
|
+
contents.each_line do |line|
|
31
|
+
if !line.match(/urn:nexus\/user#/).nil?
|
32
|
+
tag, value = parse_n3_item(line)
|
33
|
+
# Delete the nexus key if the local key has no value.
|
34
|
+
if n3_user_urns.has_key?(tag) && value.empty?
|
35
|
+
n3_user_urns.delete(tag)
|
36
|
+
else
|
37
|
+
n3_user_urns[tag] = generate_n3_item(tag, value) unless tag.empty? || value.empty?
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
return n3_user_urns
|
42
|
+
end
|
43
|
+
|
44
|
+
def generate_n3_urns_from_hash(contents, n3_user_urns={})
|
45
|
+
contents.each do |tag, value|
|
46
|
+
# Delete the nexus key if the local key has no value.
|
47
|
+
if n3_user_urns.has_key?(tag) && value.empty?
|
48
|
+
n3_user_urns.delete(tag)
|
49
|
+
else
|
50
|
+
n3_user_urns[tag] = generate_n3_item(tag, value) unless tag.empty? || value.empty?
|
51
|
+
end
|
52
|
+
end
|
53
|
+
return n3_user_urns
|
54
|
+
end
|
55
|
+
|
56
|
+
# Parses a hash of n3 user urns and returns it as an n3-formatted string.
|
57
|
+
def parse_n3_hash(contents)
|
58
|
+
return contents.values.count == 1 ? contents.values[0] + " ." : contents.values.join(" ;\n") + " ."
|
59
|
+
end
|
60
|
+
|
61
|
+
# Returns n3 as XML.
|
62
|
+
def n3_to_xml(n3)
|
63
|
+
builder = Nokogiri::XML::Builder.new do |xml|
|
64
|
+
xml.send("artifact-resolution") {
|
65
|
+
xml.data {
|
66
|
+
n3.each_line do |line|
|
67
|
+
tag, value = parse_n3_item(line)
|
68
|
+
xml.send(tag, value) unless tag.empty? || value.empty?
|
69
|
+
end
|
70
|
+
}
|
71
|
+
}
|
72
|
+
end
|
73
|
+
return builder.doc.root.to_s
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
def parse_n3_item(line)
|
78
|
+
tag = line.match(/#(\w*)>/) ? "#{$1}" : ""
|
79
|
+
value = line.match(/"([^"]*)"/) ? "#{$1}" : ""
|
80
|
+
return tag, value
|
81
|
+
end
|
82
|
+
|
83
|
+
def generate_n3_item(tag, value)
|
84
|
+
return "\t<urn:nexus/user##{tag}> \"#{value}\""
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -31,27 +31,34 @@ module NexusCli
|
|
31
31
|
end
|
32
32
|
|
33
33
|
def pull_artifact(artifact, destination)
|
34
|
+
# Using net/http because restclient dies on large files.
|
34
35
|
group_id, artifact_id, version, extension = parse_artifact_string(artifact)
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
raise ArtifactNotFoundException
|
39
|
-
end
|
40
|
-
if version.casecmp("latest")
|
41
|
-
doc = Nokogiri::XML(get_artifact_info(artifact))
|
42
|
-
version = doc.xpath("//version").first.content()
|
43
|
-
end
|
36
|
+
uri = URI(File.join(configuration["url"], "service/local/artifact/maven/redirect"))
|
37
|
+
params = {:g => group_id, :a => artifact_id, :v => version, :e => extension, :r => configuration["repository"]}.collect {|k,v| "#{k}=#{URI::escape(v.to_s)}"}.join("&")
|
38
|
+
version = Nokogiri::XML(get_artifact_info(artifact)).xpath("//version").first.content() if version.casecmp("latest")
|
44
39
|
destination = File.join(File.expand_path(destination || "."), "#{artifact_id}-#{version}.#{extension}")
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
40
|
+
Net::HTTP.start(uri.host, uri.port) do |http|
|
41
|
+
request = Net::HTTP::Get.new(URI(http.request_get(uri.request_uri + "?" + params)["location"]).request_uri)
|
42
|
+
request.basic_auth(configuration["username"], configuration["password"])
|
43
|
+
http.request(request) do |response|
|
44
|
+
case response.code.to_i
|
45
|
+
when 404
|
46
|
+
raise ArtifactNotFoundException
|
47
|
+
end
|
48
|
+
artifact_file = File.open(destination, "wb") do |io|
|
49
|
+
response.read_body do |chunk|
|
50
|
+
io.write(chunk)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
File.expand_path(destination)
|
49
56
|
end
|
50
57
|
|
51
58
|
def push_artifact(artifact, file)
|
52
59
|
group_id, artifact_id, version, extension = parse_artifact_string(artifact)
|
53
|
-
nexus['service/local/artifact/maven/content'].post(
|
54
|
-
:file => File.new(file)
|
60
|
+
nexus['service/local/artifact/maven/content'].post(:hasPom => false, :g => group_id, :a => artifact_id, :v => version, :e => extension, :p => extension, :r => configuration['repository'],
|
61
|
+
:file => File.new(file)) do |response|
|
55
62
|
case response.code
|
56
63
|
when 400
|
57
64
|
raise BadUploadRequestException
|
@@ -74,7 +81,7 @@ module NexusCli
|
|
74
81
|
def get_artifact_info(artifact)
|
75
82
|
group_id, artifact_id, version, extension = parse_artifact_string(artifact)
|
76
83
|
begin
|
77
|
-
nexus['service/local/artifact/maven/resolve'].get(
|
84
|
+
nexus['service/local/artifact/maven/resolve'].get(:params => {:r => configuration['repository'], :g => group_id, :a => artifact_id, :v => version, :e => extension})
|
78
85
|
rescue Errno::ECONNREFUSED => e
|
79
86
|
raise CouldNotConnectToNexusException
|
80
87
|
rescue RestClient::ResourceNotFound => e
|
@@ -84,25 +91,30 @@ module NexusCli
|
|
84
91
|
|
85
92
|
def search_for_artifacts(artifact)
|
86
93
|
group_id, artifact_id = artifact.split(":")
|
87
|
-
nexus['service/local/data_index'].get(
|
94
|
+
nexus['service/local/data_index'].get(:params => {:g => group_id, :a => artifact_id}) do |response|
|
88
95
|
doc = Nokogiri::XML(response.body)
|
89
96
|
return format_search_results(doc, group_id, artifact_id)
|
90
97
|
end
|
91
98
|
end
|
92
99
|
|
93
100
|
def get_global_settings
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
101
|
+
json = get_global_settings_json
|
102
|
+
pretty_json = JSON.pretty_generate(JSON.parse(json))
|
103
|
+
Dir.mkdir(File.expand_path("~/.nexus")) unless Dir.exists?(File.expand_path("~/.nexus"))
|
104
|
+
destination = File.join(File.expand_path("~/.nexus"), "global_settings.json")
|
105
|
+
artifact_file = File.open(destination, 'wb') do |file|
|
106
|
+
file.write(pretty_json)
|
100
107
|
end
|
101
108
|
end
|
102
109
|
|
103
|
-
def upload_global_settings
|
104
|
-
|
105
|
-
|
110
|
+
def upload_global_settings(json=nil)
|
111
|
+
global_settings = nil
|
112
|
+
if json == nil
|
113
|
+
global_settings = File.read(File.join(File.expand_path("~/.nexus"), "global_settings.json"))
|
114
|
+
else
|
115
|
+
global_settings = json
|
116
|
+
end
|
117
|
+
nexus['service/local/global_settings/current'].put(global_settings, {:content_type => "application/json"}) do |response|
|
106
118
|
case response.code
|
107
119
|
when 400
|
108
120
|
raise BadSettingsException.new(response.body)
|
@@ -110,9 +122,49 @@ module NexusCli
|
|
110
122
|
end
|
111
123
|
end
|
112
124
|
|
125
|
+
def get_global_settings_json
|
126
|
+
nexus['service/local/global_settings/current'].get(:accept => "application/json")
|
127
|
+
end
|
128
|
+
|
113
129
|
def reset_global_settings
|
114
|
-
default_json = nexus['service/local/global_settings/default'].get(
|
115
|
-
nexus['service/local/global_settings/current'].put(default_json,
|
130
|
+
default_json = nexus['service/local/global_settings/default'].get(:accept => "application/json")
|
131
|
+
nexus['service/local/global_settings/current'].put(default_json, :content_type => "application/json")
|
132
|
+
end
|
133
|
+
|
134
|
+
def create_repository(name)
|
135
|
+
nexus['service/local/repositories'].post(create_repository_json(name), :content_type => "application/json") do |response|
|
136
|
+
case response.code
|
137
|
+
when 400
|
138
|
+
raise CreateRepsitoryException.new(response.body)
|
139
|
+
when 201
|
140
|
+
return true
|
141
|
+
else
|
142
|
+
raise UnexpectedStatusCodeException.new(response.code)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def delete_repository(name)
|
148
|
+
nexus["service/local/repositories/#{name.downcase}"].delete do |response|
|
149
|
+
case response.code
|
150
|
+
when 404
|
151
|
+
raise RepositoryDoesNotExistException
|
152
|
+
when 204
|
153
|
+
return true
|
154
|
+
else
|
155
|
+
raise UnexpectedStatusCodeException.new(response.code)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def get_repository_info(name)
|
161
|
+
begin
|
162
|
+
nexus["service/local/repositories/#{name.downcase}"].get
|
163
|
+
rescue Errno::ECONNREFUSED => e
|
164
|
+
raise CouldNotConnectToNexusException
|
165
|
+
rescue RestClient::ResourceNotFound => e
|
166
|
+
raise RepositoryNotFoundException
|
167
|
+
end
|
116
168
|
end
|
117
169
|
|
118
170
|
private
|
@@ -135,5 +187,22 @@ module NexusCli
|
|
135
187
|
version.upcase! if version.casecmp("latest")
|
136
188
|
return group_id, artifact_id, version, extension
|
137
189
|
end
|
190
|
+
|
191
|
+
def create_repository_json(name)
|
192
|
+
%{
|
193
|
+
{
|
194
|
+
"data" : {
|
195
|
+
"provider" : "maven2",
|
196
|
+
"providerRole" : "org.sonatype.nexus.proxy.repository.Repository",
|
197
|
+
"exposed" : true,
|
198
|
+
"repoType" : "hosted",
|
199
|
+
"repoPolicy" : "RELEASE",
|
200
|
+
"name" : #{name},
|
201
|
+
"id" : #{name.downcase},
|
202
|
+
"format" : "maven2"
|
203
|
+
}
|
204
|
+
}
|
205
|
+
}
|
206
|
+
end
|
138
207
|
end
|
139
208
|
end
|
@@ -7,31 +7,50 @@ module NexusCli
|
|
7
7
|
class ProRemote < OSSRemote
|
8
8
|
|
9
9
|
def get_artifact_custom_info(artifact)
|
10
|
-
|
10
|
+
return N3Metadata::n3_to_xml(get_artifact_custom_info_n3(artifact))
|
11
11
|
end
|
12
12
|
|
13
13
|
def get_artifact_custom_info_n3(artifact)
|
14
14
|
group_id, artifact_id, version, extension = parse_artifact_string(artifact)
|
15
|
-
|
16
|
-
get_string = "content/repositories/#{configuration['repository']}/.meta/#{group_id.gsub(".", "/")}/#{artifact_id.gsub(".", "/")}/#{version}/#{file_name}"
|
15
|
+
get_string = N3Metadata::generate_n3_path(group_id, artifact_id, version, extension, configuration['repository'])
|
17
16
|
begin
|
18
|
-
nexus[get_string].get
|
17
|
+
n3 = nexus[get_string].get
|
18
|
+
if !n3.match(/<urn:maven#deleted>/).nil?
|
19
|
+
raise ArtifactNotFoundException
|
20
|
+
else
|
21
|
+
return n3
|
22
|
+
end
|
19
23
|
rescue RestClient::ResourceNotFound => e
|
20
24
|
raise ArtifactNotFoundException
|
21
25
|
end
|
22
26
|
end
|
23
27
|
|
24
|
-
def update_artifact_custom_info(artifact,
|
28
|
+
def update_artifact_custom_info(artifact, *params)
|
29
|
+
group_id, artifact_id, version, extension = parse_artifact_string(artifact)
|
30
|
+
n3_user_urns = { "n3_header" => N3Metadata::generate_n3_header(group_id, artifact_id, version, extension) }.merge(N3Metadata::generate_n3_urns_from_hash(parse_update_params(*params)))
|
31
|
+
|
32
|
+
n3_temp = Tempfile.new("nexus_n3")
|
33
|
+
begin
|
34
|
+
n3_temp.write(N3Metadata::parse_n3_hash(n3_user_urns))
|
35
|
+
n3_temp.close
|
36
|
+
update_artifact_custom_info_n3(artifact, n3_temp.path)
|
37
|
+
ensure
|
38
|
+
n3_temp.close
|
39
|
+
n3_temp.unlink
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def update_artifact_custom_info_n3(artifact, file)
|
25
44
|
# Check if artifact exists before posting custom metadata.
|
26
45
|
get_artifact_info(artifact)
|
27
46
|
# Update the custom metadata using the n3 file.
|
28
47
|
group_id, artifact_id, version, extension = parse_artifact_string(artifact)
|
29
|
-
|
30
|
-
post_string = "content/repositories/#{configuration['repository']}/.meta/#{group_id.gsub(".", "/")}/#{artifact_id.gsub(".", "/")}/#{version}/#{file_name}"
|
48
|
+
post_string = N3Metadata::generate_n3_path(group_id, artifact_id, version, extension, configuration['repository'])
|
31
49
|
|
50
|
+
# Get all the urn:nexus/user# keys and consolidate.
|
32
51
|
# Read in nexus n3 file. If this is a newly-added artifact, there will be no n3 file so escape the exception.
|
33
52
|
begin
|
34
|
-
nexus_n3 = get_artifact_custom_info_n3(artifact
|
53
|
+
nexus_n3 = get_artifact_custom_info_n3(artifact)
|
35
54
|
rescue ArtifactNotFoundException
|
36
55
|
nexus_n3 = ""
|
37
56
|
end
|
@@ -39,74 +58,112 @@ module NexusCli
|
|
39
58
|
# Read in local n3 file.
|
40
59
|
local_n3 = File.open(file).read
|
41
60
|
|
42
|
-
n3_user_urns = { "
|
43
|
-
# Get
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
n3_user_urns.delete(tag)
|
58
|
-
else
|
59
|
-
n3_user_urns[tag] = "\t<urn:nexus/user##{tag}> \"#{value}\"" unless tag.empty? || value.empty?
|
60
|
-
end
|
61
|
-
end
|
62
|
-
}
|
61
|
+
n3_user_urns = { "n3_header" => N3Metadata::generate_n3_header(group_id, artifact_id, version, extension) }
|
62
|
+
# Get the nexus keys.
|
63
|
+
n3_user_urns = N3Metadata::generate_n3_urns_from_n3(nexus_n3, n3_user_urns)
|
64
|
+
# Get the local keys and update the nexus keys.
|
65
|
+
n3_user_urns = N3Metadata::generate_n3_urns_from_n3(local_n3, n3_user_urns)
|
66
|
+
n3_temp = Tempfile.new("nexus_n3")
|
67
|
+
begin
|
68
|
+
n3_temp.write(N3Metadata::parse_n3_hash(n3_user_urns))
|
69
|
+
n3_temp.close
|
70
|
+
nexus[post_string].put({:file => File.new(n3_temp.path)})
|
71
|
+
ensure
|
72
|
+
n3_temp.close
|
73
|
+
n3_temp.unlink
|
74
|
+
end
|
75
|
+
end
|
63
76
|
|
64
|
-
|
77
|
+
def clear_artifact_custom_info(artifact)
|
78
|
+
get_artifact_info(artifact)
|
79
|
+
group_id, artifact_id, version, extension = parse_artifact_string(artifact)
|
80
|
+
post_string = N3Metadata::generate_n3_path(group_id, artifact_id, version, extension, configuration['repository'])
|
81
|
+
n3_user_urns = { "n3_header" => N3Metadata::generate_n3_header(group_id, artifact_id, version, extension) }
|
65
82
|
n3_temp = Tempfile.new("nexus_n3")
|
66
83
|
begin
|
67
|
-
n3_temp.write(
|
68
|
-
n3_temp.
|
69
|
-
|
84
|
+
n3_temp.write(N3Metadata::parse_n3_hash(n3_user_urns))
|
85
|
+
n3_temp.close
|
86
|
+
nexus[post_string].put({:file => File.new(n3_temp.path)})
|
70
87
|
ensure
|
71
88
|
n3_temp.close
|
72
89
|
n3_temp.unlink
|
73
90
|
end
|
74
91
|
end
|
75
92
|
|
76
|
-
def search_artifacts(
|
77
|
-
|
78
|
-
|
93
|
+
def search_artifacts(*params)
|
94
|
+
docs = Array.new
|
95
|
+
parse_search_params(*params).each do |param|
|
96
|
+
begin
|
97
|
+
nexus['service/local/search/m2/freeform'].get ({params: {p: param[0], t: param[1], v: param[2]}}) do |response|
|
98
|
+
raise BadSearchRequestException if response.code == 400
|
99
|
+
docs.push(Nokogiri::XML(response.body).xpath("/search-results/data"))
|
100
|
+
end
|
101
|
+
rescue RestClient::ResourceNotFound => e
|
102
|
+
raise ArtifactNotFoundException
|
103
|
+
end
|
79
104
|
end
|
105
|
+
result = docs.inject(docs.first) {|memo,doc| get_common_artifact_set(memo, doc)}
|
106
|
+
return result.nil? ? "" : result.to_xml(:indent => 4)
|
107
|
+
end
|
108
|
+
|
109
|
+
private
|
110
|
+
def parse_update_params(*params)
|
80
111
|
begin
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
112
|
+
parsed_params = Hash.new
|
113
|
+
params.each do |param|
|
114
|
+
# The first colon separates key and value.
|
115
|
+
c1 = param.index(":")
|
116
|
+
key = param[0..(c1 - 1)]
|
117
|
+
value = param[(c1 + 1)..-1]
|
118
|
+
!c1.nil? && N3Metadata::valid_n3_key?(key) && N3Metadata::valid_n3_value?(value) ? parsed_params[key] = value : raise
|
85
119
|
end
|
86
|
-
|
87
|
-
|
120
|
+
return parsed_params
|
121
|
+
rescue
|
122
|
+
raise N3ParameterMalformedException
|
88
123
|
end
|
89
124
|
end
|
90
125
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
126
|
+
def parse_search_params(*params)
|
127
|
+
begin
|
128
|
+
parsed_params = Array.new
|
129
|
+
params.each do |param|
|
130
|
+
# The first two colons separate key, type, and value.
|
131
|
+
c1 = param.index(":")
|
132
|
+
c2 = param.index(":", (c1 + 1))
|
133
|
+
key = param[0..(c1 - 1)]
|
134
|
+
type = param[(c1 + 1)..(c2 - 1)]
|
135
|
+
value = param[(c2 + 1)..-1]
|
136
|
+
!c1.nil? && !c2.nil? && N3Metadata::valid_n3_key?(key) && N3Metadata::valid_n3_value?(value) && N3Metadata::valid_n3_search_type?(type) ? parsed_params.push([key, type, value]) : raise
|
137
|
+
end
|
138
|
+
return parsed_params
|
139
|
+
rescue
|
140
|
+
raise SearchParameterMalformedException
|
102
141
|
end
|
103
|
-
return builder.doc.root.to_s
|
104
142
|
end
|
105
143
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
return
|
144
|
+
# Expects the XML set with `data` as root.
|
145
|
+
def get_common_artifact_set(set1, set2)
|
146
|
+
intersection = get_artifact_array(set1) & get_artifact_array(set2)
|
147
|
+
return intersection.count > 0 ? Nokogiri::XML("<data>#{intersection.join}</data>").root : Nokogiri::XML("").root
|
148
|
+
end
|
149
|
+
|
150
|
+
# Collect <artifact>...</artifact> elements into an array.
|
151
|
+
# This will allow use of array intersection to find common artifacts in searches.
|
152
|
+
def get_artifact_array(set)
|
153
|
+
artifacts = Array.new
|
154
|
+
artifact = nil
|
155
|
+
set.to_s.split("\n").collect {|x| x.to_s.strip}.each do |piece|
|
156
|
+
if piece == "<artifact>"
|
157
|
+
artifact = piece
|
158
|
+
elsif piece == "</artifact>"
|
159
|
+
artifact += piece
|
160
|
+
artifacts.push(artifact)
|
161
|
+
artifact = nil
|
162
|
+
elsif !artifact.nil?
|
163
|
+
artifact += piece
|
164
|
+
end
|
165
|
+
end
|
166
|
+
return artifacts
|
110
167
|
end
|
111
168
|
end
|
112
169
|
end
|
@@ -32,9 +32,9 @@ module NexusCli
|
|
32
32
|
end
|
33
33
|
|
34
34
|
private
|
35
|
-
|
36
|
-
|
37
|
-
|
35
|
+
def running_nexus_pro?
|
36
|
+
return status['edition_long'] == "Professional" ? true : false
|
37
|
+
end
|
38
38
|
end
|
39
39
|
end
|
40
|
-
end
|
40
|
+
end
|
data/lib/nexus_cli/tasks.rb
CHANGED
@@ -6,13 +6,15 @@ module NexusCli
|
|
6
6
|
base.send :include, ::Thor::Actions
|
7
7
|
base.class_eval do
|
8
8
|
|
9
|
-
map 'pull'
|
10
|
-
map 'push'
|
11
|
-
map 'info'
|
12
|
-
map 'custom'
|
13
|
-
map '
|
14
|
-
map '
|
15
|
-
map '
|
9
|
+
map 'pull' => :pull_artifact
|
10
|
+
map 'push' => :push_artifact
|
11
|
+
map 'info' => :get_artifact_info
|
12
|
+
map 'custom' => :get_artifact_custom_info
|
13
|
+
map 'custom_raw' => :get_artifact_custom_info_n3
|
14
|
+
map 'config' => :get_nexus_configuration
|
15
|
+
map 'status' => :get_nexus_status
|
16
|
+
map 'search' => :search_for_artifacts
|
17
|
+
map 'search_custom' => :search_artifacts
|
16
18
|
|
17
19
|
class_option :overrides,
|
18
20
|
:type => :hash,
|
@@ -29,7 +31,7 @@ module NexusCli
|
|
29
31
|
end
|
30
32
|
end
|
31
33
|
|
32
|
-
method_option :destination,
|
34
|
+
method_option :destination,
|
33
35
|
:type => :string,
|
34
36
|
:default => nil,
|
35
37
|
:desc => "A different folder other than the current working directory."
|
@@ -61,22 +63,36 @@ module NexusCli
|
|
61
63
|
end
|
62
64
|
|
63
65
|
desc "get_artifact_custom_info_n3 artifact", "Gets and returns the custom metadata in Nexus n3 format about a particular artifact."
|
64
|
-
def get_artifact_custom_info_n3(artifact)
|
66
|
+
def get_artifact_custom_info_n3(artifact)
|
65
67
|
raise NotNexusProException unless @nexus_remote.kind_of? ProRemote
|
66
68
|
say @nexus_remote.get_artifact_custom_info_n3(artifact), :green
|
67
69
|
end
|
68
70
|
|
69
|
-
desc "update_artifact_custom_info artifact
|
70
|
-
def update_artifact_custom_info(artifact,
|
71
|
+
desc "update_artifact_custom_info artifact param1 param2 ...", "Updates the artifact custom metadata with the given key-value pairs."
|
72
|
+
def update_artifact_custom_info(artifact, *params)
|
71
73
|
raise NotNexusProException unless @nexus_remote.kind_of? ProRemote
|
72
|
-
@nexus_remote.update_artifact_custom_info(artifact,
|
74
|
+
@nexus_remote.update_artifact_custom_info(artifact, *params)
|
73
75
|
say "Custom metadata for artifact #{artifact} has been successfully pushed to Nexus.", :green
|
74
76
|
end
|
75
77
|
|
76
|
-
desc "
|
77
|
-
def
|
78
|
+
desc "update_artifact_custom_info_n3 artifact file", "Updates the artifact custom metadata by pushing the Nexus custom artifact file (n3) from your machine onto the Nexus."
|
79
|
+
def update_artifact_custom_info_n3(artifact, file)
|
78
80
|
raise NotNexusProException unless @nexus_remote.kind_of? ProRemote
|
79
|
-
|
81
|
+
@nexus_remote.update_artifact_custom_info_n3(artifact, file)
|
82
|
+
say "Custom metadata for artifact #{artifact} has been successfully pushed to Nexus.", :green
|
83
|
+
end
|
84
|
+
|
85
|
+
desc "clear_artifact_custom_info artifact", "Clears the artifact custom metadata."
|
86
|
+
def clear_artifact_custom_info(artifact)
|
87
|
+
raise NotNexusProException unless @nexus_remote.kind_of? ProRemote
|
88
|
+
@nexus_remote.clear_artifact_custom_info(artifact)
|
89
|
+
say "Custom metadata for artifact #{artifact} has been successfully cleared.", :green
|
90
|
+
end
|
91
|
+
|
92
|
+
desc "search_artifacts param1 param2 ... ", "Searches for artifacts using artifact metadata and returns the result as a list with items in XML format."
|
93
|
+
def search_artifacts(*params)
|
94
|
+
raise NotNexusProException unless @nexus_remote.kind_of? ProRemote
|
95
|
+
say (s = @nexus_remote.search_artifacts(*params)) == "" ? "No search results." : s, :green
|
80
96
|
end
|
81
97
|
|
82
98
|
desc "get_nexus_configuration", "Prints out configuration from the .nexus_cli file that helps inform where artifacts will be uploaded."
|
@@ -102,12 +118,16 @@ module NexusCli
|
|
102
118
|
desc "get_global_settings", "Prints out your Nexus' current setttings and saves them to a file."
|
103
119
|
def get_global_settings
|
104
120
|
@nexus_remote.get_global_settings
|
105
|
-
say "Your current Nexus global settings have been written to the file: global_settings.json", :blue
|
121
|
+
say "Your current Nexus global settings have been written to the file: ~/.nexus/global_settings.json", :blue
|
106
122
|
end
|
107
123
|
|
124
|
+
method_option :json,
|
125
|
+
:type => :string,
|
126
|
+
:default => nil,
|
127
|
+
:desc => "A String of the JSON you wish to upload."
|
108
128
|
desc "upload_global_settings", "Uploads a global_settings.json file to your Nexus to update its settings."
|
109
129
|
def upload_global_settings
|
110
|
-
@nexus_remote.upload_global_settings
|
130
|
+
@nexus_remote.upload_global_settings(options[:json])
|
111
131
|
say "Your global_settings.json file has been uploaded to Nexus", :blue
|
112
132
|
end
|
113
133
|
|
@@ -116,7 +136,26 @@ module NexusCli
|
|
116
136
|
@nexus_remote.reset_global_settings
|
117
137
|
say "Your Nexus global settings have been reset to their default values", :blue
|
118
138
|
end
|
139
|
+
|
140
|
+
desc "create_repository name", "Creates a new Repository with the provided name."
|
141
|
+
def create_repository(name)
|
142
|
+
if @nexus_remote.create_repository(name)
|
143
|
+
say "A new Repository named #{name} has been created.", :blue
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
desc "delete_repository name", "Deletes a Repository with the provided name."
|
148
|
+
def delete_repository(name)
|
149
|
+
if @nexus_remote.delete_repository(name)
|
150
|
+
say "The Repository named #{name} has been deleted.", :blue
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
desc "get_repository_info name", "Finds and returns information about the provided Repository."
|
155
|
+
def get_repository_info(name)
|
156
|
+
say @nexus_remote.get_repository_info(name), :green
|
157
|
+
end
|
119
158
|
end
|
120
159
|
end
|
121
160
|
end
|
122
|
-
end
|
161
|
+
end
|
data/nexus_cli.gemspec
CHANGED
@@ -0,0 +1,110 @@
|
|
1
|
+
Feature: Use the Nexus Pro CLI
|
2
|
+
As a Pro CLI user
|
3
|
+
I need commands to get, update, search, and delete Nexus artifact custom metadata
|
4
|
+
|
5
|
+
Scenario: Get Nexus Pro Status
|
6
|
+
When I call the nexus "status" command
|
7
|
+
Then the output should contain:
|
8
|
+
"""
|
9
|
+
Application Name: Sonatype Nexus Professional
|
10
|
+
"""
|
11
|
+
And the exit status should be 0
|
12
|
+
|
13
|
+
@push
|
14
|
+
Scenario: Push an artifact
|
15
|
+
When I push an artifact with the GAV of "com.test:myprotest:1.0.0:tgz"
|
16
|
+
Then the output should contain:
|
17
|
+
"""
|
18
|
+
Artifact com.test:myprotest:1.0.0:tgz has been successfully pushed to Nexus.
|
19
|
+
"""
|
20
|
+
And the exit status should be 0
|
21
|
+
|
22
|
+
Scenario: Update an artifact's custom metadata
|
23
|
+
When I call the nexus "update_artifact_custom_info com.test:myprotest:1.0.0:tgz teemoHat:equipped" command
|
24
|
+
Then the output should contain:
|
25
|
+
"""
|
26
|
+
Custom metadata for artifact com.test:myprotest:1.0.0:tgz has been successfully pushed to Nexus.
|
27
|
+
"""
|
28
|
+
And the exit status should be 0
|
29
|
+
|
30
|
+
Scenario: Update an artifact's custom metadata with multiple parameters
|
31
|
+
When I call the nexus "update_artifact_custom_info com.test:myprotest:1.0.0:tgz teemoHat:equipped_ \"teemoSkins:many skins!!1\"" command
|
32
|
+
Then the output should contain:
|
33
|
+
"""
|
34
|
+
Custom metadata for artifact com.test:myprotest:1.0.0:tgz has been successfully pushed to Nexus.
|
35
|
+
"""
|
36
|
+
And the exit status should be 0
|
37
|
+
|
38
|
+
Scenario: Get an artifact's custom metadata
|
39
|
+
When I call the nexus "custom com.test:myprotest:1.0.0:tgz" command
|
40
|
+
Then the output should contain:
|
41
|
+
"""
|
42
|
+
<teemoHat>equipped_</teemoHat>
|
43
|
+
"""
|
44
|
+
And the output should contain:
|
45
|
+
"""
|
46
|
+
<teemoSkins>many skins!!1</teemoSkins>
|
47
|
+
"""
|
48
|
+
And the exit status should be 0
|
49
|
+
|
50
|
+
Scenario: Get an artifact's raw custom metadata
|
51
|
+
When I call the nexus "custom_raw com.test:myprotest:1.0.0:tgz" command
|
52
|
+
Then the output should contain:
|
53
|
+
"""
|
54
|
+
<urn:nexus/user#teemoHat> "equipped_"
|
55
|
+
"""
|
56
|
+
And the output should contain:
|
57
|
+
"""
|
58
|
+
<urn:nexus/user#teemoSkins> "many skins!!1"
|
59
|
+
"""
|
60
|
+
And the exit status should be 0
|
61
|
+
|
62
|
+
Scenario: Search for artifacts by custom metadata using matches
|
63
|
+
When I call the nexus "search_custom teemoHat:matches:equip*" command
|
64
|
+
Then the output should contain:
|
65
|
+
"""
|
66
|
+
<artifactId>myprotest</artifactId>
|
67
|
+
"""
|
68
|
+
And the exit status should be 0
|
69
|
+
|
70
|
+
Scenario: Search for artifacts by custom metadata using equal
|
71
|
+
When I call the nexus "search_custom teemoHat:equal:equipped_" command
|
72
|
+
Then the output should contain:
|
73
|
+
"""
|
74
|
+
<artifactId>myprotest</artifactId>
|
75
|
+
"""
|
76
|
+
And the exit status should be 0
|
77
|
+
|
78
|
+
Scenario: Search for artifacts by custom metadata using multiple parameters
|
79
|
+
When I call the nexus "search_custom teemoHat:matches:equip* teemoHat:equal:equipped_" command
|
80
|
+
Then the output should contain:
|
81
|
+
"""
|
82
|
+
<artifactId>myprotest</artifactId>
|
83
|
+
"""
|
84
|
+
And the exit status should be 0
|
85
|
+
|
86
|
+
Scenario: Search for artifacts by custom metadata that return an empty result set
|
87
|
+
When I call the nexus "search_custom bestTeemo:equal:malady" command
|
88
|
+
Then the output should contain:
|
89
|
+
"""
|
90
|
+
No search results.
|
91
|
+
"""
|
92
|
+
And the exit status should be 0
|
93
|
+
|
94
|
+
Scenario: Clear an artifact's custom metadata
|
95
|
+
When I call the nexus "clear_artifact_custom_info com.test:myprotest:1.0.0:tgz" command
|
96
|
+
Then the output should contain:
|
97
|
+
"""
|
98
|
+
Custom metadata for artifact com.test:myprotest:1.0.0:tgz has been successfully cleared.
|
99
|
+
"""
|
100
|
+
And the exit status should be 0
|
101
|
+
|
102
|
+
@delete
|
103
|
+
Scenario: Attempt to delete an artifact
|
104
|
+
When I delete an artifact with the GAV of "com.test:myprotest:1.0.0:tgz"
|
105
|
+
And I call the nexus "info com.test:myprotest:1.0.0:tgz" command
|
106
|
+
Then the output should contain:
|
107
|
+
"""
|
108
|
+
The artifact you requested information for could not be found. Please ensure it exists inside the Nexus.
|
109
|
+
"""
|
110
|
+
And the exit status should be 101
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'nexus_cli'
|
2
|
+
|
3
|
+
remote = NexusCli::ProRemote.new(nil)
|
4
|
+
|
5
|
+
describe NexusCli do
|
6
|
+
it "gives you errors when you attempt to get an artifact's custom info and don't give a valid artifact name" do
|
7
|
+
expect {remote.get_artifact_custom_info("com.something:something:1.0.0")}.to raise_error(NexusCli::ArtifactMalformedException)
|
8
|
+
end
|
9
|
+
|
10
|
+
it "gives you errors when you attempt to get an artifact's custom info and it cannot be found" do
|
11
|
+
RestClient::Resource.any_instance.stub(:get).and_raise(RestClient::ResourceNotFound)
|
12
|
+
expect {remote.get_artifact_custom_info("com.something:something:1.0.0:tgz")}.to raise_error(NexusCli::ArtifactNotFoundException)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "gives you errors when you attempt to update an artifact's custom info and don't give valid parameters" do
|
16
|
+
expect {remote.update_artifact_custom_info("com.something:something:1.0.0:tgz", "_somebadkey:_somebadvalue")}.to raise_error(NexusCli::N3ParameterMalformedException)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "gives you errors when you attempt to update an artifact's custom info and don't give valid parameters" do
|
20
|
+
expect {remote.update_artifact_custom_info("com.something:something:1.0.0:tgz", "_somebadkey")}.to raise_error(NexusCli::N3ParameterMalformedException)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "gives you errors when you attempt to clear an artifact's custom info and it cannot be found" do
|
24
|
+
RestClient::Resource.any_instance.stub(:get).and_raise(RestClient::ResourceNotFound)
|
25
|
+
expect {remote.clear_artifact_custom_info("com.something:something:1.0.0:tgz")}.to raise_error(NexusCli::ArtifactNotFoundException)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "gives you errors when you attempt to search for artifacts using custom info and don't give valid key" do
|
29
|
+
expect {remote.search_artifacts("somekey_:equal:somevalue")}.to raise_error(NexusCli::SearchParameterMalformedException)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "gives you errors when you attempt to search for artifacts using custom info and don't give valid value" do
|
33
|
+
expect {remote.search_artifacts("somekey:equal:somevalue \"\'\\/")}.to raise_error(NexusCli::SearchParameterMalformedException)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "gives you errors when you attempt to search for artifacts using custom info and don't give valid search type" do
|
37
|
+
expect {remote.search_artifacts("somekey:equals:somevalue")}.to raise_error(NexusCli::SearchParameterMalformedException)
|
38
|
+
end
|
39
|
+
|
40
|
+
it "gives you errors when you attempt to search for artifacts using custom info and don't give valid parameters" do
|
41
|
+
expect {remote.search_artifacts("somekey")}.to raise_error(NexusCli::SearchParameterMalformedException)
|
42
|
+
end
|
43
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nexus_cli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-08-
|
12
|
+
date: 2012-08-14 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: thor
|
@@ -155,6 +155,22 @@ dependencies:
|
|
155
155
|
- - ! '>='
|
156
156
|
- !ruby/object:Gem::Version
|
157
157
|
version: '0'
|
158
|
+
- !ruby/object:Gem::Dependency
|
159
|
+
name: jsonpath
|
160
|
+
requirement: !ruby/object:Gem::Requirement
|
161
|
+
none: false
|
162
|
+
requirements:
|
163
|
+
- - ! '>='
|
164
|
+
- !ruby/object:Gem::Version
|
165
|
+
version: '0'
|
166
|
+
type: :development
|
167
|
+
prerelease: false
|
168
|
+
version_requirements: !ruby/object:Gem::Requirement
|
169
|
+
none: false
|
170
|
+
requirements:
|
171
|
+
- - ! '>='
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
158
174
|
description: A command-line wrapper for making REST calls to Sonatype Nexus.
|
159
175
|
email:
|
160
176
|
- kallan@riotgames.com
|
@@ -178,14 +194,17 @@ files:
|
|
178
194
|
- lib/nexus_cli/configuration.rb
|
179
195
|
- lib/nexus_cli/errors.rb
|
180
196
|
- lib/nexus_cli/kernel.rb
|
197
|
+
- lib/nexus_cli/n3_metadata.rb
|
181
198
|
- lib/nexus_cli/nexus_oss_remote.rb
|
182
199
|
- lib/nexus_cli/nexus_pro_remote.rb
|
183
200
|
- lib/nexus_cli/nexus_remote_factory.rb
|
184
201
|
- lib/nexus_cli/tasks.rb
|
185
202
|
- lib/nexus_cli/version.rb
|
186
203
|
- nexus_cli.gemspec
|
204
|
+
- pro/nexus_pro.feature
|
187
205
|
- spec/configuration_spec.rb
|
188
206
|
- spec/oss_remote_spec.rb
|
207
|
+
- spec/pro_remote_spec.rb
|
189
208
|
homepage: https://github.com/RiotGames/nexus_cli
|
190
209
|
licenses: []
|
191
210
|
post_install_message:
|
@@ -200,7 +219,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
200
219
|
version: '0'
|
201
220
|
segments:
|
202
221
|
- 0
|
203
|
-
hash:
|
222
|
+
hash: 2849503457088068545
|
204
223
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
205
224
|
none: false
|
206
225
|
requirements:
|
@@ -209,7 +228,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
209
228
|
version: '0'
|
210
229
|
segments:
|
211
230
|
- 0
|
212
|
-
hash:
|
231
|
+
hash: 2849503457088068545
|
213
232
|
requirements: []
|
214
233
|
rubyforge_project:
|
215
234
|
rubygems_version: 1.8.21
|
@@ -222,3 +241,4 @@ test_files:
|
|
222
241
|
- features/support/env.rb
|
223
242
|
- spec/configuration_spec.rb
|
224
243
|
- spec/oss_remote_spec.rb
|
244
|
+
- spec/pro_remote_spec.rb
|