solano 1.31.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 +15 -0
- data/bin/solano +29 -0
- data/bin/tddium +29 -0
- data/lib/solano.rb +19 -0
- data/lib/solano/agent.rb +3 -0
- data/lib/solano/agent/solano.rb +128 -0
- data/lib/solano/cli.rb +25 -0
- data/lib/solano/cli/api.rb +368 -0
- data/lib/solano/cli/commands/account.rb +50 -0
- data/lib/solano/cli/commands/activate.rb +16 -0
- data/lib/solano/cli/commands/api.rb +15 -0
- data/lib/solano/cli/commands/config.rb +78 -0
- data/lib/solano/cli/commands/console.rb +85 -0
- data/lib/solano/cli/commands/describe.rb +104 -0
- data/lib/solano/cli/commands/find_failing.rb +64 -0
- data/lib/solano/cli/commands/heroku.rb +17 -0
- data/lib/solano/cli/commands/hg.rb +48 -0
- data/lib/solano/cli/commands/keys.rb +81 -0
- data/lib/solano/cli/commands/login.rb +37 -0
- data/lib/solano/cli/commands/logout.rb +14 -0
- data/lib/solano/cli/commands/password.rb +26 -0
- data/lib/solano/cli/commands/rerun.rb +59 -0
- data/lib/solano/cli/commands/server.rb +21 -0
- data/lib/solano/cli/commands/spec.rb +401 -0
- data/lib/solano/cli/commands/status.rb +117 -0
- data/lib/solano/cli/commands/stop.rb +19 -0
- data/lib/solano/cli/commands/suite.rb +110 -0
- data/lib/solano/cli/commands/support.rb +24 -0
- data/lib/solano/cli/commands/web.rb +29 -0
- data/lib/solano/cli/config.rb +246 -0
- data/lib/solano/cli/params_helper.rb +66 -0
- data/lib/solano/cli/prompt.rb +128 -0
- data/lib/solano/cli/show.rb +136 -0
- data/lib/solano/cli/solano.rb +208 -0
- data/lib/solano/cli/suite.rb +104 -0
- data/lib/solano/cli/text_helper.rb +16 -0
- data/lib/solano/cli/timeformat.rb +21 -0
- data/lib/solano/cli/util.rb +132 -0
- data/lib/solano/constant.rb +581 -0
- data/lib/solano/scm.rb +18 -0
- data/lib/solano/scm/configure.rb +37 -0
- data/lib/solano/scm/git.rb +349 -0
- data/lib/solano/scm/git_log_parser.rb +67 -0
- data/lib/solano/scm/hg.rb +263 -0
- data/lib/solano/scm/hg_log_parser.rb +66 -0
- data/lib/solano/scm/scm.rb +119 -0
- data/lib/solano/scm/scm_stub.rb +9 -0
- data/lib/solano/scm/url.rb +75 -0
- data/lib/solano/script.rb +12 -0
- data/lib/solano/script/git-remote-hg +1258 -0
- data/lib/solano/ssh.rb +66 -0
- data/lib/solano/util.rb +63 -0
- data/lib/solano/version.rb +5 -0
- metadata +413 -0
@@ -0,0 +1,50 @@
|
|
1
|
+
# Copyright (c) 2011, 2012, 2013, 2014, 2015 Solano Labs All Rights Reserved
|
2
|
+
|
3
|
+
module Solano
|
4
|
+
class SolanoCli < Thor
|
5
|
+
desc "account [--org NAME]", "View account information"
|
6
|
+
method_option :org, type: :string
|
7
|
+
def account
|
8
|
+
user_details = solano_setup({:scm => false})
|
9
|
+
|
10
|
+
if user_details then
|
11
|
+
# User is already logged in, so just display the info
|
12
|
+
show_user_details(user_details)
|
13
|
+
else
|
14
|
+
exit_failure Text::Error::USE_ACTIVATE
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
desc "account:add [ROLE] [EMAIL]", "Authorize and invite a user to use your organization"
|
19
|
+
define_method "account:add" do |role, email|
|
20
|
+
solano_setup({:scm => false})
|
21
|
+
|
22
|
+
r = Regexp.new(/\A[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]+\z/)
|
23
|
+
if r !~ email then
|
24
|
+
exit_failure Text::Error::ADD_MEMBER_ERROR % [email, "Not a valid e-mail address: must be of the form user@host.domain"]
|
25
|
+
end
|
26
|
+
|
27
|
+
params = {:role=>role, :email=>email}
|
28
|
+
begin
|
29
|
+
say Text::Process::ADDING_MEMBER % [params[:email], params[:role]]
|
30
|
+
result = @solano_api.set_memberships(params)
|
31
|
+
say Text::Process::ADDED_MEMBER % email
|
32
|
+
rescue TddiumClient::Error::API => e
|
33
|
+
exit_failure Text::Error::ADD_MEMBER_ERROR % [email, e.message]
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
desc "account:remove [EMAIL]", "Remove a user from an organization"
|
38
|
+
define_method "account:remove" do |email|
|
39
|
+
solano_setup({:scm => false})
|
40
|
+
|
41
|
+
begin
|
42
|
+
say Text::Process::REMOVING_MEMBER % email
|
43
|
+
result = @solano_api.delete_memberships(email)
|
44
|
+
say Text::Process::REMOVED_MEMBER % email
|
45
|
+
rescue TddiumClient::Error::API => e
|
46
|
+
exit_failure Text::Error::REMOVE_MEMBER_ERROR % [email, e.message]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# Copyright (c) 2011-2015 Solano Labs All Rights Reserved
|
2
|
+
|
3
|
+
module Solano
|
4
|
+
class SolanoCli < Thor
|
5
|
+
desc "activate", "Activate an account (deprecated)"
|
6
|
+
method_option :email, :type => :string, :default => nil
|
7
|
+
method_option :password, :type => :string, :default => nil
|
8
|
+
method_option :ssh_key_file, :type => :string, :default => nil
|
9
|
+
def activate
|
10
|
+
say "To activate your account, please visit"
|
11
|
+
say "https://ci.solanolabs.com/"
|
12
|
+
|
13
|
+
solano_setup({:scm => false})
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# Copyright (c) 2011-2015 Solano Labs All Rights Reserved
|
2
|
+
|
3
|
+
module Solano
|
4
|
+
class SolanoCli < Thor
|
5
|
+
desc "api:key", "Display Solano CI API Key"
|
6
|
+
define_method "api:key" do
|
7
|
+
user_details = solano_setup({:scm => false})
|
8
|
+
api_key = user_details['api_key']
|
9
|
+
if api_key.nil? then
|
10
|
+
exit_failure LIST_API_KEY_ERROR
|
11
|
+
end
|
12
|
+
say api_key
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# Copyright (c) 2011-2015 Solano Labs All Rights Reserved
|
2
|
+
|
3
|
+
module Solano
|
4
|
+
class SolanoCli < Thor
|
5
|
+
desc "config [suite | repo | org] [--org NAME]", "Display config variables.
|
6
|
+
The scope argument can be 'suite', 'repo', 'org'. The default is 'suite'."
|
7
|
+
method_option :account, :type => :string, :default => nil,
|
8
|
+
:aliases => %w(--org --organization)
|
9
|
+
def config(scope="suite")
|
10
|
+
params = {:repo => true}
|
11
|
+
if scope == 'suite' then
|
12
|
+
params[:suite] = true
|
13
|
+
end
|
14
|
+
if options[:account] then
|
15
|
+
params[:account] = options[:account]
|
16
|
+
end
|
17
|
+
solano_setup(params)
|
18
|
+
|
19
|
+
begin
|
20
|
+
config_details = @solano_api.get_config_key(scope)
|
21
|
+
show_config_details(scope, config_details['env'])
|
22
|
+
rescue TddiumClient::Error::API => e
|
23
|
+
exit_failure Text::Error::LIST_CONFIG_ERROR
|
24
|
+
rescue Exception => e
|
25
|
+
exit_failure e.message
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
desc "config:add [SCOPE] [KEY] [VALUE] [--org NAME]", "Set KEY=VALUE at SCOPE.
|
30
|
+
The scope argument can be 'suite', 'repo', 'org'."
|
31
|
+
method_option :account, :type => :string, :default => nil,
|
32
|
+
:aliases => %w(--org --organization)
|
33
|
+
define_method "config:add" do |scope, key, value|
|
34
|
+
params = {:repo => true}
|
35
|
+
if scope == 'suite' then
|
36
|
+
params[:suite] = true
|
37
|
+
end
|
38
|
+
if options[:account] then
|
39
|
+
params[:account] = options[:account]
|
40
|
+
end
|
41
|
+
solano_setup(params)
|
42
|
+
|
43
|
+
begin
|
44
|
+
say Text::Process::ADD_CONFIG % [key, value, scope]
|
45
|
+
result = @solano_api.set_config_key(scope, key, value)
|
46
|
+
say Text::Process::ADD_CONFIG_DONE % [key, value, scope]
|
47
|
+
rescue TddiumClient::Error::API => e
|
48
|
+
exit_failure Text::Error::ADD_CONFIG_ERROR
|
49
|
+
rescue Exception => e
|
50
|
+
exit_failure e.message
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
desc "config:remove [SCOPE] [KEY] [--org NAME]", "Remove config variable NAME from SCOPE."
|
55
|
+
method_option :account, :type => :string, :default => nil,
|
56
|
+
:aliases => %w(--org --organization)
|
57
|
+
define_method "config:remove" do |scope, key|
|
58
|
+
params = {:repo => true}
|
59
|
+
if scope == 'suite' then
|
60
|
+
params[:suite] = true
|
61
|
+
end
|
62
|
+
if options[:account] then
|
63
|
+
params[:account] = options[:account]
|
64
|
+
end
|
65
|
+
solano_setup(params)
|
66
|
+
|
67
|
+
begin
|
68
|
+
say Text::Process::REMOVE_CONFIG % [key, scope]
|
69
|
+
result = @solano_api.delete_config_key(scope, key)
|
70
|
+
say Text::Process::REMOVE_CONFIG_DONE % [key, scope]
|
71
|
+
rescue TddiumClient::Error::API => e
|
72
|
+
exit_failure Text::Error::REMOVE_CONFIG_ERROR
|
73
|
+
rescue Exception => e
|
74
|
+
exit_failure e.message
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# Copyright (c) 2011-2016 Solano Labs All Rights Reserved
|
2
|
+
|
3
|
+
require 'stringio'
|
4
|
+
require 'json'
|
5
|
+
require 'time'
|
6
|
+
|
7
|
+
module Solano
|
8
|
+
class SolanoCli < Thor
|
9
|
+
desc "console [COMMAND]", "Open an ssh Debug Console to the Solano worker, execute command if given else start shell."
|
10
|
+
method_option :json, :type => :boolean, :default => false
|
11
|
+
method_option :commit, :type => :string, :default => nil
|
12
|
+
def console(*cmd)
|
13
|
+
solano_setup({:repo => true})
|
14
|
+
origin = `git config --get remote.origin.url`.strip
|
15
|
+
session_result = @solano_api.call_api(:get, "/sessions", {:repo_url => origin})["sessions"]
|
16
|
+
if session_result.length > 0 then
|
17
|
+
session = session_result[0]
|
18
|
+
session_id = session["id"]
|
19
|
+
q_result = @solano_api.query_session(session_id).tddium_response["session"]
|
20
|
+
suite_id = q_result["suite_id"]
|
21
|
+
start_result = @solano_api.start_console(session_id, suite_id).tddium_response
|
22
|
+
session_id = start_result["interactive_session_id"] # the new interactive session's id
|
23
|
+
if start_result["message"] == "interactive started" then
|
24
|
+
say "Starting console session #{session_id}"
|
25
|
+
ssh_command = nil
|
26
|
+
failures = 0
|
27
|
+
while !ssh_command do
|
28
|
+
sleep(Default::SLEEP_TIME_BETWEEN_POLLS)
|
29
|
+
begin
|
30
|
+
session = @solano_api.query_session(session_id).tddium_response["session"]
|
31
|
+
failures = 0 # clear any previous transient failures
|
32
|
+
rescue Exception => e
|
33
|
+
failures += 1
|
34
|
+
say e.to_s
|
35
|
+
session = {}
|
36
|
+
end
|
37
|
+
if failures > 2 then
|
38
|
+
say "Errors connecting to server"
|
39
|
+
return # give up.
|
40
|
+
end
|
41
|
+
if session["stage2_ready"] && session["ssh_command"] then
|
42
|
+
if cmd then
|
43
|
+
ssh_command = "#{session['ssh_command']} -o StrictHostKeyChecking=no \"#{cmd.join(' ')}\""
|
44
|
+
else
|
45
|
+
ssh_command = "#{session['ssh_command']} -o StrictHostKeyChecking=no"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
say "SSH Command is #{ssh_command}"
|
50
|
+
# exec terminates this ruby process and lets user control the ssh i/o
|
51
|
+
exec ssh_command
|
52
|
+
elsif start_result["message"] == "interactive already running"
|
53
|
+
dur = duration(Time.parse(start_result['session']['expires_at']) - Time.now)
|
54
|
+
say "Interactive session already running (expires in #{dur})"
|
55
|
+
session_id = start_result["session"]["id"]
|
56
|
+
session = @solano_api.query_session(session_id).tddium_response["session"]
|
57
|
+
if cmd then
|
58
|
+
exec "#{session['ssh_command']} -o StrictHostKeyChecking=no \"#{cmd.join(' ')}\""
|
59
|
+
else
|
60
|
+
exec "#{session['ssh_command']} -o StrictHostKeyChecking=no"
|
61
|
+
end
|
62
|
+
else
|
63
|
+
say start_result["message"]
|
64
|
+
end
|
65
|
+
else
|
66
|
+
say "Unable to find any previous sessions. Execute solano run first"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
# return nice string version of hrs mins secs from time delta
|
72
|
+
def duration(d)
|
73
|
+
secs = d.to_int
|
74
|
+
mins = secs / 60
|
75
|
+
hours = mins / 60
|
76
|
+
if hours > 0 then
|
77
|
+
"#{hours} hours #{mins % 60} minutes"
|
78
|
+
elsif mins > 0 then
|
79
|
+
"#{mins} minutes #{secs % 60} seconds"
|
80
|
+
else
|
81
|
+
"#{secs} seconds"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
# Copyright (c) 2011-2015 Solano Labs All Rights Reserved
|
2
|
+
|
3
|
+
module Solano
|
4
|
+
class SolanoCli < Thor
|
5
|
+
map "show" => :describe
|
6
|
+
desc "describe [SESSION]", "Describe the state of a session, if it
|
7
|
+
is provided; otherwise, the latest session on current branch."
|
8
|
+
method_option :account, :type => :string, :default => nil,
|
9
|
+
:aliases => %w(--org --organization)
|
10
|
+
method_option :all, :type=>:boolean, :default=>false
|
11
|
+
method_option :type, :type=>:string, :default=>nil
|
12
|
+
method_option :json, :type=>:boolean, :default=>false
|
13
|
+
method_option :names, :type=>:boolean, :default=>false
|
14
|
+
method_option :verbose, :type=>:boolean, :default=>false
|
15
|
+
def describe(session_id=nil)
|
16
|
+
solano_setup({:repo => false})
|
17
|
+
|
18
|
+
status_message = ''
|
19
|
+
if !session_id then
|
20
|
+
# params to get the most recent session id on current branch
|
21
|
+
suite_params = {
|
22
|
+
:suite_id => @solano_api.current_suite_id,
|
23
|
+
:active => false,
|
24
|
+
:limit => 1
|
25
|
+
} if suite_for_current_branch?
|
26
|
+
|
27
|
+
sessions = suite_params ? @solano_api.get_sessions(suite_params) : []
|
28
|
+
if sessions.empty? then
|
29
|
+
exit_failure Text::Status::NO_INACTIVE_SESSION
|
30
|
+
end
|
31
|
+
|
32
|
+
session_id = sessions[0]['id']
|
33
|
+
|
34
|
+
session_status = sessions[0]['status'].upcase
|
35
|
+
session_commit = sessions[0]['commit']
|
36
|
+
current_commit = @scm.current_commit
|
37
|
+
if session_commit == current_commit
|
38
|
+
commit_message = "equal to your current commit"
|
39
|
+
else
|
40
|
+
cnt_ahead = @scm.number_of_commits(session_commit, current_commit)
|
41
|
+
if cnt_ahead == 0
|
42
|
+
cnt_behind = @scm.number_of_commits(current_commit, session_commit)
|
43
|
+
commit_message = "your workspace is behind by #{cnt_behind} commits"
|
44
|
+
else
|
45
|
+
commit_message = "your workspace is ahead by #{cnt_ahead} commits"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
duration = sessions[0]['duration']
|
50
|
+
start_timeago = "%s ago" % Solano::TimeFormat.seconds_to_human_time(Time.now - Time.parse(sessions[0]["start_time"]))
|
51
|
+
if duration.nil?
|
52
|
+
finish_timeago = "no info about duration found, started #{start_timeago}"
|
53
|
+
elsif session_status == 'RUNNING'
|
54
|
+
finish_timeago = "in process, started #{start_timeago}"
|
55
|
+
else
|
56
|
+
finish_time = Time.parse(sessions[0]["start_time"]) + duration
|
57
|
+
finish_timeago = "%s ago" % Solano::TimeFormat.seconds_to_human_time(Time.now - finish_time)
|
58
|
+
end
|
59
|
+
|
60
|
+
status_message = Text::Status::SESSION_STATUS % [session_commit, commit_message, session_status, finish_timeago]
|
61
|
+
end
|
62
|
+
|
63
|
+
result = @solano_api.query_session_tests(session_id)
|
64
|
+
|
65
|
+
session_result = Hash.new
|
66
|
+
if options[:verbose] then
|
67
|
+
session_result = @solano_api.query_session(session_id)
|
68
|
+
end
|
69
|
+
|
70
|
+
filtered = result['session']['tests']
|
71
|
+
if !options[:all]
|
72
|
+
filtered = filtered.select{|x| x['status'] == 'failed'}
|
73
|
+
end
|
74
|
+
|
75
|
+
if options[:type]
|
76
|
+
filtered = filtered.select{|x| x['test_type'].downcase == options[:type].downcase}
|
77
|
+
end
|
78
|
+
|
79
|
+
if options[:json]
|
80
|
+
json = result['session']
|
81
|
+
json['session'] = session_result['session']
|
82
|
+
puts JSON.pretty_generate(json)
|
83
|
+
elsif options[:names]
|
84
|
+
say filtered.map{|x| x['test_name']}.join(" ")
|
85
|
+
else
|
86
|
+
filtered.sort!{|a,b| [a['test_type'], a['test_name']] <=> [b['test_type'], b['test_name']]}
|
87
|
+
|
88
|
+
say Text::Process::DESCRIBE_SESSION % [session_id, status_message, options[:all] ? 'all' : 'failed']
|
89
|
+
|
90
|
+
table =
|
91
|
+
[["Test", "Status", "Duration"],
|
92
|
+
["----", "------", "--------"]] +
|
93
|
+
filtered.map do |x|
|
94
|
+
[
|
95
|
+
x['test_name'],
|
96
|
+
x['status'],
|
97
|
+
x['elapsed_time'] ? "#{x['elapsed_time']}s" : "-"
|
98
|
+
]
|
99
|
+
end
|
100
|
+
print_table table
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# Copyright (c) 2011-2015 Solano Labs All Rights Reserved
|
2
|
+
|
3
|
+
module Solano
|
4
|
+
class SolanoCli < Thor
|
5
|
+
desc "find_failing FILES", "Find failing ordering for ruby specs by binary searching a failing test run"
|
6
|
+
desc "find_failing files+ failing_file", "Find out which file causes pollution / makes the failing file fail"
|
7
|
+
def find_failing(*files)
|
8
|
+
solano_setup({:repo => true})
|
9
|
+
|
10
|
+
failing = files.pop
|
11
|
+
if !files.include?(failing)
|
12
|
+
exit_failure "Files have to include the failing file, use the copy helper"
|
13
|
+
elsif files.size < 2
|
14
|
+
exit_failure "Files have to be more than 2, use the copy helper"
|
15
|
+
elsif !success?([failing])
|
16
|
+
exit_failure "#{failing} fails when run on it's own"
|
17
|
+
elsif success?(files)
|
18
|
+
exit_failure "tests pass locally"
|
19
|
+
else
|
20
|
+
loop do
|
21
|
+
a = remove_from(files, files.size / 2, :not => failing)
|
22
|
+
b = files - (a - [failing])
|
23
|
+
status, files = find_failing_set([a, b], failing)
|
24
|
+
if status == :finished
|
25
|
+
say "Fails when #{files.join(", ")} are run together"
|
26
|
+
break
|
27
|
+
elsif status == :continue
|
28
|
+
next
|
29
|
+
else
|
30
|
+
exit_failure "unable to isolate failure to 2 files"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def find_failing_set(sets, failing)
|
39
|
+
sets.each do |set|
|
40
|
+
next if set == [failing]
|
41
|
+
if !success?(set)
|
42
|
+
if set.size == 2
|
43
|
+
return [:finished, set]
|
44
|
+
else
|
45
|
+
return [:continue, set]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
return [:failure, []]
|
50
|
+
end
|
51
|
+
|
52
|
+
def remove_from(set, x, options)
|
53
|
+
set.dup.delete_if { |f| f != options[:not] && (x -= 1) >= 0 }
|
54
|
+
end
|
55
|
+
|
56
|
+
def success?(files)
|
57
|
+
command = "bundle exec ruby #{files.map { |f| "-r./#{f.sub(/\.rb$/, "")}" }.join(" ")} -e ''"
|
58
|
+
say "Running: #{command}"
|
59
|
+
status = system(command)
|
60
|
+
say "Status: #{status ? "Success" : "Failure"}"
|
61
|
+
status
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# Copyright (c) 2011-2015 Solano Labs All Rights Reserved
|
2
|
+
|
3
|
+
module Solano
|
4
|
+
class SolanoCli < Thor
|
5
|
+
desc "heroku", "Connect Heroku account with Solano CI (deprecated)"
|
6
|
+
method_option :email, :type => :string, :default => nil
|
7
|
+
method_option :password, :type => :string, :default => nil
|
8
|
+
method_option :ssh_key_file, :type => :string, :default => nil
|
9
|
+
method_option :app, :type => :string, :default => nil
|
10
|
+
def heroku
|
11
|
+
say "To activate your heroku account, please visit"
|
12
|
+
say "https://ci.solanolabs.com/"
|
13
|
+
|
14
|
+
solano_setup({:scm => false})
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# Copyright (c) 2012-2015 Solano Labs All Rights Reserved
|
2
|
+
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
module Solano
|
6
|
+
class SolanoCli < Thor
|
7
|
+
desc "hg:mirror", "Construct local hg -> git mirror"
|
8
|
+
method_option :noop, :type => :boolean, :default => false
|
9
|
+
method_option :force, :type => :boolean, :default => false
|
10
|
+
define_method "hg:mirror" do |*args|
|
11
|
+
solano_setup({:repo => true, :deprecated => true})
|
12
|
+
|
13
|
+
if @scm.scm_name != 'hg' then
|
14
|
+
exit_failure("Current repository does not appear to be using Mercurial")
|
15
|
+
end
|
16
|
+
|
17
|
+
if @scm.origin_url.nil? then
|
18
|
+
exit_failure("Missing default path; please set default path in hgrc")
|
19
|
+
end
|
20
|
+
|
21
|
+
if File.exists?(@scm.mirror_path) then
|
22
|
+
if !options[:force] then
|
23
|
+
exit_failure("Mirror already exists; use --force to recreate")
|
24
|
+
end
|
25
|
+
if options[:noop] then
|
26
|
+
exit_failure("Running in no-op mode; not removing existing mirror")
|
27
|
+
end
|
28
|
+
FileUtils.rm_rf(@scm.mirror_path)
|
29
|
+
end
|
30
|
+
|
31
|
+
FileUtils.mkdir_p(@scm.mirror_path)
|
32
|
+
|
33
|
+
Solano::Scripts.prepend_script_path
|
34
|
+
|
35
|
+
clone_command = "git clone hg::#{@scm.root} #{@scm.mirror_path}"
|
36
|
+
# origin_command = "cd #{@scm.mirror_path} && git remote set-url origin #{@scm.origin_url}"
|
37
|
+
|
38
|
+
if options[:noop] then
|
39
|
+
puts "export PATH=#{ENV['PATH']}"
|
40
|
+
puts clone_command
|
41
|
+
# puts origin_command
|
42
|
+
else
|
43
|
+
Kernel.system(clone_command)
|
44
|
+
# Kernel.system(origin_command)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|