Remove unnecessary resources, add bulma, and add AdvMakefile

This commit is contained in:
2021-03-29 15:02:41 -07:00
parent 69f2d46a8c
commit bb2c9351d6
6084 changed files with 674187 additions and 0 deletions

View File

@@ -0,0 +1,236 @@
import * as assert from 'assert';
import * as fs from 'fs';
import * as path from 'path';
import * as sinon from 'sinon';
import { Dirent, Stats } from '../../../fs.macchiato';
import { IS_SUPPORT_READDIR_WITH_FILE_TYPES } from '../constants';
import Settings from '../settings';
import { Entry } from '../types';
import * as provider from './async';
const ROOT_PATH = 'root';
const FIRST_FILE_PATH = 'first.txt';
const SECOND_FILE_PATH = 'second.txt';
const FIRST_ENTRY_PATH = path.join(ROOT_PATH, FIRST_FILE_PATH);
const SECOND_ENTRY_PATH = path.join(ROOT_PATH, SECOND_FILE_PATH);
describe('Providers → Async', () => {
describe('.read', () => {
it('should call correct method based on Node.js version', (done) => {
const readdir = sinon.stub();
readdir.yields(null, []);
const settings = new Settings({
fs: { readdir: readdir as unknown as typeof fs.readdir }
});
provider.read(ROOT_PATH, settings, (error, entries) => {
assert.strictEqual(error, null);
assert.deepStrictEqual(entries, []);
if (IS_SUPPORT_READDIR_WITH_FILE_TYPES) {
sinon.assert.match(readdir.args, [[ROOT_PATH, { withFileTypes: true }, sinon.match.func]]);
} else {
sinon.assert.match(readdir.args, [[ROOT_PATH, sinon.match.func]]);
}
done();
});
});
it('should always use `readdir` method when the `stats` option is enabled', (done) => {
const readdir = sinon.stub();
readdir.yields(null, []);
const settings = new Settings({
fs: { readdir: readdir as unknown as typeof fs.readdir },
stats: true
});
provider.read(ROOT_PATH, settings, (error, entries) => {
assert.strictEqual(error, null);
assert.deepStrictEqual(entries, []);
sinon.assert.match(readdir.args, [[ROOT_PATH, sinon.match.func]]);
done();
});
});
});
describe('.readdirWithFileTypes', () => {
it('should return entries', (done) => {
const dirent = new Dirent({ name: FIRST_FILE_PATH });
const readdir = sinon.stub();
readdir.yields(null, [dirent]);
const settings = new Settings({
fs: { readdir: readdir as unknown as typeof fs.readdir }
});
const expected: Entry[] = [
{
dirent,
name: FIRST_FILE_PATH,
path: FIRST_ENTRY_PATH
}
];
provider.readdirWithFileTypes(ROOT_PATH, settings, (error, entries) => {
assert.strictEqual(error, null);
sinon.assert.match(readdir.args, [[ROOT_PATH, { withFileTypes: true }, sinon.match.func]]);
assert.deepStrictEqual(entries, expected);
done();
});
});
it('should call fs.stat for symbolic link when the "followSymbolicLink" option is enabled', (done) => {
const firstDirent = new Dirent({ name: FIRST_FILE_PATH });
const secondDirent = new Dirent({ name: SECOND_FILE_PATH, isSymbolicLink: true });
const stats = new Stats();
const readdir = sinon.stub();
const stat = sinon.stub();
readdir.yields(null, [firstDirent, secondDirent]);
stat.yields(null, stats);
const settings = new Settings({
followSymbolicLinks: true,
fs: {
readdir: readdir as unknown as typeof fs.readdir,
stat: stat as unknown as typeof fs.stat
}
});
provider.readdirWithFileTypes(ROOT_PATH, settings, (error, entries) => {
assert.strictEqual(error, null);
assert.strictEqual(entries.length, 2);
assert.ok(!entries[1].dirent.isSymbolicLink());
sinon.assert.match(stat.args, [[SECOND_ENTRY_PATH, sinon.match.func]]);
done();
});
});
it('should return lstat for broken symbolic link when the "throwErrorOnBrokenSymbolicLink" option is disabled', (done) => {
const firstDirent = new Dirent({ name: FIRST_FILE_PATH, isSymbolicLink: true });
const readdir = sinon.stub();
const stat = sinon.stub();
readdir.yields(null, [firstDirent]);
stat.yields(new Error('error'));
const settings = new Settings({
followSymbolicLinks: true,
throwErrorOnBrokenSymbolicLink: false,
fs: {
readdir: readdir as unknown as typeof fs.readdir,
stat: stat as unknown as typeof fs.stat
}
});
provider.readdirWithFileTypes(ROOT_PATH, settings, (error, entries) => {
assert.strictEqual(error, null);
assert.strictEqual(entries.length, 1);
assert.ok(entries[0].dirent.isSymbolicLink());
done();
});
});
it('should throw an error fro broken symbolic link when the "throwErrorOnBrokenSymbolicLink" option is enabled', (done) => {
const firstDirent = new Dirent({ name: FIRST_FILE_PATH, isSymbolicLink: true });
const readdir = sinon.stub();
const stat = sinon.stub();
readdir.yields(null, [firstDirent]);
stat.yields(new Error('error'));
const settings = new Settings({
followSymbolicLinks: true,
throwErrorOnBrokenSymbolicLink: true,
fs: {
readdir: readdir as unknown as typeof fs.readdir,
stat: stat as unknown as typeof fs.stat
}
});
provider.readdirWithFileTypes(ROOT_PATH, settings, (error, entries) => {
assert.strictEqual(error.message, 'error');
assert.strictEqual(entries, undefined);
done();
});
});
});
describe('.readdir', () => {
it('should return entries', (done) => {
const stats = new Stats();
const readdir = sinon.stub();
const lstat = sinon.stub();
readdir.yields(null, [FIRST_FILE_PATH]);
lstat.yields(null, stats);
const settings = new Settings({
fs: {
readdir: readdir as unknown as typeof fs.readdir,
lstat: lstat as unknown as typeof fs.lstat
}
});
provider.readdir(ROOT_PATH, settings, (error, entries) => {
assert.strictEqual(error, null);
sinon.assert.match(readdir.args, [[ROOT_PATH, sinon.match.func]]);
sinon.assert.match(lstat.args, [[FIRST_ENTRY_PATH, sinon.match.func]]);
assert.strictEqual(entries[0].name, FIRST_FILE_PATH);
assert.strictEqual(entries[0].path, FIRST_ENTRY_PATH);
assert.strictEqual(entries[0].dirent.name, FIRST_FILE_PATH);
done();
});
});
it('should return entries with `stats` property', (done) => {
const stats = new Stats();
const readdir = sinon.stub();
const lstat = sinon.stub();
readdir.yields(null, [FIRST_FILE_PATH]);
lstat.yields(null, stats);
const settings = new Settings({
fs: {
readdir: readdir as unknown as typeof fs.readdir,
lstat: lstat as unknown as typeof fs.lstat
},
stats: true
});
provider.readdir(ROOT_PATH, settings, (error, entries) => {
assert.strictEqual(error, null);
assert.deepStrictEqual(entries[0].stats, stats);
done();
});
});
});
});

