sesh 0.0.8 → 0.1.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.
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.'