Skip to content

Commit

Permalink
fix: support windows path with drive or unc volume
Browse files Browse the repository at this point in the history
  • Loading branch information
sttk committed Jul 1, 2023
1 parent 3a14ff5 commit f923d5c
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 3 deletions.
1 change: 1 addition & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package-lock=false
33 changes: 30 additions & 3 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
'use strict';

var isGlob = require('is-glob');
var pathPosixDirname = require('path').posix.dirname;
var path = require('path');
var pathPosixDirname = path.posix.dirname;
var isWin32 = require('os').platform() === 'win32';

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

var winDriveOrUncVolume = '';
if (isWin32) {
winDriveOrUncVolume = getWinDriveOrUncVolume(str);
str = str.slice(winDriveOrUncVolume.length);
}

// flip windows path separators
if (options.flipBackslashes && isWin32 && str.indexOf(slash) < 0) {
str = str.replace(backslash, slash);
Expand All @@ -28,14 +35,23 @@ module.exports = function globParent(str, opts) {

// preserves full path in case of trailing path separator
str += 'a';

// remove path parts that are globby
do {
str = pathPosixDirname(str);
} while (isGlobby(str));

// remove escape chars and return result
return str.replace(escaped, '$1');
str = str.replace(escaped, '$1');

// replace continuous slashes to single slash
str = str.replace(/\/+/g, '/');

if (isWin32 && winDriveOrUncVolume) {
str = winDriveOrUncVolume + str;
}

return str;
};

function isEnclosure(str) {
Expand Down Expand Up @@ -73,3 +89,14 @@ function isGlobby(str) {
}
return isGlob(str);
}

function getWinDriveOrUncVolume(fp) {
if (/^([a-zA-Z]:|\\\\)/.test(fp)) {
var root = path.win32.parse(fp).root;
if (path.win32.isAbsolute(fp)) {
root = root.slice(0, -1); // Strip last path separator
}
return root;
}
return '';
}
Empty file removed test/.gitkeep
Empty file.
71 changes: 71 additions & 0 deletions test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ describe('glob-parent', function () {
expect(gp('.*')).toEqual('.');
expect(gp('/.*')).toEqual('/');
expect(gp('/.*/')).toEqual('/');
expect(gp('//')).toEqual('/');
expect(gp('//*')).toEqual('/');
expect(gp('.//')).toEqual('./');
expect(gp('.//*')).toEqual('./');
expect(gp('a/.*/b')).toEqual('a');
expect(gp('a*/.*/b')).toEqual('.');
expect(gp('*/a/b/c')).toEqual('.');
Expand Down Expand Up @@ -258,4 +262,71 @@ if (isWin32) {
done();
});
});

describe('windows path with drive or UNC volume', function() {
it('should return parent dirname from absolute path with drive letter', function(done) {
expect(gp('C:/')).toEqual('C:/');
expect(gp('C:/.')).toEqual('C:/');
expect(gp('C:/*')).toEqual('C:/');
expect(gp('C:/./*')).toEqual('C:/.');
expect(gp('C://')).toEqual('C:/');
expect(gp('C://*')).toEqual('C:/');
expect(gp('C:/path/*.js')).toEqual('C:/path');

expect(gp('C:\\')).toEqual('C:/');
expect(gp('C:\\.')).toEqual('C:/');
expect(gp('C:\\*')).toEqual('C:/');
expect(gp('C:\\.\\*')).toEqual('C:/.');
expect(gp('C:\\\\')).toEqual('C:/');
expect(gp('C:\\\\*')).toEqual('C:/');
expect(gp('C:\\path\\*.js')).toEqual('C:/path');

done();
});

it('should return parent dirname from relative path with drive letter', function(done) {
expect(gp('C:')).toEqual('C:.');
expect(gp('C:.')).toEqual('C:.');
expect(gp('C:*')).toEqual('C:.');
expect(gp('C:./*')).toEqual('C:.');
expect(gp('C:.//')).toEqual('C:./');
expect(gp('C:.//*')).toEqual('C:./');
expect(gp('C:path/*.js')).toEqual('C:path');

expect(gp('C:.\\*')).toEqual('C:.');
expect(gp('C:.\\\\')).toEqual('C:./');
expect(gp('C:.\\\\*')).toEqual('C:./');
expect(gp('C:path\\*.js')).toEqual('C:path');

done();
});

it('should return parent dirname from UNC path', function(done) {
expect(gp('\\\\System07\\C$/')).toEqual('\\\\System07\\C$/');
expect(gp('\\\\System07\\C$/.')).toEqual('\\\\System07\\C$/');
expect(gp('\\\\System07\\C$/*')).toEqual('\\\\System07\\C$/');
expect(gp('\\\\System07\\C$/./*')).toEqual('\\\\System07\\C$/.');
expect(gp('\\\\System07\\C$//')).toEqual('\\\\System07\\C$/');
expect(gp('\\\\System07\\C$//*')).toEqual('\\\\System07\\C$/');
expect(gp('\\\\System07\\C$/path/*.js')).toEqual('\\\\System07\\C$/path');

expect(gp('\\\\System07\\C$/', { flipBackslashes: false })).toEqual('\\\\System07\\C$/');
expect(gp('\\\\System07\\C$/.', { flipBackslashes: false })).toEqual('\\\\System07\\C$/');
expect(gp('\\\\System07\\C$/*', { flipBackslashes: false })).toEqual('\\\\System07\\C$/');
expect(gp('\\\\System07\\C$/./*', { flipBackslashes: false })).toEqual('\\\\System07\\C$/.');
expect(gp('\\\\System07\\C$//', { flipBackslashes: false })).toEqual('\\\\System07\\C$/');
expect(gp('\\\\System07\\C$//*', { flipBackslashes: false })).toEqual('\\\\System07\\C$/');
expect(gp('\\\\System07\\C$/path/*.js')).toEqual('\\\\System07\\C$/path');

expect(gp('\\\\System07\\C$\\')).toEqual('\\\\System07\\C$/');
expect(gp('\\\\System07\\C$\\.')).toEqual('\\\\System07\\C$/');
expect(gp('\\\\System07\\C$\\*')).toEqual('\\\\System07\\C$/');
expect(gp('\\\\System07\\C$\\.\\*')).toEqual('\\\\System07\\C$/.');
expect(gp('\\\\System07\\C$\\\\')).toEqual('\\\\System07\\C$/');
expect(gp('\\\\System07\\C$\\\\*')).toEqual('\\\\System07\\C$/');
expect(gp('\\\\System07\\C$\\path\\*.js')).toEqual('\\\\System07\\C$/path');

done();
});
});
}

0 comments on commit f923d5c

Please sign in to comment.