Skip to content

Commit

Permalink
feat(utils): feat: use @nodelib/fs.walk [wip]
Browse files Browse the repository at this point in the history
  • Loading branch information
mrmlnc committed May 18, 2019
1 parent 10e45c4 commit 905289f
Show file tree
Hide file tree
Showing 19 changed files with 142 additions and 103 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"implementation"
],
"devDependencies": {
"@nodelib/fs.macchiato": "^1.0.0",
"@types/compute-stdev": "^1.0.0",
"@types/easy-table": "^0.0.32",
"@types/execa": "^0.9.0",
Expand Down Expand Up @@ -50,6 +51,7 @@
"dependencies": {
"@mrmlnc/readdir-enhanced": "^2.2.1",
"@nodelib/fs.stat": "^2.0.0",
"@nodelib/fs.walk": "^1.1.0",
"glob-parent": "^5.0.0",
"is-glob": "^4.0.0",
"merge2": "^1.2.3",
Expand Down
19 changes: 6 additions & 13 deletions src/adapters/fs-stream.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import * as assert from 'assert';
import * as fs from 'fs';

import { Stats } from '@nodelib/fs.macchiato';

import Settings from '../settings';
import { Entry, Pattern } from '../types/index';
import FileSystemStream from './fs-stream';
Expand All @@ -11,7 +13,7 @@ class FileSystemStreamFake extends FileSystemStream {
}

public getStat(): Promise<fs.Stats> {
return getStats(1);
return Promise.resolve(new Stats());
}
}

Expand All @@ -25,14 +27,10 @@ class FileSystemStreamThrowStatError extends FileSystemStreamFake {
return Promise.reject(new Error('something'));
}

return getStats(1);
return Promise.resolve(new Stats());
}
}

function getStats(uid: number): Promise<fs.Stats> {
return Promise.resolve({ uid } as fs.Stats);
}

