sesh 0.0.8 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
metadata CHANGED
@@ -1,15 +1,57 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sesh
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.8
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - MacKinley Smith
8
8
  autorequire:
9
- bindir: bin
9
+ bindir: exe
10
10
  cert_chain: []
11
11
  date: 2015-03-17 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.10'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.10'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
13
55
  - !ruby/object:Gem::Dependency
14
56
  name: tmuxinator
15
57
  requirement: !ruby/object:Gem::Requirement
@@ -24,6 +66,48 @@ dependencies:
24
66
  - - "~>"
25
67
  - !ruby/object:Gem::Version
26
68
  version: 0.6.9
69
+ - !ruby/object:Gem::Dependency
70
+ name: deep_merge
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: awesome_print
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: colorize
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
27
111
  description: Remote background sessions powered by tmux and tmuxinator.
28
112
  email: smithmackinley@gmail.com
29
113
  executables:
@@ -31,9 +115,24 @@ executables:
31
115
  extensions: []
32
116
  extra_rdoc_files: []
33
117
  files:
34
- - bin/sesh
118
+ - ".gitignore"
119
+ - Gemfile
120
+ - Gemfile.lock
121
+ - LICENSE
122
+ - README.md
123
+ - Rakefile
124
+ - bin/console
125
+ - bin/setup
126
+ - exe/sesh
127
+ - lib/sesh.rb
35
128
  - lib/sesh/assets/sample.yml
129
+ - lib/sesh/cli.rb
130
+ - lib/sesh/inferences.rb
131
+ - lib/sesh/logger.rb
132
+ - lib/sesh/ssh_control.rb
133
+ - lib/sesh/tmux_control.rb
36
134
  - lib/sesh/version.rb
135
+ - sesh.gemspec
37
136
  homepage: http://rubygems.org/gems/sesh
38
137
  licenses:
39
138
  - GNU GPLv3
@@ -54,9 +153,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
54
153
  version: '0'
55
154
  requirements: []
56
155
  rubyforge_project:
57
- rubygems_version: 2.2.2
156
+ rubygems_version: 2.4.8
58
157
  signing_key:
59
158
  specification_version: 4
60
159
  summary: Sesh
61
160
  test_files: []
