sesh 0.1.4 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/lib/sesh.rb +5 -0
- data/lib/sesh/cli.rb +92 -115
- data/lib/sesh/tmux_control.rb +60 -2
- data/lib/sesh/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 519e114e15fb6c5fea66d92a8a696ce80308ff4c
|
4
|
+
data.tar.gz: fe5045bde290d181b8d8d395b721914a7fd87b17
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c8ea6c0cf3cf02d4b642bd7cfcd950f990cadafd973f30a02e530c419f038eb12566edd79b69c254608a26d3bf1345ae7c2f17ebf3a6397c5c4fd7e33cca0fa1
|
7
|
+
data.tar.gz: 205abe6b579f35abc141abd18b377698914125d3a6ce6758aab73c9e47c5d3da5697ef83cfc834848171369abd5c27854d69e9772926f00c908d4104c3df6514
|
data/Gemfile.lock
CHANGED
data/lib/sesh.rb
CHANGED
data/lib/sesh/cli.rb
CHANGED
@@ -12,119 +12,10 @@ module Sesh
|
|
12
12
|
puts; puts " Sesh v#{VERSION}".green; puts ' ==========='.green; puts
|
13
13
|
if ARGV.empty? or ARGV.include? '-h' or ARGV.include? '--help'
|
14
14
|
puts HELP_BANNER.blue; exit end
|
15
|
-
|
16
15
|
parse_options!
|
17
16
|
@tmux_control = TmuxControl.new @options[:project], @options[:tmux]
|
18
17
|
@ssh_control = SshControl.new @tmux_control, @options[:ssh]
|
19
|
-
|
20
|
-
if @command
|
21
|
-
case @command
|
22
|
-
when 'start'
|
23
|
-
if @tmux_control.already_running?
|
24
|
-
Logger.fatal "Sesh project '#{@options[:project]}' is already running!"
|
25
|
-
else
|
26
|
-
Logger.info "Starting Sesh project '#{@options[:project]}'..."
|
27
|
-
end
|
28
|
-
@tmux_control.kill_running_processes
|
29
|
-
if @tmux_control.issue_start_command! &&
|
30
|
-
Logger.show_progress_until(-> { @tmux_control.already_running? })
|
31
|
-
sleep 1
|
32
|
-
if @tmux_control.already_running?
|
33
|
-
@tmux_control.store_pids_from_session!
|
34
|
-
Logger.success 'Sesh started successfully.'
|
35
|
-
puts
|
36
|
-
else Logger.fatal 'Sesh failed to start!' end
|
37
|
-
else Logger.fatal 'Sesh failed to start after ten seconds!' end
|
38
|
-
when 'stop'
|
39
|
-
if @tmux_control.already_running?
|
40
|
-
Logger.info "Stopping Sesh project '#{@options[:project]}'..."
|
41
|
-
else
|
42
|
-
Logger.fatal "Sesh project '#{@options[:project]}' is not running!"
|
43
|
-
end
|
44
|
-
@tmux_control.kill_running_processes
|
45
|
-
@tmux_control.issue_stop_command!
|
46
|
-
if $? && Logger.show_progress_until(-> { !@tmux_control.already_running? })
|
47
|
-
Logger.success 'Sesh stopped successfully.'
|
48
|
-
puts
|
49
|
-
else
|
50
|
-
Logger.fatal 'Sesh failed to stop after ten seconds!'
|
51
|
-
end
|
52
|
-
when 'restart'
|
53
|
-
Logger.fatal("Sesh project '#{@options[:project]}' is not running!") unless already_running?
|
54
|
-
puts `sesh stop #{@options[:project]} #{@options if @options.any?}`.strip
|
55
|
-
sleep 0.5
|
56
|
-
puts `sesh start #{@options[:project]} #{@options if @options.any?}`.strip
|
57
|
-
when 'new'
|
58
|
-
config = Tmuxinator::Config.project(@options[:project])
|
59
|
-
unless Tmuxinator::Config.exists?(@options[:project])
|
60
|
-
template = File.join(File.dirname(File.expand_path(__FILE__)),
|
61
|
-
"../lib/sesh/assets/sample.yml")
|
62
|
-
erb = Erubis::Eruby.new(File.read(template)).result(binding)
|
63
|
-
File.open(config, "w") { |f| f.write(erb) }
|
64
|
-
end
|
65
|
-
|
66
|
-
Kernel.system("#{Inferences.infer_default_editor} #{config}") ||
|
67
|
-
Tmuxinator::Cli.new.doctor
|
68
|
-
puts
|
69
|
-
when 'edit'
|
70
|
-
config = Tmuxinator::Config.project(@options[:project])
|
71
|
-
if Tmuxinator::Config.exists? @options[:project]
|
72
|
-
Kernel.system("#{Inferences.infer_default_editor} #{config}") ||
|
73
|
-
Tmuxinator::Cli.new.doctor
|
74
|
-
puts
|
75
|
-
else
|
76
|
-
Logger.fatal "Sesh project '#{@options[:project]}' does not exist yet!"
|
77
|
-
end
|
78
|
-
when 'list'
|
79
|
-
output = Sesh.format_and_run_command <<-BASH
|
80
|
-
ps aux | grep tmux | grep "sesh begin" | grep -v "[g]rep" \
|
81
|
-
| sed -e "s/.*\\/tmp\\/\\(.*\\)\\.sock.*/\\1/"
|
82
|
-
BASH
|
83
|
-
running_projects = output.split("\n")
|
84
|
-
pcount = running_projects.count
|
85
|
-
if pcount > 0
|
86
|
-
Logger.success "#{pcount} project#{pcount>1 ? 's':''} currently running:"
|
87
|
-
puts; running_projects.each {|rp| Logger.info rp, 1 }
|
88
|
-
puts
|
89
|
-
else
|
90
|
-
Logger.fatal "There are no Sesh projects currently running."
|
91
|
-
end
|
92
|
-
when 'connect'
|
93
|
-
if @options[:ssh][:local_addr] == @options[:ssh][:remote_addr]
|
94
|
-
unless @tmux_control.already_running?
|
95
|
-
Logger.fatal "Sesh project '#{@options[:project]}' is not running!"
|
96
|
-
end
|
97
|
-
end
|
98
|
-
system @ssh_control.enter_slave_mode_command
|
99
|
-
when 'enslave'
|
100
|
-
Logger.fatal("Sesh project '#{@options[:project]}' is not running!") unless @tmux_control.already_running?
|
101
|
-
Logger.fatal("You must specify a machine to enslave! Eg: user@ip") if @options[:ssh][:remote_addr].nil?
|
102
|
-
Logger.info "Attempting to connect #{@options[:ssh][:remote_addr]} to Sesh project '#{@options[:project]}'..."
|
103
|
-
if @ssh_control.enslave_peer!
|
104
|
-
Logger.success "Sesh client connected successfully."
|
105
|
-
else
|
106
|
-
Logger.fatal 'Sesh client failed to start.'
|
107
|
-
end
|
108
|
-
when 'begin' then @tmux_control.begin_tmuxinator_session!
|
109
|
-
when 'run'
|
110
|
-
unless ARGV.any?
|
111
|
-
Logger.fatal 'A second command is required!'
|
112
|
-
end
|
113
|
-
@shell_command = ARGV.join(' ')
|
114
|
-
puts "Subcommand: #{@shell_command}"
|
115
|
-
when 'rspec'
|
116
|
-
unless ARGV.any?
|
117
|
-
Logger.fatal 'A path to a spec is required!'
|
118
|
-
end
|
119
|
-
@shell_command = ARGV.join(' ')
|
120
|
-
puts "Spec: #{@shell_command}"
|
121
|
-
else
|
122
|
-
Logger.fatal "Command not recognized!"
|
123
|
-
end
|
124
|
-
exit 0
|
125
|
-
end
|
126
|
-
|
127
|
-
Logger.fatal 'You must specify a command.'
|
18
|
+
handle_command!
|
128
19
|
end
|
129
20
|
|
130
21
|
def self.parse_options!
|
@@ -164,9 +55,16 @@ module Sesh
|
|
164
55
|
opts.on('-S', '--tmux-socket-file=path', 'Path to Tmux Socket File') {|v|
|
165
56
|
# fatal("Socket file #{v} does not exist.") unless File.exist?(v)
|
166
57
|
parsed_options[:tmux][:socket_file] = v }
|
167
|
-
opts.on('
|
58
|
+
opts.on('--tmux-pids-file=path', 'Path to Tmux Pids File') {|v|
|
168
59
|
parsed_options[:tmux][:pids_file] = v }
|
169
60
|
|
61
|
+
opts.on('-C', '--shell-command=cmd', 'Shell Command to Execute') {|v|
|
62
|
+
parsed_options[:shell][:command] = v }
|
63
|
+
opts.on('-P', '--shell-pane=pane', 'Pane to Execute Shell Command in') {|v|
|
64
|
+
parsed_options[:shell][:pane] = v }
|
65
|
+
opts.on('--spec-path=path', 'Path to Spec File to Run') {|v|
|
66
|
+
parsed_options[:shell][:spec] = v }
|
67
|
+
|
170
68
|
# # target_opts = DEPLOYMENT_TARGETS.join '|'
|
171
69
|
# opts.on("-T", "--target=target", 'Titanium Deployment Target') do |v|
|
172
70
|
# if DEPLOYMENT_TARGETS.include? v
|
@@ -221,9 +119,9 @@ module Sesh
|
|
221
119
|
end
|
222
120
|
@options[:tmux][:socket_file] ||= "/tmp/#{@options[:project]}.sock"
|
223
121
|
@options[:tmux][:pids_file] ||= "/tmp/#{@options[:project]}.pids.txt"
|
224
|
-
|
225
|
-
|
226
|
-
if ARGV.any?
|
122
|
+
if %w(enslave connect).include? @command
|
123
|
+
@options[:ssh][:local_addr] ||= Sesh::Inferences.infer_local_ssh_addr
|
124
|
+
if @options[:ssh][:remote_addr].nil? && ARGV.any?
|
227
125
|
ARGV.each {|a|
|
228
126
|
if a =~ /\.local$/ || a =~ /[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/ || a =~ /^(.+)@(.+)$/
|
229
127
|
@options[:ssh][:remote_addr] = a
|
@@ -231,7 +129,7 @@ module Sesh
|
|
231
129
|
@options[:ssh][:remote_addr] ||= ARGV.shift
|
232
130
|
end
|
233
131
|
if @options[:ssh][:remote_addr].nil?
|
234
|
-
if %w(enslave
|
132
|
+
if %w(enslave).include? @command
|
235
133
|
Logger.warn 'A remote address is required.'
|
236
134
|
Logger.fatal 'Hint: specify a remote ssh address using the -R flag.'
|
237
135
|
elsif %w(connect).include? @command
|
@@ -239,6 +137,85 @@ module Sesh
|
|
239
137
|
end
|
240
138
|
end
|
241
139
|
end
|
140
|
+
# TODO: parse a spec file
|
141
|
+
# This block should always go at the end because it eats the rest of ARGV.
|
142
|
+
if %w(run).include?(@command) && @options[:shell][:command].nil?
|
143
|
+
if ARGV.any?
|
144
|
+
argv_cmd_parts = []
|
145
|
+
argv_cmd_parts << ARGV.shift while ARGV.any?
|
146
|
+
@options[:shell][:command] = argv_cmd_parts.join(' ')
|
147
|
+
end
|
148
|
+
if @options[:shell][:command].nil? || @options[:shell][:command].length == 0
|
149
|
+
Logger.fatal 'You must specify a command to run.'
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def self.handle_command!
|
155
|
+
if @command
|
156
|
+
case @command
|
157
|
+
when 'start' then @tmux_control.start_project!
|
158
|
+
when 'stop' then @tmux_control.stop_project!
|
159
|
+
when 'restart' then @tmux_control.restart_project!
|
160
|
+
when 'new'
|
161
|
+
config = Tmuxinator::Config.project(@options[:project])
|
162
|
+
unless Tmuxinator::Config.exists?(@options[:project])
|
163
|
+
template = File.join(File.dirname(File.expand_path(__FILE__)),
|
164
|
+
"../lib/sesh/assets/sample.yml")
|
165
|
+
erb = Erubis::Eruby.new(File.read(template)).result(binding)
|
166
|
+
File.open(config, "w") { |f| f.write(erb) }
|
167
|
+
end
|
168
|
+
|
169
|
+
Kernel.system("#{Inferences.infer_default_editor} #{config}") ||
|
170
|
+
Tmuxinator::Cli.new.doctor
|
171
|
+
puts
|
172
|
+
when 'edit'
|
173
|
+
config = Tmuxinator::Config.project(@options[:project])
|
174
|
+
if Tmuxinator::Config.exists? @options[:project]
|
175
|
+
Kernel.system("#{Inferences.infer_default_editor} #{config}") ||
|
176
|
+
Tmuxinator::Cli.new.doctor
|
177
|
+
puts
|
178
|
+
else
|
179
|
+
Logger.fatal "Sesh project '#{@options[:project]}' does not exist yet!"
|
180
|
+
end
|
181
|
+
when 'list'
|
182
|
+
output = Sesh.format_and_run_command <<-BASH
|
183
|
+
ps aux | grep tmux | grep "sesh begin" | grep -v "[g]rep" \
|
184
|
+
| sed -e "s/.*\\/tmp\\/\\(.*\\)\\.sock.*/\\1/"
|
185
|
+
BASH
|
186
|
+
running_projects = output.split("\n")
|
187
|
+
pcount = running_projects.count
|
188
|
+
if pcount > 0
|
189
|
+
Logger.success "#{pcount} project#{pcount>1 ? 's':''} currently running:"
|
190
|
+
puts; running_projects.each {|rp| Logger.info rp, 1 }
|
191
|
+
puts
|
192
|
+
else Logger.fatal "There are no Sesh projects currently running." end
|
193
|
+
when 'connect'
|
194
|
+
if @options[:ssh][:local_addr] == @options[:ssh][:remote_addr]
|
195
|
+
unless @tmux_control.already_running?
|
196
|
+
Logger.fatal "Sesh project '#{@options[:project]}' is not running!"
|
197
|
+
end
|
198
|
+
end
|
199
|
+
system @ssh_control.enter_slave_mode_command
|
200
|
+
when 'enslave'
|
201
|
+
Logger.fatal("Sesh project '#{@options[:project]}' is not running!") unless @tmux_control.already_running?
|
202
|
+
Logger.fatal("You must specify a machine to enslave! Eg: user@ip") if @options[:ssh][:remote_addr].nil?
|
203
|
+
Logger.info "Attempting to connect #{@options[:ssh][:remote_addr]} to Sesh project '#{@options[:project]}'..."
|
204
|
+
if @ssh_control.enslave_peer!
|
205
|
+
Logger.success "Sesh client connected successfully."
|
206
|
+
else Logger.fatal 'Sesh client failed to start.' end
|
207
|
+
when 'begin' then @tmux_control.begin_tmuxinator_session!
|
208
|
+
when 'run'
|
209
|
+
@tmux_control.do_shell_operation! @options[:shell]
|
210
|
+
when 'rspec'
|
211
|
+
puts "Spec: #{@options[:shell][:spec]}"
|
212
|
+
else
|
213
|
+
Logger.fatal "Command not recognized!"
|
214
|
+
end
|
215
|
+
exit 0
|
216
|
+
end
|
217
|
+
|
218
|
+
Logger.fatal 'You must specify a command.'
|
242
219
|
end
|
243
220
|
end
|
244
221
|
end
|
data/lib/sesh/tmux_control.rb
CHANGED
@@ -19,7 +19,6 @@ module Sesh
|
|
19
19
|
cmd = Sesh.format_command <<-BASH
|
20
20
|
tmux -S "#{@options[:socket_file]}" new-session -d "eval \\"\$SHELL -l -c 'rvm use default; sesh begin'\\"" 2>&1
|
21
21
|
BASH
|
22
|
-
# puts cmd
|
23
22
|
output = `#{cmd}`.strip
|
24
23
|
return true if $? && output.length == 0
|
25
24
|
Logger.warn "Tmux failed to start with the following error: #{output}"; false
|
@@ -30,7 +29,6 @@ module Sesh
|
|
30
29
|
def connection_command; "tmux -S #{@options[:socket_file]} a" end
|
31
30
|
|
32
31
|
def obtain_pids_from_session
|
33
|
-
# TODO: grep this to just those pids from the current project
|
34
32
|
`tmux -S "#{@options[:socket_file]}" list-panes -s -F "\#{pane_pid} \#{pane_current_command}" | grep -v tmux | awk '{print $1}'`.strip.lines
|
35
33
|
end
|
36
34
|
def store_pids_from_session!
|
@@ -49,6 +47,66 @@ module Sesh
|
|
49
47
|
def begin_tmuxinator_session!
|
50
48
|
%x[env TMUX='' mux start #{@project}] end
|
51
49
|
|
50
|
+
def start_project!
|
51
|
+
if already_running?
|
52
|
+
Logger.fatal "Sesh project '#{@project}' is already running!" end
|
53
|
+
Logger.info "Starting Sesh project '#{@project}'..."
|
54
|
+
kill_running_processes
|
55
|
+
if issue_start_command! && Logger.show_progress_until(-> { already_running? })
|
56
|
+
sleep 1
|
57
|
+
if already_running?
|
58
|
+
store_pids_from_session!
|
59
|
+
Logger.success 'Sesh started successfully.'
|
60
|
+
puts
|
61
|
+
else Logger.fatal 'Sesh failed to start!' end
|
62
|
+
else Logger.fatal 'Sesh failed to start after ten seconds!' end
|
63
|
+
end
|
64
|
+
def stop_project!
|
65
|
+
unless already_running?
|
66
|
+
Logger.fatal "Sesh project '#{@project}' is not running!" end
|
67
|
+
Logger.info "Stopping Sesh project '#{@project}'..."
|
68
|
+
kill_running_processes
|
69
|
+
issue_stop_command!
|
70
|
+
if $? && Logger.show_progress_until(-> { !already_running? })
|
71
|
+
Logger.success 'Sesh stopped successfully.'
|
72
|
+
puts
|
73
|
+
else Logger.fatal 'Sesh failed to stop after ten seconds!' end
|
74
|
+
end
|
75
|
+
def restart_project!; stop_project!; sleep 0.5; start_project! end
|
76
|
+
|
77
|
+
def send_keys_to_project!(keys)
|
78
|
+
`tmux -S "#{@options[:socket_file]}" send-keys #{keys}`.strip.length == 0
|
79
|
+
end
|
80
|
+
def send_interrupt!; send_keys_to_project! 'C-c' end
|
81
|
+
def interrupt_and_send_keys_to_project!(keys)
|
82
|
+
send_interrupt!; send_keys_to_project! keys end
|
83
|
+
def send_keys_to_pane!(pane, keys)
|
84
|
+
move_cursor_to_pane! pane
|
85
|
+
send_keys_to_project! keys end
|
86
|
+
def interrupt_and_send_keys_to_pane!(pane, keys)
|
87
|
+
move_cursor_to_pane_and_interrupt! pane
|
88
|
+
send_keys_to_project! keys end
|
89
|
+
def send_command_to_project!(command)
|
90
|
+
send_keys_to_project! "\"#{command}\" Enter" end
|
91
|
+
def interrupt_and_send_command_to_project!(command)
|
92
|
+
send_interrupt!; send_command_to_project!(command) end
|
93
|
+
def send_command_to_pane!(pane, command)
|
94
|
+
send_keys_to_pane! pane, "\"#{command}\" Enter" end
|
95
|
+
def interrupt_and_send_command_to_pane!(pane, command)
|
96
|
+
interrupt_and_send_keys_to_pane!(pane, "\"#{command}\" Enter") end
|
97
|
+
def move_cursor_to_pane!(pane); send_keys_to_project! "C-a q #{pane}" end
|
98
|
+
def move_cursor_to_pane_and_interrupt!(pane)
|
99
|
+
move_cursor_to_pane!(pane); send_interrupt! end
|
100
|
+
def do_shell_operation!(options=DEFAULT_OPTIONS[:shell])
|
101
|
+
unless options[:spec].nil?
|
102
|
+
options[:command] ||= "spring rspec #{options[:spec]}" end
|
103
|
+
if options[:pane].nil?
|
104
|
+
interrupt_and_send_command_to_project! options[:command]
|
105
|
+
else
|
106
|
+
interrupt_and_send_command_to_pane! options[:pane], options[:command]
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
52
110
|
# Getter methods for passthru to SshControl class
|
53
111
|
def project; @project end
|
54
112
|
def options; @options end
|
data/lib/sesh/version.rb
CHANGED