Skip to content

Commit 75c3e1d

Browse files
authored
fix: support relative paths and path mappings (#887)
1 parent 453ebc3 commit 75c3e1d

File tree

3 files changed

+70
-3
lines changed

3 files changed

+70
-3
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
44

55
The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/).
66

7+
## [1.31.1]
8+
9+
- Fix relative paths and path mappings support.
10+
711
## [1.31.0]
812

913
- Allow more flexible path mappings in url format.

src/paths.ts

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import fileUrl from 'file-url'
22
import * as url from 'url'
3-
import * as path from 'path'
3+
import * as Path from 'path'
44
import minimatch from 'minimatch'
55

66
/** converts a server-side Xdebug file URI to a local path for VS Code with respect to source root settings */
@@ -45,7 +45,7 @@ export function convertDebuggerPathToClient(fileUri: string, pathMapping?: { [in
4545
let pathname = u.pathname
4646
if (isWindowsUri(fileUri)) {
4747
// From Node.js lib/internal/url.js pathToFileURL
48-
pathname = pathname.replace(/\//g, path.win32.sep)
48+
pathname = pathname.replace(/\//g, Path.win32.sep)
4949
pathname = decodeURIComponent(pathname)
5050
if (u.hostname !== '') {
5151
localPath = `\\\\${url.domainToUnicode(u.hostname)}${pathname}`
@@ -123,14 +123,16 @@ function pathOrUrlToUrl(path: string): string {
123123
try {
124124
// try to parse, but do not modify
125125
new URL(path).toString()
126-
return path
126+
// super simple relative path resolver
127+
return simpleResolveUrl(path)
127128
} catch (ex) {
128129
// should be a path
129130
}
130131
}
131132
// Not a URL, do some windows path mangling before it is converted to URL
132133
if (path.startsWith('\\\\')) {
133134
// UNC
135+
path = Path.win32.resolve(path)
134136
const hostEndIndex = path.indexOf('\\', 2)
135137
const host = path.substring(2, hostEndIndex)
136138
const outURL = new URL('file://')
@@ -147,6 +149,7 @@ function pathOrUrlToUrl(path: string): string {
147149
// // Xdebug always lowercases Windows drive letters in file URIs
148150
// //path = path.replace(/^[A-Z]:/, match => match.toLowerCase())
149151
// }
152+
path = isWindowsPath(path) ? Path.win32.resolve(path) : Path.posix.resolve(path)
150153
return fileUrl(path, { resolve: false })
151154
}
152155

@@ -163,3 +166,15 @@ export function isPositiveMatchInGlobs(path: string, globs: string[]): boolean {
163166
const f = globs.find(glob => minimatch(path, glob.charAt(0) == '!' ? glob.substring(1) : glob))
164167
return f !== undefined && f.charAt(0) !== '!'
165168
}
169+
170+
function simpleResolveUrl(path: string): string {
171+
if (path.indexOf('/../') != -1) {
172+
const pp = path.split('/')
173+
let i
174+
while ((i = pp.findIndex(v => v == '..')) > 0) {
175+
pp.splice(i - 1, 2)
176+
}
177+
path = pp.join('/')
178+
}
179+
return path
180+
}

src/test/paths.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,38 @@ describe('paths', () => {
180180
)
181181
})
182182
})
183+
describe('relative paths', () => {
184+
it('should resolve relative path posix', () => {
185+
assert.equal(convertClientPathToDebugger('/var/www/foo/../bar'), 'file:///var/www/bar')
186+
})
187+
it('should resolve relative path maps posix', () => {
188+
assert.equal(
189+
convertClientPathToDebugger('/work/foo/test.php', {
190+
'/var/www/html/bar': '/work/project/folder/../../foo',
191+
}),
192+
'file:///var/www/html/bar/test.php'
193+
)
194+
})
195+
it('should resolve relative path win32', () => {
196+
assert.equal(convertClientPathToDebugger('C:\\var\\www\\foo\\..\\bar'), 'file:///C:/var/www/bar')
197+
})
198+
it('should resolve relative path maps win32 to posix', () => {
199+
assert.equal(
200+
convertClientPathToDebugger('C:\\work\\foo\\test.php', {
201+
'/var/www/html/bar': 'C:\\work\\project\\folder\\..\\..\\foo',
202+
}),
203+
'file:///var/www/html/bar/test.php'
204+
)
205+
})
206+
it('should resolve relative path maps win32 to win32', () => {
207+
assert.equal(
208+
convertClientPathToDebugger('C:\\work\\foo\\test.php', {
209+
'C:\\var\\www\\html\\bar': 'C:\\work\\project\\folder\\..\\..\\foo',
210+
}),
211+
'file:///C:/var/www/html/bar/test.php'
212+
)
213+
})
214+
})
183215
})
184216
describe('convertDebuggerPathToClient', () => {
185217
describe('without source mapping', () => {
@@ -366,6 +398,22 @@ describe('paths', () => {
366398
'ssh://host/path/file.php'
367399
)
368400
})
401+
it('should map sshfs to remote unix relative', () => {
402+
assert.equal(
403+
convertClientPathToDebugger('ssh://host/path/file.php', {
404+
'/root/path': 'ssh://host/test/../path/',
405+
}),
406+
'file:///root/path/file.php'
407+
)
408+
})
409+
it('should map remote unix to sshfs relative', () => {
410+
assert.equal(
411+
convertDebuggerPathToClient('file:///root/path/file.php', {
412+
'/root/path': 'ssh://host/test/../path/',
413+
}),
414+
'ssh://host/path/file.php'
415+
)
416+
})
369417
})
370418
describe('UNC', () => {
371419
it('should convert UNC to url', () => {

0 commit comments

Comments
 (0)