sesh 0.1.4 → 0.1.5
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 +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