tinybucket2 1.0.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 +7 -0
- data/.rubocop.yml +86 -0
- data/Gemfile +32 -0
- data/LICENSE +21 -0
- data/README.md +387 -0
- data/Rakefile +47 -0
- data/lib/faraday_middleware/follow_oauth_redirects.rb +71 -0
- data/lib/tinybucket.rb +76 -0
- data/lib/tinybucket/api.rb +26 -0
- data/lib/tinybucket/api/base_api.rb +44 -0
- data/lib/tinybucket/api/branch_restrictions_api.rb +51 -0
- data/lib/tinybucket/api/branches_api.rb +48 -0
- data/lib/tinybucket/api/build_status_api.rb +69 -0
- data/lib/tinybucket/api/comments_api.rb +81 -0
- data/lib/tinybucket/api/commits_api.rb +97 -0
- data/lib/tinybucket/api/diff_api.rb +40 -0
- data/lib/tinybucket/api/helper.rb +27 -0
- data/lib/tinybucket/api/helper/api_helper.rb +39 -0
- data/lib/tinybucket/api/helper/branch_restrictions_helper.rb +29 -0
- data/lib/tinybucket/api/helper/branches_helper.rb +29 -0
- data/lib/tinybucket/api/helper/build_status_helper.rb +46 -0
- data/lib/tinybucket/api/helper/comments_helper.rb +51 -0
- data/lib/tinybucket/api/helper/commits_helper.rb +42 -0
- data/lib/tinybucket/api/helper/diff_helper.rb +31 -0
- data/lib/tinybucket/api/helper/issues_helper.rb +29 -0
- data/lib/tinybucket/api/helper/projects_helper.rb +28 -0
- data/lib/tinybucket/api/helper/pull_requests_helper.rb +58 -0
- data/lib/tinybucket/api/helper/repo_helper.rb +31 -0
- data/lib/tinybucket/api/helper/repos_helper.rb +23 -0
- data/lib/tinybucket/api/helper/team_helper.rb +45 -0
- data/lib/tinybucket/api/helper/user_helper.rb +33 -0
- data/lib/tinybucket/api/issues_api.rb +48 -0
- data/lib/tinybucket/api/projects_api.rb +26 -0
- data/lib/tinybucket/api/pull_requests_api.rb +117 -0
- data/lib/tinybucket/api/repo_api.rb +56 -0
- data/lib/tinybucket/api/repos_api.rb +28 -0
- data/lib/tinybucket/api/team_api.rb +91 -0
- data/lib/tinybucket/api/user_api.rb +66 -0
- data/lib/tinybucket/api_factory.rb +21 -0
- data/lib/tinybucket/client.rb +107 -0
- data/lib/tinybucket/config.rb +10 -0
- data/lib/tinybucket/connection.rb +84 -0
- data/lib/tinybucket/constants.rb +7 -0
- data/lib/tinybucket/enumerator.rb +47 -0
- data/lib/tinybucket/error.rb +12 -0
- data/lib/tinybucket/error/base_error.rb +14 -0
- data/lib/tinybucket/error/conflict.rb +8 -0
- data/lib/tinybucket/error/not_found.rb +8 -0
- data/lib/tinybucket/error/service_error.rb +26 -0
- data/lib/tinybucket/iterator.rb +79 -0
- data/lib/tinybucket/model.rb +25 -0
- data/lib/tinybucket/model/base.rb +45 -0
- data/lib/tinybucket/model/branch.rb +48 -0
- data/lib/tinybucket/model/branch_restriction.rb +46 -0
- data/lib/tinybucket/model/build_status.rb +57 -0
- data/lib/tinybucket/model/comment.rb +67 -0
- data/lib/tinybucket/model/commit.rb +114 -0
- data/lib/tinybucket/model/concerns.rb +19 -0
- data/lib/tinybucket/model/concerns/acceptable_attributes.rb +34 -0
- data/lib/tinybucket/model/concerns/api_callable.rb +21 -0
- data/lib/tinybucket/model/concerns/enumerable.rb +20 -0
- data/lib/tinybucket/model/concerns/reloadable.rb +41 -0
- data/lib/tinybucket/model/concerns/repository_keys.rb +45 -0
- data/lib/tinybucket/model/error_response.rb +24 -0
- data/lib/tinybucket/model/issue.rb +48 -0
- data/lib/tinybucket/model/page.rb +45 -0
- data/lib/tinybucket/model/profile.rb +70 -0
- data/lib/tinybucket/model/project.rb +44 -0
- data/lib/tinybucket/model/pull_request.rb +160 -0
- data/lib/tinybucket/model/repository.rb +219 -0
- data/lib/tinybucket/model/team.rb +96 -0
- data/lib/tinybucket/null_logger.rb +37 -0
- data/lib/tinybucket/parser.rb +15 -0
- data/lib/tinybucket/parser/collection_parser.rb +17 -0
- data/lib/tinybucket/parser/object_parser.rb +17 -0
- data/lib/tinybucket/request.rb +59 -0
- data/lib/tinybucket/resource.rb +75 -0
- data/lib/tinybucket/resource/base.rb +35 -0
- data/lib/tinybucket/resource/branch_restrictions.rb +47 -0
- data/lib/tinybucket/resource/branches.rb +35 -0
- data/lib/tinybucket/resource/commit/base.rb +14 -0
- data/lib/tinybucket/resource/commit/build_statuses.rb +50 -0
- data/lib/tinybucket/resource/commit/comments.rb +34 -0
- data/lib/tinybucket/resource/commits.rb +46 -0
- data/lib/tinybucket/resource/forks.rb +24 -0
- data/lib/tinybucket/resource/issues.rb +35 -0
- data/lib/tinybucket/resource/projects.rb +49 -0
- data/lib/tinybucket/resource/pull_request/base.rb +20 -0
- data/lib/tinybucket/resource/pull_request/comments.rb +32 -0
- data/lib/tinybucket/resource/pull_request/commits.rb +19 -0
- data/lib/tinybucket/resource/pull_requests.rb +50 -0
- data/lib/tinybucket/resource/repos.rb +40 -0
- data/lib/tinybucket/resource/team/base.rb +24 -0
- data/lib/tinybucket/resource/team/followers.rb +15 -0
- data/lib/tinybucket/resource/team/following.rb +15 -0
- data/lib/tinybucket/resource/team/members.rb +15 -0
- data/lib/tinybucket/resource/team/repos.rb +15 -0
- data/lib/tinybucket/resource/teams.rb +22 -0
- data/lib/tinybucket/resource/user/base.rb +26 -0
- data/lib/tinybucket/resource/user/followers.rb +15 -0
- data/lib/tinybucket/resource/user/following.rb +15 -0
- data/lib/tinybucket/resource/user/repos.rb +15 -0
- data/lib/tinybucket/resource/watchers.rb +24 -0
- data/lib/tinybucket/response.rb +9 -0
- data/lib/tinybucket/response/handler.rb +23 -0
- data/lib/tinybucket/version.rb +5 -0
- data/tinybucket.gemspec +30 -0
- metadata +248 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Tinybucket
|
|
4
|
+
class NullLogger
|
|
5
|
+
attr_accessor :level
|
|
6
|
+
|
|
7
|
+
def fatal(_progname = nil, &_block); end
|
|
8
|
+
|
|
9
|
+
def fatal?
|
|
10
|
+
false
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def error(_progname = nil, &_block); end
|
|
14
|
+
|
|
15
|
+
def error?
|
|
16
|
+
false
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def warn(_progname = nil, &_block); end
|
|
20
|
+
|
|
21
|
+
def warn?
|
|
22
|
+
false
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def info(_progname = nil, &_block); end
|
|
26
|
+
|
|
27
|
+
def info?
|
|
28
|
+
false
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def debug(_progname = nil, &_block); end
|
|
32
|
+
|
|
33
|
+
def debug?
|
|
34
|
+
false
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Tinybucket
|
|
4
|
+
module Parser
|
|
5
|
+
class CollectionParser < FaradayMiddleware::ResponseMiddleware
|
|
6
|
+
define_parser do |hash, parser_options|
|
|
7
|
+
cls = parser_options[:model_class]
|
|
8
|
+
throw 'model_class option does not provided' unless cls
|
|
9
|
+
::Tinybucket::Model::Page.new(hash, cls)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def parse_response?(env)
|
|
13
|
+
env[:body].is_a? Hash
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Tinybucket
|
|
4
|
+
module Parser
|
|
5
|
+
class ObjectParser < FaradayMiddleware::ResponseMiddleware
|
|
6
|
+
define_parser do |hash, parser_options|
|
|
7
|
+
cls = parser_options[:model_class]
|
|
8
|
+
throw 'model_class option does not provided' unless cls
|
|
9
|
+
cls.new(hash)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def parse_response?(env)
|
|
13
|
+
env[:body].is_a? Hash
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Tinybucket
|
|
4
|
+
module Request
|
|
5
|
+
protected
|
|
6
|
+
|
|
7
|
+
def get_path(path, params = {}, parser = nil, options = {})
|
|
8
|
+
request(:get, path, params, parser, options)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def patch_path(path, params = {}, parser = nil, options = {})
|
|
12
|
+
request(:patch, path, params, parser, options)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def post_path(path, params = {}, parser = nil, options = {})
|
|
16
|
+
request(:post, path, params, parser, options)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def put_path(path, params = {}, parser = nil, options = {})
|
|
20
|
+
request(:put, path, params, parser, options)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def delete_path(path, params = {}, parser = nil, options = {})
|
|
24
|
+
request(:delete, path, params, parser, options)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
def request(method, path, params, parser, options)
|
|
30
|
+
conn = connection(parser, options)
|
|
31
|
+
|
|
32
|
+
path = (conn.path_prefix + path).gsub(%r{//}, '/') \
|
|
33
|
+
if conn.path_prefix != '/'
|
|
34
|
+
|
|
35
|
+
response = conn.send(method) do |request|
|
|
36
|
+
case method.intern
|
|
37
|
+
when :get, :delete
|
|
38
|
+
request.body = params.delete('data') if params.key?('data')
|
|
39
|
+
request.url(path, params)
|
|
40
|
+
when :post, :put, :patch
|
|
41
|
+
request.path = path
|
|
42
|
+
request.body = extract_data_from_params(params) unless params.empty?
|
|
43
|
+
else
|
|
44
|
+
raise ArgumentError, 'unknown http method: ' + method
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
response.body
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def extract_data_from_params(params)
|
|
52
|
+
if params.key?('data') && !params['data'].nil?
|
|
53
|
+
params['data']
|
|
54
|
+
else
|
|
55
|
+
params
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Tinybucket
|
|
4
|
+
module Resource
|
|
5
|
+
extend ActiveSupport::Autoload
|
|
6
|
+
|
|
7
|
+
[
|
|
8
|
+
:Base,
|
|
9
|
+
:Branches,
|
|
10
|
+
:BranchRestrictions,
|
|
11
|
+
:Commits,
|
|
12
|
+
:Forks,
|
|
13
|
+
:OwnersRepos,
|
|
14
|
+
:Projects,
|
|
15
|
+
:PublicRepos,
|
|
16
|
+
:PullRequests,
|
|
17
|
+
:Repos,
|
|
18
|
+
:Teams,
|
|
19
|
+
:Watchers
|
|
20
|
+
].each do |klass_name|
|
|
21
|
+
autoload klass_name
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
module Team
|
|
25
|
+
extend ActiveSupport::Autoload
|
|
26
|
+
|
|
27
|
+
[
|
|
28
|
+
:Base,
|
|
29
|
+
:Followers,
|
|
30
|
+
:Following,
|
|
31
|
+
:Members,
|
|
32
|
+
:Repos
|
|
33
|
+
].each do |klass_name|
|
|
34
|
+
autoload klass_name
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
module User
|
|
39
|
+
extend ActiveSupport::Autoload
|
|
40
|
+
|
|
41
|
+
[
|
|
42
|
+
:Base,
|
|
43
|
+
:Followers,
|
|
44
|
+
:Following,
|
|
45
|
+
:Repos
|
|
46
|
+
].each do |klass_name|
|
|
47
|
+
autoload klass_name
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
module PullRequest
|
|
52
|
+
extend ActiveSupport::Autoload
|
|
53
|
+
|
|
54
|
+
[
|
|
55
|
+
:Base,
|
|
56
|
+
:Commits,
|
|
57
|
+
:Comments
|
|
58
|
+
].each do |klass_name|
|
|
59
|
+
autoload klass_name
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
module Commit
|
|
64
|
+
extend ActiveSupport::Autoload
|
|
65
|
+
|
|
66
|
+
[
|
|
67
|
+
:Base,
|
|
68
|
+
:BuildStatuses,
|
|
69
|
+
:Comments
|
|
70
|
+
].each do |klass_name|
|
|
71
|
+
autoload klass_name
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Tinybucket
|
|
4
|
+
module Resource
|
|
5
|
+
class Base
|
|
6
|
+
include Tinybucket::Model::Concerns::ApiCallable
|
|
7
|
+
|
|
8
|
+
protected
|
|
9
|
+
|
|
10
|
+
def method_missing(method, *args)
|
|
11
|
+
enum = enumerator
|
|
12
|
+
return super unless enum.respond_to?(method)
|
|
13
|
+
|
|
14
|
+
enum.send(method, *args) do |m|
|
|
15
|
+
block_given? ? yield(m) : m
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def respond_to_missing?(symbol, include_all)
|
|
20
|
+
enumerator.respond_to?(symbol, include_all)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def create_enumerator(api_client, method, *args, &block)
|
|
24
|
+
iter = Tinybucket::Iterator.new(api_client, method, *args)
|
|
25
|
+
Tinybucket::Enumerator.new(iter, block)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def inject_repo_keys(model, repo_keys)
|
|
29
|
+
return model unless model.respond_to?(:repo_keys=)
|
|
30
|
+
|
|
31
|
+
model.tap { |m| m.repo_keys = repo_keys }
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Tinybucket
|
|
4
|
+
module Resource
|
|
5
|
+
class BranchRestrictions < Base
|
|
6
|
+
# Constructor
|
|
7
|
+
#
|
|
8
|
+
# @param repo [Tinybucket::Model::Repository]
|
|
9
|
+
# @param options [Hash]
|
|
10
|
+
def initialize(repo, options)
|
|
11
|
+
@repo = repo
|
|
12
|
+
@args = [options]
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Create new BranchRestriction on the repository.
|
|
16
|
+
#
|
|
17
|
+
# @param _options [Hash]
|
|
18
|
+
# @return [Tinybucket::Model::BranchRestriction]
|
|
19
|
+
def create(_options)
|
|
20
|
+
raise NotImplementedError
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Find the BranchRestriction on the repository.
|
|
24
|
+
#
|
|
25
|
+
# @param restriction_id [String]
|
|
26
|
+
# @param options [Hash]
|
|
27
|
+
# @return [Tinybucket::Model::BranchRestriction]
|
|
28
|
+
def find(restriction_id, options = {})
|
|
29
|
+
restrictions_api.find(restriction_id, options).tap do |m|
|
|
30
|
+
inject_repo_keys(m, @repo.repo_keys)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
def restrictions_api
|
|
37
|
+
create_api('BranchRestrictions', @repo.repo_keys)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def enumerator
|
|
41
|
+
create_enumerator(restrictions_api, :list, *@args) do |m|
|
|
42
|
+
inject_repo_keys(m, @repo.repo_keys)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Tinybucket
|
|
4
|
+
module Resource
|
|
5
|
+
class Branches < Tinybucket::Resource::Base
|
|
6
|
+
def initialize(repo, options)
|
|
7
|
+
@repo = repo
|
|
8
|
+
@args = [options]
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# Find the branch
|
|
12
|
+
#
|
|
13
|
+
# @param branch [String]
|
|
14
|
+
# @param options [Hash]
|
|
15
|
+
# @return [Tinybucket::Model::Branch]
|
|
16
|
+
def find(branch, options = {})
|
|
17
|
+
branches_api.find(branch, options).tap do |m|
|
|
18
|
+
inject_repo_keys(m, @repo.repo_keys)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
def branches_api
|
|
25
|
+
create_api('Branches', @repo.repo_keys)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def enumerator
|
|
29
|
+
create_enumerator(branches_api, :list, *@args) do |m|
|
|
30
|
+
inject_repo_keys(m, @repo.repo_keys)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Tinybucket
|
|
4
|
+
module Resource
|
|
5
|
+
module Commit
|
|
6
|
+
class BuildStatuses < Tinybucket::Resource::Commit::Base
|
|
7
|
+
# Get the build status for the commit
|
|
8
|
+
#
|
|
9
|
+
# @param key [String]
|
|
10
|
+
# @param options [Hash]
|
|
11
|
+
# @option options [String] :state
|
|
12
|
+
# @option options [String] :key
|
|
13
|
+
# @option options [String] :name
|
|
14
|
+
# @option options [String] :url
|
|
15
|
+
# @option options [String] :description
|
|
16
|
+
# @return [Tinybucket::Model::BuildStatus]
|
|
17
|
+
def find(key, options = {})
|
|
18
|
+
build_status_api.find(@commit.hash, key, options).tap do |m|
|
|
19
|
+
m.revision = @commit.hash
|
|
20
|
+
m.repo_keys = @commit.repo_keys
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Create a build status for the commit
|
|
25
|
+
#
|
|
26
|
+
# @param key [String]
|
|
27
|
+
# @param options [Hash]
|
|
28
|
+
# @return [Tinybucket::Model::BuildStatus]
|
|
29
|
+
def create(key, options)
|
|
30
|
+
build_status_api.post(@commit.hash, key, options).tap do |m|
|
|
31
|
+
m.revision = @commit.hash
|
|
32
|
+
m.repo_keys = @commit.repo_keys
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
|
|
38
|
+
def build_status_api
|
|
39
|
+
create_api('BuildStatus', @commit.repo_keys).tap do |api|
|
|
40
|
+
api.revision = @commit.hash
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def enumerator
|
|
45
|
+
create_enumerator(build_status_api, :list, *@args)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Tinybucket
|
|
4
|
+
module Resource
|
|
5
|
+
module Commit
|
|
6
|
+
class Comments < Tinybucket::Resource::Commit::Base
|
|
7
|
+
# Get the specific commit comment which associate with the commit.
|
|
8
|
+
#
|
|
9
|
+
# @param comment_id [String]
|
|
10
|
+
# @param options [Hash]
|
|
11
|
+
# @return [Tinybucket::Model::Comment]
|
|
12
|
+
def find(comment_id, options = {})
|
|
13
|
+
comments_api.find(comment_id, options).tap do |m|
|
|
14
|
+
m.repo_keys = @commit.repo_keys
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
def comments_api
|
|
21
|
+
create_api('Comments', @commit.repo_keys).tap do |api|
|
|
22
|
+
api.commented_to = @commit
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def enumerator
|
|
27
|
+
create_enumerator(comments_api, :list, *@args) do |m|
|
|
28
|
+
inject_repo_keys(m, @commit.repo_keys)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|