Skip to content

Commit bea4bf5

Browse files
committed
local_fs_map for DAP
On DAP via TCP/IP connection, all the source code are detected as remote files (without `localfs:true` in launch.json for VSCode). In this case, DAP clients (VSCode, ...) receive the contents of the file from DAP server and open an editor window in readonly mode. `local_fs_map` configuration can set remote->local path translation. For example, ``` RUBY_DEBUG_LOCAL_FS_MAP=/remote/src/:/local/src/ rdbg -O --port=... ``` On this case, if remote path is `/remote/src/is/foo.rb`, then DAP returns `/local/src/is/foo.rb` and open the local file as writable mode. You can specify multiple path maps with ',' character like ``` RUBY_DEBUG_LOCAL_FS_MAP=/r1/:/l1/,/r2/:/l2/ ... ``` and also you can specify this map within launch.json for VSCode like: ``` { "type": "rdbg", "name": "Attach with rdbg (TCP/IP 12345)", "request": "attach", "debugPort": "localhost:12345", "localfsMap": "/remote/src/:/local/src/" } ``` If both are provided, launch.json setting is used. fix #463 fix ruby/vscode-rdbg#32
1 parent 85d29dc commit bea4bf5

File tree

2 files changed

+42
-10
lines changed

2 files changed

+42
-10
lines changed

lib/debug/config.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ module DEBUGGER__
4242
host: ['RUBY_DEBUG_HOST', "REMOTE: TCP/IP remote debugging: host", :string, "127.0.0.1"],
4343
sock_path: ['RUBY_DEBUG_SOCK_PATH', "REMOTE: UNIX Domain Socket remote debugging: socket path"],
4444
sock_dir: ['RUBY_DEBUG_SOCK_DIR', "REMOTE: UNIX Domain Socket remote debugging: socket directory"],
45+
local_fs_map: ['RUBY_DEBUG_LOCAL_FS_MAP', "REMOTE: Specify local fs map", :path_map],
4546
cookie: ['RUBY_DEBUG_COOKIE', "REMOTE: Cookie for negotiation"],
4647
open_frontend: ['RUBY_DEBUG_OPEN_FRONTEND',"REMOTE: frontend used by open command (vscode, chrome, default: rdbg)."],
4748
chrome_path: ['RUBY_DEBUG_CHROME_PATH', "REMOTE: Platform dependent path of Chrome (For more information, See [here](https://github.com/ruby/debug/pull/334/files#diff-5fc3d0a901379a95bc111b86cf0090b03f857edfd0b99a0c1537e26735698453R55-R64))"],
@@ -238,6 +239,8 @@ def self.parse_config_value name, valstr
238239
e
239240
end
240241
}
242+
when :path_map
243+
valstr.split(',').map{|e| e.split(':')}
241244
else
242245
valstr
243246
end
@@ -384,6 +387,8 @@ def self.config_to_env_hash config
384387
case CONFIG_SET[key][2]
385388
when :path
386389
valstr = config[key].map{|e| e.kind_of?(Regexp) ? e.inspect : e}.join(':')
390+
when :path_map
391+
valstr = config[key].map{|e| e.join(':')}.join(',')
387392
else
388393
valstr = config[key].to_s
389394
end

lib/debug/server_dap.rb

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -70,14 +70,39 @@ def show_protocol dir, msg
7070
end
7171
end
7272

73-
@local_fs = false
73+
# true: all localfs
74+
# Array: part of localfs
75+
# nil: no localfs
76+
@local_fs_map = nil
77+
78+
def self.local_fs_map_path path
79+
case @local_fs_map
80+
when nil
81+
false
82+
when true
83+
path
84+
else # Array
85+
@local_fs_map.each do |(remote_path_prefix, local_path_prefix)|
86+
if path.start_with? remote_path_prefix
87+
return path.sub(remote_path_prefix){ local_path_prefix }
88+
end
89+
end
7490

75-
def self.local_fs
76-
@local_fs
91+
nil
92+
end
7793
end
7894

79-
def self.local_fs_set
80-
@local_fs = true
95+
def self.local_fs_map_set map
96+
return if @local_fs_map # already setup
97+
98+
case map
99+
when String
100+
@local_fs_map = map.split(',').map{|e| e.split(':')}
101+
when true
102+
@local_fs_map = map
103+
when nil
104+
@local_fs_map = CONFIG[:local_fs_map]
105+
end
81106
end
82107

83108
def dap_setup bytes
@@ -86,7 +111,7 @@ def dap_setup bytes
86111

87112
case self
88113
when UI_UnixDomainServer
89-
UI_DAP.local_fs_set
114+
UI_DAP.local_fs_map_set true
90115
when UI_TcpServer
91116
# TODO: loopback address can be used to connect other FS env, like Docker containers
92117
# UI_DAP.local_fs_set if @local_addr.ipv4_loopback? || @local_addr.ipv6_loopback?
@@ -228,12 +253,12 @@ def process
228253
when 'launch'
229254
send_response req
230255
@is_attach = false
231-
UI_DAP.local_fs_set if req.dig('arguments', 'localfs')
256+
UI_DAP.local_fs_map_set req.dig('arguments', 'localfs') || req.dig('arguments', 'localfsMap')
232257
when 'attach'
233258
send_response req
234259
Process.kill(UI_ServerBase::TRAP_SIGNAL, Process.pid)
235260
@is_attach = true
236-
UI_DAP.local_fs_set if req.dig('arguments', 'localfs')
261+
UI_DAP.local_fs_map_set req.dig('arguments', 'localfs') || req.dig('arguments', 'localfsMap')
237262
when 'setBreakpoints'
238263
path = args.dig('source', 'path')
239264
SESSION.clear_line_breakpoints path
@@ -647,7 +672,9 @@ def process_dap args
647672
path = frame.realpath || frame.path
648673
source_name = path ? File.basename(path) : frame.location.to_s
649674

650-
if !UI_DAP.local_fs || !(path && File.exist?(path))
675+
if (path && File.exist?(path)) && (local_path = UI_DAP.local_fs_map_path(path))
676+
# ok
677+
else
651678
ref = frame.file_lines
652679
end
653680

@@ -658,7 +685,7 @@ def process_dap args
658685
column: 1,
659686
source: {
660687
name: source_name,
661-
path: path,
688+
path: (local_path || path),
662689
sourceReference: ref,
663690
},
664691
}

0 commit comments

Comments
 (0)