travis-async-listener 1.8.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (184) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +22 -0
  3. data/README.md +2486 -0
  4. data/Rakefile +63 -0
  5. data/assets/cacert.pem +69 -0
  6. data/assets/init/c.yml +4 -0
  7. data/assets/init/clojure.yml +1 -0
  8. data/assets/init/cpp.yml +4 -0
  9. data/assets/init/erlang.yml +3 -0
  10. data/assets/init/go.yml +4 -0
  11. data/assets/init/groovy.yml +1 -0
  12. data/assets/init/haskell.yml +1 -0
  13. data/assets/init/java.yml +4 -0
  14. data/assets/init/node_js.yml +4 -0
  15. data/assets/init/objective-c.yml +1 -0
  16. data/assets/init/perl.yml +4 -0
  17. data/assets/init/php.yml +4 -0
  18. data/assets/init/python.yml +5 -0
  19. data/assets/init/ruby.yml +6 -0
  20. data/assets/init/scala.yml +4 -0
  21. data/assets/notifications/Travis CI.app/Contents/Info.plist +52 -0
  22. data/assets/notifications/Travis CI.app/Contents/MacOS/Travis CI +0 -0
  23. data/assets/notifications/Travis CI.app/Contents/PkgInfo +1 -0
  24. data/assets/notifications/Travis CI.app/Contents/Resources/Travis CI.icns +0 -0
  25. data/assets/notifications/Travis CI.app/Contents/Resources/en.lproj/Credits.rtf +29 -0
  26. data/assets/notifications/Travis CI.app/Contents/Resources/en.lproj/InfoPlist.strings +0 -0
  27. data/assets/notifications/Travis CI.app/Contents/Resources/en.lproj/MainMenu.nib +0 -0
  28. data/assets/notifications/Travis CI.app/Contents/_CodeSignature/CodeResources +173 -0
  29. data/assets/notifications/Travis CI.app/Contents/embedded.provisionprofile +0 -0
  30. data/assets/notifications/icon.png +0 -0
  31. data/assets/travis.sh +163 -0
  32. data/assets/travis.sh.erb +64 -0
  33. data/bin/travis +18 -0
  34. data/examples/org_overview.rb +3 -0
  35. data/examples/pro_auth.rb +23 -0
  36. data/examples/stream.rb +6 -0
  37. data/lib/travis.rb +8 -0
  38. data/lib/travis/auto_login.rb +3 -0
  39. data/lib/travis/cli.rb +126 -0
  40. data/lib/travis/cli/accounts.rb +31 -0
  41. data/lib/travis/cli/api_command.rb +180 -0
  42. data/lib/travis/cli/branches.rb +25 -0
  43. data/lib/travis/cli/cache.rb +76 -0
  44. data/lib/travis/cli/cancel.rb +18 -0
  45. data/lib/travis/cli/command.rb +422 -0
  46. data/lib/travis/cli/console.rb +31 -0
  47. data/lib/travis/cli/disable.rb +15 -0
  48. data/lib/travis/cli/enable.rb +31 -0
  49. data/lib/travis/cli/encrypt.rb +108 -0
  50. data/lib/travis/cli/encrypt_file.rb +140 -0
  51. data/lib/travis/cli/endpoint.rb +35 -0
  52. data/lib/travis/cli/env.rb +66 -0
  53. data/lib/travis/cli/help.rb +23 -0
  54. data/lib/travis/cli/history.rb +49 -0
  55. data/lib/travis/cli/init.rb +82 -0
  56. data/lib/travis/cli/lint.rb +49 -0
  57. data/lib/travis/cli/login.rb +76 -0
  58. data/lib/travis/cli/logout.rb +14 -0
  59. data/lib/travis/cli/logs.rb +65 -0
  60. data/lib/travis/cli/monitor.rb +110 -0
  61. data/lib/travis/cli/open.rb +39 -0
  62. data/lib/travis/cli/parser.rb +43 -0
  63. data/lib/travis/cli/pubkey.rb +30 -0
  64. data/lib/travis/cli/raw.rb +20 -0
  65. data/lib/travis/cli/repo_command.rb +154 -0
  66. data/lib/travis/cli/report.rb +101 -0
  67. data/lib/travis/cli/repos.rb +53 -0
  68. data/lib/travis/cli/requests.rb +47 -0
  69. data/lib/travis/cli/restart.rb +18 -0
  70. data/lib/travis/cli/settings.rb +77 -0
  71. data/lib/travis/cli/setup.rb +66 -0
  72. data/lib/travis/cli/setup/anynines.rb +21 -0
  73. data/lib/travis/cli/setup/appfog.rb +19 -0
  74. data/lib/travis/cli/setup/artifacts.rb +23 -0
  75. data/lib/travis/cli/setup/biicode.rb +19 -0
  76. data/lib/travis/cli/setup/cloud_66.rb +20 -0
  77. data/lib/travis/cli/setup/cloud_control.rb +21 -0
  78. data/lib/travis/cli/setup/cloud_files.rb +20 -0
  79. data/lib/travis/cli/setup/cloud_foundry.rb +23 -0
  80. data/lib/travis/cli/setup/code_deploy.rb +55 -0
  81. data/lib/travis/cli/setup/deis.rb +20 -0
  82. data/lib/travis/cli/setup/divshot.rb +18 -0
  83. data/lib/travis/cli/setup/elastic_beanstalk.rb +23 -0
  84. data/lib/travis/cli/setup/engine_yard.rb +24 -0
  85. data/lib/travis/cli/setup/gcs.rb +22 -0
  86. data/lib/travis/cli/setup/hackage.rb +18 -0
  87. data/lib/travis/cli/setup/heroku.rb +20 -0
  88. data/lib/travis/cli/setup/modulus.rb +18 -0
  89. data/lib/travis/cli/setup/ninefold.rb +20 -0
  90. data/lib/travis/cli/setup/nodejitsu.rb +27 -0
  91. data/lib/travis/cli/setup/npm.rb +20 -0
  92. data/lib/travis/cli/setup/open_shift.rb +20 -0
  93. data/lib/travis/cli/setup/opsworks.rb +22 -0
  94. data/lib/travis/cli/setup/pypi.rb +22 -0
  95. data/lib/travis/cli/setup/releases.rb +35 -0
  96. data/lib/travis/cli/setup/ruby_gems.rb +25 -0
  97. data/lib/travis/cli/setup/s3.rb +25 -0
  98. data/lib/travis/cli/setup/sauce_connect.rb +21 -0
  99. data/lib/travis/cli/setup/service.rb +73 -0
  100. data/lib/travis/cli/show.rb +69 -0
  101. data/lib/travis/cli/sshkey.rb +118 -0
  102. data/lib/travis/cli/status.rb +19 -0
  103. data/lib/travis/cli/sync.rb +30 -0
  104. data/lib/travis/cli/token.rb +14 -0
  105. data/lib/travis/cli/version.rb +17 -0
  106. data/lib/travis/cli/whatsup.rb +30 -0
  107. data/lib/travis/cli/whoami.rb +15 -0
  108. data/lib/travis/client.rb +39 -0
  109. data/lib/travis/client/account.rb +56 -0
  110. data/lib/travis/client/annotation.rb +21 -0
  111. data/lib/travis/client/artifact.rb +88 -0
  112. data/lib/travis/client/auto_login.rb +45 -0
  113. data/lib/travis/client/broadcast.rb +14 -0
  114. data/lib/travis/client/build.rb +47 -0
  115. data/lib/travis/client/cache.rb +25 -0
  116. data/lib/travis/client/commit.rb +28 -0
  117. data/lib/travis/client/entity.rb +238 -0
  118. data/lib/travis/client/env_var.rb +102 -0
  119. data/lib/travis/client/error.rb +38 -0
  120. data/lib/travis/client/has_uuid.rb +13 -0
  121. data/lib/travis/client/job.rb +61 -0
  122. data/lib/travis/client/lint_result.rb +25 -0
  123. data/lib/travis/client/listener.rb +184 -0
  124. data/lib/travis/client/methods.rb +104 -0
  125. data/lib/travis/client/namespace.rb +85 -0
  126. data/lib/travis/client/not_loadable.rb +13 -0
  127. data/lib/travis/client/repository.rb +224 -0
  128. data/lib/travis/client/request.rb +36 -0
  129. data/lib/travis/client/restartable.rb +23 -0
  130. data/lib/travis/client/session.rb +339 -0
  131. data/lib/travis/client/settings.rb +25 -0
  132. data/lib/travis/client/singleton_setting.rb +36 -0
  133. data/lib/travis/client/ssh_key.rb +11 -0
  134. data/lib/travis/client/states.rb +98 -0
  135. data/lib/travis/client/user.rb +67 -0
  136. data/lib/travis/client/weak_entity.rb +26 -0
  137. data/lib/travis/pro.rb +5 -0
  138. data/lib/travis/pro/auto_login.rb +3 -0
  139. data/lib/travis/tools/assets.rb +21 -0
  140. data/lib/travis/tools/completion.rb +54 -0
  141. data/lib/travis/tools/formatter.rb +50 -0
  142. data/lib/travis/tools/github.rb +279 -0
  143. data/lib/travis/tools/notification.rb +69 -0
  144. data/lib/travis/tools/safe_string.rb +22 -0
  145. data/lib/travis/tools/ssl_key.rb +48 -0
  146. data/lib/travis/tools/system.rb +88 -0
  147. data/lib/travis/version.rb +3 -0
  148. data/spec/cli/cancel_spec.rb +15 -0
  149. data/spec/cli/encrypt_spec.rb +43 -0
  150. data/spec/cli/endpoint_spec.rb +34 -0
  151. data/spec/cli/help_spec.rb +33 -0
  152. data/spec/cli/history_spec.rb +38 -0
  153. data/spec/cli/init_spec.rb +226 -0
  154. data/spec/cli/login_spec.rb +13 -0
  155. data/spec/cli/logs_spec.rb +8 -0
  156. data/spec/cli/open_spec.rb +33 -0
  157. data/spec/cli/repo_command_spec.rb +25 -0
  158. data/spec/cli/restart_spec.rb +15 -0
  159. data/spec/cli/setup_spec.rb +5 -0
  160. data/spec/cli/show_spec.rb +9 -0
  161. data/spec/cli/status_spec.rb +28 -0
  162. data/spec/cli/token_spec.rb +22 -0
  163. data/spec/cli/version_spec.rb +18 -0
  164. data/spec/cli/whoami_spec.rb +34 -0
  165. data/spec/client/account_spec.rb +32 -0
  166. data/spec/client/annotation_spec.rb +14 -0
  167. data/spec/client/broadcast_spec.rb +10 -0
  168. data/spec/client/build_spec.rb +31 -0
  169. data/spec/client/commit_spec.rb +22 -0
  170. data/spec/client/job_spec.rb +30 -0
  171. data/spec/client/methods_spec.rb +15 -0
  172. data/spec/client/namespace_spec.rb +19 -0
  173. data/spec/client/repository_spec.rb +39 -0
  174. data/spec/client/session_spec.rb +165 -0
  175. data/spec/client/user_spec.rb +16 -0
  176. data/spec/client_spec.rb +17 -0
  177. data/spec/pro_spec.rb +10 -0
  178. data/spec/spec_helper.rb +29 -0
  179. data/spec/support/fake_api.rb +738 -0
  180. data/spec/support/fake_github.rb +24 -0
  181. data/spec/support/helpers.rb +45 -0
  182. data/spec/travis_spec.rb +10 -0
  183. data/travis.gemspec +323 -0
  184. metadata +489 -0
