audc-gerry 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 8a1b763d810800ab1dcb57c97e7df8ba54e09d207e549b5e3270b5d09b16aadf
4
+ data.tar.gz: 194d9b4dda05ca8cc5b1bf70ef454c706331bb8a32e3f48c3f84f4754675fa18
5
+ SHA512:
6
+ metadata.gz: eca9ab70813663d3b95aa85aeaec1918743246d611b19c9690fc388dd6266149e8af2ec10ad1d55d859c92ddebd389bdb6337b490ef2c26f00e64dfd8fab57f9
7
+ data.tar.gz: 30bde14c9bc657860cf403d3482b14f2ef13c7f76d65f6ad449b050208e22aeb46c754d2501c7547769a080dd445380e98896b3ab43a1dc30e2a25574a4adefe
data/README.md ADDED
@@ -0,0 +1,62 @@
1
+ # gerry[![Build Status](https://travis-ci.org/trumant/gerry.svg)][travis]
2
+
3
+ Base Gerrit Version V2.14.6
4
+
5
+ Simple Ruby wrapper for the Gerrit Code Review REST-API.
6
+
7
+ ![Gary from spongebob square pants](http://en.spongepedia.org/images/3/37/Garry.jpg)
8
+
9
+ [travis]: https://travis-ci.org/trumant/gerry
10
+
11
+ ## Documentation
12
+ [http://rdoc.info/github/trumant/gerry][documentation]
13
+
14
+ [documentation]: http://rdoc.info/github/trumant/gerry
15
+
16
+ ## Install
17
+ ```
18
+ bundle
19
+ bundle exec rake install
20
+ ```
21
+
22
+ ## Examples
23
+ ### Get the global capabilities
24
+ ```ruby
25
+ client = Gerry.new('https://review')
26
+ client.account_capabilities
27
+ => {"queryLimit"=>{"min"=>0, "max"=>250}}
28
+ ```
29
+
30
+ ### List projects
31
+ ```ruby
32
+ client = Gerry.new('https://review')
33
+ client.projects
34
+ => { "awesome"=>{ "description"=>"Awesome project"}}
35
+ ```
36
+
37
+ ### List open changes
38
+ ```ruby
39
+ client = Gerry.new('https://review')
40
+ client.changes(['q=is:open'])
41
+ => [{"project"=>"awesome", "branch"=>"master", "id"=>"Ibfedd978...."}]
42
+ ```
43
+
44
+ ### Authentication type
45
+ Since 2.14, Gerrit no longer supports digest authentication.
46
+ Gerry uses basic authentication against gerrit.
47
+
48
+ ## Licence
49
+ The MIT Licence
50
+
51
+ Copyright (c) Fabian Mettler, Andrew Erickson, Travis Truman, Sebastian Schuberth, Orgad Shaneh
52
+
53
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
54
+
55
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
56
+
57
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
58
+
59
+ ## References
60
+ https://www.gerritcodereview.com/
61
+
62
+ https://gerrit-review.googlesource.com/Documentation/rest-api.html
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require 'rspec/core/rake_task'
2
+ require 'bundler/gem_tasks'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
7
+
@@ -0,0 +1,17 @@
1
+ require 'erb'
2
+
3
+ module Gerry
4
+ module Api
5
+ module Access
6
+ # Get access rights for the specified project
7
+ #
8
+ # @param [VarArgs] projects the project names
9
+ # @return [Hash] the list of access rights
10
+ def access(*projects)
11
+ projects = projects.flatten.map { |name| ERB::Util.url_encode(name) }
12
+ url = "/access/?project=#{projects.join('&project=')}"
13
+ get(url)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,38 @@
1
+ module Gerry
2
+ module Api
3
+ module Accounts
4
+ # Get the account info for the specified account ID.
5
+ #
6
+ # @param [String] account_id the account.
7
+ # @return [Hash] the account info.
8
+ def account_info(account_id)
9
+ url = "/accounts/#{account_id}"
10
+ get(url)
11
+ end
12
+
13
+ # Get the global capabilities that are enabled for the calling user.
14
+ #
15
+ # @param [Array] options the query parameters.
16
+ # @return [Hash] the account capabilities.
17
+ def account_capabilities(options = [])
18
+ url = '/accounts/self/capabilities'
19
+
20
+ if options.empty?
21
+ return get(url)
22
+ end
23
+
24
+ options = map_options(options)
25
+ get("#{url}?#{options}")
26
+ end
27
+
28
+ # Get all groups that contain the specified account as a member
29
+ #
30
+ # @param [String] account_id the account
31
+ # @return [Enumberable] the groups
32
+ def groups_for_account(account_id)
33
+ url = "/accounts/#{account_id}/groups/"
34
+ get(url)
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gerry
4
+ module Api
5
+ module Branches
6
+ ##
7
+ # Get the branches of project
8
+ #
9
+ def branches(project_name)
10
+ get("/projects/#{project_name}/branches")
11
+ end
12
+
13
+ # Get the projects that start with the specified prefix
14
+ # and accessible by the caller.
15
+ #
16
+ # @param [String] name the project name.
17
+ # @return [Hash] the projects.
18
+ def branch(project_name, branch_name)
19
+ get("/projects/#{project_name}/branches/#{branch_name}")
20
+ end
21
+
22
+ ##
23
+ # create branch that derived from branch name or revision
24
+ #
25
+ # example: create_branch('foo', 'master', 'stable')
26
+ # create_branch('foo', 'revision', 'stable')
27
+ #
28
+ def create_branch(project_name, source, branch)
29
+ # try source as ref
30
+ body = { ref: source }
31
+ put("/projects/#{project_name}/branches/#{branch}", body)
32
+ rescue Gerry::Api::Request::RequestError
33
+ # try source as revision
34
+ body = { revision: source }
35
+ put("/projects/#{project_name}/branches/#{branch}", body)
36
+ end
37
+
38
+ ##
39
+ # Gets the reflog of a certain branch.
40
+ def branch_reflog(project_name, branch, number)
41
+ get("/projects/#{project_name}/branches/#{branch}/reflog?n=#{number}")
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,38 @@
1
+ require 'cgi'
2
+
3
+ module Gerry
4
+ module Api
5
+ module Changes
6
+ # Get changes visible to the caller.
7
+ #
8
+ # @param [Array] options the query parameters.
9
+ # @return [Hash] the changes.
10
+ def changes(options = [])
11
+ endpoint = '/changes/'
12
+ url = endpoint
13
+
14
+ if !options.empty?
15
+ url += '?' + map_options(options)
16
+ end
17
+
18
+ response = get(url)
19
+ return response if response.empty? || !response.last.delete('_more_changes')
20
+
21
+ # Get the original start parameter, if any, else start from 0.
22
+ query = URI.parse(url).query
23
+ query = query ? CGI.parse(query) : { 'S' => ['0'] }
24
+ start = query['S'].join.to_i
25
+
26
+ # Keep getting data until there are no more changes.
27
+ loop do
28
+ # Replace the start parameter, using the original start as an offset.
29
+ query['S'] = ["#{start + response.size}"]
30
+ url = endpoint + '?' + map_options(query)
31
+
32
+ response.concat(get(url))
33
+ return response if response.empty? || !response.last.delete('_more_changes')
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,72 @@
1
+ require 'json'
2
+
3
+ module Gerry
4
+ module Api
5
+ module Groups
6
+ # Get all groups
7
+ #
8
+ # @return [Hash] the groups
9
+ def groups
10
+ url = '/groups/'
11
+ get(url)
12
+ end
13
+
14
+ # Get all members for a group
15
+ #
16
+ # @param [Array] options the query parameters
17
+ # @return [Array] the members
18
+ def group_members(group_id, options = [])
19
+ url = "/groups/#{group_id}/members/"
20
+
21
+ if options.empty?
22
+ return get(url)
23
+ end
24
+
25
+ options = map_options(options)
26
+ get("#{url}?#{options}")
27
+ end
28
+
29
+ # Get the directly included groups of a group
30
+ #
31
+ # @return [Array] the included groups
32
+ def included_groups(group_id)
33
+ url = "/groups/#{group_id}/groups/"
34
+ get(url)
35
+ end
36
+
37
+ # Create a new group
38
+ #
39
+ # @return [Hash] the group details
40
+ def create_group(name, description, visible, owner_id=nil)
41
+ url = "/groups/#{name}"
42
+ body = {
43
+ description: description,
44
+ visible_to_all: visible,
45
+ }
46
+ body[:owner_id] = owner_id unless owner_id.nil? || owner_id.empty?
47
+ put(url, body)
48
+ end
49
+
50
+ # Adds one or more users to a group
51
+ #
52
+ # @param [String] group_id the group id
53
+ # @param [Enumberable] users the list of users identified by email address
54
+ # @return [Hash] the account info details for each user added
55
+ def add_to_group(group_id, users)
56
+ url = "/groups/#{group_id}/members"
57
+ body = {
58
+ members: users
59
+ }
60
+ post(url, body)
61
+ end
62
+
63
+ def remove_from_group(group_id, users)
64
+ url = "/groups/#{group_id}/members.delete"
65
+ body = {
66
+ members: users
67
+ }
68
+ post(url, body)
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,73 @@
1
+ module Gerry
2
+ module Api
3
+ module Projects
4
+ # Get the projects accessible by the caller.
5
+ #
6
+ # @return [Hash] the projects.
7
+ def projects
8
+ get('/projects/')
9
+ end
10
+
11
+ # Get the projects that start with the specified prefix
12
+ # and accessible by the caller.
13
+ #
14
+ # @param [String] name the project name.
15
+ # @return [Hash] the projects.
16
+ def find_project(name)
17
+ get("/projects/#{name}")
18
+ end
19
+
20
+ # Get the symbolic HEAD ref for the specified project.
21
+ #
22
+ # @param [String] project the project name.
23
+ # @return [String] the current ref to which HEAD points to.
24
+ def get_head(project)
25
+ get("/projects/#{project}/HEAD")
26
+ end
27
+
28
+ # Set the symbolic HEAD ref for the specified project to
29
+ # point to the specified branch.
30
+ #
31
+ # @param [String] project the project name.
32
+ # @param [String] branch the branch to point to.
33
+ # @return [String] the new ref to which HEAD points to.
34
+ def set_head(project, branch)
35
+ url = "/projects/#{project}/HEAD"
36
+ body = {
37
+ ref: 'refs/heads/' + branch
38
+ }
39
+ put(url, body)
40
+ end
41
+
42
+ ##
43
+ # lists the access rights for signle project
44
+ def project_access(project)
45
+ get("/projects/#{project}/access")
46
+ end
47
+
48
+ def create_project_access(project, permissions)
49
+ access = {
50
+ 'add' => permissions
51
+ }
52
+ post("/projects/#{project}/access", access)
53
+ end
54
+
55
+ def remove_project_access(project, permissions)
56
+ access = {
57
+ 'remove' => permissions
58
+ }
59
+ post("/projects/#{project}/access", access)
60
+ end
61
+
62
+ ##
63
+ # Retrieves a commit of a project.
64
+ def project_commit(project, commit_id)
65
+ get("/projects/#{project}/commits/#{commit_id}")
66
+ end
67
+
68
+ def project_file(project, commit_id, file_id)
69
+ get("/projects/#{project}/commits/#{commit_id}/files/#{file_id}/content")
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gerry
4
+ module Api
5
+ module Request # :nodoc:
6
+ class RequestError < StandardError
7
+ end
8
+
9
+ # Get the mapped options.
10
+ #
11
+ # @param [Array] or [Hash] options the query parameters.
12
+ # @return [String] the mapped options.
13
+ def map_options(options)
14
+ if options.is_a?(Array)
15
+ options.map { |v| "#{v}" }.join('&')
16
+ elsif options.is_a?(Hash)
17
+ options.map { |k,v| "#{k}=#{v.join(',')}" }.join('&')
18
+ end
19
+ end
20
+
21
+ def options(body = nil, is_json = true)
22
+ return {} unless body
23
+ default_options = {
24
+ headers: {
25
+ 'Content-Type' => is_json ? 'application/json' : 'text/plain'
26
+ }
27
+ }
28
+ default_options[:body] = is_json ? body.to_json : body
29
+ default_options
30
+ end
31
+
32
+ def get(url)
33
+ response = self.class.get(auth_url(url))
34
+ parse(response)
35
+ end
36
+
37
+ def auth_url(url)
38
+ self.class.default_options[:basic_auth] ? "/a#{url}" : url
39
+ end
40
+
41
+ def put(url, body = nil, is_json = true)
42
+ response = self.class.put(auth_url(url), options(body, is_json))
43
+ parse(response)
44
+ end
45
+
46
+ def post(url, body, is_json = true)
47
+ response = self.class.post(auth_url(url), options(body, is_json))
48
+ parse(response)
49
+ end
50
+
51
+ def delete(url)
52
+ response = self.class.delete(auth_url(url))
53
+ parse(response)
54
+ end
55
+
56
+ private
57
+
58
+ def parse(response)
59
+ unless /2[0-9][0-9]/.match(response.code.to_s)
60
+ raise_request_error(response)
61
+ end
62
+ return nil if !response.body || response.body.size.zero?
63
+
64
+ source = remove_magic_prefix(response.body)
65
+ if source.lines.count == 1 && !source.start_with?('{') && !source.start_with?('[')
66
+ # Work around the JSON gem not being able to parse top-level values, see
67
+ # https://github.com/flori/json/issues/206.
68
+ source.gsub!(/^"|"$/, '')
69
+ else
70
+ JSON.parse(source)
71
+ end
72
+ end
73
+
74
+ def raise_request_error(response)
75
+ raise RequestError.new("There was a request error! Response was: #{response.message}")
76
+ end
77
+
78
+ def remove_magic_prefix(response_body)
79
+ # We need to strip the magic prefix from the first line of the response, see
80
+ # https://gerrit-review.googlesource.com/Documentation/rest-api.html#output.
81
+ # magic prefix: )]}
82
+ response_body[4..-1].strip!
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'httparty'
4
+ require 'json'
5
+
6
+ require_relative 'api/access'
7
+ require_relative 'api/accounts'
8
+ require_relative 'api/changes'
9
+ require_relative 'api/groups'
10
+ require_relative 'api/projects'
11
+ require_relative 'api/request'
12
+ require_relative 'api/branches'
13
+
14
+
15
+ module Gerry
16
+ ##
17
+ # Client for gerrit request api
18
+ #
19
+ # - for anonymout user
20
+ # client = Gerry::Client.new('http://gerrit.example.com')
21
+ # - for user/password
22
+ # client = Gerry::Client.new('http://gerrit.example.com', 'username', 'password')
23
+ #
24
+ #
25
+
26
+ class Client
27
+ include HTTParty
28
+ headers 'Accept' => 'application/json'
29
+
30
+ include Api::Access
31
+ include Api::Accounts
32
+ include Api::Changes
33
+ include Api::Groups
34
+ include Api::Projects
35
+ include Api::Branches
36
+ include Api::Request
37
+
38
+ def set_auth_type(auth_type)
39
+ warn 'set_auth_type is deprecated. digest auth is no longer supported'
40
+ end
41
+
42
+ def initialize(url, username = nil, password = nil)
43
+ self.class.base_uri(url)
44
+
45
+ if username && password
46
+ @username = username
47
+ @password = password
48
+ else
49
+ require 'netrc'
50
+ @username, @password = Netrc.read[URI.parse(url).host]
51
+ end
52
+ if @username && @password
53
+ self.class.basic_auth(@username, @password)
54
+ end
55
+ end
56
+ end
57
+ end
58
+
@@ -0,0 +1,5 @@
1
+ module Gerry
2
+
3
+ VERSION = "0.1.6"
4
+
5
+ end
data/lib/gerry.rb ADDED
@@ -0,0 +1,12 @@
1
+ require_relative 'gerry/client'
2
+
3
+ module Gerry
4
+ class << self
5
+ # Alias for Gerry::Client.new
6
+ #
7
+ # @return [Gerry::Client]
8
+ def new(url, username = nil, password = nil)
9
+ Gerry::Client.new(url, username, password)
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ describe '.list_access_rights' do
4
+ it 'lists the access rights for projects' do
5
+ projects = ['All-Projects', 'MyProject']
6
+ stub = stub_get("/access/?project=#{projects.join('&project=')}", 'access_rights.json')
7
+
8
+ client = MockGerry.new
9
+ access_rights = client.access(projects)
10
+ expect(stub).to have_been_requested
11
+
12
+ expect(access_rights['All-Projects']['revision']).to eq('edd453d18e08640e67a8c9a150cec998ed0ac9aa')
13
+ expect(access_rights['MyProject']['revision']).to eq('61157ed63e14d261b6dca40650472a9b0bd88474')
14
+ end
15
+ end
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+
3
+ describe '.account_capabilities' do
4
+ it 'should fetch all account capabilities' do
5
+ stub = stub_get('/accounts/self/capabilities', 'capabilities.json')
6
+
7
+ client = MockGerry.new
8
+ capabilities = client.account_capabilities
9
+
10
+ expect(capabilities['queryLimit']['min']).to eq(0)
11
+ expect(capabilities['queryLimit']['max']).to eq(500)
12
+ end
13
+
14
+ it 'should fetch some account capabilities' do
15
+ stub = stub_get('/accounts/self/capabilities?q=createAccount&q=createGroup', 'query_capabilities.json')
16
+
17
+ client = MockGerry.new
18
+ capabilities = client.account_capabilities(['q=createAccount', 'q=createGroup'])
19
+ expect(stub).to have_been_requested
20
+
21
+ expect(capabilities['createAccount']).to eq(true)
22
+ expect(capabilities['createGroup']).to eq(true)
23
+ end
24
+ end
25
+
26
+ describe '.groups_for_account' do
27
+ it "fetches all groups for which the account is a member" do
28
+ user = "jane.roe@example.com"
29
+
30
+ stub = stub_get("/accounts/#{user}/groups/", "account_groups.json")
31
+
32
+ client = MockGerry.new
33
+ new_group = client.groups_for_account(user)
34
+ expect(stub).to have_been_requested
35
+ end
36
+ end
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'branches' do
4
+ before(:all) do
5
+ @client = MockGerry.new
6
+ end
7
+
8
+ it 'fetchs all branches' do
9
+ stub = stub_get('/projects/foo/branches', 'project_branches.json')
10
+
11
+ groups = @client.branches('foo')
12
+ expect(stub).to have_been_requested
13
+
14
+ expect(groups.size).to eq(3)
15
+ expect(groups.first.fetch('ref')).to eq('master')
16
+ end
17
+
18
+ it 'create branch' do
19
+ body = {
20
+ ref: 'master'
21
+ }
22
+ response = %Q<)]}'
23
+ {
24
+ "ref": "/refs/heads/stable",
25
+ "revision": "b43",
26
+ "can_delete": true
27
+ }
28
+ >
29
+ stub = stub_put('/projects/foo/branches/stable', body, response)
30
+ branch = @client.create_branch('foo', 'master', 'stable')
31
+
32
+ expect(stub).to have_been_requested
33
+
34
+ expect(branch.fetch('ref')).to eql('/refs/heads/stable')
35
+ end
36
+ end
@@ -0,0 +1,55 @@
1
+ require 'spec_helper'
2
+
3
+ describe '.changes' do
4
+ it 'should fetch all changes' do
5
+ stub = stub_get('/changes/', 'changes.json')
6
+
7
+ client = MockGerry.new
8
+ changes = client.changes
9
+
10
+ expect(stub).to have_been_requested
11
+
12
+ expect(changes[0]['project']).to eq('awesome')
13
+ expect(changes[0]['branch']).to eq('master')
14
+
15
+ expect(changes[1]['project']).to eq('clean')
16
+ expect(changes[1]['subject']).to eq('Refactor code')
17
+ expect(changes[1]['owner']['name']).to eq('Batman')
18
+ end
19
+
20
+ it 'should fetch all changes in batches' do
21
+ stub_batch_0 = stub_get('/changes/', 'changes_batch_0.json')
22
+ stub_batch_1 = stub_get('/changes/?S=1', 'changes_batch_1.json')
23
+ stub_batch_2 = stub_get('/changes/?S=2', 'changes_batch_2.json')
24
+
25
+ client = MockGerry.new
26
+ changes = client.changes
27
+
28
+ expect(stub_batch_0).to have_been_requested
29
+ expect(stub_batch_1).to have_been_requested
30
+
31
+ expect(changes[0]['project']).to eq('awesome')
32
+ expect(changes[0]['branch']).to eq('master')
33
+ expect(changes[0]['owner']['name']).to eq('The Duke')
34
+
35
+ expect(changes[1]['project']).to eq('clean')
36
+ expect(changes[1]['subject']).to eq('Refactor code')
37
+ expect(changes[1]['owner']['name']).to eq('Batman')
38
+
39
+ expect(changes[2]['project']).to eq('X')
40
+ expect(changes[2]['subject']).to eq('Remove unused imports')
41
+ expect(changes[2]['owner']['name']).to eq('Bill')
42
+ end
43
+
44
+ it 'should fetch all open changes' do
45
+ stub = stub_get('/changes/?q=is:open+owner:self', 'open_changes.json')
46
+
47
+ client = MockGerry.new
48
+ changes = client.changes(['q=is:open+owner:self'])
49
+
50
+ expect(stub).to have_been_requested
51
+
52
+ expect(changes[0]['status']).to eq('OPEN')
53
+ expect(changes[0]['owner']['name']).to eq('The Duke')
54
+ end
55
+ end
@@ -0,0 +1,2 @@
1
+ )]}'
2
+ "Hello World!"