Skip to content

Commit f923d5c

Browse files
committed
fix: support windows path with drive or unc volume
1 parent 3a14ff5 commit f923d5c

File tree

4 files changed

+102
-3
lines changed

4 files changed

+102
-3
lines changed

.npmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
package-lock=false

index.js

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
'use strict';
22

33
var isGlob = require('is-glob');
4-
var pathPosixDirname = require('path').posix.dirname;
4+
var path = require('path');
5+
var pathPosixDirname = path.posix.dirname;
56
var isWin32 = require('os').platform() === 'win32';
67

78
var slash = '/';
@@ -16,6 +17,12 @@ var escaped = /\\([!*?|[\](){}])/g;
1617
module.exports = function globParent(str, opts) {
1718
var options = Object.assign({ flipBackslashes: true }, opts);
1819

20+
var winDriveOrUncVolume = '';
21+
if (isWin32) {
22+
winDriveOrUncVolume = getWinDriveOrUncVolume(str);
23+
str = str.slice(winDriveOrUncVolume.length);
24+
}
25+
1926
// flip windows path separators
2027
if (options.flipBackslashes && isWin32 && str.indexOf(slash) < 0) {
2128
str = str.replace(backslash, slash);
@@ -28,14 +35,23 @@ module.exports = function globParent(str, opts) {
2835

2936
// preserves full path in case of trailing path separator
3037
str += 'a';
31-
38+
3239
// remove path parts that are globby
3340
do {
3441
str = pathPosixDirname(str);
3542
} while (isGlobby(str));
3643

3744
// remove escape chars and return result
38-
return str.replace(escaped, '$1');
45+
str = str.replace(escaped, '$1');
46+
47+
// replace continuous slashes to single slash
48+
str = str.replace(/\/+/g, '/');
49+
50+
if (isWin32 && winDriveOrUncVolume) {
51+
str = winDriveOrUncVolume + str;
52+
}
53+
54+
return str;
3955
};
4056

4157
function isEnclosure(str) {
@@ -73,3 +89,14 @@ function isGlobby(str) {
7389
}
7490
return isGlob(str);
7591
}
92+
93+
function getWinDriveOrUncVolume(fp) {
94+
if (/^([a-zA-Z]:|\\\\)/.test(fp)) {
95+
var root = path.win32.parse(fp).root;
96+
if (path.win32.isAbsolute(fp)) {
97+
root = root.slice(0, -1); // Strip last path separator
98+
}
99+
return root;
100+
}
101+
return '';
102+
}

test/.gitkeep

Whitespace-only changes.

test/index.test.js

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ describe('glob-parent', function () {
1010
expect(gp('.*')).toEqual('.');
1111
expect(gp('/.*')).toEqual('/');
1212
expect(gp('/.*/')).toEqual('/');
13+
expect(gp('//')).toEqual('/');
14+
expect(gp('//*')).toEqual('/');
15+
expect(gp('.//')).toEqual('./');
16+
expect(gp('.//*')).toEqual('./');
1317
expect(gp('a/.*/b')).toEqual('a');
1418
expect(gp('a*/.*/b')).toEqual('.');
1519
expect(gp('*/a/b/c')).toEqual('.');
@@ -258,4 +262,71 @@ if (isWin32) {
258262
done();
259263
});
260264
});
265+
266+
describe('windows path with drive or UNC volume', function() {
267+
it('should return parent dirname from absolute path with drive letter', function(done) {
268+
expect(gp('C:/')).toEqual('C:/');
269+
expect(gp('C:/.')).toEqual('C:/');
270+
expect(gp('C:/*')).toEqual('C:/');
271+
expect(gp('C:/./*')).toEqual('C:/.');
272+
expect(gp('C://')).toEqual('C:/');
273+
expect(gp('C://*')).toEqual('C:/');
274+
expect(gp('C:/path/*.js')).toEqual('C:/path');
275+
276+
expect(gp('C:\\')).toEqual('C:/');
277+
expect(gp('C:\\.')).toEqual('C:/');
278+
expect(gp('C:\\*')).toEqual('C:/');
279+
expect(gp('C:\\.\\*')).toEqual('C:/.');
280+
expect(gp('C:\\\\')).toEqual('C:/');
281+
expect(gp('C:\\\\*')).toEqual('C:/');
282+
expect(gp('C:\\path\\*.js')).toEqual('C:/path');
283+
284+
done();
285+
});
286+
287+
it('should return parent dirname from relative path with drive letter', function(done) {
288+
expect(gp('C:')).toEqual('C:.');
289+
expect(gp('C:.')).toEqual('C:.');
290+
expect(gp('C:*')).toEqual('C:.');
291+
expect(gp('C:./*')).toEqual('C:.');
292+
expect(gp('C:.//')).toEqual('C:./');
293+
expect(gp('C:.//*')).toEqual('C:./');
294+
expect(gp('C:path/*.js')).toEqual('C:path');
295+
296+
expect(gp('C:.\\*')).toEqual('C:.');
297+
expect(gp('C:.\\\\')).toEqual('C:./');
298+
expect(gp('C:.\\\\*')).toEqual('C:./');
299+
expect(gp('C:path\\*.js')).toEqual('C:path');
300+
301+
done();
302+
});
303+
304+
it('should return parent dirname from UNC path', function(done) {
305+
expect(gp('\\\\System07\\C$/')).toEqual('\\\\System07\\C$/');
306+
expect(gp('\\\\System07\\C$/.')).toEqual('\\\\System07\\C$/');
307+
expect(gp('\\\\System07\\C$/*')).toEqual('\\\\System07\\C$/');
308+
expect(gp('\\\\System07\\C$/./*')).toEqual('\\\\System07\\C$/.');
309+
expect(gp('\\\\System07\\C$//')).toEqual('\\\\System07\\C$/');
310+
expect(gp('\\\\System07\\C$//*')).toEqual('\\\\System07\\C$/');
311+
expect(gp('\\\\System07\\C$/path/*.js')).toEqual('\\\\System07\\C$/path');
312+
313+
expect(gp('\\\\System07\\C$/', { flipBackslashes: false })).toEqual('\\\\System07\\C$/');
314+
expect(gp('\\\\System07\\C$/.', { flipBackslashes: false })).toEqual('\\\\System07\\C$/');
315+
expect(gp('\\\\System07\\C$/*', { flipBackslashes: false })).toEqual('\\\\System07\\C$/');
316+
expect(gp('\\\\System07\\C$/./*', { flipBackslashes: false })).toEqual('\\\\System07\\C$/.');
317+
expect(gp('\\\\System07\\C$//', { flipBackslashes: false })).toEqual('\\\\System07\\C$/');
318+
expect(gp('\\\\System07\\C$//*', { flipBackslashes: false })).toEqual('\\\\System07\\C$/');
319+
expect(gp('\\\\System07\\C$/path/*.js')).toEqual('\\\\System07\\C$/path');
320+
321+
expect(gp('\\\\System07\\C$\\')).toEqual('\\\\System07\\C$/');
322+
expect(gp('\\\\System07\\C$\\.')).toEqual('\\\\System07\\C$/');
323+
expect(gp('\\\\System07\\C$\\*')).toEqual('\\\\System07\\C$/');
324+
expect(gp('\\\\System07\\C$\\.\\*')).toEqual('\\\\System07\\C$/.');
325+
expect(gp('\\\\System07\\C$\\\\')).toEqual('\\\\System07\\C$/');
326+
expect(gp('\\\\System07\\C$\\\\*')).toEqual('\\\\System07\\C$/');
327+
expect(gp('\\\\System07\\C$\\path\\*.js')).toEqual('\\\\System07\\C$/path');
328+
329+
done();
330+
});
331+
});
261332
}

0 commit comments

Comments
 (0)