( db: Database, path: string, options: WriteFileOptions, now: () => number, )
| 479 | } |
| 480 | |
| 481 | export function createFileSync( |
| 482 | db: Database, |
| 483 | path: string, |
| 484 | options: WriteFileOptions, |
| 485 | now: () => number, |
| 486 | ): void { |
| 487 | const { path: canonical } = canonicalizePath(path); |
| 488 | assertNotReadOnly(db, canonical); |
| 489 | const [parentInode, leafName] = parentAndNameForResolvedPath(db, path); |
| 490 | const mode = (options.mode ?? 0o644) & 0o7777; |
| 491 | const mtime = now(); |
| 492 | |
| 493 | db.transactionSync(() => { |
| 494 | const existing = db.one<{ child_inode: number }>( |
| 495 | "SELECT child_inode FROM vfs_dirents WHERE parent_inode = ? AND name = ?", |
| 496 | parentInode, |
| 497 | leafName, |
| 498 | ); |
| 499 | if (existing !== undefined) { |
| 500 | throw createWorkspaceError("EEXIST", `path exists: ${canonical}`, canonical); |
| 501 | } |
| 502 | const rev = incrementRev(db); |
| 503 | // INSERT with RETURNING folds the last_insert_rowid lookup into |
| 504 | // the same statement, and computing rev up front lets us write |
| 505 | // the node row with its final stamp in one shot. |
| 506 | const row = db.one<{ inode: number }>( |
| 507 | "INSERT INTO vfs_nodes (type, mode, mtime, rev, manifest_hash) VALUES ('file', ?, ?, ?, NULL) RETURNING inode", |
| 508 | mode, |
| 509 | mtime, |
| 510 | rev, |
| 511 | ); |
| 512 | if (row === undefined) throw createWorkspaceError("EIO", "failed to allocate inode"); |
| 513 | insertFileDirent(db, parentInode, leafName, row.inode, canonical); |
| 514 | }); |
| 515 | } |
| 516 | |
| 517 | // Open a write buffer for an existing file. Subsequent writes, |
| 518 | // truncates, and reads against the same Database operate on the |
no test coverage detected