Skip to content

Commit

Permalink
Removed internal supportsLinks
Browse files Browse the repository at this point in the history
Removed FileSystem.realpath (internal)
  • Loading branch information
james-pre committed Mar 5, 2024
1 parent ecd4353 commit 91c29c6
Show file tree
Hide file tree
Showing 8 changed files with 44 additions and 151 deletions.
14 changes: 0 additions & 14 deletions src/backends/Locked.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,20 +153,6 @@ export default class LockedFS<T extends FileSystem> implements FileSystem {
return this.fs.existsSync(p, cred);
}

public async realpath(p: string, cred: Cred): Promise<string> {
await this._mu.lock(p);
const resolvedPath = await this.fs.realpath(p, cred);
this._mu.unlock(p);
return resolvedPath;
}

public realpathSync(p: string, cred: Cred): string {
if (this._mu.isLocked(p)) {
throw new Error('invalid sync call');
}
return this.fs.realpathSync(p, cred);
}

public async link(srcpath: string, dstpath: string, cred: Cred): Promise<void> {
await this._mu.lock(srcpath);
await this.fs.link(srcpath, dstpath, cred);
Expand Down
1 change: 0 additions & 1 deletion src/backends/SyncStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,6 @@ export class SyncStoreFileSystem extends SyncFileSystem {
return {
name: this.store.name,
readonly: false,
supportsLinks: false,
supportsProperties: true,
synchronous: true,
freeSpace: 0,
Expand Down
2 changes: 1 addition & 1 deletion src/emulation/promises.ts
Original file line number Diff line number Diff line change
Expand Up @@ -611,7 +611,7 @@ rmdir satisfies typeof Node.promises.rmdir;
export async function mkdir(path: PathLike, mode?: Node.Mode | (Node.MakeDirectoryOptions & { recursive?: false })): Promise<void>;
export async function mkdir(path: PathLike, mode: Node.MakeDirectoryOptions & { recursive: true }): Promise<string>;
export async function mkdir(path: PathLike, mode?: Node.Mode | Node.MakeDirectoryOptions): Promise<string | void> {
return doOp('mkdir', true, path, normalizeMode(typeof mode == 'object' ? mode?.mode : mode, 0o777), cred);
await doOp('mkdir', true, path, normalizeMode(typeof mode == 'object' ? mode?.mode : mode, 0o777), cred);
}
mkdir satisfies typeof Node.promises.mkdir;

Expand Down
57 changes: 0 additions & 57 deletions src/filesystem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,6 @@ export interface FileSystemMetadata {
*/
supportsProperties: boolean;

/**
* Does the FS support links
*/
supportsLinks: boolean;

/**
* The total space
*/
Expand Down Expand Up @@ -75,7 +70,6 @@ export abstract class FileSystem {
readonly: false,
synchronous: false,
supportsProperties: false,
supportsLinks: false,
totalSpace: 0,
freeSpace: 0,
};
Expand Down Expand Up @@ -199,57 +193,6 @@ export abstract class FileSystem {
}
}

/**
* Asynchronous `realpath`.
*
* Note that the Node API will resolve `path` to an absolute path.
*/
public async realpath(path: string, cred: Cred): Promise<string> {
if (this.metadata.supportsLinks) {
// The path could contain symlinks. Split up the path,
// resolve any symlinks, return the resolved string.
const splitPath = path.split(sep);
// TODO: Simpler to just pass through file, find sep and such.
for (let i = 0; i < splitPath.length; i++) {
const addPaths = splitPath.slice(0, i + 1);
splitPath[i] = join(...addPaths);
}
return splitPath.join(sep);
} else {
// No symlinks. We just need to verify that it exists.
if (!(await this.exists(path, cred))) {
throw ApiError.ENOENT(path);
}
return path;
}
}

/**
* Synchronous `realpath`.
*
* Note that the Node API will resolve `path` to an absolute path.
*/
public realpathSync(path: string, cred: Cred): string {
if (this.metadata.supportsLinks) {
// The path could contain symlinks. Split up the path,
// resolve any symlinks, return the resolved string.
const splitPath = path.split(sep);
// TODO: Simpler to just pass through file, find sep and such.
for (let i = 0; i < splitPath.length; i++) {
const addPaths = splitPath.slice(0, i + 1);
splitPath[i] = join(...addPaths);
}
return splitPath.join(sep);
} else {
// No symlinks. We just need to verify that it exists.
if (this.existsSync(path, cred)) {
return path;
} else {
throw ApiError.ENOENT(path);
}
}
}

/**
* Asynchronous `link`.
*/
Expand Down
14 changes: 3 additions & 11 deletions test/tests/chmod.test.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,14 @@
import { fs, createMockStats, backends, configure, tmpDir, fixturesDir } from '../common';
import { fs, createMockStats, fixturesDir } from '../common';
import * as path from 'path';
import { jest } from '@jest/globals';

const isWindows = process.platform === 'win32';
const asyncMode = 0o777;
const modeSync = 0o644;

describe.each(backends)('%s chmod tests', (name, options) => {
const configured = configure(options);

afterEach(() => {
jest.restoreAllMocks();
});
describe('chmod tests', () => {

it('should change file mode using chmod', async () => {
await configured;
const file1 = path.join(fixturesDir, 'a.js');

jest.spyOn(fs, 'chmod').mockImplementation(async (path, mode) => {
Expand All @@ -33,7 +27,6 @@ describe.each(backends)('%s chmod tests', (name, options) => {
});

it('should change file mode using fchmod', async () => {
await configured;
const file2 = path.join(fixturesDir, 'a1.js');

jest.spyOn(fs, 'open').mockImplementation(async (path, flags, mode) => {
Expand All @@ -58,8 +51,7 @@ describe.each(backends)('%s chmod tests', (name, options) => {
});

it('should change symbolic link mode using lchmod', async () => {
await configured;
const link = path.join(tmpDir, 'symbolic-link');
const link = path.join('symbolic-link');
const file2 = path.join(fixturesDir, 'a1.js');

jest.spyOn(fs, 'unlinkSync').mockImplementation(path => {
Expand Down
22 changes: 6 additions & 16 deletions test/tests/error-messages.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,20 +48,15 @@ describe.each(backends)('%s Error tests', (name, options) => {
await expectError(fs.promises.open, fn, 'r');
await expectError(fs.promises.readdir, fn);
await expectError(fs.promises.unlink, fn);

if (fs.getMount('/').metadata.supportsLinks) {
await expectError(fs.promises.link, fn, 'foo');
}
await expectError(fs.promises.link, fn, 'foo');

if (fs.getMount('/').metadata.supportsProperties) {
await expectError(fs.promises.chmod, fn, 0o666);
}
}

if (fs.getMount('/').metadata.supportsLinks) {
await expectError(fs.promises.lstat, fn);
await expectError(fs.promises.readlink, fn);
}
await expectError(fs.promises.lstat, fn);
await expectError(fs.promises.readlink, fn);
});

// Sync operations
Expand All @@ -81,20 +76,15 @@ describe.each(backends)('%s Error tests', (name, options) => {
expectSyncError(fs.openSync, fn, 'r');
expectSyncError(fs.readdirSync, fn);
expectSyncError(fs.unlinkSync, fn);
expectSyncError(fs.linkSync, fn, 'foo');

if (fs.getMount('/').metadata.supportsProperties) {
expectSyncError(fs.chmodSync, fn, 0o666);
}

if (fs.getMount('/').metadata.supportsLinks) {
expectSyncError(fs.linkSync, fn, 'foo');
}
}

if (fs.getMount('/').metadata.supportsLinks) {
expectSyncError(fs.lstatSync, fn);
expectSyncError(fs.readlinkSync, fn);
}
expectSyncError(fs.lstatSync, fn);
expectSyncError(fs.readlinkSync, fn);
});
}
});
13 changes: 5 additions & 8 deletions test/tests/null-bytes.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,11 @@ describe.each(backends)('%s fs path validation', (name, options) => {
check(fs.promises.truncate, fs.truncateSync, 'foo\u0000bar');
check(fs.promises.unlink, fs.unlinkSync, 'foo\u0000bar');
check(fs.promises.writeFile, fs.writeFileSync, 'foo\u0000bar');

if (fs.getMount('/').metadata.supportsLinks) {
check(fs.promises.link, fs.linkSync, 'foo\u0000bar', 'foobar');
check(fs.promises.link, fs.linkSync, 'foobar', 'foo\u0000bar');
check(fs.promises.readlink, fs.readlinkSync, 'foo\u0000bar');
check(fs.promises.symlink, fs.symlinkSync, 'foo\u0000bar', 'foobar');
check(fs.promises.symlink, fs.symlinkSync, 'foobar', 'foo\u0000bar');
}
check(fs.promises.link, fs.linkSync, 'foo\u0000bar', 'foobar');
check(fs.promises.link, fs.linkSync, 'foobar', 'foo\u0000bar');
check(fs.promises.readlink, fs.readlinkSync, 'foo\u0000bar');
check(fs.promises.symlink, fs.symlinkSync, 'foo\u0000bar', 'foobar');
check(fs.promises.symlink, fs.symlinkSync, 'foobar', 'foo\u0000bar');

if (fs.getMount('/').metadata.supportsProperties) {
check(fs.promises.chmod, fs.chmodSync, 'foo\u0000bar', '0644');
Expand Down
72 changes: 29 additions & 43 deletions test/tests/symlink.test.ts
Original file line number Diff line number Diff line change
@@ -1,59 +1,48 @@
import { backends, fs, configure, tmpDir, fixturesDir } from '../common';
import { backends, fs, fixturesDir } from '../common';
import * as path from 'path';

describe.each(backends)('%s Link and Symlink Test', (name, options) => {
const configured = configure(options);

it('should create and read symbolic link', async () => {
await configured;
if (fs.getMount('/').metadata.supportsLinks) {
const linkData = path.join(fixturesDir, '/cycles/root.js');
const linkPath = path.join(tmpDir, 'symlink1.js');
const linkData = path.join(fixturesDir, '/cycles/root.js');
const linkPath = 'symlink1.js';

// Delete previously created link
try {
await fs.promises.unlink(linkPath);
} catch (e) {}
// Delete previously created link
try {
await fs.promises.unlink(linkPath);
} catch (e) {}

await fs.promises.symlink(linkData, linkPath);
console.log('symlink done');
await fs.promises.symlink(linkData, linkPath);
console.log('symlink done');

const destination = await fs.promises.readlink(linkPath);
expect(destination).toBe(linkData);
}
const destination = await fs.promises.readlink(linkPath);
expect(destination).toBe(linkData);
});

it('should create and read hard link', async () => {
await configured;
if (fs.getMount('/').metadata.supportsLinks) {
const srcPath = path.join(fixturesDir, 'cycles', 'root.js');
const dstPath = path.join(tmpDir, 'link1.js');

// Delete previously created link
try {
await fs.promises.unlink(dstPath);
} catch (e) {}

await fs.promises.link(srcPath, dstPath);
console.log('hard link done');

const srcContent = await fs.promises.readFile(srcPath, 'utf8');
const dstContent = await fs.promises.readFile(dstPath, 'utf8');
expect(srcContent).toBe(dstContent);
}
const srcPath = path.join(fixturesDir, 'cycles', 'root.js');
const dstPath = 'link1.js';

// Delete previously created link
try {
await fs.promises.unlink(dstPath);
} catch (e) {}

await fs.promises.link(srcPath, dstPath);
console.log('hard link done');

const srcContent = await fs.promises.readFile(srcPath, 'utf8');
const dstContent = await fs.promises.readFile(dstPath, 'utf8');
expect(srcContent).toBe(dstContent);
});
});

describe.each(backends)('%s Symbolic Link Test', (name, options) => {
const configured = configure(options);

// test creating and reading symbolic link
const linkData = path.join(fixturesDir, 'cycles/');
const linkPath = path.join(tmpDir, 'cycles_link');
const linkPath = 'cycles_link';

beforeAll(async () => {
await configured;

// Delete previously created link
await fs.promises.unlink(linkPath);

Expand All @@ -65,8 +54,7 @@ describe.each(backends)('%s Symbolic Link Test', (name, options) => {
});

it('should lstat symbolic link', async () => {
await configured;
if (fs.getMount('/').metadata.readonly || !fs.getMount('/').metadata.supportsLinks) {
if (fs.getMount('/').metadata.readonly) {
return;
}

Expand All @@ -75,17 +63,15 @@ describe.each(backends)('%s Symbolic Link Test', (name, options) => {
});

it('should readlink symbolic link', async () => {
await configured;
if (fs.getMount('/').metadata.readonly || !fs.getMount('/').metadata.supportsLinks) {
if (fs.getMount('/').metadata.readonly) {
return;
}
const destination = await fs.promises.readlink(linkPath);
expect(destination).toBe(linkData);
});

it('should unlink symbolic link', async () => {
await configured;
if (fs.getMount('/').metadata.readonly || !fs.getMount('/').metadata.supportsLinks) {
if (fs.getMount('/').metadata.readonly) {
return;
}
await fs.promises.unlink(linkPath);
Expand Down

0 comments on commit 91c29c6

Please sign in to comment.