open-build-service-api 0.0.2 → 0.1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9bf527982bd90cbc256ebf065939281cf3f6448c3c77ae6de5bccf60e576a01b
4
- data.tar.gz: 9de0695570ac504b8b7172cc251dcec5a1712495002c643743d286e1a35e0900
3
+ metadata.gz: 02f4ce3a2f1f328cead66065db1d5b5ff6b12c54a964d29134905bdabbcc5223
4
+ data.tar.gz: 857c13405e1b116ac1607a2bf3ce3316db46d47d83fc7910b0f6402a85958409
5
5
  SHA512:
6
- metadata.gz: 23f3d09d60d92aa116caa2ad2296ed5ef9b6d525aff16e81e64a9c9905cb9f77eb1e91e359b6ac342ac7b1f45192b6abf84b4a7d0da66957f42ec5b30de46a5c
7
- data.tar.gz: b9fe7c2dbec2cb50272097637f08236b505662dfc713b6158e0ddd794490716c9b40fa2cbf56bd9777bc077f6b9715c3be013b2ced4c5c9220d7032234508e18
6
+ metadata.gz: 9013c7b9d55d8bf2ddf3752570d6bc0c2a944728f9a675ac062bfd79ad6cb9142e3dd3d88b74c50592c0c06e306757b120a60889ac7b83794e61c279b2f27d57
7
+ data.tar.gz: 24f6529b60d5a2bffefd2f705384d4c685d07b5a8b75cde9f0ea83832856e431f84b1cec4960b2083e44c14303d0febbc21170f8f65e65e155e53c9b160109d7
@@ -1,3 +1,11 @@
1
+ ## Version: 0.1.0 (alpha)
2
+
3
+ - Exception `RemoteAPIError` does now store the `error_code` and `error_summary` if it is available
4
+ - Added a method to allow creation of Open Build Service projects
5
+ - Added `exists?` method to `Projects module in order to check whether a project exists or not
6
+ - Added a `branch_package` method to Project model to allow branching of source packages
7
+ - Added a `delete!` method to Project model to allow deletion of source projects
8
+
1
9
  ## Version: 0.0.2 (alpha)
2
10
 
3
11
  - Adds `Connection` module to establish a connection with a Build Service instance
@@ -5,9 +5,29 @@ module OpenBuildServiceAPI
5
5
  @connection = connection
6
6
  end
7
7
 
8
+ def create(name, meta = nil)
9
+ raise ProjectAlreadyExistsError.new("Project name '#{name}' has already been taken.") if exists?(name)
10
+
11
+ meta = meta ? meta : meta_for_new_project(name)
12
+
13
+ begin
14
+ response = @connection.send_request(:put, "/source/#{CGI.escape(name)}/_meta", request_body: meta)
15
+ rescue RequestError => err
16
+ raise ProjectCreationPermissionError.new(err.error_summary) if err.error_code == 'create_project_no_permission'
17
+ raise
18
+ end
19
+
20
+ return Project.new(projects: self, connection: @connection, name: name) if response.is_a?(Net::HTTPOK)
21
+ raise ProjectCreationFailedError.new("could not create project. API responded with '#{response.code}': #{response.body}")
22
+ end
23
+
8
24
  def list
9
25
  projects = Nokogiri::XML(@connection.send_request(:get, '/source').body)
10
- projects.xpath('//entry').map {|project| Project.new(projects: self, name: project.attr('name')) }
26
+ projects.xpath('//entry').map {|project| Project.new(projects: self, connection: @connection, name: project.attr('name')) }
27
+ end
28
+
29
+ def exists?(name)
30
+ !!find(name)
11
31
  end
12
32
 
13
33
  def find(name)
@@ -15,8 +35,10 @@ module OpenBuildServiceAPI
15
35
  project_data = Nokogiri::XML(@connection.send_request(:get, "/source/#{CGI.escape(name)}").body)
16
36
  packages = project_data.xpath('//entry').map { |package| package.attr('name') }
17
37
 
18
- Project.new(projects: self, name: name, packages: packages)
19
- rescue NotFoundError
38
+ Project.new(projects: self, name: name, packages: packages, connection: @connection)
39
+ rescue RequestError => err
40
+ return if err.error_code == 'unknown_project'
41
+ raise
20
42
  end
21
43
  end
22
44
 
@@ -26,6 +48,19 @@ module OpenBuildServiceAPI
26
48
  raise ProjectNotFoundError.new("Project '#{name}' does not exist.") unless project
27
49
  project
28
50
  end
51
+
52
+ private
53
+
54
+ def meta_for_new_project(name)
55
+ project_meta = Nokogiri::XML::Builder.new do |xml|
56
+ xml.project('name': name) do
57
+ xml.title name
58
+ xml.description
59
+ end
60
+ end
61
+
62
+ project_meta.to_xml
63
+ end
29
64
  end
30
65
  end
31
66
  end
@@ -13,6 +13,12 @@ module OpenBuildServiceAPI
13
13
  send_request(:get, '/')
14
14
  end
15
15
 
16
+ def inspect
17
+ inspected_object = super
18
+ inspected_object.gsub!(/\@username="([^\"]+)"/, '@username="..."')
19
+ inspected_object.gsub(/\@password="([^\"]+)"/, '@password="..."')
20
+ end
21
+
16
22
  def send_request(method, path, params = {})
17
23
  request_body = params[:request_body] if params[:request_body]
18
24
  params.delete(:request_body)
@@ -31,6 +37,8 @@ module OpenBuildServiceAPI
31
37
  request_method = Net::HTTP::Put.new(uri)
32
38
  elsif method.to_s.downcase == 'get'
33
39
  request_method = Net::HTTP::Get.new(uri)
40
+ elsif method.to_s.downcase == 'delete'
41
+ request_method = Net::HTTP::Delete.new(uri)
34
42
  end
35
43
 
36
44
  request_method['Accept'] = 'application/xml'
@@ -42,9 +50,11 @@ module OpenBuildServiceAPI
42
50
  response = request.request(request_method)
43
51
 
44
52
  raise InternalServerError.new(response) if response.is_a?(Net::HTTPInternalServerError)
45
- raise NotFoundError.new(response) if response.is_a?(Net::HTTPNotFound)
46
53
  raise AuthenticationError.new(response, "Authentication failed. Please check your credentials.") if response.is_a?(Net::HTTPUnauthorized)
47
54
 
55
+ code = response.code.to_i
56
+ raise RequestError.new(response) if code >= 400
57
+
48
58
  return response
49
59
  rescue Errno::ECONNREFUSED, SocketError, Net::OpenTimeout => err
50
60
  raise ConnectionError.new(err.to_s)
@@ -1,11 +1,23 @@
1
1
  module OpenBuildServiceAPI
2
2
  # remote API network errors
3
3
  class RemoteAPIError < Exception
4
- attr_accessor :response, :message
4
+ attr_accessor :response, :message, :error_code, :error_summary
5
5
 
6
6
  def initialize(response, message=nil)
7
+ response_body = response.body
8
+
7
9
  @response = response
8
- @message = message ? message : response.body
10
+ @message = message ? message : response_body
11
+
12
+ response_xml = Nokogiri::XML(response_body)
13
+ status = response_xml.xpath('./status')[0]
14
+
15
+ if status
16
+ @error_code = status.attr('code')
17
+
18
+ summary = status.xpath('./summary')
19
+ @error_summary = summary.text if summary[0]
20
+ end
9
21
  end
10
22
 
11
23
  def to_s
@@ -15,11 +27,17 @@ module OpenBuildServiceAPI
15
27
 
16
28
  class InternalServerError < RemoteAPIError; end
17
29
  class AuthenticationError < RemoteAPIError; end
18
- class NotFoundError < RemoteAPIError; end
30
+ class RequestError < RemoteAPIError; end
19
31
 
20
32
  # remote API errors
21
33
  class APIError < Exception; end
22
34
  class ProjectNotFoundError < APIError; end
35
+ class ProjectCreationPermissionError < APIError; end
36
+ class ProjectCreationFailedError < APIError; end
37
+ class ProjectDeletionPermissionError < APIError; end
38
+ class ProjectAlreadyExistsError < APIError; end
39
+ class PackageAlreadyExistsError < APIError; end
40
+ class TargetProjectPermissionError < APIError; end
23
41
 
24
42
  # library specific exceptions
25
43
  class GeneralError < Exception; end
@@ -0,0 +1,16 @@
1
+ module OpenBuildServiceAPI
2
+ class Package
3
+ attr_reader :name
4
+ attr_accessor :project
5
+
6
+ def initialize(params = {})
7
+ @name = params[:name]
8
+ @project = params[:project]
9
+ @connection = params[:connection]
10
+ end
11
+
12
+ def to_s
13
+ @name
14
+ end
15
+ end
16
+ end
@@ -1,15 +1,62 @@
1
1
  module OpenBuildServiceAPI
2
2
  class Project
3
- attr_accessor :name, :projects, :packages
3
+ attr_accessor :name, :projects
4
4
 
5
5
  def initialize(params = {})
6
6
  @name = params[:name]
7
7
  @projects = params[:projects]
8
- @packages = params[:packages]
8
+ @connection = params[:connection]
9
9
  end
10
10
 
11
11
  def to_s
12
12
  @name
13
13
  end
14
+
15
+ def delete!(message=nil)
16
+ begin
17
+ @connection.send_request(:delete, "/source/#{CGI.escape(@name)}", comment: message)
18
+ rescue RequestError => err
19
+ raise ProjectDeletionPermissionError.new("No permission to delete project '#{@name}'.") if err.error_code == 'delete_project_no_permission'
20
+ raise
21
+ end
22
+
23
+ true
24
+ end
25
+
26
+ def packages
27
+ return @cached_packages if @cached_packages && !@package_reload
28
+ @package_reload = false
29
+ @cached_packages = []
30
+
31
+ packages = Nokogiri::XML(@connection.send_request(:get, "/source/#{CGI.escape(@name)}").body)
32
+ packages.xpath('//entry').each do |package|
33
+ @cached_packages << Package.new(name: package.attr('name'), connection: @connection, project: self)
34
+ end
35
+
36
+ @cached_packages
37
+ end
38
+
39
+ def branch_package(source_project, source_package, package_name_after_branch=nil)
40
+ params = { cmd: 'branch', target_project: name }
41
+ params[:target_package] = package_name_after_branch ? package_name_after_branch : source_package
42
+
43
+ begin
44
+ response = @connection.send_request(:post, "/source/#{CGI.escape(source_project.to_s)}/#{CGI.escape(source_package.to_s)}", params)
45
+ response_xml = Nokogiri::XML(response.body)
46
+
47
+ @package_reload = true
48
+ Package.new(name: response_xml.xpath('//data[@name="targetpackage"]')[0].text, connection: @connection, project: self)
49
+ rescue RequestError => err
50
+ raise PackageAlreadyExistsError.new("Package '#{params[:target_package]}' does already exist " \
51
+ "in project '#{@name}'.") if err.error_code == 'double_branch_package'
52
+ raise TargetProjectPermissionError.new("Branching to project '#{@name}' is not possible: No " \
53
+ "access in target project.") if err.error_code == 'cmd_execution_no_permission'
54
+ raise
55
+ end
56
+ end
57
+
58
+ def reload!
59
+ @package_reload = true
60
+ end
14
61
  end
15
62
  end
@@ -11,4 +11,5 @@ require_relative 'api/about'
11
11
  require_relative 'api/projects'
12
12
 
13
13
  # Models
14
+ require_relative 'models/package'
14
15
  require_relative 'models/project'
@@ -1,3 +1,4 @@
1
1
  module OpenBuildServiceAPI
2
- VERSION = '0.0.2'
2
+ VERSION = '0.1.0'
3
+ RELEASE_DATE = '2019-06-15'
3
4
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: open-build-service-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Manuel Schnitzer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-06-07 00:00:00.000000000 Z
11
+ date: 2019-06-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: date
@@ -50,6 +50,26 @@ dependencies:
50
50
  - - ">="
51
51
  - !ruby/object:Gem::Version
52
52
  version: 1.10.0
53
+ - !ruby/object:Gem::Dependency
54
+ name: byebug
55
+ requirement: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - "~>"
58
+ - !ruby/object:Gem::Version
59
+ version: '11.0'
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: 11.0.1
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '11.0'
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: 11.0.1
53
73
  description: The Open Build Service API wrapped into a Ruby gem.
54
74
  email: webmaster@mschnitzer.de
55
75
  executables: []
@@ -62,6 +82,7 @@ files:
62
82
  - lib/api/projects.rb
63
83
  - lib/connection.rb
64
84
  - lib/exception.rb
85
+ - lib/models/package.rb
65
86
  - lib/models/project.rb
66
87
  - lib/open-build-service-api.rb
67
88
  - lib/version.rb