gitlab-akerl 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (201) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +20 -0
  3. data/.prospectus +11 -0
  4. data/.travis.yml +8 -0
  5. data/CHANGELOG.md +229 -0
  6. data/CONTRIBUTING.md +195 -0
  7. data/Gemfile +4 -0
  8. data/LICENSE.txt +24 -0
  9. data/README.md +192 -0
  10. data/Rakefile +9 -0
  11. data/bin/console +10 -0
  12. data/bin/setup +6 -0
  13. data/exe/gitlab +7 -0
  14. data/gitlab-akerl.gemspec +31 -0
  15. data/lib/gitlab.rb +45 -0
  16. data/lib/gitlab/api.rb +19 -0
  17. data/lib/gitlab/cli.rb +89 -0
  18. data/lib/gitlab/cli_helpers.rb +241 -0
  19. data/lib/gitlab/client.rb +48 -0
  20. data/lib/gitlab/client/branches.rb +91 -0
  21. data/lib/gitlab/client/build_triggers.rb +51 -0
  22. data/lib/gitlab/client/build_variables.rb +66 -0
  23. data/lib/gitlab/client/builds.rb +106 -0
  24. data/lib/gitlab/client/commits.rb +121 -0
  25. data/lib/gitlab/client/groups.rb +144 -0
  26. data/lib/gitlab/client/issues.rb +113 -0
  27. data/lib/gitlab/client/labels.rb +57 -0
  28. data/lib/gitlab/client/merge_requests.rb +168 -0
  29. data/lib/gitlab/client/milestones.rb +78 -0
  30. data/lib/gitlab/client/namespaces.rb +20 -0
  31. data/lib/gitlab/client/notes.rb +161 -0
  32. data/lib/gitlab/client/pipelines.rb +68 -0
  33. data/lib/gitlab/client/projects.rb +471 -0
  34. data/lib/gitlab/client/repositories.rb +78 -0
  35. data/lib/gitlab/client/repository_files.rb +88 -0
  36. data/lib/gitlab/client/runners.rb +115 -0
  37. data/lib/gitlab/client/services.rb +50 -0
  38. data/lib/gitlab/client/snippets.rb +91 -0
  39. data/lib/gitlab/client/system_hooks.rb +59 -0
  40. data/lib/gitlab/client/tags.rb +96 -0
  41. data/lib/gitlab/client/users.rb +250 -0
  42. data/lib/gitlab/configuration.rb +55 -0
  43. data/lib/gitlab/error.rb +85 -0
  44. data/lib/gitlab/file_response.rb +46 -0
  45. data/lib/gitlab/help.rb +95 -0
  46. data/lib/gitlab/objectified_hash.rb +34 -0
  47. data/lib/gitlab/page_links.rb +33 -0
  48. data/lib/gitlab/paginated_response.rb +97 -0
  49. data/lib/gitlab/request.rb +117 -0
  50. data/lib/gitlab/shell.rb +84 -0
  51. data/lib/gitlab/shell_history.rb +59 -0
  52. data/lib/gitlab/version.rb +3 -0
  53. data/spec/fixtures/branch.json +1 -0
  54. data/spec/fixtures/branch_delete.json +3 -0
  55. data/spec/fixtures/branches.json +1 -0
  56. data/spec/fixtures/build.json +38 -0
  57. data/spec/fixtures/build_artifacts.json +0 -0
  58. data/spec/fixtures/build_cancel.json +24 -0
  59. data/spec/fixtures/build_erase.json +24 -0
  60. data/spec/fixtures/build_retry.json +24 -0
  61. data/spec/fixtures/builds.json +78 -0
  62. data/spec/fixtures/builds_commits.json +64 -0
  63. data/spec/fixtures/compare_merge_request_diff.json +31 -0
  64. data/spec/fixtures/error_already_exists.json +1 -0
  65. data/spec/fixtures/error_project_not_found.json +1 -0
  66. data/spec/fixtures/get_repository_file.json +1 -0
  67. data/spec/fixtures/git_hook.json +1 -0
  68. data/spec/fixtures/group.json +60 -0
  69. data/spec/fixtures/group_create.json +1 -0
  70. data/spec/fixtures/group_create_with_description.json +1 -0
  71. data/spec/fixtures/group_delete.json +1 -0
  72. data/spec/fixtures/group_member.json +1 -0
  73. data/spec/fixtures/group_member_delete.json +1 -0
  74. data/spec/fixtures/group_member_edit.json +1 -0
  75. data/spec/fixtures/group_members.json +1 -0
  76. data/spec/fixtures/group_projects.json +44 -0
  77. data/spec/fixtures/group_search.json +2 -0
  78. data/spec/fixtures/groups.json +2 -0
  79. data/spec/fixtures/issue.json +1 -0
  80. data/spec/fixtures/issues.json +1 -0
  81. data/spec/fixtures/key.json +1 -0
  82. data/spec/fixtures/keys.json +1 -0
  83. data/spec/fixtures/label.json +1 -0
  84. data/spec/fixtures/labels.json +1 -0
  85. data/spec/fixtures/merge_request.json +1 -0
  86. data/spec/fixtures/merge_request_changes.json +1 -0
  87. data/spec/fixtures/merge_request_comment.json +1 -0
  88. data/spec/fixtures/merge_request_comments.json +1 -0
  89. data/spec/fixtures/merge_request_commits.json +1 -0
  90. data/spec/fixtures/merge_requests.json +1 -0
  91. data/spec/fixtures/milestone.json +1 -0
  92. data/spec/fixtures/milestone_issues.json +1 -0
  93. data/spec/fixtures/milestones.json +1 -0
  94. data/spec/fixtures/namespaces.json +1 -0
  95. data/spec/fixtures/note.json +1 -0
  96. data/spec/fixtures/notes.json +1 -0
  97. data/spec/fixtures/pipeline.json +23 -0
  98. data/spec/fixtures/pipeline_cancel.json +23 -0
  99. data/spec/fixtures/pipeline_create.json +23 -0
  100. data/spec/fixtures/pipeline_retry.json +23 -0
  101. data/spec/fixtures/pipelines.json +48 -0
  102. data/spec/fixtures/project.json +1 -0
  103. data/spec/fixtures/project_commit.json +13 -0
  104. data/spec/fixtures/project_commit_comment.json +1 -0
  105. data/spec/fixtures/project_commit_comments.json +1 -0
  106. data/spec/fixtures/project_commit_diff.json +10 -0
  107. data/spec/fixtures/project_commit_status.json +42 -0
  108. data/spec/fixtures/project_commits.json +1 -0
  109. data/spec/fixtures/project_edit.json +21 -0
  110. data/spec/fixtures/project_events.json +1 -0
  111. data/spec/fixtures/project_for_user.json +1 -0
  112. data/spec/fixtures/project_fork.json +50 -0
  113. data/spec/fixtures/project_fork_link.json +1 -0
  114. data/spec/fixtures/project_forked_for_user.json +50 -0
  115. data/spec/fixtures/project_hook.json +1 -0
  116. data/spec/fixtures/project_hooks.json +1 -0
  117. data/spec/fixtures/project_issues.json +1 -0
  118. data/spec/fixtures/project_key.json +6 -0
  119. data/spec/fixtures/project_keys.json +6 -0
  120. data/spec/fixtures/project_runner_enable.json +7 -0
  121. data/spec/fixtures/project_runners.json +16 -0
  122. data/spec/fixtures/project_search.json +1 -0
  123. data/spec/fixtures/project_star.json +44 -0
  124. data/spec/fixtures/project_tag_annotated.json +1 -0
  125. data/spec/fixtures/project_tag_lightweight.json +1 -0
  126. data/spec/fixtures/project_tags.json +1 -0
  127. data/spec/fixtures/project_unstar.json +44 -0
  128. data/spec/fixtures/project_update_commit_status.json +20 -0
  129. data/spec/fixtures/projects.json +1 -0
  130. data/spec/fixtures/raw_file.json +2 -0
  131. data/spec/fixtures/release_create.json +1 -0
  132. data/spec/fixtures/release_update.json +1 -0
  133. data/spec/fixtures/repository_file.json +1 -0
  134. data/spec/fixtures/runner.json +26 -0
  135. data/spec/fixtures/runner_delete.json +7 -0
  136. data/spec/fixtures/runner_edit.json +26 -0
  137. data/spec/fixtures/runners.json +16 -0
  138. data/spec/fixtures/runners_all.json +30 -0
  139. data/spec/fixtures/service.json +1 -0
  140. data/spec/fixtures/session.json +1 -0
  141. data/spec/fixtures/shell_history.json +2 -0
  142. data/spec/fixtures/snippet.json +1 -0
  143. data/spec/fixtures/snippet_content.json +3 -0
  144. data/spec/fixtures/snippets.json +1 -0
  145. data/spec/fixtures/system_hook.json +1 -0
  146. data/spec/fixtures/system_hooks.json +1 -0
  147. data/spec/fixtures/tag.json +1 -0
  148. data/spec/fixtures/tag_create.json +1 -0
  149. data/spec/fixtures/tag_create_with_description.json +1 -0
  150. data/spec/fixtures/tag_delete.json +1 -0
  151. data/spec/fixtures/tags.json +1 -0
  152. data/spec/fixtures/team_member.json +1 -0
  153. data/spec/fixtures/team_members.json +1 -0
  154. data/spec/fixtures/tree.json +1 -0
  155. data/spec/fixtures/trigger.json +7 -0
  156. data/spec/fixtures/triggers.json +16 -0
  157. data/spec/fixtures/user.json +1 -0
  158. data/spec/fixtures/user_block_unblock.json +1 -0
  159. data/spec/fixtures/user_email.json +1 -0
  160. data/spec/fixtures/user_emails.json +1 -0
  161. data/spec/fixtures/user_search.json +1 -0
  162. data/spec/fixtures/users.json +1 -0
  163. data/spec/fixtures/variable.json +4 -0
  164. data/spec/fixtures/variables.json +10 -0
  165. data/spec/gitlab/cli_helpers_spec.rb +57 -0
  166. data/spec/gitlab/cli_spec.rb +110 -0
  167. data/spec/gitlab/client/branches_spec.rb +99 -0
  168. data/spec/gitlab/client/build_triggers_spec.rb +67 -0
  169. data/spec/gitlab/client/build_variables_spec.rb +86 -0
  170. data/spec/gitlab/client/builds_spec.rb +148 -0
  171. data/spec/gitlab/client/client_spec.rb +11 -0
  172. data/spec/gitlab/client/commits_spec.rb +137 -0
  173. data/spec/gitlab/client/groups_spec.rb +197 -0
  174. data/spec/gitlab/client/issues_spec.rb +138 -0
  175. data/spec/gitlab/client/labels_spec.rb +68 -0
  176. data/spec/gitlab/client/merge_requests_spec.rb +177 -0
  177. data/spec/gitlab/client/milestones_spec.rb +82 -0
  178. data/spec/gitlab/client/namespaces_spec.rb +22 -0
  179. data/spec/gitlab/client/notes_spec.rb +205 -0
  180. data/spec/gitlab/client/pipelines_spec.rb +95 -0
  181. data/spec/gitlab/client/projects_spec.rb +603 -0
  182. data/spec/gitlab/client/repositories_spec.rb +109 -0
  183. data/spec/gitlab/client/repository_files_spec.rb +62 -0
  184. data/spec/gitlab/client/runners_spec.rb +185 -0
  185. data/spec/gitlab/client/services_spec.rb +55 -0
  186. data/spec/gitlab/client/snippets_spec.rb +100 -0
  187. data/spec/gitlab/client/system_hooks_spec.rb +69 -0
  188. data/spec/gitlab/client/tags_spec.rb +109 -0
  189. data/spec/gitlab/client/users_spec.rb +418 -0
  190. data/spec/gitlab/error_spec.rb +45 -0
  191. data/spec/gitlab/file_response_spec.rb +33 -0
  192. data/spec/gitlab/help_spec.rb +46 -0
  193. data/spec/gitlab/objectified_hash_spec.rb +48 -0
  194. data/spec/gitlab/page_links_spec.rb +16 -0
  195. data/spec/gitlab/paginated_response_spec.rb +60 -0
  196. data/spec/gitlab/request_spec.rb +73 -0
  197. data/spec/gitlab/shell_history_spec.rb +53 -0
  198. data/spec/gitlab/shell_spec.rb +80 -0
  199. data/spec/gitlab_spec.rb +97 -0
  200. data/spec/spec_helper.rb +74 -0
  201. metadata +476 -0
