solano 1.31.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +15 -0
  2. data/bin/solano +29 -0
  3. data/bin/tddium +29 -0
  4. data/lib/solano.rb +19 -0
  5. data/lib/solano/agent.rb +3 -0
  6. data/lib/solano/agent/solano.rb +128 -0
  7. data/lib/solano/cli.rb +25 -0
  8. data/lib/solano/cli/api.rb +368 -0
  9. data/lib/solano/cli/commands/account.rb +50 -0
  10. data/lib/solano/cli/commands/activate.rb +16 -0
  11. data/lib/solano/cli/commands/api.rb +15 -0
  12. data/lib/solano/cli/commands/config.rb +78 -0
  13. data/lib/solano/cli/commands/console.rb +85 -0
  14. data/lib/solano/cli/commands/describe.rb +104 -0
  15. data/lib/solano/cli/commands/find_failing.rb +64 -0
  16. data/lib/solano/cli/commands/heroku.rb +17 -0
  17. data/lib/solano/cli/commands/hg.rb +48 -0
  18. data/lib/solano/cli/commands/keys.rb +81 -0
  19. data/lib/solano/cli/commands/login.rb +37 -0
  20. data/lib/solano/cli/commands/logout.rb +14 -0
  21. data/lib/solano/cli/commands/password.rb +26 -0
  22. data/lib/solano/cli/commands/rerun.rb +59 -0
  23. data/lib/solano/cli/commands/server.rb +21 -0
  24. data/lib/solano/cli/commands/spec.rb +401 -0
  25. data/lib/solano/cli/commands/status.rb +117 -0
  26. data/lib/solano/cli/commands/stop.rb +19 -0
  27. data/lib/solano/cli/commands/suite.rb +110 -0
  28. data/lib/solano/cli/commands/support.rb +24 -0
  29. data/lib/solano/cli/commands/web.rb +29 -0
  30. data/lib/solano/cli/config.rb +246 -0
  31. data/lib/solano/cli/params_helper.rb +66 -0
  32. data/lib/solano/cli/prompt.rb +128 -0
  33. data/lib/solano/cli/show.rb +136 -0
  34. data/lib/solano/cli/solano.rb +208 -0
  35. data/lib/solano/cli/suite.rb +104 -0
  36. data/lib/solano/cli/text_helper.rb +16 -0
  37. data/lib/solano/cli/timeformat.rb +21 -0
  38. data/lib/solano/cli/util.rb +132 -0
  39. data/lib/solano/constant.rb +581 -0
  40. data/lib/solano/scm.rb +18 -0
  41. data/lib/solano/scm/configure.rb +37 -0
  42. data/lib/solano/scm/git.rb +349 -0
  43. data/lib/solano/scm/git_log_parser.rb +67 -0
  44. data/lib/solano/scm/hg.rb +263 -0
  45. data/lib/solano/scm/hg_log_parser.rb +66 -0
  46. data/lib/solano/scm/scm.rb +119 -0
  47. data/lib/solano/scm/scm_stub.rb +9 -0
  48. data/lib/solano/scm/url.rb +75 -0
  49. data/lib/solano/script.rb +12 -0
  50. data/lib/solano/script/git-remote-hg +1258 -0
  51. data/lib/solano/ssh.rb +66 -0
  52. data/lib/solano/util.rb +63 -0
  53. data/lib/solano/version.rb +5 -0
  54. metadata +413 -0
