History

Use tagged workspace read errors

Cursor Agent committed 4 months ago

Commit 7f891481 parent 05760162 files · +75 −8Browse files

Showing the changes to apps/server/src/workspace/WorkspaceFileSystem.ts (1 of 2 files). Show all

Unified · Split

apps/server/src/workspace/WorkspaceFileSystem.ts+62−4
@@ -24,6 +24,46 @@ import * as WorkspacePaths from "./WorkspacePaths.ts"; · 23 unmodified lines
24 24
25const PROJECT_READ_FILE_MAX_BYTES = 1024 * 1024;25const PROJECT_READ_FILE_MAX_BYTES = 1024 * 1024;
26 26
27class WorkspaceReadFileResolvedOutsideRootError extends Schema.TaggedErrorClass<WorkspaceReadFileResolvedOutsideRootError>()(
28 "WorkspaceReadFileResolvedOutsideRootError",
29 {
30 cwd: Schema.String,
31 relativePath: Schema.String,
32 realWorkspaceRoot: Schema.String,
33 realTargetPath: Schema.String,
34 },
35) {
36 override get message(): string {
37 return "Workspace file path resolves outside the project root.";
38 }
39}
40
41class WorkspaceReadFileNotFileError extends Schema.TaggedErrorClass<WorkspaceReadFileNotFileError>()(
42 "WorkspaceReadFileNotFileError",
43 {
44 cwd: Schema.String,
45 relativePath: Schema.String,
46 fileType: Schema.String,
47 },
48) {
49 override get message(): string {
50 return "Workspace path is not a file.";
51 }
52}
53
54class WorkspaceReadFileBinaryFileError extends Schema.TaggedErrorClass<WorkspaceReadFileBinaryFileError>()(
55 "WorkspaceReadFileBinaryFileError",
56 {
57 cwd: Schema.String,
58 relativePath: Schema.String,
59 nulByteOffset: Schema.Number,
60 },
61) {
62 override get message(): string {
63 return "Binary files cannot be previewed as text.";
64 }
65}
66
27export class WorkspaceFileSystemError extends Schema.TaggedErrorClass<WorkspaceFileSystemError>()(67export class WorkspaceFileSystemError extends Schema.TaggedErrorClass<WorkspaceFileSystemError>()(
28 "WorkspaceFileSystemError",68 "WorkspaceFileSystemError",
29 {69 {
@@ -96,22 +136,40 @@ export const make = Effect.gen(function* () { · 66 unmodified lines
96 path.isAbsolute(relativeRealPath)136 path.isAbsolute(relativeRealPath)
97 ) {137 ) {
98 return yield* Effect.fail(138 return yield* Effect.fail(
99 new Error("Workspace file path resolves outside the project root."),139 new WorkspaceReadFileResolvedOutsideRootError({
140 cwd: input.cwd,
141 relativePath: target.relativePath,
142 realWorkspaceRoot,
143 realTargetPath,
144 }),
100 );145 );
101 }146 }
102 147
103 const handle = yield* fileSystem.open(realTargetPath, { flag: "r" });148 const handle = yield* fileSystem.open(realTargetPath, { flag: "r" });
104 const stat = yield* handle.stat;149 const stat = yield* handle.stat;
105 if (stat.type !== "File") {150 if (stat.type !== "File") {
106 return yield* Effect.fail(new Error("Workspace path is not a file."));151 return yield* Effect.fail(
152 new WorkspaceReadFileNotFileError({
153 cwd: input.cwd,
154 relativePath: target.relativePath,
155 fileType: stat.type,
156 }),
157 );
107 }158 }
108 const byteLength = Number(stat.size);159 const byteLength = Number(stat.size);
109 const bytesToRead = Math.min(byteLength, PROJECT_READ_FILE_MAX_BYTES);160 const bytesToRead = Math.min(byteLength, PROJECT_READ_FILE_MAX_BYTES);
110 const buffer = new Uint8Array(bytesToRead);161 const buffer = new Uint8Array(bytesToRead);
111 const bytesRead = yield* handle.read(buffer);162 const bytesRead = yield* handle.read(buffer);
112 const fileBytes = buffer.subarray(0, Number(bytesRead));163 const fileBytes = buffer.subarray(0, Number(bytesRead));
113 if (fileBytes.includes(0)) {164 const nulByteOffset = fileBytes.indexOf(0);
114 return yield* Effect.fail(new Error("Binary files cannot be previewed as text."));165 if (nulByteOffset !== -1) {
166 return yield* Effect.fail(
167 new WorkspaceReadFileBinaryFileError({
168 cwd: input.cwd,
169 relativePath: target.relativePath,
170 nulByteOffset,
171 }),
172 );
115 }173 }
116 const contents = new TextDecoder("utf-8").decode(fileBytes);174 const contents = new TextDecoder("utf-8").decode(fileBytes);
117 return {175 return {