62
- has_rdoc:
data/bin/sesh DELETED
@@ -1,254 +0,0 @@
1
- #!/usr/bin/env ruby
2
- require 'tmuxinator'
3
-
4
- if ARGV.empty? or ARGV.include? '-h' or ARGV.include? '--help' then puts <<-HELP
5
- Sesh: remote background sessions powered by tmux and tmuxinator.
6
- Runs a headless tmuxinator session for remote slave machines to connect to.
7
-
8
- Usage: #{File.basename $0} command [project]
9
-
10
- Commands:
11
-
12
- sesh new Create a new tmuxinator configuration.
13
- sesh edit [project] Edit an existing tmuxinator configuration.
14
- sesh start [project] Start a Sesh session for a project.
15
- sesh stop [project] Stop a Sesh session for a project.
16
- sesh list List running Sesh sessions on this machine.
17
- sesh enslave [project] user@host Connect a slave to a local Sesh session.
18
- sesh connect [project] [user@host] Connect as a slave to a Sesh session.
19
-
20
- Leave project blank to use the name of your current directory.
21
-
22
- HELP
23
- exit; end
24
-
25
- def warn(msg) $stderr.puts msg end
26
- def fatal(msg) $stderr.puts msg; $stderr.puts; exit 1 end
27
- def debug(msg) $stderr.puts "> #{msg}" end
28
-
29
- @command = ARGV[0]
30
- @options = ARGV[1..-1] || []
31
- # debug("Options received: #{@options}") if @options.any?
32
-
33
- def get_local_username
34
- `echo $USER`.strip
35
- end
36
- def get_local_hostname
37
- `scutil --get LocalHostName`.strip.downcase + '.local'
38
- end
39
- @local_ssh_addr = "#{get_local_username}@#{get_local_hostname}"
40
-
41
- def get_project_name
42
- return if @command == 'list'
43
- new_project = @command == 'new'
44
- remote_project = @command == 'connect' && @options.select{|o| o.include? '@' }.any?
45
- if @options.any? && !@options[0].include?('@')
46
- return @options.shift if new_project || remote_project ||
47
- Tmuxinator::Config.exists?(@options[0])
48
- end
49
- output = `printf '%q\n' "${PWD##*/}"`.strip
50
- return output if new_project || Tmuxinator::Config.exists?(output)
51
- puts "Sesh project '#{output}' could not be found."
52
- fatal "Hint: run sesh new or specify an existing project after your commmand."
53
- end
54
- @project_name = get_project_name
55
-
56
-
57
- @socket_file = "/tmp/#{@project_name}.sock"
58
- @pids_file = "/tmp/#{@project_name}.pids.txt"
59
-
60
- def get_remote_address
61
- @options[@options.length>1 ? 1:0] if @options.any?
62
- end
63
- @remote_address = get_remote_address
64
-
65
- def get_term_app
66
- output = `osascript -e 'try' -e 'get exists application "iTerm"' -e 'end try'`.strip
67
- output.length > 0 ? 'iTerm' : fatal("iTerm 2 is not installed.") # 'Terminal'
68
- end
69
-
70
- def get_editor
71
- editor = `echo $EDITOR`.strip
72
- editor = 'vim' unless editor.length > 0
73
- editor
74
- end
75
-
76
- def project_name_matcher
77
- pn = @project_name.gsub '-', '\-'
78
- "[t]mux.*[#{pn[0]}]#{pn[1..-1]}"
79
- end
80
-
81
- def already_running?
82
- output = `ps aux | grep "#{project_name_matcher}"`.strip
83
- output.length > 0
84
- end
85
-
86
- def format_command(command) command.gsub(/\ [ ]+/, ' ').strip end
87
- def format_and_run_command(command) `#{format_command(command)}`.strip end
88
-
89
- def issue_server_start_command!
90
- `tmux -S "#{@socket_file}" new-session -d "env TMUX='' mux start #{@project_name}"`
91
- end
92
-
93
- def issue_server_stop_command!
94
- `pkill -f "#{project_name_matcher}"`
95
- end
96
-
97
- def connection_command(local=false, addr=nil)
98
- addr ||= @local_ssh_addr
99
- local_command = "tmux -S #{@socket_file} a"
100
- return local_command if local
101
- "ssh #{addr} -t '#{local_command}'"
102
- end
103
-
104
- def enter_slave_mode_command(local=false, addr=nil)
105
- @term_app ||= get_term_app
106
- case @term_app
107
- when 'iTerm'
108
- tell_term_app = 'tell application "' + @term_app + '"'
109
- tell_term_process = 'tell application "System Events" to tell process "' +
110
- @term_app + '"'
111
- format_command <<-BASH
112
- osascript \
113
- -e '#{tell_term_app} to activate' \
114
- -e '#{tell_term_process} to keystroke \"n\" using command down' \
115
- -e 'delay 1' \
116
- -e "#{tell_term_app.gsub('"', '\\"')} to tell session -1 of current \
117
- terminal to write text \\"#{connection_command(local, addr)}\\"" \
118
- -e '#{tell_term_process} to keystroke return using command down'
119
- BASH
120
- when 'Terminal'
121
- format_command connection_command(local, addr)
122
- end
123
- end
124
-
125
- def show_progress_until(condition_lambda, timeout=10)
126
- started_progress_at = Time.now
127
- return true if condition_lambda.call
128
- print '> '
129
- until condition_lambda.call or Time.now - started_progress_at > timeout
130
- print '.'
131
- $stdout.flush
132
- sleep 0.5
133
- end
134
- puts
135
- return condition_lambda.call
136
- end
137
-
138
- def kill_running_processes
139
- if File.exists? @pids_file
140
- File.readlines(@pids_file).each{|pid| kill_process! pid }
141
- File.delete @pids_file
142
- end
143
- end
144
- def kill_process!(pid)
145
- `kill -9 #{pid}`
146
- end
147
-
148
- if @command
149
- case @command
150
- when 'start'
151
- fatal("Sesh project '#{@project_name}' is already running!") if already_running?
152
- debug "Starting Sesh project '#{@project_name}'..."
153
- kill_running_processes
154
- output = issue_server_start_command!
155
- success = show_progress_until ->{ already_running? }
156
- if success
157
- sleep 1
158
- if $? && already_running?
159
- pids = `tmux list-panes -s -F "\#{pane_pid} \#{pane_current_command}" | grep -v tmux | awk '{print $1}'`.strip.lines
160
- File.open(@pids_file, 'w') {|f| pids.each{|pid| f.puts pid } }
161
- debug 'Sesh started successfully.'
162
- debug "To connect: #{connection_command}"
163
- # TODO: show other sesh commands (connect, enslave), specify full
164
- # command as what is needed for machines without sesh.
165
- puts
166
- else
167
- fatal 'Sesh failed to start!'
168
- end
169
- else
170
- fatal 'Sesh failed to start after ten seconds!'
171
- end
172
- when 'stop'
173
- fatal("Sesh project '#{@project_name}' is not running!") unless already_running?
174
- debug "Stopping Sesh project '#{@project_name}'..."
175
- kill_running_processes
176
- output = issue_server_stop_command!
177
- success = show_progress_until ->{ !already_running? }
178
- if success && $?
179
- debug 'Sesh stopped successfully.'
180
- puts
181
- else
182
- fatal 'Sesh failed to stop after ten seconds!'
183
- end
184
- when 'restart'
185
- fatal("Sesh project '#{@project_name}' is not running!") unless already_running?
186
- puts `sesh stop #{@project_name} #{@options if @options.any?}`.strip
187
- sleep(0.5)
188
- puts `sesh start #{@project_name} #{@options if @options.any?}`.strip
189
- when 'new'
190
- name = @project_name
191
- config = Tmuxinator::Config.project(name)
192
-
193
- unless Tmuxinator::Config.exists?(name)
194
- template = File.join(File.dirname(File.expand_path(__FILE__)), "../lib/sesh/assets/sample.yml")
195
- erb = Erubis::Eruby.new(File.read(template)).result(binding)
196
- File.open(config, "w") { |f| f.write(erb) }
197
- end
198
-
199
- Kernel.system("#{get_editor} #{config}") || Tmuxinator::Cli.new.doctor
200
- puts
201
- when 'edit'
202
- config = Tmuxinator::Config.project(@project_name)
203
- if Tmuxinator::Config.exists? @project_name
204
- Kernel.system("#{get_editor} #{config}") || Tmuxinator::Cli.new.doctor
205
- puts
206
- else
207
- fatal "Sesh project '#{@project_name}' does not exist yet!"
208
- end
209
- when 'list'
210
- output = format_and_run_command <<-BASH
211
- ps aux | grep tmux | grep "env TMUX='' mux start" \
212
- | grep -v "[g]rep" | sed -e "s/.*mux start \\(.*\\)/\\1/"
213
- BASH
214
- running_projects = output.split("\n")
215
- pcount = running_projects.count
216
- if pcount > 0
217
- puts "#{pcount} project#{pcount>1 ? 's':''} currently running:"
218
- puts running_projects
219
- puts
220
- else
221
- fatal "There are no Sesh projects currently running."
222
- end
223
- when 'connect'
224
- addr = @remote_address
225
- if (is_local=@remote_address.nil?)
226
- addr = @local_ssh_addr
227
- fatal("Sesh project '#{@project_name}' is not running!") unless already_running?
228
- end
229
- command = enter_slave_mode_command(is_local, addr)
230
- puts `#{command}`.strip
231
- when 'enslave'
232
- fatal("Sesh project '#{@project_name}' is not running!") unless already_running?
233
- fatal("You must specify a machine to enslave! Eg: user@ip") if @remote_address.nil?
234
- debug "Attempting to connect #{@remote_address} to Sesh project '#{@project_name}'..."
235
- # ssh #{@remote_address} "#{enter_slave_mode_command.gsub(/([^\\])"/, '\1\\"')}"
236
- # puts <<-BASH
237
- output = format_and_run_command <<-BASH
238
- ssh #{@remote_address} "sesh connect #{@project_name} #{@local_ssh_addr}"
239
- BASH
240
- # 1>/dev/null 2>&1 &
241
- puts output
242
- if $?
243
- debug "Sesh client connected successfully."
244
- puts
245
- else
246
- fatal 'Sesh client failed to start.'
247
- end
248
- else
249
- fatal "Command not recognized!"
250
- end
251
- exit 0
252
- end
253
-
254
- fatal 'You must specify a command.'