nexus_cli 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|