rosh 0.9.4 → 0.9.6

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3934908cd1559287bd808f7774a044e7e598850d814bfcfe15604df715653114
4
- data.tar.gz: 71f530ac4d74d582a4c4145f07f941e7ca63323a0bc054e33ac7cffd72b475ef
3
+ metadata.gz: 1399835146cfcd6615a17868694c426b4c06b25649fab1c02192bf8f4534fe1d
4
+ data.tar.gz: 835a84fe3a697e322fb28aa6c67e16f0ad1cbf832616b23991c65f0333fde8f9
5
5
  SHA512:
6
- metadata.gz: 922807c829ec873dbcb5a617cbcfd5b50a3d3da0cdfac24c6914223c27da717c9c29d109893402ca6f2666e3287035d34827b9efced35eaf4bc8cb7cdb6459e9
7
- data.tar.gz: 0da6edde2a9f4825d029d2e8a37b5edf728e518d31997ede1522562e8d24d8ebd0f4a74f93211529ebb412824508a4105d0c50046775b042f3ee59469cb8851c
6
+ metadata.gz: ecaffa32659f87db955a586bced2a742f15735cc75c5d76b00cc7113a9378673cfb54294b7d33ffa29eefdda0213cee56ea09f07de4caae68b3239875f4d9d7c
7
+ data.tar.gz: 66a075c156779a0d33907187ada1195f8d7ebce66fb59de8136e585f7e3b4ce1d0e9f641961d3be12c6b956ae8215f0071e60e16a2a46ea153f0b5c8f377fbd0
data/Makefile ADDED
@@ -0,0 +1,6 @@
1
+ start:
2
+ codex --search --dangerously-bypass-approvals-and-sandbox
3
+ continue:
4
+ codex resume --search --dangerously-bypass-approvals-and-sandbox --last
5
+ resume:
6
+ codex resume --search --dangerously-bypass-approvals-and-sandbox
data/README.md CHANGED
@@ -26,6 +26,7 @@ Or install it yourself as:
26
26
  Default: "^t"
27
27
  -I interval Reconnection interval.
28
28
  -S Use GNU screen instead of tmux
29
+ -L socket-name Specify tmux socket name (tmux -L socket-name)
29
30
 
30
31
  If ~/.ssh/config contains LocalForward or RemoteForward for the host, the same
31
32
  forwarding options are passed to `ssh` automatically.
data/lib/rosh/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  class Rosh
2
- VERSION = '0.9.4'
2
+ VERSION = '0.9.6'
3
3
  end
data/lib/rosh.rb CHANGED
@@ -11,6 +11,7 @@ class Rosh
11
11
  @ssh_opts = []
12
12
  alive_interval = 5
13
13
  @escape = '^t'
14
+ @tmux_socket_name = nil
14
15
  OptionParser.new("test").tap do |opt|
15
16
  opt.banner = 'Usage: rosh [options] hostname [session-name]'
16
17
  opt.on('-a alive-interval'){|v| alive_interval = v.to_i}
@@ -18,6 +19,7 @@ class Rosh
18
19
  opt.on('-I interval'){|v| @interval = v.to_f}
19
20
  opt.on('-V'){|v| @verbose = true}
20
21
  opt.on('-S'){|v| @screen = true}
22
+ opt.on('-L socket-name'){|v| @tmux_socket_name = v}
21
23
  end.parse! args
22
24
  @host, @name = *args, :default
23
25
  abort 'hostname is required' if @host == :default
@@ -30,8 +32,6 @@ class Rosh
30
32
  if @verbose
31
33
  puts "ssh-config: #{config}"
32
34
  end
33
- @forward_opts = []
34
- @forwarding_disabled = false
35
35
  @oom_reported = false
36
36
  @last_exit_status = nil
37
37
  local_forwards(alias_name).each do |f|
@@ -62,8 +62,9 @@ class Rosh
62
62
  ["ssh", *@ssh_opts, resolv,
63
63
  '-t', "'screen -rx #{@name}'", '2>/dev/null']*' '
64
64
  else
65
+ remote_cmd = single_quote(tmux_attach_command)
65
66
  ["ssh", *@ssh_opts, resolv,
66
- '-t', "'tmux attach -t #{@name}'", '2>/dev/null']*' '
67
+ '-t', remote_cmd, '2>/dev/null']*' '
67
68
  end
68
69
  if @verbose
69
70
  puts "connecting to #{@host}..."
@@ -117,26 +118,12 @@ private
117
118
  end
118
119
 
119
120
  def add_forward_option(kind, spec)
120
- return if forwarding_disabled?
121
121
  if kind == :local && !local_forward_available?(spec)
122
122
  puts "skip forwarding: #{spec} is already in use"
123
- disable_forwarding!
124
123
  return
125
124
  end
126
125
  opt = kind == :local ? "-L #{spec}" : "-R #{spec}"
127
126
  @ssh_opts << opt
