Skip to content

Commit

Permalink
fix(fs.scandir): correctly handle the leading slash
Browse files Browse the repository at this point in the history
  • Loading branch information
mrmlnc committed Aug 15, 2020
1 parent 7f48cc8 commit 639f7b7
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 4 deletions.
5 changes: 3 additions & 2 deletions packages/fs/fs.scandir/src/providers/async.ts
Expand Up @@ -5,6 +5,7 @@ import { IS_SUPPORT_READDIR_WITH_FILE_TYPES } from '../constants';
import Settings from '../settings';
import { Entry, Stats } from '../types';
import * as utils from '../utils';
import * as common from './common';

type RplTaskStats = rpl.Task<Stats>;
type RplTaskEntry = rpl.Task<Entry>;
Expand All @@ -30,7 +31,7 @@ export function readdirWithFileTypes(directory: string, settings: Settings, call
const entries: Entry[] = dirents.map((dirent) => ({
dirent,
name: dirent.name,
path: `${directory}${settings.pathSegmentSeparator}${dirent.name}`
path: common.joinPathSegments(directory, dirent.name, settings.pathSegmentSeparator)
}));

if (!settings.followSymbolicLinks) {
Expand Down Expand Up @@ -77,7 +78,7 @@ export function readdir(directory: string, settings: Settings, callback: AsyncCa
return callFailureCallback(callback, readdirError);
}

const filepaths = names.map((name) => `${directory}${settings.pathSegmentSeparator}${name}`);
const filepaths = names.map((name) => common.joinPathSegments(directory, name, settings.pathSegmentSeparator));

const tasks: RplTaskStats[] = filepaths.map((filepath): RplTaskStats => {
return (done) => fsStat.stat(filepath, settings.fsStatSettings, done);
Expand Down
24 changes: 24 additions & 0 deletions packages/fs/fs.scandir/src/providers/common.spec.ts
@@ -0,0 +1,24 @@
import * as assert from 'assert';

import * as common from './common';

describe('Readers → Common', () => {
describe('.joinPathSegments', () => {
it('should return concatenated string', () => {
assert.strictEqual(common.joinPathSegments('.', 'a', '/'), './a');
});

it('should return correct string when the first segment ens with the separator symbol', () => {
// Unix
assert.strictEqual(common.joinPathSegments('/', 'a', '/'), '/a');
assert.strictEqual(common.joinPathSegments('//', 'a', '/'), '//a');
assert.strictEqual(common.joinPathSegments('/a/', 'b', '/'), '/a/b');

// Windows
assert.strictEqual(common.joinPathSegments('C:/', 'Users', '/'), 'C:/Users');
assert.strictEqual(common.joinPathSegments('C:\\', 'Users', '\\'), 'C:\\Users');
assert.strictEqual(common.joinPathSegments('//?/C:/', 'Users', '/'), '//?/C:/Users');
assert.strictEqual(common.joinPathSegments('\\\\?\\C:\\', 'Users', '\\'), '\\\\?\\C:\\Users');
});
});
});
10 changes: 10 additions & 0 deletions packages/fs/fs.scandir/src/providers/common.ts
@@ -0,0 +1,10 @@
export function joinPathSegments(a: string, b: string, separator: string): string {
/**
* The correct handling of cases when the first segment is a root (`/`, `C:/`) or UNC path (`//?/C:/`).
*/
if (a.endsWith(separator)) {
return a + b;
}

return a + separator + b;
}
5 changes: 3 additions & 2 deletions packages/fs/fs.scandir/src/providers/sync.ts
Expand Up @@ -4,6 +4,7 @@ import { IS_SUPPORT_READDIR_WITH_FILE_TYPES } from '../constants';
import Settings from '../settings';
import { Entry } from '../types';
import * as utils from '../utils';
import * as common from './common';

export function read(directory: string, settings: Settings): Entry[] {
if (!settings.stats && IS_SUPPORT_READDIR_WITH_FILE_TYPES) {
Expand All @@ -20,7 +21,7 @@ export function readdirWithFileTypes(directory: string, settings: Settings): Ent
const entry: Entry = {
dirent,
name: dirent.name,
path: `${directory}${settings.pathSegmentSeparator}${dirent.name}`
path: common.joinPathSegments(directory, dirent.name, settings.pathSegmentSeparator)
};

if (entry.dirent.isSymbolicLink() && settings.followSymbolicLinks) {
Expand All @@ -43,7 +44,7 @@ export function readdir(directory: string, settings: Settings): Entry[] {
const names = settings.fs.readdirSync(directory);

return names.map((name) => {
const entryPath = `${directory}${settings.pathSegmentSeparator}${name}`;
const entryPath = common.joinPathSegments(directory, name, settings.pathSegmentSeparator);
const stats = fsStat.statSync(entryPath, settings.fsStatSettings);

const entry: Entry = {
Expand Down

0 comments on commit 639f7b7

Please sign in to comment.