Skip to content

Commit

Permalink
Merge branch 'main' into context
Browse files Browse the repository at this point in the history
  • Loading branch information
james-pre committed Nov 24, 2024
2 parents a54255b + b3ef005 commit 19c7a85
Show file tree
Hide file tree
Showing 16 changed files with 220 additions and 160 deletions.
16 changes: 8 additions & 8 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@zenfs/core",
"version": "1.3.3",
"version": "1.3.6",
"description": "A filesystem, anywhere",
"funding": {
"type": "individual",
Expand Down Expand Up @@ -74,10 +74,12 @@
"@types/readable-stream": "^4.0.10",
"buffer": "^6.0.3",
"eventemitter3": "^5.0.1",
"minimatch": "^9.0.3",
"readable-stream": "^4.5.2",
"utilium": "^1.0.0"
},
"optionalDependencies": {
"minimatch": "^9.0.3"
},
"devDependencies": {
"@eslint/js": "^9.8.0",
"@types/eslint__js": "^8.42.3",
Expand Down
2 changes: 2 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ await configure({
};
```
Note that while you aren't required to use absolute paths for the keys of `mounts`, it is a good practice to do so.
> [!TIP]
> When configuring a mount point, you can pass in
>
Expand Down
31 changes: 24 additions & 7 deletions scripts/make-index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#!/usr/bin/env node
import { readdirSync, statSync, writeFileSync } from 'node:fs';
import { minimatch } from 'minimatch';
import { join, relative, resolve } from 'node:path/posix';
import _path from 'node:path/posix';
import { parseArgs } from 'node:util';

const { values: options, positionals } = parseArgs({
Expand Down Expand Up @@ -37,6 +36,24 @@ if (options.quiet && options.verbose) {
process.exit();
}

let matchesGlob = _path.matchesGlob;

if (matchesGlob && options.verbose) {
console.debug('[debug] path.matchesGlob is available.');
}

if (!matchesGlob) {
console.warn('Warning: path.matchesGlob is not available, falling back to minimatch. (Node 20.17.0+ or 22.5.0+ needed)');

try {
const { minimatch } = await import('minimatch');
matchesGlob = minimatch;
} catch {
console.error('Fatal error: Failed to fall back to minimatch (is it installed?)');
process.exit(1);
}
}

function fixSlash(path) {
return path.replaceAll('\\', '/');
}
Expand Down Expand Up @@ -71,25 +88,25 @@ const entries = new Map();

function computeEntries(path) {
try {
if (options.ignore.some(pattern => minimatch(path, pattern))) {
if (options.ignore.some(pattern => matchesGlob(path, pattern))) {
if (!options.quiet) console.log(`${color('yellow', 'skip')} ${path}`);
return;
}

const stats = statSync(path);

if (stats.isFile()) {
entries.set('/' + relative(resolvedRoot, path), stats);
entries.set('/' + _path.relative(resolvedRoot, path), stats);
if (options.verbose) {
console.log(`${color('green', 'file')} ${path}`);
}
return;
}

for (const file of readdirSync(path)) {
computeEntries(join(path, file));
computeEntries(_path.join(path, file));
}
entries.set('/' + relative(resolvedRoot, path), stats);
entries.set('/' + _path.relative(resolvedRoot, path), stats);
if (options.verbose) {
console.log(`${color('bright_green', ' dir')} ${path}`);
}
Expand All @@ -102,7 +119,7 @@ function computeEntries(path) {

computeEntries(resolvedRoot);
if (!options.quiet) {
console.log('Generated listing for ' + fixSlash(resolve(root)));
console.log('Generated listing for ' + fixSlash(_path.resolve(root)));
}

const index = {
Expand Down
6 changes: 1 addition & 5 deletions src/backends/port/fs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { Errno, ErrnoError } from '../../error.js';
import { File } from '../../file.js';
import { FileSystem, type FileSystemMetadata } from '../../filesystem.js';
import { Async } from '../../mixins/async.js';
import { Stats, type FileType } from '../../stats.js';
import { Stats } from '../../stats.js';
import type { Backend, FilesystemOf } from '../backend.js';
import { InMemory } from '../memory.js';
import * as RPC from './rpc.js';
Expand Down Expand Up @@ -104,10 +104,6 @@ export class PortFile extends File {
this._throwNoSync('utimes');
}

public _setType(type: FileType): Promise<void> {
return this.rpc('_setType', type);
}

public _setTypeSync(): void {
this._throwNoSync('_setType');
}
Expand Down
18 changes: 9 additions & 9 deletions src/config.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import type { Backend, BackendConfiguration, FilesystemOf, SharedConfig } from './backends/backend.js';
import { checkOptions, isBackend, isBackendConfig } from './backends/backend.js';
import { credentials } from './credentials.js';
import { useCredentials } from './credentials.js';
import { DeviceFS } from './devices.js';
import * as cache from './emulation/cache.js';
import { config } from './emulation/config.js';
import * as fs from './emulation/index.js';
import type { AbsolutePath } from './emulation/path.js';
import { Errno, ErrnoError } from './error.js';
import { FileSystem } from './filesystem.js';

Expand Down Expand Up @@ -68,8 +67,11 @@ export async function resolveMountConfig<T extends Backend>(configuration: Mount
return mount;
}

/**
* An object mapping mount points to backends
*/
export interface ConfigMounts {
[K: AbsolutePath]: Backend;
[K: string]: Backend;
}

/**
Expand All @@ -79,7 +81,7 @@ export interface Configuration<T extends ConfigMounts> extends SharedConfig {
/**
* An object mapping mount points to mount configuration
*/
mounts: { [K in keyof T & AbsolutePath]: MountConfiguration<T[K]> };
mounts: { [K in keyof T]: MountConfiguration<T[K]> };

/**
* The uid to use
Expand Down Expand Up @@ -188,7 +190,7 @@ export async function configure<T extends ConfigMounts>(configuration: Partial<C
const uid = 'uid' in configuration ? configuration.uid || 0 : 0;
const gid = 'gid' in configuration ? configuration.gid || 0 : 0;

Object.assign(credentials, { uid, gid, suid: uid, sgid: gid, euid: uid, egid: gid });
useCredentials({ uid, gid });

cache.stats.isEnabled = configuration.cacheStats ?? false;
cache.paths.isEnabled = configuration.cachePaths ?? false;
Expand All @@ -200,10 +202,8 @@ export async function configure<T extends ConfigMounts>(configuration: Partial<C
const toMount: [string, FileSystem][] = [];
let unmountRoot = false;

for (const [point, mountConfig] of Object.entries(configuration.mounts)) {
if (!point.startsWith('/')) {
throw new ErrnoError(Errno.EINVAL, 'Mount points must have absolute paths');
}
for (const [_point, mountConfig] of Object.entries(configuration.mounts)) {
const point = _point.startsWith('/') ? _point : '/' + _point;

if (isBackendConfig(mountConfig)) {
mountConfig.disableAsyncCache ??= configuration.disableAsyncCache || false;
Expand Down
33 changes: 24 additions & 9 deletions src/credentials.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ export interface Credentials {
sgid: number;
euid: number;
egid: number;
/**
* List of group IDs.
*/
groups: number[];
}

export const credentials: Credentials = {
Expand All @@ -19,16 +23,27 @@ export const credentials: Credentials = {
sgid: 0,
euid: 0,
egid: 0,
groups: [],
};

export interface CredentialInit {
uid: number;
gid: number;
suid?: number;
sgid?: number;
euid?: number;
egid?: number;
}

/**
* @deprecated
* Uses credentials from the provided uid and gid.
*/
export const rootCredentials: Credentials = {
uid: 0,
gid: 0,
suid: 0,
sgid: 0,
euid: 0,
egid: 0,
};
export function useCredentials(source: CredentialInit): void {
Object.assign(credentials, {
suid: source.uid,
sgid: source.gid,
euid: source.uid,
egid: source.gid,
...source,
});
}
25 changes: 15 additions & 10 deletions src/emulation/cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,17 @@ export class Cache<T> {

protected async = new Map<string, Promise<T>>();

/**
* Whether the data exists in the cache
*/
has(path: string): boolean {
return this.isEnabled && this.sync.has(path);
}

/**
* Gets data from the cache, if is exists and the cache is enabled.
*/
getSync(path: string): T | undefined {
get(path: string): T | undefined {
if (!this.isEnabled) return;

return this.sync.get(path);
Expand All @@ -25,26 +32,24 @@ export class Cache<T> {
/**
* Adds data if the cache is enabled
*/
setSync(path: string, value: T): void {
set(path: string, value: T): void {
if (!this.isEnabled) return;

this.sync.set(path, value);
this.async.set(path, Promise.resolve(value));
}

/**
* Clears the cache if it is enabled
* Whether the data exists in the cache
*/
clearSync(): void {
if (!this.isEnabled) return;

this.sync.clear();
hasAsync(path: string): boolean {
return this.isEnabled && this.async.has(path);
}

/**
* Gets data from the cache, if it exists and the cache is enabled.
*/
get(path: string): Promise<T> | undefined {
getAsync(path: string): Promise<T> | undefined {
if (!this.isEnabled) return;

return this.async.get(path);
Expand All @@ -53,7 +58,7 @@ export class Cache<T> {
/**
* Adds data if the cache is enabled
*/
set(path: string, value: Promise<T>): void {
setAsync(path: string, value: Promise<T>): void {
if (!this.isEnabled) return;

this.async.set(path, value);
Expand All @@ -65,7 +70,7 @@ export class Cache<T> {
*/
clear(): void {
if (!this.isEnabled) return;

this.sync.clear();
this.async.clear();
}
}
Expand Down
Loading

0 comments on commit 19c7a85

Please sign in to comment.