@@ -0,0 +1,46 @@
1
+ module Gitlab
2
+ # Wrapper class of file response.
3
+ class FileResponse
4
+ HEADER_CONTENT_DISPOSITION = 'Content-Disposition'.freeze
5
+
6
+ attr_reader :filename
7
+
8
+ def initialize(file)
9
+ @file = file
10
+ end
11
+
12
+ # @return [bool] Always false
13
+ def empty?
14
+ false
15
+ end
16
+
17
+ # @return [Hash] A hash consisting of filename and io object
18
+ def to_hash
19
+ { filename: @filename, data: @file }
20
+ end
21
+ alias_method :to_h, :to_hash
22
+
23
+ # @return [String] Formatted string with the class name, object id and filename.
24
+ def inspect
25
+ "#<#{self.class}:#{object_id} {filename: #{filename.inspect}}>"
26
+ end
27
+
28
+ def method_missing(name, *args, &block)
29
+ if @file.respond_to?(name)
30
+ @file.send(name, *args, &block)
31
+ else
32
+ super
33
+ end
34
+ end
35
+
36
+ def respond_to_missing?(method_name, include_private = false)
37
+ super || @file.respond_to?(method_name, include_private)
38
+ end
39
+
40
+ # Parse filename from the 'Content Disposition' header.
41
+ def parse_headers!(headers)
42
+ @filename = headers[HEADER_CONTENT_DISPOSITION].split("filename=")[1]
43
+ @filename = @filename[1...-1] if @filename[0] == '"' # Unquote filenames
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,95 @@
1
+ require 'gitlab'
2
+ require 'gitlab/cli_helpers'
3
+
4
+ module Gitlab::Help
5
+ extend Gitlab::CLI::Helpers
6
+
7
+ class << self
8
+ # Returns the (modified) help from the 'ri' command or returns an error.
9
+ #
10
+ # @return [String]
11
+ def get_help(cmd)
12
+ cmd_namespace = namespace cmd
13
+
14
+ if cmd_namespace
15
+ ri_output = `#{ri_cmd} -T #{cmd_namespace} 2>&1`.chomp
16
+
17
+ if $CHILD_STATUS == 0
18
+ change_help_output! cmd, ri_output
19
+ yield ri_output if block_given?
20
+
21
+ ri_output
22
+ else
23
+ "Ri docs not found for #{cmd}, please install the docs to use 'help'."
24
+ end
25
+ else
26
+ "Unknown command: #{cmd}."
27
+ end
28
+ end
29
+
30
+ # Finds the location of 'ri' on a system.
31
+ #
32
+ # @return [String]
33
+ def ri_cmd
34
+ which_ri = `which ri`.chomp
35
+ if which_ri.empty?
36
+ fail "'ri' tool not found in $PATH. Please install it to use the help."
37
+ end
38
+
39
+ which_ri
40
+ end
41
+
42
+ # A hash map that contains help topics (Branches, Groups, etc.)
43
+ # and a list of commands that are defined under a topic (create_branch,
44
+ # branches, protect_branch, etc.).
45
+ #
46
+ # @return [Hash<Array>]
47
+ def help_map
48
+ @help_map ||= begin
49
+ actions.each_with_object({}) do |action, hsh|
50
+ key = client.method(action).
51
+ owner.to_s.gsub(/Gitlab::(?:Client::)?/, '')
52
+ hsh[key] ||= []
53
+ hsh[key] << action.to_s
54
+ end
55
+ end
56
+ end
57
+
58
+ # Table with available commands.
59
+ #
60
+ # @return [Terminal::Table]
61
+ def actions_table(topic=nil)
62
+ rows = topic ? help_map[topic] : help_map.keys
63
+ table do |t|
64
+ t.title = topic || "Help Topics"
65
+
66
+ # add_row expects an array and we have strings hence the map.
67
+ rows.sort.map { |r| [r] }.each_with_index do |row, index|
68
+ t.add_row row
69
+ t.add_separator unless rows.size - 1 == index
70
+ end
71
+ end
72
+ end
73
+
74
+ # Returns full namespace of a command (e.g. Gitlab::Client::Branches.cmd)
75
+ def namespace(cmd)
76
+ method_owners.select { |method| method[:name] === cmd }.
77
+ map { |method| method[:owner] + '.' + method[:name] }.
78
+ shift
79
+ end
80
+
81
+ # Massage output from 'ri'.
82
+ def change_help_output!(cmd, output_str)
83
+ output_str.gsub!(/#{cmd}\((.*?)\)/m, cmd + ' \1')
84
+ output_str.gsub!(/\,[\s]*/, ' ')
85
+
86
+ # Ensure @option descriptions are on a single line
87
+ output_str.gsub!(/\n\[/, " \[")
88
+ output_str.gsub!(/\s(@)/, "\n@")
89
+ output_str.gsub!(/(\])\n(\:)/, '\1 \2')
90
+ output_str.gsub!(/(\:.*)(\n)(.*\.)/, '\1 \3')
91
+ output_str.gsub!(/\{(.+)\}/, '"{\1}"')
92
+
93
+ end
94
+ end # class << self
95
+ end
@@ -0,0 +1,34 @@
1
+ module Gitlab
2
+ # Converts hashes to the objects.
3
+ class ObjectifiedHash
4
+ # Creates a new ObjectifiedHash object.
5
+ def initialize(hash)
6
+ @hash = hash
7
+ @data = hash.inject({}) do |data, (key, value)|
8
+ value = ObjectifiedHash.new(value) if value.is_a? Hash
9
+ data[key.to_s] = value
10
+ data
11
+ end
12
+ end
13
+
14
+ # @return [Hash] The original hash.
15
+ def to_hash
16
+ @hash
17
+ end
18
+ alias_method :to_h, :to_hash
19
+
20
+ # @return [String] Formatted string with the class name, object id and original hash.
21
+ def inspect
22
+ "#<#{self.class}:#{object_id} {hash: #{@hash.inspect}}"
23
+ end
24
+
25
+ # Delegate to ObjectifiedHash.
26
+ def method_missing(key)
27
+ @data.key?(key.to_s) ? @data[key.to_s] : nil
28
+ end
29
+
30
+ def respond_to_missing?(method_name, include_private = false)
31
+ @hash.keys.map(&:to_sym).include?(method_name.to_sym) || super
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,33 @@
1
+ module Gitlab
2
+ # Parses link header.
3
+ #
4
+ # @private
5
+ class PageLinks
6
+ HEADER_LINK = 'Link'.freeze
7
+ DELIM_LINKS = ','.freeze
8
+ LINK_REGEX = /<([^>]+)>; rel=\"([^\"]+)\"/
9
+ METAS = %w(last next first prev)
10
+
11
+ attr_accessor(*METAS)
12
+
13
+ def initialize(headers)
14
+ link_header = headers[HEADER_LINK]
15
+
16
+ if link_header && link_header =~ /(next|first|last|prev)/
17
+ extract_links(link_header)
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ def extract_links(header)
24
+ header.split(DELIM_LINKS).each do |link|
25
+ LINK_REGEX.match(link.strip) do |match|
26
+ url, meta = match[1], match[2]
27
+ next if !url || !meta || METAS.index(meta).nil?
28
+ self.send("#{meta}=", url)
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,97 @@
1
+ module Gitlab
2
+ # Wrapper class of paginated response.
3
+ class PaginatedResponse
4
+ attr_accessor :client
5
+
6
+ def initialize(array)
7
+ @array = array
8
+ end
9
+
10
+ def ==(other)
11
+ @array == other
12
+ end
13
+
14
+ def inspect
15
+ @array.inspect
16
+ end
17
+
18
+ def method_missing(name, *args, &block)
19
+ if @array.respond_to?(name)
20
+ @array.send(name, *args, &block)
21
+ else
22
+ super
23
+ end
24
+ end
25
+
26
+ def respond_to_missing?(method_name, include_private = false)
27
+ super || @array.respond_to?(method_name, include_private)
28
+ end
29
+
30
+ def parse_headers!(headers)
31
+ @links = PageLinks.new headers
32
+ end
33
+
34
+ def each_page
35
+ current = self
36
+ yield current
37
+ while current.has_next_page?
38
+ current = current.next_page
39
+ yield current
40
+ end
41
+ end
42
+
43
+ def auto_paginate
44
+ response = block_given? ? nil : []
45
+ each_page do |page|
46
+ if block_given?
47
+ page.each do |item|
48
+ yield item
49
+ end
50
+ else
51
+ response += page
52
+ end
53
+ end
54
+ response
55
+ end
56
+
57
+ def has_last_page?
58
+ !(@links.nil? || @links.last.nil?)
59
+ end
60
+
61
+ def last_page
62
+ return nil if @client.nil? || !has_last_page?
63
+ path = @links.last.sub(/#{@client.endpoint}/, '')
64
+ @client.get(path)
65
+ end
66
+
67
+ def has_first_page?
68
+ !(@links.nil? || @links.first.nil?)
69
+ end
70
+
71
+ def first_page
72
+ return nil if @client.nil? || !has_first_page?
73
+ path = @links.first.sub(/#{@client.endpoint}/, '')
74
+ @client.get(path)
75
+ end
76
+
77
+ def has_next_page?
78
+ !(@links.nil? || @links.next.nil?)
79
+ end
80
+
81
+ def next_page
82
+ return nil if @client.nil? || !has_next_page?
83
+ path = @links.next.sub(/#{@client.endpoint}/, '')
84
+ @client.get(path)
85
+ end
86
+
87
+ def has_prev_page?
88
+ !(@links.nil? || @links.prev.nil?)
89
+ end
90
+
91
+ def prev_page
92
+ return nil if @client.nil? || !has_prev_page?
93
+ path = @links.prev.sub(/#{@client.endpoint}/, '')
94
+ @client.get(path)
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,117 @@
1
+ require 'httparty'
2
+ require 'json'
3
+
4
+ module Gitlab
5
+ # @private
6
+ class Request
7
+ include HTTParty
8
+ format :json
9
+ headers 'Accept' => 'application/json'
10
+ parser proc { |body, _| parse(body) }
11
+
12
+ attr_accessor :private_token, :endpoint
13
+
14
+ # Converts the response body to an ObjectifiedHash.
15
+ def self.parse(body)
16
+ body = decode(body)
17
+
18
+ if body.is_a? Hash
19
+ ObjectifiedHash.new body
20
+ elsif body.is_a? Array
21
+ PaginatedResponse.new(body.collect! { |e| ObjectifiedHash.new(e) })
22
+ elsif body
23
+ true
24
+ elsif !body
25
+ false
26
+ elsif body.nil?
27
+ false
28
+ else
29
+ raise Error::Parsing.new "Couldn't parse a response body"
30
+ end
31
+ end
32
+
33
+ # Decodes a JSON response into Ruby object.
34
+ def self.decode(response)
35
+ JSON.load response
36
+ rescue JSON::ParserError
37
+ raise Error::Parsing.new "The response is not a valid JSON"
38
+ end
39
+
40
+ def get(path, options={})
41
+ set_httparty_config(options)
42
+ set_authorization_header(options)
43
+ validate self.class.get(@endpoint + path, options)
44
+ end
45
+
46
+ def post(path, options={})
47
+ set_httparty_config(options)
48
+ set_authorization_header(options, path)
49
+ validate self.class.post(@endpoint + path, options)
50
+ end
51
+
52
+ def put(path, options={})
53
+ set_httparty_config(options)
54
+ set_authorization_header(options)
55
+ validate self.class.put(@endpoint + path, options)
56
+ end
57
+
58
+ def delete(path, options={})
59
+ set_httparty_config(options)
60
+ set_authorization_header(options)
61
+ validate self.class.delete(@endpoint + path, options)
62
+ end
63
+
64
+ # Checks the response code for common errors.
65
+ # Returns parsed response for successful requests.
66
+ def validate(response)
67
+ error_klass = case response.code
68
+ when 400 then Error::BadRequest
69
+ when 401 then Error::Unauthorized
70
+ when 403 then Error::Forbidden
71
+ when 404 then Error::NotFound
72
+ when 405 then Error::MethodNotAllowed
73
+ when 409 then Error::Conflict
74
+ when 422 then Error::Unprocessable
75
+ when 500 then Error::InternalServerError
76
+ when 502 then Error::BadGateway
77
+ when 503 then Error::ServiceUnavailable
78
+ end
79
+
80
+ fail error_klass.new(response) if error_klass
81
+
82
+ parsed = response.parsed_response
83
+ parsed.client = self if parsed.respond_to?(:client=)
84
+ parsed.parse_headers!(response.headers) if parsed.respond_to?(:parse_headers!)
85
+ parsed
86
+ end
87
+
88
+ # Sets a base_uri and default_params for requests.
89
+ # @raise [Error::MissingCredentials] if endpoint not set.
90
+ def set_request_defaults(sudo=nil)
91
+ self.class.default_params sudo: sudo
92
+ raise Error::MissingCredentials.new("Please set an endpoint to API") unless @endpoint
93
+ self.class.default_params.delete(:sudo) if sudo.nil?
94
+ end
95
+
96
+ private
97
+
98
+ # Sets a PRIVATE-TOKEN or Authorization header for requests.
99
+ # @raise [Error::MissingCredentials] if private_token and auth_token are not set.
100
+ def set_authorization_header(options, path=nil)
101
+ unless path == '/session'
102
+ raise Error::MissingCredentials.new("Please provide a private_token or auth_token for user") unless @private_token
103
+ if @private_token.length <= 20
104
+ options[:headers] = { 'PRIVATE-TOKEN' => @private_token }
105
+ else
106
+ options[:headers] = { 'Authorization' => "Bearer #{@private_token}" }
107
+ end
108
+ end
109
+ end
110
+
111
+ # Set HTTParty configuration
112
+ # @see https://github.com/jnunemaker/httparty
113
+ def set_httparty_config(options)
114
+ options.merge!(httparty) if httparty
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,84 @@
1
+ require 'gitlab'
2
+ require 'gitlab/help'
3
+ require 'gitlab/cli_helpers'
4
+ require 'gitlab/shell_history'
5
+ require 'readline'
6
+ require 'shellwords'
7
+
8
+ class Gitlab::Shell
9
+ extend Gitlab::CLI::Helpers
10
+
11
+ class << self
12
+ attr_reader :arguments, :command
13
+
14
+ def start
15
+ trap('INT') { quit_shell } # capture ctrl-c
16
+ setup
17
+
18
+ while buffer = Readline.readline('gitlab> ')
19
+ begin
20
+ parse_input buffer
21
+
22
+ @arguments.map! { |arg| symbolize_keys(yaml_load(arg)) }
23
+
24
+ case buffer
25
+ when nil, ''
26
+ next
27
+ when 'exit'
28
+ quit_shell
29
+ when /^\bhelp\b+/
30
+ puts help(arguments[0]) { |out| out.gsub!(/Gitlab\./, 'gitlab> ') }
31
+ else
32
+ history << buffer
33
+
34
+ data = execute command, arguments
35
+ output_table command, arguments, data
36
+ end
37
+ rescue => e
38
+ puts e.message
39
+ end
40
+ end
41
+
42
+ quit_shell # save history if user presses ctrl-d
43
+ end
44
+
45
+ def parse_input(buffer)
46
+ buf = Shellwords.shellwords(buffer)
47
+
48
+ @command = buf.shift
49
+ @arguments = buf.count > 0 ? buf : []
50
+ end
51
+
52
+ def setup
53
+ history.load
54
+
55
+ Readline.completion_proc = completion
56
+ Readline.completion_append_character = ' '
57
+ end
58
+
59
+ # Gets called when user hits TAB key to do completion
60
+ def completion
61
+ proc { |str| actions.map(&:to_s).grep(/^#{Regexp.escape(str)}/) }
62
+ end
63
+
64
+ # Execute a given command with arguements
65
+ def execute(cmd=command, args=arguments)
66
+ if actions.include?(cmd.to_sym)
67
+ confirm_command(cmd)
68
+ gitlab_helper(cmd, args)
69
+ else
70
+ fail "Unknown command: #{cmd}. " \
71
+ "See the 'help' for a list of valid commands."
72
+ end
73
+ end
74
+
75
+ def quit_shell
76
+ history.save
77
+ exit
78
+ end
79
+
80
+ def history
81
+ @history ||= History.new
82
+ end
83
+ end # class << self
84
+ end