View File

@@ -0,0 +1,121 @@
import * as fsStat from '@nodelib/fs.stat';
import * as rpl from 'run-parallel';
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>;
type FailureCallback = (err: NodeJS.ErrnoException) => void;
type SuccessCallback = (err: null, entries: Entry[]) => void;
export type AsyncCallback = (err: NodeJS.ErrnoException, entries: Entry[]) => void;
export function read(directory: string, settings: Settings, callback: AsyncCallback): void {
if (!settings.stats && IS_SUPPORT_READDIR_WITH_FILE_TYPES) {
return readdirWithFileTypes(directory, settings, callback);
}
return readdir(directory, settings, callback);
}
export function readdirWithFileTypes(directory: string, settings: Settings, callback: AsyncCallback): void {
settings.fs.readdir(directory, { withFileTypes: true }, (readdirError, dirents) => {
if (readdirError !== null) {
return callFailureCallback(callback, readdirError);
}
const entries: Entry[] = dirents.map((dirent) => ({
dirent,
name: dirent.name,
path: common.joinPathSegments(directory, dirent.name, settings.pathSegmentSeparator)
}));
if (!settings.followSymbolicLinks) {
return callSuccessCallback(callback, entries);
}
const tasks: RplTaskEntry[] = entries.map((entry) => makeRplTaskEntry(entry, settings));
rpl(tasks, (rplError: Error | null, rplEntries) => {
if (rplError !== null) {
return callFailureCallback(callback, rplError);
}
callSuccessCallback(callback, rplEntries);
});
});
}
function makeRplTaskEntry(entry: Entry, settings: Settings): RplTaskEntry {
return (done) => {
if (!entry.dirent.isSymbolicLink()) {
return done(null, entry);
}
settings.fs.stat(entry.path, (statError, stats) => {
if (statError !== null) {
if (settings.throwErrorOnBrokenSymbolicLink) {
return done(statError);
}
return done(null, entry);
}
entry.dirent = utils.fs.createDirentFromStats(entry.name, stats);
return done(null, entry);
});
};
}
export function readdir(directory: string, settings: Settings, callback: AsyncCallback): void {
settings.fs.readdir(directory, (readdirError, names) => {
if (readdirError !== null) {
return callFailureCallback(callback, readdirError);
}
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);
});
rpl(tasks, (rplError: Error | null, results) => {
if (rplError !== null) {
return callFailureCallback(callback, rplError);
}
const entries: Entry[] = [];
names.forEach((name, index) => {
const stats = results[index];
const entry: Entry = {
name,
path: filepaths[index],
dirent: utils.fs.createDirentFromStats(name, stats)
};
if (settings.stats) {
entry.stats = stats;
}
entries.push(entry);
});
callSuccessCallback(callback, entries);
});
});
}
function callFailureCallback(callback: AsyncCallback, error: NodeJS.ErrnoException): void {
(callback as FailureCallback)(error);
}
function callSuccessCallback(callback: AsyncCallback, result: Entry[]): void {
(callback as unknown as SuccessCallback)(null, result);
}

