Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix!: remove last '.' and `./' #66

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions .npmrc
@@ -0,0 +1 @@
package-lock=false
45 changes: 42 additions & 3 deletions index.js
@@ -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,35 @@ 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, '/');

// remove last single dot
if (str.slice(-2) === '/.') {
str = str.slice(0, -1)
}
// remove last './'
while (str.slice(-3) === '/./') {
str = str.slice(0, -2)
}

if (isWin32 && winDriveOrUncVolume) {
if (str === '.' || str === './') {
str = '';
}
str = winDriveOrUncVolume + str;
}

return str;
};

function isEnclosure(str) {
Expand Down Expand Up @@ -73,3 +101,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.
106 changes: 106 additions & 0 deletions test/index.test.js
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 @@ -248,6 +252,41 @@ describe('glob2base test patterns', function () {
gp('/('.repeat(500000) + ')');
done();
});

it('should remove tail \'.\' and \'./\'', function(done) {
expect(gp('foo/./*')).toEqual('foo/');
expect(gp('foo/./././*')).toEqual('foo/');
expect(gp('./././*')).toEqual('./');
expect(gp('/./././*')).toEqual('/');

if (isWin32) {
expect(gp('C:/foo/./*')).toEqual('C:/foo/');
expect(gp('C:/foo/./././*')).toEqual('C:/foo/');
expect(gp('C:/./././*')).toEqual('C:/');

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

expect(gp('C:foo/./*')).toEqual('C:foo/');
expect(gp('C:foo/./././*')).toEqual('C:foo/');
expect(gp('C:./././*')).toEqual('C:');

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

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

expect(gp('\\\\System07\\C$\\foo\\.\\*')).toEqual('\\\\System07\\C$/foo/');
expect(gp('\\\\System07\\C$\\foo\\.\\.\\.\\*')).toEqual('\\\\System07\\C$/foo/');
expect(gp('\\\\System07\\C$\\.\\.\\.\\*')).toEqual('\\\\System07\\C$/');
}

done();
});
});

if (isWin32) {
Expand All @@ -258,4 +297,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();
});
});
}