function getAdapter(): FileSystemStreamFake {
return new FileSystemStreamFake();
}
Expand Down Expand Up @@ -91,15 +89,10 @@ describe('Adapters → FileSystemStream', () => {
it('should return created entry', async () => {
const adapter = getAdapter();

const expected: Entry = {
path: 'pattern',
depth: 1,
uid: 1
} as Entry;

const actual = await adapter.getEntry('filepath', 'pattern');

assert.deepStrictEqual(actual, expected);
assert.strictEqual((actual as Entry).name, 'pattern');
assert.strictEqual((actual as Entry).path, 'pattern');
});

it('should return null when lstat throw error', async () => {
Expand Down
19 changes: 6 additions & 13 deletions src/adapters/fs-sync.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import * as assert from 'assert';
import * as fs from 'fs';

import { Stats } from '@nodelib/fs.macchiato';

import Settings from '../settings';
import { Entry, Pattern } from '../types/index';
import FileSystemSync from './fs-sync';
Expand All @@ -11,7 +13,7 @@ class FileSystemSyncFake extends FileSystemSync {
}

public getStat(): fs.Stats {
return getStats(1);
return new Stats();
}
}

Expand All @@ -28,14 +30,10 @@ class FileSystemSyncThrowStatError extends FileSystemSyncFake {
throw new Error('Something');
}

return getStats(1);
return new Stats();
}
}

function getStats(uid: number): fs.Stats {
return { uid } as fs.Stats;
}

function getAdapter(): FileSystemSyncFake {
return new FileSystemSyncFake();
}
Expand Down Expand Up @@ -85,15 +83,10 @@ describe('Adapters → FileSystemSync', () => {
it('should return created entry', () => {
const adapter = getAdapter();

const expected: Entry = {
path: 'pattern',
depth: 1,
uid: 1
} as Entry;

const actual = adapter.getEntry('filepath', 'pattern');

assert.deepStrictEqual(actual, expected);
assert.strictEqual((actual as Entry).name, 'pattern');
assert.strictEqual((actual as Entry).path, 'pattern');
});

it('should return null when lstat throw error', () => {
Expand Down
15 changes: 4 additions & 11 deletions src/adapters/fs.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import * as assert from 'assert';
import * as path from 'path';

import { Stats } from '@nodelib/fs.macchiato';

import Settings from '../settings';
import * as tests from '../tests/index';
import FileSystem from './fs';

class FileSystemFake extends FileSystem<never[]> {
Expand Down Expand Up @@ -53,18 +54,10 @@ describe('Adapters → FileSystem', () => {
const adapter = getAdapter();

const filepath = path.join('base', 'file.json');
const actual = adapter.makeEntry(tests.getFileEntry(), filepath);
const actual = adapter.makeEntry(new Stats(), filepath);

assert.strictEqual(actual.path, filepath);
assert.strictEqual(actual.depth, 2);
});

it('issue-144: should return entry with methods from fs.Stats', () => {
const adapter = getAdapter();

const actual = adapter.makeEntry(tests.getFileEntry(), 'file.json');

assert.ok(actual.isFile());
assert.ok(actual.dirent.isFile());
});
});
});
16 changes: 12 additions & 4 deletions src/adapters/fs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import * as path from 'path';

import Settings from '../settings';
import { Entry, EntryFilterFunction, Pattern } from '../types/index';
import * as utils from '../utils/index';

export default abstract class FileSystem<T> {
constructor(private readonly _settings: Settings) { }
Expand All @@ -22,10 +23,17 @@ export default abstract class FileSystem<T> {
/**
* Return an implementation of the Entry interface.
*/
public makeEntry(stat: fs.Stats, pattern: Pattern): Entry {
(stat as Entry).path = pattern;
(stat as Entry).depth = pattern.split(path.sep).length;
public makeEntry(stats: fs.Stats, pattern: Pattern): Entry {
const entry: Entry = {
name: pattern,
path: pattern,
dirent: utils.fs.createDirentFromStats(pattern, stats)
};

return stat as Entry;
if (this._settings.stats) {
entry.stats = stats;
}

return entry;
}
}
2 changes: 1 addition & 1 deletion src/providers/filters/deep.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ function getDeepFilterInstance(options?: Options): DeepFilter {
}

function getFilter(positive: Pattern[], negative: Pattern[], options?: Options): EntryFilterFunction {
return getDeepFilterInstance(options).getFilter(positive, negative);
return getDeepFilterInstance(options).getFilter('base', positive, negative);
}

describe('Providers → Filters → Deep', () => {
Expand Down
17 changes: 11 additions & 6 deletions src/providers/filters/deep.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import * as path from 'path';

import Settings from '../../settings';
import { Entry, EntryFilterFunction, MicromatchOptions, Pattern, PatternRe } from '../../types/index';
import * as utils from '../../utils/index';
Expand All @@ -8,11 +10,11 @@ export default class DeepFilter {
/**
* Returns filter for directories.
*/
public getFilter(positive: Pattern[], negative: Pattern[]): EntryFilterFunction {
public getFilter(basePath: string, positive: Pattern[], negative: Pattern[]): EntryFilterFunction {
const maxPatternDepth = this._getMaxPatternDepth(positive);
const negativeRe: PatternRe[] = this._getNegativePatternsRe(negative);

return (entry: Entry) => this._filter(entry, negativeRe, maxPatternDepth);
return (entry: Entry) => this._filter(basePath, entry, negativeRe, maxPatternDepth);
}

/**
Expand All @@ -36,12 +38,15 @@ export default class DeepFilter {
/**
* Returns «true» for directory that should be read.
*/
private _filter(entry: Entry, negativeRe: PatternRe[], maxPatternDepth: number): boolean {
if (this._isSkippedByDeepOption(entry.depth)) {
private _filter(basePath: string, entry: Entry, negativeRe: PatternRe[], maxPatternDepth: number): boolean {
const basePathDepth = basePath.split(path.posix.sep).length;
const depth = entry.path.split(path.sep).length - (basePath === '' ? 0 : basePathDepth) - 1;

if (this._isSkippedByDeepOption(depth)) {
return false;
}

if (this._isSkippedByMaxPatternDepth(entry.depth, maxPatternDepth)) {
if (this._isSkippedByMaxPatternDepth(depth, maxPatternDepth)) {
return false;
}

Expand Down Expand Up @@ -74,7 +79,7 @@ export default class DeepFilter {
* Returns «true» for symlinked directory if the «followSymlinkedDirectories» option is disabled.
*/
private _isSkippedSymlinkedDirectory(entry: Entry): boolean {
return !this._settings.followSymlinkedDirectories && entry.isSymbolicLink();
return !this._settings.followSymlinkedDirectories && entry.dirent.isSymbolicLink();
}

/**
Expand Down
4 changes: 2 additions & 2 deletions src/providers/filters/entry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,14 +62,14 @@ export default class EntryFilter {
* Returns true for non-files if the «onlyFiles» option is enabled.
*/
private _onlyFileFilter(entry: Entry): boolean {
return this._settings.onlyFiles && !entry.isFile();
return this._settings.onlyFiles && !entry.dirent.isFile();
}

/**
* Returns true for non-directories if the «onlyDirectories» option is enabled.
*/
private _onlyDirectoryFilter(entry: Entry): boolean {
return this._settings.onlyDirectories && !entry.isDirectory();
return this._settings.onlyDirectories && !entry.dirent.isDirectory();
}

/**
Expand Down
10 changes: 6 additions & 4 deletions src/providers/provider.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,9 @@ describe('Providers → Provider', () => {
});

assert.strictEqual(actual.basePath, '');
assert.strictEqual(typeof actual.filter, 'function');
assert.strictEqual(typeof actual.deep, 'function');
assert.strictEqual(typeof actual.entryFilter, 'function');
assert.strictEqual(typeof actual.deepFilter, 'function');
assert.strictEqual(typeof actual.transform, 'function');
});

it('should return options for reader with non-global base (fixtures)', () => {
Expand All @@ -79,8 +80,9 @@ describe('Providers → Provider', () => {
});

assert.strictEqual(actual.basePath, 'fixtures');
assert.strictEqual(typeof actual.filter, 'function');
assert.strictEqual(typeof actual.deep, 'function');
assert.strictEqual(typeof actual.entryFilter, 'function');
assert.strictEqual(typeof actual.deepFilter, 'function');
assert.strictEqual(typeof actual.transform, 'function');
});
});

Expand Down
8 changes: 5 additions & 3 deletions src/providers/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,12 @@ export default abstract class Provider<T> {
* Returns options for reader.
*/
public getReaderOptions(task: Task): ReaderOptions {
const basePath = task.base === '.' ? '' : task.base;

return {
basePath: task.base === '.' ? '' : task.base,
filter: this.entryFilter.getFilter(task.positive, task.negative),
deep: this.deepFilter.getFilter(task.positive, task.negative),
basePath,
entryFilter: this.entryFilter.getFilter(task.positive, task.negative),
deepFilter: this.deepFilter.getFilter(basePath, task.positive, task.negative),
transform: this.entryTransformer.getTransformer()
};
}
Expand Down
2 changes: 1 addition & 1 deletion src/providers/transformers/entry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export default class EntryTransformer {
entry.path = utils.path.makeAbsolute(this._settings.cwd, entry.path);
}

if (this._settings.markDirectories && entry.isDirectory()) {
if (this._settings.markDirectories && entry.dirent.isDirectory()) {
entry.path = path.join(entry.path, path.sep);
}

Expand Down
8 changes: 4 additions & 4 deletions src/readers/stream.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import * as readdir from '@mrmlnc/readdir-enhanced';
import * as fsWalk from '@nodelib/fs.walk';

import FileSystemStream from '../adapters/fs-stream';
import { EntryFilterFunction, ReaderOptions } from '../types/index';
import { ReaderOptions } from '../types/index';
import Reader from './reader';

export default class ReaderStream extends Reader<NodeJS.ReadableStream> {
private readonly _fsAdapter: FileSystemStream = new FileSystemStream(this._settings);

public dynamic(root: string, options: ReaderOptions): NodeJS.ReadableStream {
return readdir.readdirStreamStat(root, options);
return fsWalk.walkStream(root, options);
}

public static(filepaths: string[], options: ReaderOptions): NodeJS.ReadableStream {
return this._fsAdapter.read(filepaths, options.filter as EntryFilterFunction);
return this._fsAdapter.read(filepaths, options.entryFilter);
}
}
8 changes: 4 additions & 4 deletions src/readers/sync.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import * as readdir from '@mrmlnc/readdir-enhanced';
import * as fsWalk from '@nodelib/fs.walk';

import FileSystemSync from '../adapters/fs-sync';
import { Entry, EntryFilterFunction, ReaderOptions } from '../types/index';
import { Entry, ReaderOptions } from '../types/index';
import Reader from './reader';

export default class ReaderSync extends Reader<Entry[]> {
private readonly _fsAdapter: FileSystemSync = new FileSystemSync(this._settings);

public dynamic(root: string, options: ReaderOptions): Entry[] {
return readdir.readdirSyncStat(root, options);
return fsWalk.walkSync(root, options);
}

public static(filepaths: string[], options: ReaderOptions): Entry[] {
return this._fsAdapter.read(filepaths, options.filter as EntryFilterFunction);
return this._fsAdapter.read(filepaths, options.entryFilter);
}
}
Loading

0 comments on commit 905289f

Please sign in to comment.