View File

@@ -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');
});
});
});

View File

@@ -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;
}

View File

@@ -0,0 +1,186 @@
import * as assert from 'assert';
import * as fs from 'fs';
import * as path from 'path';
import * as sinon from 'sinon';
import { Dirent, Stats } from '../../../fs.macchiato';
import { IS_SUPPORT_READDIR_WITH_FILE_TYPES } from '../constants';
import Settings from '../settings';
import { Entry } from '../types';
import * as provider from './sync';
const ROOT_PATH = 'root';
const FIRST_FILE_PATH = 'first.txt';
const SECOND_FILE_PATH = 'second.txt';
const FIRST_ENTRY_PATH = path.join(ROOT_PATH, FIRST_FILE_PATH);
const SECOND_ENTRY_PATH = path.join(ROOT_PATH, SECOND_FILE_PATH);
describe('Providers → Sync', () => {
describe('.read', () => {
it('should call correct method based on Node.js version', () => {
const readdirSync = sinon.stub().returns([]);
const settings = new Settings({
fs: { readdirSync: readdirSync as unknown as typeof fs.readdirSync }
});
const actual = provider.read(ROOT_PATH, settings);
assert.deepStrictEqual(actual, []);
if (IS_SUPPORT_READDIR_WITH_FILE_TYPES) {
assert.deepStrictEqual(readdirSync.args, [[ROOT_PATH, { withFileTypes: true }]]);
} else {
assert.deepStrictEqual(readdirSync.args, [[ROOT_PATH]]);
}
});
it('should always use `readdir` method when the `stats` option is enabled', () => {
const readdirSync = sinon.stub().returns([]);
const settings = new Settings({
fs: { readdirSync: readdirSync as unknown as typeof fs.readdirSync },
stats: true
});
provider.read(ROOT_PATH, settings);
assert.deepStrictEqual(readdirSync.args, [[ROOT_PATH]]);
});
});
describe('.readdirWithFileTypes', () => {
it('should return entries', () => {
const dirent = new Dirent({ name: FIRST_FILE_PATH });
const readdirSync = sinon.stub().returns([dirent]);
const settings = new Settings({
fs: { readdirSync: readdirSync as unknown as typeof fs.readdirSync }
});
const expected: Entry[] = [
{
dirent,
name: FIRST_FILE_PATH,
path: FIRST_ENTRY_PATH
}
];
const actual = provider.readdirWithFileTypes(ROOT_PATH, settings);
assert.deepStrictEqual(readdirSync.args, [[ROOT_PATH, { withFileTypes: true }]]);
assert.deepStrictEqual(actual, expected);
});
it('should call fs.stat for symbolic link when the "followSymbolicLink" option is enabled', () => {
const firstDirent = new Dirent({ name: FIRST_FILE_PATH });
const secondDirent = new Dirent({ name: SECOND_FILE_PATH, isSymbolicLink: true });
const stats = new Stats();
const readdirSync = sinon.stub().returns([firstDirent, secondDirent]);
const statSync = sinon.stub().returns(stats);
const settings = new Settings({
followSymbolicLinks: true,
fs: {
readdirSync: readdirSync as unknown as typeof fs.readdirSync,
statSync: statSync as unknown as typeof fs.statSync
}
});
const actual = provider.readdirWithFileTypes(ROOT_PATH, settings);
assert.strictEqual(actual.length, 2);
assert.deepStrictEqual(statSync.args, [[SECOND_ENTRY_PATH]]);
assert.ok(!actual[1].dirent.isSymbolicLink());
});
it('should return lstat for broken symbolic link when the "throwErrorOnBrokenSymbolicLink" option is disabled', () => {
const dirent = new Dirent({ name: FIRST_FILE_PATH, isSymbolicLink: true });
const readdirSync = sinon.stub().returns([dirent]);
const statSync = (): never => {
throw new Error('error');
};
const settings = new Settings({
followSymbolicLinks: true,
throwErrorOnBrokenSymbolicLink: false,
fs: {
readdirSync: readdirSync as unknown as typeof fs.readdirSync,
statSync: statSync as unknown as typeof fs.statSync
}
});
const actual = provider.readdirWithFileTypes(ROOT_PATH, settings);
assert.strictEqual(actual.length, 1);
});
it('should throw an error fro broken symbolic link when the "throwErrorOnBrokenSymbolicLink" option is enabled', () => {
const dirent = new Dirent({ name: FIRST_FILE_PATH, isSymbolicLink: true });
const readdirSync = sinon.stub().returns([dirent]);
const statSync = (): never => {
throw new Error('error');
};
const settings = new Settings({
followSymbolicLinks: true,
throwErrorOnBrokenSymbolicLink: true,
fs: {
readdirSync: readdirSync as unknown as typeof fs.readdirSync,
statSync: statSync as unknown as typeof fs.statSync
}
});
const expectedErrorMessageRe = /Error: error/;
assert.throws(() => provider.readdirWithFileTypes(ROOT_PATH, settings), expectedErrorMessageRe);
});
});
describe('.readdir', () => {
it('should return entries', () => {
const stats = new Stats();
const readdirSync = sinon.stub().returns([FIRST_FILE_PATH]);
const lstatSync = sinon.stub().returns(stats);
const settings = new Settings({
fs: {
readdirSync: readdirSync as unknown as typeof fs.readdirSync,
lstatSync: lstatSync as unknown as typeof fs.lstatSync
}
});
const actual = provider.readdir(ROOT_PATH, settings);
assert.deepStrictEqual(readdirSync.args, [[ROOT_PATH]]);
assert.strictEqual(actual[0].name, FIRST_FILE_PATH);
assert.strictEqual(actual[0].path, FIRST_ENTRY_PATH);
assert.strictEqual(actual[0].dirent.name, FIRST_FILE_PATH);
});
it('should return entries with `stats` property', () => {
const stats = new Stats();
const readdirSync = sinon.stub().returns([FIRST_FILE_PATH]);
const lstatSync = sinon.stub().returns(stats);
const settings = new Settings({
fs: {
readdirSync: readdirSync as unknown as typeof fs.readdirSync,
lstatSync: lstatSync as unknown as typeof fs.lstatSync
},
stats: true
});
const actual = provider.readdir(ROOT_PATH, settings);
assert.deepStrictEqual(actual[0].stats, stats);
});
});
});