@@ -0,0 +1,263 @@
1
+ # Copyright (c) 2011-2015 Solano Labs All Rights Reserved
2
+
3
+ require 'uri'
4
+ require 'shellwords'
5
+
6
+ module Solano
7
+ class Hg < SCM
8
+ include SolanoConstant
9
+
10
+ def initialize
11
+ super
12
+ end
13
+
14
+ def scm_name
15
+ return 'hg'
16
+ end
17
+
18
+ def repo?
19
+ if File.directory?('.hg') then
20
+ return true
21
+ end
22
+ ignore = `hg status 2>&1`
23
+ ok = $?.success?
24
+ return ok
25
+ end
26
+
27
+ def root
28
+ root = `hg root`
29
+ if $?.exitstatus == 0 then
30
+ root.chomp! if root
31
+ return root
32
+ end
33
+ return Dir.pwd
34
+ end
35
+
36
+ def repo_name
37
+ return File.basename(self.root)
38
+ end
39
+
40
+ def origin_url
41
+ return @default_origin_url if @default_origin_url
42
+
43
+ result = `hg paths default`
44
+ return nil unless $?.success?
45
+ return nil if result.empty?
46
+ result.strip!
47
+ u = URI.parse(result) rescue nil
48
+ if u && u.host.nil? then
49
+ warn(Text::Warning::HG_PATHS_DEFAULT_NOT_URI)
50
+ return nil
51
+ end
52
+ return result
53
+ end
54
+
55
+ def ignore_path
56
+ path = File.join(self.root, Config::HG_IGNORE)
57
+ return path
58
+ end
59
+
60
+ def current_branch
61
+ branch = `hg branch`
62
+ branch.chomp!
63
+ return branch
64
+ end
65
+
66
+ def default_branch
67
+ # NOTE: not necessarily quite right in HG 2.1+ with a default bookmark
68
+ return "default"
69
+ end
70
+
71
+ def changes?(options={})
72
+ return Solano::Hg.hg_changes?(:exclude=>".hgignore")
73
+ end
74
+
75
+ def hg_push(uri)
76
+ cmd = "hg push -f -b #{self.current_branch} "
77
+ cmd += " #{uri}"
78
+
79
+ # git outputs something to stderr when it runs git push.
80
+ # hg doesn't always ... so show the command that's being run and its
81
+ # output to indicate progress.
82
+ puts cmd
83
+ puts `#{cmd}`
84
+ return [0,1].include?( $?.exitstatus )
85
+ end
86
+
87
+ def push_latest(session_data, suite_details, options={})
88
+ uri = if options[:use_private_uri] then
89
+ suite_details["git_repo_private_uri"] || suite_details["git_repo_uri"]
90
+ else
91
+ suite_details["git_repo_uri"]
92
+ end
93
+ self.hg_push(uri)
94
+ end
95
+
96
+ def current_commit
97
+ commit = `hg id -i`
98
+ commit.chomp!
99
+ return commit
100
+ end
101
+
102
+ def commits
103
+ commits = HgCommitLogParser.new(self.latest_commit).commits
104
+ return commits
105
+ end
106
+
107
+ def number_of_commits(id_from, id_to)
108
+ result = `hg log --template='{node}\\n' #{id_from}..#{id_to}`
109
+ result.split("\n").length
110
+ end
111
+
112
+ def create_snapshot(session_id, options={})
113
+ api = options[:api]
114
+ res = api.request_snapshot_url({:session_id => session_id})
115
+ auth_url = res['auth_url']
116
+
117
+ say Text::Process::SNAPSHOT_URL % auth_url
118
+
119
+ unique = SecureRandom.hex(10)
120
+ snaphot_path = File.join(Dir.tmpdir,".solano-#{unique}-snapshot")
121
+ file = File.join(Dir.tmpdir, "solano-#{unique}-snapshot.tar")
122
+
123
+ # #git default branch
124
+ # branch = options[:default_branch]
125
+ # branch ||= /\-\>.*\/(.*)$/.match( (`git branch -r | grep origin/HEAD`).strip)[1]
126
+
127
+ # if branch.nil? then
128
+ # raise Text::Error::DEFAULT_BRANCH
129
+ # end
130
+
131
+ out = `hg clone #{root} #{snaphot_path}`
132
+ out = `tar -C #{snaphot_path} -czpf #{file} .`
133
+ upload_file(auth_url, file)
134
+ Dir.chdir(snaphot_path){
135
+ @snap_id = (`hg --debug id -i`).strip
136
+ }
137
+
138
+ desc = {"url" => auth_url.gsub(/\?.*/,''),
139
+ "size" => File.stat(file).size,
140
+ "sha1"=> Digest::SHA1.file(file).hexdigest.upcase,
141
+ "commit_id"=> @snap_id,
142
+ "session_id" => session_id,
143
+ }
144
+ api.update_snapshot({:repo_snapshot => desc})
145
+ ensure
146
+ FileUtils.rm_rf(snaphot_path) if snaphot_path && File.exists?(snaphot_path)
147
+ FileUtils.rm_f(file) if file && File.exists?(file)
148
+ end
149
+
150
+ def create_patch(session_id, options={})
151
+ api = options[:api]
152
+ snapshot_commit = options[:commit]
153
+ if "#{snapshot_commit}" == `hg --debug id -i`.to_s.strip then
154
+ say Text::Warning::SAME_SNAPSHOT_COMMIT
155
+ return
156
+ end
157
+ #check if commit is known locally
158
+ if (`hg log --rev "ancestors(.) and #{snapshot_commit}" 2>&1 >/dev/null | grep -o 'error:' | wc -l`).to_i > 0 then
159
+ raise Text::Error::PATCH_CREATION_ERROR % snapshot_commit
160
+ end
161
+
162
+ file_name = "solano-#{SecureRandom.hex(10)}.patch"
163
+ tmp_dir = Dir.mktmpdir("patches")
164
+ file_path = File.join(tmp_dir, file_name)
165
+ Dir
166
+ out = `hg export -o #{tmp_dir}/patch-%n -r #{snapshot_commit}:tip`
167
+ say out
168
+ build_patch(tmp_dir, file_path)
169
+
170
+ file_size = File.size(file_path)
171
+ file_sha1 = Digest::SHA1.file(file_path).hexdigest.upcase
172
+
173
+ #upload patch
174
+ say Text::Process::REQUST_PATCH_URL
175
+ res = api.request_patch_url({:session_id => session_id})
176
+ if (auth_url = res['auth_url']) then
177
+ say Text::Process::UPLOAD_PATCH % auth_url
178
+ upload_file(auth_url, file_path)
179
+ else
180
+ raise Text::Error::NO_PATCH_URL
181
+ end
182
+
183
+ args = { :session_id => session_id,
184
+ :sha1 => file_sha1,
185
+ :size => file_size,}
186
+ api.upload_session_patch(args)
187
+
188
+ ensure
189
+ FileUtils.rm_rf(file_path) if file_path && File.exists?(file_path)
190
+ FileUtils.rm_rf(tmp_dir) if tmp_dir && File.exists?(tmp_dir)
191
+ end
192
+
193
+ protected
194
+
195
+ def build_patch(tmp_dir, file_path)
196
+ #patch currently includes one two many commits
197
+ files = Dir.glob(File.join(tmp_dir,"patch-*"))
198
+ files.sort!
199
+ files.shift
200
+
201
+ File.open( file_path, "w" ){|f_out|
202
+ files.each {|f_name|
203
+ File.open(f_name){|f_in|
204
+ f_in.each {|f_str| f_out.puts(f_str) }
205
+ }
206
+ }
207
+ }
208
+ end
209
+
210
+ def latest_commit
211
+ `hg log -f -l 1 --template='{node}\\n{desc|firstline}\\n{author|user}\\n{author|email}\\n{date}\\n{author|user}\\n{author|email}\\n{date}\\n\\n'`
212
+ end
213
+
214
+ class << self
215
+ include SolanoConstant
216
+
217
+ def hg_changes?(options={})
218
+ options[:exclude] ||= []
219
+ options[:exclude] = [options[:exclude]] unless options[:exclude].is_a?(Array)
220
+ cmd = "hg status -mardu"
221
+ p = IO.popen(cmd)
222
+ changes = false
223
+ while line = p.gets do
224
+ line = line.strip
225
+ status, name = line.split(/\s+/)
226
+ next if options[:exclude].include?(name)
227
+ if status !~ /^\?/ then
228
+ changes = true
229
+ break
230
+ end
231
+ end
232
+ unless $?.success? then
233
+ warn(Text::Warning::SCM_UNABLE_TO_DETECT)
234
+ return false
235
+ end
236
+ return changes
237
+ end
238
+
239
+ def hg_push(this_branch, additional_refs=[])
240
+ raise "not implemented"
241
+ end
242
+
243
+ def version_ok
244
+ version = nil
245
+ begin
246
+ version_string = `hg -q --version`
247
+ m = version_string.match(Dependency::VERSION_REGEXP)
248
+ version = m[0] unless m.nil?
249
+ rescue Errno
250
+ rescue Exception
251
+ end
252
+ if version.nil? || version.empty? then
253
+ return false
254
+ end
255
+ version_parts = version.split(".")
256
+ if version_parts[0].to_i < 2 then
257
+ warn(Text::Warning::HG_VERSION % version)
258
+ end
259
+ true
260
+ end
261
+ end
262
+ end
263
+ end
@@ -0,0 +1,66 @@
1
+ # Copyright (c) 2011, 2012, 2013, 2014 Solano Labs All Rights Reserved
2
+
3
+ # this is not namespaced under Solano because we want to eventually move this out into another gem
4
+ class HgCommitLogParser
5
+ attr_accessor :commit_log
6
+
7
+ # example commit_log generated by
8
+ # `hg log -f -l 1 --template='{node}\n{desc|firstline}\n{author|user}\n{author|email}\n{date}\n{author|user}\n{author|email}\n{date}\n'`
9
+
10
+ # beb3d918995bbe6370bb21fd76b4f433bfd64dc4
11
+ # commit summary
12
+ # user
13
+ # user@host.domain
14
+ # 1399437808.00
15
+ # user
16
+ # user@host.domain
17
+ # 1399437808.00
18
+
19
+ def initialize(commit_log)
20
+ @commit_log = commit_log
21
+ end
22
+
23
+ # Returns a list of commits in the following format
24
+ # [{
25
+ # "id" => "15e8cbd88d68d210953d51c28e26c6b9944a313b",
26
+ # "author" => {"name"=>"Bob Smith", "email"=>"bob@example.com"},
27
+ # "committer" => {"name"=>"Fred Smith", "email"=>"fred@example.com"},
28
+ # "summary" => "ignore .ruby-version for rvm",
29
+ # "date" => 1380603292
30
+ # }]
31
+
32
+ def commits
33
+ record = []
34
+ commits = []
35
+ commit_log.lines.each do |line|
36
+ line.strip!
37
+ line.sanitize!
38
+ if line.empty?
39
+ c = parse_commit(record)
40
+ commits.push(c)
41
+ record = []
42
+ else
43
+ record.push(line)
44
+ end
45
+ end
46
+
47
+ commits
48
+ end
49
+
50
+ private
51
+
52
+ def parse_commit(record)
53
+ time = record[4].to_i
54
+ author = build_user(record[2], record[3])
55
+ committer = build_user(record[5], record[6])
56
+ build_commit(record[0], author, committer, record[1], time)
57
+ end
58
+
59
+ def build_user(name, email)
60
+ {"name" => name, "email" => email}
61
+ end
62
+
63
+ def build_commit(sha, author, committer, summary, date)
64
+ {"id" => sha, "author" => author, "committer" => committer, "summary" => summary, "date" => date}
65
+ end
66
+ end
@@ -0,0 +1,119 @@
1
+ # Copyright (c) 2011-2015 Solano Labs All Rights Reserved
2
+
3
+ module Solano
4
+ class SCM
5
+ attr_accessor :default_origin_url
6
+
7
+ def initialize
8
+ @default_origin_url = nil
9
+ end
10
+
11
+ def support_data
12
+ data = Hash.new
13
+ data['scm_name'] = self.scm_name
14
+ if !self.repo? then
15
+ data['is_repo'] = false
16
+ return data
17
+ end
18
+
19
+ %w(scm_name repo? root repo_name origin_url current_branch default_branch changes?).each do |method|
20
+ key = method
21
+ if method =~ /[?]\z/ then
22
+ key = "is_#{method.sub(/[?]\z/, '')}"
23
+ end
24
+
25
+ value = self.send(method.to_sym) rescue nil
26
+
27
+ data[key] = value
28
+ end
29
+
30
+ return data
31
+ end
32
+
33
+ def scm_name
34
+ end
35
+
36
+ def repo?
37
+ return false
38
+ end
39
+
40
+ def root
41
+ return Dir.pwd
42
+ end
43
+
44
+ def repo_name
45
+ return "unknown"
46
+ end
47
+
48
+ def origin_url
49
+ return @default_origin_url
50
+ end
51
+
52
+ def ignore_path
53
+ return nil
54
+ end
55
+
56
+ def current_branch
57
+ return nil
58
+ end
59
+
60
+ def default_branch
61
+ return nil
62
+ end
63
+
64
+ def changes?(options={})
65
+ return false
66
+ end
67
+
68
+ def get_snap_id
69
+ return @snap_id
70
+ end
71
+
72
+ def push_latest(session_data, suite_details, options={})
73
+ return false
74
+ end
75
+
76
+ def create_snapshot(session_id, options={})
77
+ raise Text::Error:SNAPSHOT_NOT_SUPPORTED
78
+ end
79
+
80
+ def create_patch(session_id, options={})
81
+ raise Text::Error:PATCH_NOT_SUPPORTED
82
+ end
83
+
84
+ def upload_file(auth_url, file_path)
85
+ if (`which curl >/dev/null 2>&1 ; echo $?`).to_i == 0 then
86
+ `curl -f --upload-file "#{file_path}" "#{auth_url}"`
87
+ if(`echo $?`).to_i == 22 then
88
+ raise "Failed to upload #{file_path} URL (#{out.code})"
89
+ end
90
+ else
91
+ uri = URI(auth_url)
92
+ body = File.read(file_path)
93
+ out = Net::HTTP.start(uri.host, :use_ssl => true) do |http|
94
+ http.send_request("PUT", uri.request_uri, body, {"content-type" => "",})
95
+ end
96
+ if out.code.to_i != 200
97
+ raise "Failed to upload to #{file_path} (#{out.code})"
98
+ end
99
+ end
100
+ end
101
+
102
+
103
+ def current_commit
104
+ return nil
105
+ end
106
+
107
+ def commits
108
+ []
109
+ end
110
+
111
+ def number_of_commits(id_from, id_to)
112
+ return 0
113
+ end
114
+
115
+ def latest_commit
116
+ return nil
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,9 @@
1
+ # Copyright (c) 2015 Solano Labs All Rights Reserved
2
+
3
+ module Solano
4
+ class StubSCM < SCM
5
+ def initialize
6
+ super
7
+ end
8
+ end
9
+ end