pagoda 0.3.2 → 0.5.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.
- data/.DS_Store +0 -0
- data/Gemfile +3 -3
- data/Gemfile.lock +33 -24
- data/README.md +68 -0
- data/Rakefile +4 -7
- data/bin/pagoda +100 -8
- data/lib/pagoda/cli/commands/clone.rb +13 -0
- data/lib/pagoda/cli/commands/create.rb +13 -0
- data/lib/pagoda/cli/commands/deploy.rb +12 -0
- data/lib/pagoda/cli/commands/destroy.rb +16 -0
- data/lib/pagoda/cli/commands/info.rb +13 -0
- data/lib/pagoda/cli/commands/init.rb +13 -0
- data/lib/pagoda/cli/commands/list.rb +20 -0
- data/lib/pagoda/cli/commands/rename.rb +17 -0
- data/lib/pagoda/cli/commands/rollback.rb +12 -0
- data/lib/pagoda/cli/commands/ssh_key.rb +27 -0
- data/lib/pagoda/cli/commands/tunnel.rb +18 -0
- data/lib/pagoda/cli/commands.rb +11 -0
- data/lib/pagoda/{helpers.rb → cli/core_ext.rb} +10 -118
- data/lib/pagoda/cli/helpers/app.rb +143 -0
- data/lib/pagoda/cli/helpers/base.rb +199 -0
- data/lib/pagoda/cli/helpers/key.rb +69 -0
- data/lib/pagoda/cli/helpers/tunnel.rb +36 -0
- data/lib/pagoda/cli/helpers.rb +127 -0
- data/lib/pagoda/cli/override.rb +23 -0
- data/lib/pagoda/cli/version.rb +5 -0
- data/lib/pagoda/cli.rb +11 -0
- data/lib/pagoda-cli.rb +1 -0
- data/pagoda.gemspec +20 -24
- data/pagoda.rdoc +139 -0
- data/pkg/newpagoda-0.1.10.gem +0 -0
- data/pkg/newpagoda-0.1.11.gem +0 -0
- data/pkg/newpagoda-0.1.12.gem +0 -0
- data/pkg/newpagoda-0.1.13.gem +0 -0
- data/pkg/newpagoda-0.1.15.gem +0 -0
- data/pkg/newpagoda-0.1.4.gem +0 -0
- data/pkg/newpagoda-0.1.6.gem +0 -0
- data/pkg/newpagoda-0.1.7.gem +0 -0
- data/pkg/newpagoda-0.1.8.gem +0 -0
- data/pkg/newpagoda-0.1.9.gem +0 -0
- data/pkg/newpagoda-0.5.0.gem +0 -0
- data/spec/lib/helper_spec.rb +32 -0
- data/spec/lib/helpers/app_spec.rb +104 -0
- data/spec/lib/helpers/base_spec.rb +27 -0
- data/spec/lib/helpers/key_spec.rb +42 -0
- data/spec/lib/helpers/tunnel_spec.rb +30 -0
- data/spec/spec_helper.rb +17 -0
- metadata +74 -50
- data/.bundle/config +0 -1
- data/README +0 -3
- data/lib/pagoda/client.rb +0 -225
- data/lib/pagoda/command.rb +0 -96
- data/lib/pagoda/commands/app.rb +0 -247
- data/lib/pagoda/commands/auth.rb +0 -149
- data/lib/pagoda/commands/base.rb +0 -184
- data/lib/pagoda/commands/db.rb +0 -18
- data/lib/pagoda/commands/help.rb +0 -100
- data/lib/pagoda/commands/tunnel.rb +0 -49
- data/lib/pagoda/tunnel_proxy.rb +0 -130
- data/lib/pagoda/version.rb +0 -3
- data/lib/pagoda.rb +0 -3
- data/spec/base.rb +0 -21
- data/spec/client_spec.rb +0 -255
- data/spec/command_spec.rb +0 -26
- data/spec/commands/auth_spec.rb +0 -57
@@ -0,0 +1,143 @@
|
|
1
|
+
module Pagoda
|
2
|
+
module Command
|
3
|
+
|
4
|
+
class App < Base
|
5
|
+
|
6
|
+
def list
|
7
|
+
apps = client.app_list
|
8
|
+
unless apps.empty?
|
9
|
+
display
|
10
|
+
display "APPS"
|
11
|
+
display "//////////////////////////////////"
|
12
|
+
display
|
13
|
+
apps.each do |app|
|
14
|
+
display "- #{app[:name]}"
|
15
|
+
end
|
16
|
+
else
|
17
|
+
error ["looks like you haven't launched any apps", "type 'pagoda create' to create this project on pagodabox"]
|
18
|
+
end
|
19
|
+
display
|
20
|
+
end
|
21
|
+
|
22
|
+
def info
|
23
|
+
display
|
24
|
+
info = client.app_info(app)
|
25
|
+
error("What application are you looking for?") unless info.is_a?(Hash)
|
26
|
+
display "INFO - #{info[:name]}"
|
27
|
+
display "//////////////////////////////////"
|
28
|
+
display "name : #{info[:name]}"
|
29
|
+
display "clone url : git@pagodabox.com:#{info[:id]}.git"
|
30
|
+
display
|
31
|
+
display "owner"
|
32
|
+
display " username : #{info[:owner][:username]}"
|
33
|
+
display " email : #{info[:owner][:email]}"
|
34
|
+
display
|
35
|
+
display "collaborators"
|
36
|
+
info[:collaborators].each do |collab|
|
37
|
+
display " username : #{collab[:username]}"
|
38
|
+
display " email : #{collab[:email]}"
|
39
|
+
end
|
40
|
+
display
|
41
|
+
display "ssh_portal : #{info[:ssh] ? 'enabled' : 'disabled'}"
|
42
|
+
display
|
43
|
+
end
|
44
|
+
|
45
|
+
def rename
|
46
|
+
old_name = options[:old] || app
|
47
|
+
new_name = options[:new] || args.first
|
48
|
+
error "I need the new name" unless new_name
|
49
|
+
error "New name and existiong name cannot be the same" if new_name == old_name
|
50
|
+
client.app_update(old_name, {:name => new_name})
|
51
|
+
display "Successfully changed name to #{new_name}"
|
52
|
+
rescue
|
53
|
+
error "Given name was either invalid or already in use"
|
54
|
+
end
|
55
|
+
|
56
|
+
def init
|
57
|
+
id = client.app_info(args.first || app)[:id] rescue error("We could not find the application you were looking for")
|
58
|
+
create_git_remote(id, remote)
|
59
|
+
end
|
60
|
+
|
61
|
+
def clone
|
62
|
+
my_app = args.first || app
|
63
|
+
id = client.app_info(my_app)[:id]
|
64
|
+
display
|
65
|
+
git "clone git@git.pagodabox.com:#{id}.git #{my_app}"
|
66
|
+
Dir.chdir(my_app)
|
67
|
+
git "config --add pagoda.id #{id}"
|
68
|
+
Dir.chdir("..")
|
69
|
+
display
|
70
|
+
display "+> Repo has been added. Navigate to folder #{my_app}."
|
71
|
+
rescue
|
72
|
+
error "We were not able to access that app"
|
73
|
+
end
|
74
|
+
|
75
|
+
def create
|
76
|
+
name = args.first || app
|
77
|
+
if client.app_available?(name)
|
78
|
+
id = client.app_create(name)[:id]
|
79
|
+
display("Creating #{name}...", false)
|
80
|
+
loop_transaction(name)
|
81
|
+
d_remote = create_git_remote(id, remote)
|
82
|
+
display "#{name} created"
|
83
|
+
display "----------------------------------------------------"
|
84
|
+
display
|
85
|
+
display "LIVE URL : http://#{name}.pagodabox.com"
|
86
|
+
display "ADMIN PANEL : http://dashboard.pagodabox.com/apps/#{name}"
|
87
|
+
display
|
88
|
+
display "----------------------------------------------------"
|
89
|
+
display
|
90
|
+
display "+> Use 'git push #{d_remote} --all' to push your code live"
|
91
|
+
else
|
92
|
+
error "App name (#{name}) is already taken"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def deploy
|
97
|
+
display
|
98
|
+
my_app = app
|
99
|
+
if client.app_info(my_app)[:active_transaction_id] == nil
|
100
|
+
begin
|
101
|
+
client.app_deploy(my_app, branch, commit)
|
102
|
+
rescue RestClient::Found => e
|
103
|
+
# do nothing because we found it HURRAY!
|
104
|
+
end
|
105
|
+
display "+> deploying current branch and commit...", true
|
106
|
+
loop_transaction
|
107
|
+
else
|
108
|
+
error "Your app is currently in transaction, Please try again later."
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def rollback
|
113
|
+
display
|
114
|
+
client.app_rollback(app)
|
115
|
+
display "+> undo..."
|
116
|
+
loop_transaction
|
117
|
+
display
|
118
|
+
end
|
119
|
+
|
120
|
+
def destroy
|
121
|
+
display
|
122
|
+
my_app = app
|
123
|
+
dname = display_name(my_app) # Make the app name look better
|
124
|
+
if options[:force]
|
125
|
+
display "+> Destroying #{dname}"
|
126
|
+
client.app_destroy(my_app)
|
127
|
+
display "+> #{dname} has been successfully destroyed. RIP #{dname}."
|
128
|
+
remove_app(my_app)
|
129
|
+
else
|
130
|
+
if confirm ["Are you totally completely sure you want to delete #{dname} forever and ever?", "THIS CANNOT BE UNDONE! (y/n)"]
|
131
|
+
display
|
132
|
+
display "+> Destroying #{dname}"
|
133
|
+
client.app_destroy(my_app)
|
134
|
+
display "+> #{dname} has been successfully destroyed. RIP #{dname}."
|
135
|
+
remove_app(my_app)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
display
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
@@ -0,0 +1,199 @@
|
|
1
|
+
require 'pagoda-client'
|
2
|
+
|
3
|
+
module Pagoda
|
4
|
+
module Command
|
5
|
+
|
6
|
+
class Base
|
7
|
+
include Pagoda::Helpers
|
8
|
+
|
9
|
+
class << self
|
10
|
+
include Pagoda::Helpers
|
11
|
+
def ask_for_credentials
|
12
|
+
username = ask "Username: "
|
13
|
+
display "Password: ", false
|
14
|
+
password = running_on_windows? ? ask_for_password_on_windows : ask_for_password
|
15
|
+
# api_key = Pagoda::Client.new(user, password).api_key
|
16
|
+
[username, password] # return
|
17
|
+
end
|
18
|
+
|
19
|
+
def ask_for_password
|
20
|
+
echo_off
|
21
|
+
password = ask
|
22
|
+
puts
|
23
|
+
echo_on
|
24
|
+
return password
|
25
|
+
end
|
26
|
+
|
27
|
+
def ask_for_password_on_windows
|
28
|
+
require "Win32API"
|
29
|
+
char = nil
|
30
|
+
password = ''
|
31
|
+
|
32
|
+
while char = Win32API.new("crtdll", "_getch", [ ], "L").Call do
|
33
|
+
break if char == 10 || char == 13 # received carriage return or newline
|
34
|
+
if char == 127 || char == 8 # backspace and delete
|
35
|
+
password.slice!(-1, 1)
|
36
|
+
else
|
37
|
+
# windows might throw a -1 at us so make sure to handle RangeError
|
38
|
+
(password << char.chr) rescue RangeError
|
39
|
+
end
|
40
|
+
end
|
41
|
+
return password
|
42
|
+
end
|
43
|
+
|
44
|
+
def echo_off
|
45
|
+
silently(system("stty -echo"))
|
46
|
+
rescue
|
47
|
+
end
|
48
|
+
|
49
|
+
def echo_on
|
50
|
+
silently(system("stty echo"))
|
51
|
+
rescue
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
attr_reader :client
|
57
|
+
attr_reader :globals
|
58
|
+
attr_reader :options
|
59
|
+
attr_reader :args
|
60
|
+
|
61
|
+
def initialize(globals, options, args)
|
62
|
+
@globals = globals
|
63
|
+
@options = options
|
64
|
+
@args = args
|
65
|
+
end
|
66
|
+
|
67
|
+
def user
|
68
|
+
globals[:username]
|
69
|
+
end
|
70
|
+
|
71
|
+
def password
|
72
|
+
globals[:password]
|
73
|
+
end
|
74
|
+
|
75
|
+
def client
|
76
|
+
@client ||= Pagoda::Client.new(user, password)
|
77
|
+
end
|
78
|
+
|
79
|
+
# protected
|
80
|
+
|
81
|
+
def shell(cmd)
|
82
|
+
FileUtils.cd(Dir.pwd) {|d| return `#{cmd}`}
|
83
|
+
end
|
84
|
+
|
85
|
+
def remote
|
86
|
+
options[:remote] || "pagoda"
|
87
|
+
end
|
88
|
+
|
89
|
+
def app(soft_fail=true)
|
90
|
+
if app = globals[:app] || options[:app]
|
91
|
+
app
|
92
|
+
elsif app = extract_app_from_git_config
|
93
|
+
app
|
94
|
+
elsif app = extract_app_from_remote
|
95
|
+
app
|
96
|
+
else
|
97
|
+
if soft_fail
|
98
|
+
display "I was unable to find your application name."
|
99
|
+
ask "what is the name of your application? "
|
100
|
+
else
|
101
|
+
error "Unable to find the app. please specify using -a or --app="
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def extract_app_from_git_config
|
107
|
+
remote = git("config pagoda.id")
|
108
|
+
if remote =~ /error: More than one value for the key pagoda.id/
|
109
|
+
git("config --unset-all pagoda.id")
|
110
|
+
return nil
|
111
|
+
end
|
112
|
+
remote == "" ? nil : remote
|
113
|
+
end
|
114
|
+
|
115
|
+
def extract_app_from_remote
|
116
|
+
remotes = git_remotes
|
117
|
+
if remotes.length == 1
|
118
|
+
remotes.values.first
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def git_remotes(base_dir=Dir.pwd)
|
123
|
+
remotes = {}
|
124
|
+
original_dir = Dir.pwd
|
125
|
+
Dir.chdir(base_dir)
|
126
|
+
git("remote -v").split("\n").each do |remote|
|
127
|
+
name, url, method = remote.split(/\s/)
|
128
|
+
if url =~ /^git@git.pagodabox.com:([\w\d-]+)\.git$/
|
129
|
+
remotes[name] = $1
|
130
|
+
end
|
131
|
+
end
|
132
|
+
Dir.chdir(original_dir)
|
133
|
+
remotes
|
134
|
+
end
|
135
|
+
|
136
|
+
def branch
|
137
|
+
options[:branch] || find_branch
|
138
|
+
end
|
139
|
+
|
140
|
+
def commit
|
141
|
+
options[:commit] || find_commit
|
142
|
+
end
|
143
|
+
|
144
|
+
def find_branch
|
145
|
+
if git("name-rev --refs=$(git symbolic-ref HEAD) --name-only HEAD") =~ /Could not get/
|
146
|
+
error "Cannot find your branch"
|
147
|
+
else
|
148
|
+
git("name-rev --refs=$(git symbolic-ref HEAD) --name-only HEAD")
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
def home_dir
|
153
|
+
File.expand_path("~")
|
154
|
+
end
|
155
|
+
|
156
|
+
def find_commit
|
157
|
+
if git("rev-parse --verify HEAD") =~ /Could not get/
|
158
|
+
error "Cannot find your commit"
|
159
|
+
else
|
160
|
+
git("rev-parse --verify HEAD")
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
def extract_git_clone_url(remote="pagoda")
|
165
|
+
git("config remote.#{remote}.url")
|
166
|
+
end
|
167
|
+
|
168
|
+
def locate_app_root(dir=Dir.pwd)
|
169
|
+
return dir if File.exists? "#{dir}/.git/config"
|
170
|
+
parent = dir.split('/')[0..-2].join('/')
|
171
|
+
return false if parent.empty?
|
172
|
+
locate_app_root(parent)
|
173
|
+
end
|
174
|
+
|
175
|
+
def loop_transaction(app_name = nil)
|
176
|
+
use_app = app_name || app
|
177
|
+
transaction_id = client.app_info(use_app)[:active_transaction_id]
|
178
|
+
if transaction_id
|
179
|
+
log_stream_length = 0
|
180
|
+
display("",true,0)
|
181
|
+
while true
|
182
|
+
start = Time.now
|
183
|
+
active = client.transaction_info(use_app, transaction_id)
|
184
|
+
unless active[:log_stream].length == log_stream_length
|
185
|
+
display( active[:log_stream][log_stream_length..-1].join("\n"),true,0)
|
186
|
+
log_stream_length = active[:log_stream].length
|
187
|
+
end
|
188
|
+
break unless active[:state] == "incomplete"
|
189
|
+
sleep(Time.now - start) if (Time.now - start) > 0
|
190
|
+
end
|
191
|
+
end
|
192
|
+
display('',true,0)
|
193
|
+
display( "Complete!",true,0)
|
194
|
+
display('',true,0)
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
end
|
199
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
|
2
|
+
module Pagoda
|
3
|
+
module Command
|
4
|
+
|
5
|
+
class Key < Base
|
6
|
+
|
7
|
+
def generate_key_and_push
|
8
|
+
display
|
9
|
+
display "+> Generating a ssh key pair"
|
10
|
+
display
|
11
|
+
if running_on_windows?
|
12
|
+
display "It appears you are running on windows"
|
13
|
+
display "the best way to generate a key is with an external tool"
|
14
|
+
display "We suggest using 'PuTTY'"
|
15
|
+
else
|
16
|
+
(options[:file] ? `ssh-keygen -f #{options[:file]}` : `ssh-keygen`)
|
17
|
+
display
|
18
|
+
push_existing_key
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def push_existing_key
|
23
|
+
if file_path = options[:file] || args.first
|
24
|
+
unless file_path[0] == '/'
|
25
|
+
file_path = Dir.pwd << '/' << file_path
|
26
|
+
end
|
27
|
+
unless file_path.end_with?(".pub")
|
28
|
+
file_path << ".pub"
|
29
|
+
end
|
30
|
+
if File.exists?(file_path)
|
31
|
+
send_key_file(file_path)
|
32
|
+
else
|
33
|
+
error "file given '#{file_path}' does not exist"
|
34
|
+
end
|
35
|
+
else
|
36
|
+
if File.exists?("#{home_dir}/.ssh/id_rsa.pub") || File.exists?("~/.ssh/id_dsa.pub")
|
37
|
+
if File.exists?("#{home_dir}/.ssh/id_rsa.pub")
|
38
|
+
send_key_file("#{home_dir}/.ssh/id_rsa.pub")
|
39
|
+
end
|
40
|
+
|
41
|
+
if File.exists?("#{home_dir}/.ssh/id_dsa.pub")
|
42
|
+
send_key_file("#{home_dir}/.ssh/id_dsa.pub")
|
43
|
+
end
|
44
|
+
else
|
45
|
+
display "It appears you do not have a public key."
|
46
|
+
display "One should be generated with either id-rsa.pub or id-rsa.pub"
|
47
|
+
display "in the #{home_dir}/.ssh folder."
|
48
|
+
display "Or you could specify the file 'pagoda key:gen ~/.ssh/my_awesome_key.pub"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def send_key_file(file)
|
54
|
+
key = File.read(file).strip
|
55
|
+
if key =~ /^ssh-(?:dss|rsa) [A-Za-z0-9+\/]+/
|
56
|
+
client.user_add_key(key)
|
57
|
+
display "+> Pushing ssh key to Pagoda Box"
|
58
|
+
display "+> done"
|
59
|
+
else
|
60
|
+
error "that key is not the correct format"
|
61
|
+
end
|
62
|
+
rescue RestClient::UnprocessableEntity
|
63
|
+
error "It Appears this key is already in use"
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'pagoda-tunnel'
|
2
|
+
|
3
|
+
module Pagoda::Command
|
4
|
+
class Tunnel < Base
|
5
|
+
|
6
|
+
def run
|
7
|
+
user_input = options[:component] || args.first
|
8
|
+
component = {}
|
9
|
+
begin
|
10
|
+
if user_input =~ /^(web\d*)|(db\d*)|(cache\d*)|(worker\d*)$/
|
11
|
+
components = client.component_list(app)
|
12
|
+
components.delete_if {|x| x[:cuid] != user_input }
|
13
|
+
component = components[0]
|
14
|
+
else
|
15
|
+
component = client.component_info(app, user_input)
|
16
|
+
end
|
17
|
+
rescue
|
18
|
+
errors = []
|
19
|
+
errors << "Input unrecoginized"
|
20
|
+
errors << "try 'pagoda -a <appname> tunnel <component>'"
|
21
|
+
errors << "ie. 'pagoda -a app tunnel db1'"
|
22
|
+
error errors
|
23
|
+
end
|
24
|
+
if component[:tunnelable]
|
25
|
+
type = component[:_type]
|
26
|
+
component_id = component[:_id]
|
27
|
+
app_id = component[:app_id]
|
28
|
+
Pagoda::Tunnel.new(type, user, password, app_id, component_id).start
|
29
|
+
else
|
30
|
+
error "Either the component is not tunnelable or you do not have access"
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
module Pagoda
|
2
|
+
module Helpers
|
3
|
+
INDENT = " "
|
4
|
+
|
5
|
+
def home_directory
|
6
|
+
running_on_windows? ? ENV['USERPROFILE'] : ENV['HOME']
|
7
|
+
end
|
8
|
+
|
9
|
+
def running_on_windows?
|
10
|
+
RUBY_PLATFORM =~ /mswin32|mingw32/
|
11
|
+
end
|
12
|
+
|
13
|
+
def running_on_a_mac?
|
14
|
+
RUBY_PLATFORM =~ /-darwin\d/
|
15
|
+
end
|
16
|
+
|
17
|
+
def display(msg="", newline=true, level=1)
|
18
|
+
indent = build_indent(level)
|
19
|
+
if newline
|
20
|
+
(running_on_windows?) ? puts("#{indent}#{msg}") : puts("#{indent}#{msg}".green)
|
21
|
+
else
|
22
|
+
(running_on_windows?) ? print("#{indent}#{msg}") : print("#{indent}#{msg}".green)
|
23
|
+
STDOUT.flush
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def format_date(date)
|
28
|
+
date = Time.parse(date) if date.is_a?(String)
|
29
|
+
date.strftime("%Y-%m-%d %H:%M %Z")
|
30
|
+
end
|
31
|
+
|
32
|
+
def ask(message=nil, level=1)
|
33
|
+
(running_on_windows?) ? print("#{build_indent(level)}#{message}") : print("#{build_indent(level)}#{message}".blue)
|
34
|
+
STDOUT.flush
|
35
|
+
STDIN.gets.strip
|
36
|
+
end
|
37
|
+
|
38
|
+
def confirm(message="Are you sure you wish to continue? (y/n)?", level=1)
|
39
|
+
return true if ARGV.include? "-f"
|
40
|
+
case message
|
41
|
+
when Array
|
42
|
+
count = message.length
|
43
|
+
iteration = 0
|
44
|
+
message.each do |m|
|
45
|
+
if iteration == count - 1
|
46
|
+
(running_on_windows?) ? display("#{m} ", false, level) : display("#{m} ".blue, false, level)
|
47
|
+
else
|
48
|
+
(running_on_windows?) ? display("#{m} ", false, level) : display("#{m} ".blue, true, level)
|
49
|
+
end
|
50
|
+
iteration += 1
|
51
|
+
end
|
52
|
+
when String
|
53
|
+
(running_on_windows?) ? display("#{message} ", false, level) : display("#{message} ".blue, false, level)
|
54
|
+
end
|
55
|
+
ask.downcase == 'y'
|
56
|
+
end
|
57
|
+
|
58
|
+
def error(msg, exit=true, level=1)
|
59
|
+
indent = build_indent(level)
|
60
|
+
STDERR.puts
|
61
|
+
case msg
|
62
|
+
when Array
|
63
|
+
(running_on_windows?) ? STDERR.puts("#{indent}** Error:") : STDERR.puts("#{indent}** Error:".red)
|
64
|
+
msg.each do |m|
|
65
|
+
(running_on_windows?) ? STDERR.puts("#{indent}** #{m}") : STDERR.puts("#{indent}** #{m}".red)
|
66
|
+
end
|
67
|
+
when String
|
68
|
+
(running_on_windows?) ? STDERR.puts("#{indent}** Error: #{msg}") : STDERR.puts("#{indent}** Error: #{msg}".red)
|
69
|
+
end
|
70
|
+
STDERR.puts
|
71
|
+
exit 1 if exit
|
72
|
+
end
|
73
|
+
|
74
|
+
def has_git?
|
75
|
+
%x{ git --version }
|
76
|
+
$?.success?
|
77
|
+
end
|
78
|
+
|
79
|
+
def display_name(app)
|
80
|
+
client.app_info(app)[:name]
|
81
|
+
end
|
82
|
+
|
83
|
+
def git(args)
|
84
|
+
return "" unless has_git?
|
85
|
+
flattened_args = [args].flatten.compact.join(" ")
|
86
|
+
%x{ git #{flattened_args} 2>&1 }.strip
|
87
|
+
end
|
88
|
+
|
89
|
+
def create_git_remote(id, remote)
|
90
|
+
error "you do not have git installed on your computer" unless has_git?
|
91
|
+
if git('remote').split("\n").include?(remote)
|
92
|
+
display "Given remote (#{remote}) is already in use on this repo"
|
93
|
+
remote = ask "what would you like to call the new remote? "
|
94
|
+
end
|
95
|
+
unless File.directory?(".git")
|
96
|
+
if confirm "git has not been initialized yet, would you like us to do this for you? (y/n)?"
|
97
|
+
display "git repo is being created in '#{Dir.pwd}'"
|
98
|
+
git "init"
|
99
|
+
else
|
100
|
+
error(["repo has not been initialized." , "try 'git init'"])
|
101
|
+
end
|
102
|
+
end
|
103
|
+
git "remote add #{remote} git@git.pagodabox.com:#{id}.git"
|
104
|
+
git "config --add pagoda.id #{id}"
|
105
|
+
display "Git remote #{remote} added"
|
106
|
+
remote
|
107
|
+
end
|
108
|
+
|
109
|
+
def remove_app(app)
|
110
|
+
remove_git_remote(app)
|
111
|
+
end
|
112
|
+
|
113
|
+
def remove_git_remote(app)
|
114
|
+
git "remote rm pagoda"
|
115
|
+
git "config --unset pagoda.id"
|
116
|
+
end
|
117
|
+
|
118
|
+
def build_indent(level=1)
|
119
|
+
indent = ""
|
120
|
+
level.times do
|
121
|
+
indent += INDENT
|
122
|
+
end
|
123
|
+
indent
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
unless Object.respond_to? :tap
|
2
|
+
class Object
|
3
|
+
def tap
|
4
|
+
yield(self)
|
5
|
+
self
|
6
|
+
end
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
module GLI
|
11
|
+
def command(*names, &block)
|
12
|
+
command = Command.new([names].flatten,@@next_desc,@@next_arg_name,@@next_long_desc,@@skips_pre,@@skips_post)
|
13
|
+
commands[command.name] = command
|
14
|
+
command.instance_eval(&block)
|
15
|
+
# yield command
|
16
|
+
command.tap do |c|
|
17
|
+
c.desc "Help"
|
18
|
+
c.switch [:h, :help]
|
19
|
+
end
|
20
|
+
clear_nexts
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
data/lib/pagoda/cli.rb
ADDED
data/lib/pagoda-cli.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'pagoda/cli'
|
data/pagoda.gemspec
CHANGED
@@ -1,29 +1,25 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
|
-
|
3
|
-
require "pagoda/version"
|
2
|
+
require File.expand_path('../lib/pagoda/cli/version', __FILE__)
|
4
3
|
|
5
|
-
Gem::Specification.new do |
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
s.homepage = "http://www.pagodabox.com/"
|
12
|
-
s.summary = %q{Terminal client for interacting with the pagodabox}
|
13
|
-
s.description = %q{Terminal client for interacting with the pagodabox. This client does not contain full api functionality, just functionality that will enhance the workflow experience.}
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Lyon Hill"]
|
6
|
+
gem.email = ["lyon@pagodabox.com"]
|
7
|
+
gem.summary = %q{Pagoda Box CLI}
|
8
|
+
gem.description = %q{Pagoda Box User facing interface to improve workflow with Pagoda Box}
|
9
|
+
gem.homepage = "http://www.pagodabox.com"
|
14
10
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
11
|
+
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
12
|
+
gem.files = `git ls-files`.split("\n")
|
13
|
+
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
14
|
+
gem.name = "pagoda"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = Pagoda::CLI::VERSION
|
19
17
|
|
20
|
-
|
21
|
-
|
22
|
-
s.add_dependency "json_pure"
|
23
|
-
s.add_dependency "rest-client"
|
18
|
+
gem.add_development_dependency "rspec"
|
19
|
+
gem.add_development_dependency "pry"
|
24
20
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
end
|
21
|
+
gem.add_dependency "pagoda-client"
|
22
|
+
gem.add_dependency "pagoda-tunnel"
|
23
|
+
gem.add_dependency "rest-client"
|
24
|
+
gem.add_dependency "gli"
|
25
|
+
end
|