View File

@@ -0,0 +1,62 @@
import * as fsStat from '@nodelib/fs.stat';
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) {
return readdirWithFileTypes(directory, settings);
}
return readdir(directory, settings);
}
export function readdirWithFileTypes(directory: string, settings: Settings): Entry[] {
const dirents = settings.fs.readdirSync(directory, { withFileTypes: true });
return dirents.map((dirent) => {
const entry: Entry = {
dirent,
name: dirent.name,
path: common.joinPathSegments(directory, dirent.name, settings.pathSegmentSeparator)
};
if (entry.dirent.isSymbolicLink() && settings.followSymbolicLinks) {
try {
const stats = settings.fs.statSync(entry.path);
entry.dirent = utils.fs.createDirentFromStats(entry.name, stats);
} catch (error) {
if (settings.throwErrorOnBrokenSymbolicLink) {
throw error;
}
}
}
return entry;
});
}
export function readdir(directory: string, settings: Settings): Entry[] {
const names = settings.fs.readdirSync(directory);
return names.map((name) => {
const entryPath = common.joinPathSegments(directory, name, settings.pathSegmentSeparator);
const stats = fsStat.statSync(entryPath, settings.fsStatSettings);
const entry: Entry = {
name,
path: entryPath,
dirent: utils.fs.createDirentFromStats(name, stats)
};
if (settings.stats) {
entry.stats = stats;
}
return entry;
});
}