128
- @forward_opts << opt
129
- end
130
-
131
- def disable_forwarding!
132
- return if @forwarding_disabled
133
- @forwarding_disabled = true
134
- @forward_opts.each { |opt| @ssh_opts.delete(opt) }
135
- @forward_opts.clear
136
- end
137
-
138
- def forwarding_disabled?
139
- @forwarding_disabled
140
127
  end
141
128
 
142
129
  def local_forward_available?(spec)
@@ -227,24 +214,25 @@ private
227
214
 
228
215
  def sh_has_session?
229
216
  # tmux has-session -t <session_name>
230
- ssh_tmux("tmux has-session -t #{@name} 2>/dev/null")
217
+ ssh_tmux("#{tmux_prefix} has-session -t #{tmux_session_name} 2>/dev/null")
231
218
  end
232
219
 
233
220
  def sh_new_session?
234
221
  # tmux new-session -s <session_name> -d
235
- create_with_override = "tmux new-session -s #{@name} -d \\; set-option -t #{@name} destroy-unattached off"
222
+ create_with_override = "#{tmux_prefix} new-session -s #{tmux_session_name} -d \\; set-option -t #{tmux_session_name} destroy-unattached off"
236
223
  return true if ssh_tmux(create_with_override)
237
224
 
238
225
  puts "retrying tmux new-session without destroy-unattached override" if @verbose
239
- ssh_tmux("tmux new-session -s #{@name} -d")
226
+ ssh_tmux("#{tmux_prefix} new-session -s #{tmux_session_name} -d")
240
227
  end
241
228
 
242
229
  def ssh_tmux(command)
230
+ remote_command = single_quote(command.to_s)
243
231
  cmd = [
244
232
  "ssh",
245
233
  *@ssh_opts,
246
234
  resolv,
247
- "'#{command}'"
235
+ remote_command
248
236
  ]*' '
249
237
  puts cmd if @verbose
250
238
  system cmd
@@ -293,4 +281,27 @@ private
293
281
  rescue Exception
294
282
  @host
295
283
  end
284
+
285
+ def tmux_attach_command
286
+ "#{tmux_prefix} attach -t #{tmux_session_name}"
287
+ end
288
+
289
+ def tmux_prefix
290
+ return 'tmux' unless @tmux_socket_name
291
+ "tmux -L #{format_remote_arg(@tmux_socket_name)}"
292
+ end
293
+
294
+ def tmux_session_name
295
+ format_remote_arg(@name)
296
+ end
297
+
298
+ def format_remote_arg(value)
299
+ str = value.to_s
300
+ return str if str.match?(%r{\A[[:alnum:]@%+=:,./_-]+\z})
301
+ %("#{str.gsub(/(["\\$`])/, '\\\\\1')}")
302
+ end
303
+
304
+ def single_quote(str)
305
+ "'" + str.to_s.gsub("'", %q('\'') ) + "'"
306
+ end
296
307
  end
@@ -57,7 +57,7 @@ class RoshForwardingTest < Minitest::Test
57
57
  ssh_opts = rosh.instance_variable_get(:@ssh_opts)
58
58
 
59
59
  refute_includes ssh_opts, '-L 127.0.0.1:3131:localhost:3131'
60
- refute_includes ssh_opts, '-R 8082:localhost:8082'
60
+ assert_includes ssh_opts, '-R 8082:localhost:8082'
61
61
  end
62
62
 
63
63
  def test_verbose_logs_when_session_is_missing
@@ -118,4 +118,26 @@ class RoshForwardingTest < Minitest::Test
118
118
  assert_includes commands.first, 'set-option -t grav destroy-unattached off'
119
119
  refute_includes commands.last, 'set-option -t grav destroy-unattached off'
120
120
  end
121
+
122
+ def test_tmux_commands_include_socket_name_when_specified
123
+ socket_name = 'work'
124
+ rosh = Rosh.new('-L', socket_name, 'grav')
125
+ rosh.instance_variable_set(:@name, 'grav')
126
+
127
+ assert_includes rosh.send(:tmux_attach_command), "-L #{socket_name}"
128
+
129
+ commands = []
130
+ rosh.stub(:system, ->(cmd) { commands << cmd; true }) do
131
+ rosh.send(:sh_has_session?)
132
+ end
133
+
134
+ assert_includes commands.first, "-L #{socket_name}"
135
+ end
136
+
137
+ def test_tmux_default_socket_used_when_not_specified
138
+ rosh = Rosh.new('grav')
139
+ command = rosh.send(:tmux_attach_command)
140
+
141
+ refute_includes command, '-L'
142
+ end
121
143
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rosh
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.4
4
+ version: 0.9.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Genki Takiuchi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-10-09 00:00:00.000000000 Z
11
+ date: 2025-12-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: net-ssh
@@ -79,6 +79,7 @@ files:
79
79
  - ".gitignore"
80
80
  - Gemfile
81
81
  - LICENSE.txt
82
+ - Makefile
82
83
  - README.md
83
84
  - Rakefile
84
85
  - bin/rosh