Skip to content

Commit 254a481

Browse files
authored
fix(config): handle unavailable config directories (anomalyco#35632)
Co-authored-by: James Long <jlongster@users.noreply.github.com>
1 parent 26885e7 commit 254a481

3 files changed

Lines changed: 30 additions & 3 deletions

File tree

packages/core/src/fs-util.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,10 @@ export namespace FSUtil {
6060
})
6161

6262
const readFileStringSafe = Effect.fn("FileSystem.readFileStringSafe")(function* (path: string) {
63-
return yield* fs
64-
.readFileString(path)
65-
.pipe(Effect.catchReason("PlatformError", "NotFound", () => Effect.succeed(undefined)))
63+
return yield* fs.readFileString(path).pipe(
64+
Effect.catchReason("PlatformError", "NotFound", () => Effect.succeed(undefined)),
65+
Effect.catchReason("PlatformError", "PermissionDenied", () => Effect.succeed(undefined)),
66+
)
6667
})
6768

6869
const isDir = Effect.fn("FileSystem.isDir")(function* (path: string) {

packages/opencode/src/config/config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,7 @@ const layer = Layer.effect(
293293
})
294294

295295
const ensureGitignore = Effect.fn("Config.ensureGitignore")(function* (dir: string) {
296+
yield* fs.ensureDir(dir)
296297
const gitignore = path.join(dir, ".gitignore")
297298
const hasIgnore = yield* fs.existsSafe(gitignore)
298299
if (!hasIgnore) {

packages/opencode/test/config/config.test.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -923,6 +923,31 @@ it.effect("does not try to install dependencies in read-only OPENCODE_CONFIG_DIR
923923
}).pipe(Effect.provide(testInstanceStoreLayer), Effect.provide(LayerNode.compile(CrossSpawnSpawner.node))),
924924
)
925925

926+
it.effect("ignores an inaccessible OPENCODE_CONFIG_DIR", () =>
927+
Effect.gen(function* () {
928+
if (process.platform === "win32") return
929+
930+
const dir = yield* tmpdirScoped()
931+
const configDir = path.join(dir, "inaccessible")
932+
yield* FSUtil.use.ensureDir(configDir)
933+
yield* FSUtil.use.chmod(configDir, 0o000)
934+
yield* Effect.addFinalizer(() => FSUtil.use.chmod(configDir, 0o755).pipe(Effect.ignore))
935+
936+
yield* withProcessEnv("OPENCODE_CONFIG_DIR", configDir, Config.use.get().pipe(provideInstanceEffect(dir)))
937+
}).pipe(Effect.provide(testInstanceStoreLayer), Effect.provide(LayerNode.compile(CrossSpawnSpawner.node))),
938+
)
939+
940+
it.effect("creates a missing OPENCODE_CONFIG_DIR", () =>
941+
Effect.gen(function* () {
942+
const dir = yield* tmpdirScoped()
943+
const configDir = path.join(dir, "configdir")
944+
945+
yield* withProcessEnv("OPENCODE_CONFIG_DIR", configDir, Config.use.get().pipe(provideInstanceEffect(dir)))
946+
947+
expect(yield* FSUtil.use.readFileString(path.join(configDir, ".gitignore"))).toContain("node_modules")
948+
}).pipe(Effect.provide(testInstanceStoreLayer), Effect.provide(LayerNode.compile(CrossSpawnSpawner.node))),
949+
)
950+
926951
it.effect("installs dependencies in writable OPENCODE_CONFIG_DIR", () =>
927952
Effect.gen(function* () {
928953
const dir = yield* tmpdirScoped()

0 commit comments

Comments
 (0)