@zenfs/core 2.3.10 → 2.3.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -30,6 +30,8 @@ export declare abstract class IndexFS extends FileSystem {
30
30
  protected create(path: string, options: CreationOptions): Inode;
31
31
  createFile(path: string, options: CreationOptions): Promise<InodeLike>;
32
32
  createFileSync(path: string, options: CreationOptions): InodeLike;
33
+ protected _mkdir?(path: string, options: CreationOptions): Promise<void>;
34
+ protected _mkdirSync?(path: string, options: CreationOptions): void;
33
35
  mkdir(path: string, options: CreationOptions): Promise<InodeLike>;
34
36
  mkdirSync(path: string, options: CreationOptions): InodeLike;
35
37
  link(target: string, link: string): Promise<void>;
@@ -38,31 +38,56 @@ export class IndexFS extends FileSystem {
38
38
  to = to.slice(0, -1);
39
39
  toRename.push({ from, to, inode });
40
40
  }
41
+ toRename.sort((a, b) => b.from.length - a.from.length);
41
42
  return toRename;
42
43
  }
43
44
  async rename(oldPath, newPath) {
44
45
  if (oldPath == newPath)
45
46
  return;
46
- for (const { from, to, inode } of this.pathsForRename(oldPath, newPath)) {
47
+ const toRename = this.pathsForRename(oldPath, newPath);
48
+ const contents = new Map();
49
+ for (const { from, to, inode } of toRename) {
47
50
  const data = new Uint8Array(inode.size);
48
51
  await this.read(from, data, 0, inode.size);
52
+ contents.set(to, data);
49
53
  this.index.delete(from);
54
+ await this.remove(from);
55
+ if (this.index.has(to))
56
+ await this.remove(to);
57
+ }
58
+ toRename.reverse();
59
+ for (const { to, inode } of toRename) {
60
+ const data = contents.get(to);
50
61
  this.index.set(to, inode);
51
- await this.write(to, data, 0);
62
+ if ((inode.mode & S_IFMT) == S_IFDIR)
63
+ await this._mkdir?.(to, inode);
64
+ else
65
+ await this.write(to, data, 0);
52
66
  }
53
- await this.remove(oldPath);
54
67
  }
55
68
  renameSync(oldPath, newPath) {
56
69
  if (oldPath == newPath)
57
70
  return;
58
- for (const { from, to, inode } of this.pathsForRename(oldPath, newPath)) {
71
+ const toRename = this.pathsForRename(oldPath, newPath);
72
+ const contents = new Map();
73
+ for (const { from, to, inode } of toRename) {
59
74
  const data = new Uint8Array(inode.size);
60
75
  this.readSync(from, data, 0, inode.size);
76
+ contents.set(to, data);
61
77
  this.index.delete(from);
78
+ this.removeSync(from);
79
+ if (this.index.has(to))
80
+ this.removeSync(to);
81
+ }
82
+ toRename.reverse();
83
+ for (const { to, inode } of toRename) {
84
+ const data = contents.get(to);
62
85
  this.index.set(to, inode);
63
- this.writeSync(to, data, 0);
86
+ if ((inode.mode & S_IFMT) == S_IFDIR)
87
+ this._mkdirSync?.(to, inode);
88
+ else
89
+ this.writeSync(to, data, 0);
64
90
  }
65
- this.removeSync(oldPath);
66
91
  }
67
92
  async stat(path) {
68
93
  const inode = this.index.get(path);
@@ -148,11 +173,15 @@ export class IndexFS extends FileSystem {
148
173
  }
149
174
  async mkdir(path, options) {
150
175
  options.mode |= S_IFDIR;
151
- return this.create(path, options);
176
+ const inode = this.create(path, options);
177
+ await this._mkdir?.(path, options);
178
+ return inode;
152
179
  }
153
180
  mkdirSync(path, options) {
154
181
  options.mode |= S_IFDIR;
155
- return this.create(path, options);
182
+ const inode = this.create(path, options);
183
+ this._mkdirSync?.(path, options);
184
+ return inode;
156
185
  }
157
186
  link(target, link) {
158
187
  throw withErrno('ENOSYS');
@@ -49,7 +49,7 @@ export declare class _MutexedFS<T extends FileSystem> implements FileSystem {
49
49
  * If the path is currently locked, waits for it to be unlocked.
50
50
  * @internal
51
51
  */
52
- lock(): Promise<MutexLock>;
52
+ lock(timeout?: number): Promise<MutexLock>;
53
53
  /**
54
54
  * Locks `path` asynchronously.
55
55
  * If the path is currently locked, an error will be thrown
@@ -135,7 +135,7 @@ export class _MutexedFS {
135
135
  * If the path is currently locked, waits for it to be unlocked.
136
136
  * @internal
137
137
  */
138
- async lock() {
138
+ async lock(timeout = 5000) {
139
139
  const previous = this.currentLock;
140
140
  const lock = this.addLock();
141
141
  const stack = new Error().stack;
@@ -145,7 +145,7 @@ export class _MutexedFS {
145
145
  error.stack += stack?.slice('Error'.length);
146
146
  throw err(error);
147
147
  }
148
- }, 5000);
148
+ }, timeout);
149
149
  await previous?.done();
150
150
  return lock;
151
151
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zenfs/core",
3
- "version": "2.3.10",
3
+ "version": "2.3.11",
4
4
  "description": "A filesystem, anywhere",
5
5
  "funding": {
6
6
  "type": "individual",
@@ -60,7 +60,7 @@
60
60
  "format": "prettier --write .",
61
61
  "format:check": "prettier --check .",
62
62
  "lint": "eslint src tests",
63
- "test": "npx zenfs-test --clean; npx zenfs-test -abcfp; tests/fetch/run.sh; npx zenfs-test --report",
63
+ "test": "npx zenfs-test --clean; npx zenfs-test -abcp; tests/fetch/run.sh; npx zenfs-test --report",
64
64
  "build": "tsc -p tsconfig.json",
65
65
  "build:docs": "typedoc",
66
66
  "dev": "npm run build -- --watch",
@@ -12,7 +12,7 @@ setupLogs();
12
12
  const timeoutChannel = new MessageChannel();
13
13
  timeoutChannel.port2.unref();
14
14
 
15
- await suite('Timeout', { timeout: 1000 }, () => {
15
+ await suite('Timeout', () => {
16
16
  test('Misconfiguration', async () => {
17
17
  const configured = configure({
18
18
  mounts: {
@@ -20,11 +20,11 @@ suite('Mutexed FS', () => {
20
20
  let lock1Resolved = false;
21
21
  let lock2Resolved = false;
22
22
 
23
- const lock1 = fs.lock().then(lock => {
23
+ const lock1 = fs.lock(100).then(lock => {
24
24
  lock1Resolved = true;
25
25
  lock.unlock();
26
26
  });
27
- const lock2 = fs.lock().then(lock => {
27
+ const lock2 = fs.lock(100).then(lock => {
28
28
  lock2Resolved = true;
29
29
  lock.unlock();
30
30
  });
@@ -50,7 +50,7 @@ suite('Mutexed FS', () => {
50
50
  let x = 1;
51
51
 
52
52
  async function foo() {
53
- const lock = await fs.lock();
53
+ const lock = await fs.lock(100);
54
54
  await wait(25);
55
55
  x++;
56
56
  lock.unlock();