@@ -0,0 +1,13 @@
1
+ module Travis
2
+ module Client
3
+ module NotLoadable
4
+ def missing?(attribute)
5
+ false
6
+ end
7
+
8
+ def complete?
9
+ true
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,224 @@
1
+ require 'travis/client'
2
+ require 'travis/tools/ssl_key'
3
+
4
+ module Travis
5
+ module Client
6
+ class Repository < Entity
7
+ class Key
8
+ attr_reader :to_s, :fingerprint
9
+
10
+ def initialize(data, fingerprint)
11
+ @to_s = data
12
+ @fingerprint = fingerprint
13
+ end
14
+
15
+ def encrypt(value)
16
+ encrypted = to_rsa.public_encrypt(value)
17
+ Base64.encode64(encrypted).gsub(/\s+/, "")
18
+ end
19
+
20
+ def to_rsa
21
+ Tools::SSLKey.public_rsa_key(to_s)
22
+ end
23
+
24
+ def to_ssh
25
+ Tools::SSLKey.rsa_ssh(to_rsa)
26
+ end
27
+
28
+ def ==(other)
29
+ other.to_s == self
30
+ end
31
+ end
32
+
33
+ include States
34
+ preloadable
35
+
36
+ # @!parse attr_reader :slug, :description
37
+ attributes :slug, :active, :private, :admin, :description, :last_build_id, :last_build_number, :last_build_state, :last_build_duration, :last_build_started_at, :last_build_finished_at, :github_language
38
+ inspect_info :slug
39
+
40
+ time :last_build_finished_at, :last_build_started_at
41
+
42
+ one :repo
43
+ many :repos
44
+ aka :repository, :permissions, :admin, :pull, :push, :hooks
45
+
46
+ has_singleton :ssh_key
47
+
48
+ def initialize(*)
49
+ super
50
+ attributes['active'] = attributes['private'] = attributes['admin'] = nil
51
+ end
52
+
53
+ def public_key
54
+ attributes["public_key"] ||= begin
55
+ payload = session.get_raw("/repos/#{id}/key")
56
+ Key.new(payload.fetch('key'), payload['fingerprint'])
57
+ end
58
+ end
59
+
60
+ def name
61
+ slug[/[^\/]+$/]
62
+ end
63
+
64
+ def public_key=(key)
65
+ # ignored
66
+ end
67
+
68
+ alias key public_key
69
+ alias key= public_key=
70
+
71
+ def encrypt(value)
72
+ key.encrypt(value)
73
+ end
74
+
75
+ # @!parse attr_reader :last_build
76
+ def last_build
77
+ return unless last_build_id
78
+ attributes['last_build'] ||= begin
79
+ last_build = session.find_one(Build, last_build_id)
80
+ last_build.number = last_build_number
81
+ last_build.state = last_build_state
82
+ last_build.duration = last_build_duration
83
+ last_build.started_at = last_build_started_at
84
+ last_build.finished_at = last_build_finished_at
85
+ last_build.repository_id = id
86
+ last_build
87
+ end
88
+ end
89
+
90
+ def builds(params = nil)
91
+ return each_build unless params
92
+ session.find_many(Build, params.merge(:repository_id => id))
93
+ end
94
+
95
+ def build(number)
96
+ builds(:number => number.to_s).first
97
+ end
98
+
99
+ def recent_builds
100
+ builds({})
101
+ end
102
+
103
+ def last_on_branch(name = nil)
104
+ return branch(name) if name
105
+ attributes['last_on_branch'] ||= session.get('branches', :repository_id => id)['branches']
106
+ end
107
+
108
+ def branches
109
+ last_on_branch.map { |b| { b.commit.branch => b } }.inject(:merge)
110
+ end
111
+
112
+ def branch(name)
113
+ attributes['branches'] ||= {}
114
+ attributes['branches'][name] ||= begin
115
+ build = attributes['last_on_branch'].detect { |b| b.commit.branch == name.to_s } if attributes['last_on_branch']
116
+ build || session.get("/repos/#{id}/branches/#{name}")['branch']
117
+ end
118
+ end
119
+
120
+ def each_build(params = nil, &block)
121
+ return enum_for(__method__, params) unless block_given?
122
+ params ||= {}
123
+ chunk = builds(params)
124
+ until chunk.empty?
125
+ chunk.each(&block)
126
+ number = chunk.last.number
127
+ chunk = number == '1' ? [] : builds(params.merge(:after_number => number))
128
+ end
129
+ self
130
+ end
131
+
132
+ def job(number)
133
+ build_number = number.to_s[/^\d+/] or return nil
134
+ build = build(build_number) or return nil
135
+ job = build.jobs.detect { |j| j.number == number } if number != build_number
136
+ job ||= build.jobs.first if build and build.jobs.size == 1
137
+ job
138
+ end
139
+
140
+ def set_hook(flag)
141
+ result = session.put_raw('/hooks/', :hook => { :id => id, :active => flag })
142
+ result['result']
143
+ end
144
+
145
+ def disable
146
+ set_hook(false)
147
+ end
148
+
149
+ def enable
150
+ set_hook(true)
151
+ end
152
+
153
+ def pusher_channels
154
+ attributes['pusher_channels'] ||= if session.private_channels?
155
+ ["user-#{session.user.id}", "repo-#{id}"]
156
+ else
157
+ ["common"]
158
+ end
159
+ end
160
+
161
+ def member?
162
+ session.user.repositories.include? self
163
+ end
164
+
165
+ def owner_name
166
+ slug[/^[^\/]+/]
167
+ end
168
+
169
+ def owner
170
+ session.account(owner_name)
171
+ end
172
+
173
+ def requests
174
+ attributes['requests'] ||= session.find_many(Request, :repository_id => id)
175
+ end
176
+
177
+ def settings
178
+ attributes['settings'] ||= begin
179
+ settings = session.get("/repos/#{id}/settings")['settings']
180
+ settings.repository = self
181
+ settings
182
+ end
183
+ rescue Travis::Client::NotFound
184
+ raise Travis::Client::Error, "not allowed to access settings"
185
+ end
186
+
187
+ def caches(params = {})
188
+ session.get("/repos/#{id}/caches", params)['caches']
189
+ end
190
+
191
+ def delete_caches(params = {})
192
+ session.delete("/repos/#{id}/caches", params)['caches']
193
+ end
194
+
195
+ def active?
196
+ # TODO remove once active is properly synced and exposed by api
197
+ return active unless active.nil?
198
+ last_build_id?
199
+ end
200
+
201
+ def admin?(user = session.user)
202
+ user.admin_access? self
203
+ end
204
+
205
+ def push?(user = session.user)
206
+ user.push_access? self
207
+ end
208
+
209
+ def pull?(user = session.user)
210
+ user.pull_access? self
211
+ end
212
+
213
+ def env_vars
214
+ attributes['env_vars'] ||= EnvVar::List.new(self)
215
+ end
216
+
217
+ private
218
+
219
+ def state
220
+ last_build_state
221
+ end
222
+ end
223
+ end
224
+ end
@@ -0,0 +1,36 @@
1
+ require 'travis/client/weak_entity'
2
+
3
+ module Travis
4
+ module Client
5
+ class Request < WeakEntity
6
+ # @!parse attr_reader :commit_id, :repository_id, :created_at, :owner_id, :owner_type, :event_type, :base_commit, :head_commit, :result, :message, :pull_request, :pull_request_number, :pull_request_title, :branch, :tag
7
+ attributes :commit_id, :repository_id, :created_at, :owner_id, :owner_type, :event_type, :base_commit, :head_commit, :result, :message, :pull_request, :pull_request_number, :pull_request_title, :branch, :tag
8
+ time :created_at
9
+
10
+ # @!parse attr_reader :repository
11
+ has :repository, :commit
12
+
13
+ one :request
14
+ many :requests
15
+
16
+ def owner
17
+ repository.owner
18
+ end
19
+
20
+ def accepted?
21
+ result == 'accepted'
22
+ end
23
+
24
+ def rejected?
25
+ result == 'rejected'
26
+ end
27
+
28
+ def inspect_info
29
+ [
30
+ repository && repository.slug,
31
+ event_type, branch || pull_request_number, result
32
+ ].compact.join(" ")
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,23 @@
1
+ require 'travis/client'
2
+
3
+ module Travis
4
+ module Client
5
+ module Restartable
6
+ def restartable?
7
+ true
8
+ end
9
+
10
+ def restart
11
+ session.restart(self)
12
+ end
13
+
14
+ def cancelable?
15
+ true
16
+ end
17
+
18
+ def cancel
19
+ session.cancel(self)
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,339 @@
1
+ require 'travis/client'
2
+ require 'travis/version'
3
+
4
+ require 'faraday'
5
+ require 'faraday_middleware'
6
+ require 'travis/tools/system'
7
+ require 'travis/tools/assets'
8
+
9
+ begin
10
+ require 'typhoeus/adapters/faraday' unless Travis::Tools::System.windows?
11
+ rescue LoadError
12
+ end
13
+
14
+ require 'json'
15
+
16
+ module Travis
17
+ module Client
18
+ class Session
19
+ PRIMITIVE = [nil, false, true]
20
+ SSL_OPTIONS = { :ca_file => Tools::Assets['cacert.pem'] }
21
+
22
+ include Methods
23
+ attr_reader :connection, :headers, :access_token, :instruments, :faraday_adapter, :agent_info, :ssl
24
+ attr_accessor :debug_http
25
+
26
+ def initialize(options = Travis::Client::ORG_URI)
27
+ @headers = {}
28
+ @cache = {}
29
+ @instruments = []
30
+ @agent_info = []
31
+ @config = nil
32
+ @faraday_adapter = defined?(Typhoeus) ? :typhoeus : :net_http
33
+ @ssl = SSL_OPTIONS
34
+
35
+ options = { :uri => options } unless options.respond_to? :each_pair
36
+ options.each_pair { |key, value| public_send("#{key}=", value) }
37
+
38
+ raise ArgumentError, "neither :uri nor :connection specified" unless connection
39
+ headers['Accept'] = 'application/vnd.travis-ci.2+json'
40
+ set_user_agent
41
+ check_ssl
42
+ end
43
+
44
+ def uri
45
+ connection.url_prefix.to_s if connection
46
+ end
47
+
48
+ def agent_info=(info)
49
+ @agent_info = [info].flatten.freeze
50
+ set_user_agent
51
+ end
52
+
53
+ def ssl=(options)
54
+ @ssl = options.dup.freeze
55
+ self.uri = uri if uri
56
+ end
57
+
58
+ def uri=(uri)
59
+ clear_cache!
60
+ self.connection = Faraday.new(:url => uri, :ssl => ssl) do |faraday|
61
+ faraday.request :url_encoded
62
+ faraday.response :logger if debug_http
63
+ faraday.adapter(*faraday_adapter)
64
+ end
65
+ end
66
+
67
+ def faraday_adapter=(adapter)
68
+ @faraday_adapter = adapter
69
+ self.uri &&= uri
70
+ set_user_agent
71
+ end
72
+
73
+ def access_token=(token)
74
+ clear_cache!
75
+ @access_token = token
76
+ headers['Authorization'] = "token #{token}"
77
+ headers.delete('Authorization') unless token
78
+ end
79
+
80
+ def connection=(connection)
81
+ clear_cache!
82
+ connection.headers.merge! headers
83
+ @config = nil
84
+ @connection = connection
85
+ @headers = connection.headers
86
+ end
87
+
88
+ def headers=(headers)
89
+ clear_cache!
90
+ connection.headers = headers if connection
91
+ @headers = headers
92
+ end
93
+
94
+ def find_one(entity, id = nil)
95
+ raise Travis::Client::Error, "cannot fetch #{entity}" unless entity.respond_to?(:many) and entity.many
96
+ return create_entity(entity, entity.id_field => id) if entity.id? id
97
+ cached(entity, :by, id) { fetch_one(entity, id) }
98
+ end
99
+
100
+ def find_many(entity, args = {})
101
+ raise Travis::Client::Error, "cannot fetch #{entity}" unless entity.respond_to?(:many) and entity.many
102
+ cached(entity, :many, args) { fetch_many(entity, args) }
103
+ end
104
+
105
+ def find_one_or_many(entity, args = nil)
106
+ raise Travis::Client::Error, "cannot fetch #{entity}" unless entity.respond_to?(:many) and entity.many
107
+ cached(entity, :one_or_many, args) do
108
+ path = "/#{entity.many}"
109
+ path, args = "#{path}/#{args}", {} unless args.is_a? Hash
110
+ result = get(path, args)
111
+ one = result[entity.one]
112
+
113
+ if result.include? entity.many
114
+ Array(one) + Array(result[entity.many])
115
+ else
116
+ one
117
+ end
118
+ end
119
+ end
120
+
121
+ def reset(entity)
122
+ entity.attributes.clear
123
+ entity
124
+ end
125
+
126
+ def reload(entity)
127
+ reset(entity)
128
+ result = fetch_one(entity.class, entity.id)
129
+ entity.update_attributes(result.attributes) if result.attributes != entity.attributes
130
+ result
131
+ end
132
+
133
+ def config
134
+ @config ||= get_raw('/config')['config'] || {}
135
+ end
136
+
137
+ def load(data)
138
+ result = {}
139
+ (data || {}).each_pair do |key, value|
140
+ entity = load_entity(key, value)
141
+ result[key] = entity if entity
142
+ end
143
+ result
144
+ end
145
+
146
+ def load_entity(key, value)
147
+ type = Entity.subclass_for(key)
148
+ if value.respond_to? :to_ary
149
+ value.to_ary.map { |e| create_entity(type, e) }
150
+ else
151
+ create_entity(type, value)
152
+ end
153
+ rescue IndexError
154
+ end
155
+
156
+ def preload(list)
157
+ list.group_by(&:class).each do |type, instances|
158
+ next unless type.preloadable?
159
+ ids = instances.map { |e| e.id unless e.complete? }.compact
160
+ find_many(type, :ids => ids) if ids.any?
161
+ end
162
+ list
163
+ end
164
+
165
+ def get(*args)
166
+ load get_raw(*args)
167
+ end
168
+
169
+ def delete(*args)
170
+ load delete_raw(*args)
171
+ end
172
+
173
+ def patch(*args)
174
+ load patch_raw(*args)
175
+ end
176
+
177
+ def post(*args)
178
+ load post_raw(*args)
179
+ end
180
+
181
+ def put(*args)
182
+ load put_raw(*args)
183
+ end
184
+
185
+ def get_raw(*args)
186
+ raw(:get, *args)
187
+ end
188
+
189
+ def post_raw(*args)
190
+ raw(:post, *args)
191
+ end
192
+
193
+ def put_raw(*args)
194
+ raw(:put, *args)
195
+ end
196
+
197
+ def patch_raw(*args)
198
+ raw(:patch, *args)
199
+ end
200
+
201
+ def delete_raw(*args)
202
+ raw(:delete, *args)
203
+ end
204
+
205
+ def raw(verb, url, *args)
206
+ url = url.sub(/^\//, '')
207
+ result = instrumented(verb.to_s.upcase, url, *args) do
208
+ if url !~ /^https?:/ or url.start_with? api_endpoint
209
+ connection.public_send(verb, url, *args)
210
+ else
211
+ Faraday.public_send(verb, url, *args) { |r| r.headers.delete("Authorization") }
212
+ end
213
+ end
214
+
215
+ case result.status
216
+ when 0 then raise Travis::Client::SSLError, 'SSL error: could not verify peer'
217
+ when 200..299 then JSON.parse(result.body) rescue result.body
218
+ when 301, 303 then raw(:get, result.headers['Location'])
219
+ when 302, 307, 308 then raw(verb, result.headers['Location'])
220
+ when 401 then raise Travis::Client::NotLoggedIn, 'not logged in'
221
+ when 403 then raise Travis::Client::NotLoggedIn, 'invalid access token'
222
+ when 404 then raise Travis::Client::NotFound, result.body
223
+ when 422 then raise Travis::Client::ValidationFailed, result.body
224
+ when 400..499 then raise Travis::Client::Error, "%s: %p" % [result.status, result.body]
225
+ when 500..599 then raise Travis::Client::Error, "server error (%s: %p)" % [result.status, result.body]
226
+ else raise Travis::Client::Error, "unhandled status code #{result.status}"
227
+ end
228
+ end
229
+
230
+ def inspect
231
+ "#<#{self.class}: #{uri}>"
232
+ end
233
+
234
+ def clear_cache
235
+ reset_entities
236
+ clear_find_cache
237
+ self
238
+ end
239
+
240
+ def clear_cache!
241
+ reset_entities
242
+ @cache.clear
243
+ self
244
+ end
245
+
246
+ def session
247
+ self
248
+ end
249
+
250
+ def instrument(&block)
251
+ instruments << block
252
+ end
253
+
254
+ def private_channels?
255
+ !!config['pusher']['private']
256
+ end
257
+
258
+ private
259
+
260
+ def set_user_agent
261
+ adapter = Array === faraday_adapter ? faraday_adapter.first : faraday_adapter
262
+ adapter = adapter.to_s.capitalize.gsub(/_http_(.)/) { "::HTTP::#{$1.upcase}" }.gsub(/_http/, '::HTTP')
263
+ headers['User-Agent'] = "Travis/#{Travis::VERSION} (#{Travis::Tools::System.description(agent_info)}) Faraday/#{Faraday::VERSION} #{adapter}/#{adapter_version(adapter)}"
264
+ end
265
+
266
+ def adapter_version(adapter)
267
+ version = Object.const_get(adapter).const_get("VERSION")
268
+ [*version].join('.')
269
+ rescue Exception
270
+ "unknown"
271
+ end
272
+
273
+ def instrumented(name, *args)
274
+ name = [name, *args.map(&:inspect)].join(" ") if args.any?
275
+ result = nil
276
+ chain = instruments + [proc { |n,l| result = yield }]
277
+ lift = proc { chain.shift.call(name, lift) }
278
+ lift.call
279
+ result
280
+ end
281
+
282
+ def create_entity(type, data)
283
+ return data if primitive?(data)
284
+ data = { type.id_field => data } if type.id? data
285
+ id = type.cast_id(data.fetch(type.id_field)) unless type.weak?
286
+ entity = id ? cached(type, :id, id) { type.new(self, id) } : type.new(self, nil)
287
+ entity.update_attributes(data)
288
+ entity
289
+ end
290
+
291
+ def primitive?(data)
292
+ PRIMITIVE.include? data
293
+ end
294
+
295
+ def error_message(e)
296
+ message = e.response[:body].to_str rescue e.message
297
+ JSON.parse(message).fetch('error').fetch('message') rescue message
298
+ end
299
+
300
+ def reset_entities
301
+ subcaches do |subcache|
302
+ subcache[:id].each_value { |e| e.attributes.clear } if subcache.include? :id
303
+ end
304
+ end
305
+
306
+ def clear_find_cache
307
+ subcaches do |subcache|
308
+ subcache.delete_if { |k, v| k != :id }
309
+ end
310
+ end
311
+
312
+ def subcaches
313
+ @cache.each_value do |subcache|
314
+ yield subcache if subcache.is_a? Hash
315
+ end
316
+ end
317
+
318
+ def fetch_one(entity, id = nil)
319
+ get("/#{entity.base_path}/#{id}")[entity.one]
320
+ end
321
+
322
+ def fetch_many(entity, params = {})
323
+ get("/#{entity.base_path}/", params)[entity.many]
324
+ end
325
+
326
+ def cached(*keys)
327
+ last = keys.pop
328
+ cache = keys.inject(@cache) { |store, key| store[key] ||= {} }
329
+ cache[last] ||= yield
330
+ end
331
+
332
+ def check_ssl
333
+ raw(:head, '/') if ssl == SSL_OPTIONS
334
+ rescue SSLError => error
335
+ self.ssl = {}
336
+ end
337
+ end
338
+ end
339
+ end