Procházet zdrojové kódy

fix(config): fallback when user info unavailable (#29332)

Shoubhit Dash před 3 měsíci
rodič
revize
b5632ea700

+ 8 - 1
packages/opencode/src/config/config.ts

@@ -762,7 +762,14 @@ export const layer = Layer.effect(
           result.permission = mergeDeep(perms, result.permission ?? {})
         }
 
-        if (!result.username) result.username = os.userInfo().username
+        if (!result.username) {
+          try {
+            result.username = os.userInfo().username || "user"
+          } catch (err) {
+            log.warn("failed to read system username, using fallback", { err })
+            result.username = "user"
+          }
+        }
 
         if (result.autoshare === true && !result.share) {
           result.share = "auto"

+ 8 - 1
packages/opencode/src/config/managed.ts

@@ -46,7 +46,14 @@ export function parseManagedPlist(json: string): string {
 export async function readManagedPreferences() {
   if (process.platform !== "darwin") return
 
-  const user = os.userInfo().username
+  const user = (() => {
+    try {
+      return os.userInfo().username || "user"
+    } catch (err) {
+      log.warn("failed to read system username, using fallback", { err })
+      return "user"
+    }
+  })()
   const paths = [
     path.join("/Library/Managed Preferences", user, `${MANAGED_PLIST_DOMAIN}.plist`),
     path.join("/Library/Managed Preferences", `${MANAGED_PLIST_DOMAIN}.plist`),

+ 16 - 1
packages/opencode/test/config/config.test.ts

@@ -1,4 +1,4 @@
-import { test, expect, describe, afterEach, beforeEach } from "bun:test"
+import { test, expect, describe, afterEach, beforeEach, spyOn } from "bun:test"
 import { Effect, Exit, Layer, Option } from "effect"
 import { FetchHttpClient, HttpClient, HttpClientResponse } from "effect/unstable/http"
 import { NodeFileSystem, NodePath } from "@effect/platform-node"
@@ -28,6 +28,7 @@ import { CrossSpawnSpawner } from "@opencode-ai/core/cross-spawn-spawner"
 import { testEffect } from "../lib/effect"
 import path from "path"
 import fs from "fs/promises"
+import os from "os"
 import { pathToFileURL } from "url"
 import { Global } from "@opencode-ai/core/global"
 import { ProjectID } from "../../src/project/schema"
@@ -291,6 +292,20 @@ it.instance("loads config with defaults when no files exist", () =>
   }),
 )
 
+it.instance("falls back to generic username when system user info is unavailable", () =>
+  Effect.gen(function* () {
+    const userInfo = spyOn(os, "userInfo").mockImplementation(() => {
+      throw Object.assign(new Error("missing passwd entry"), { code: "ENOENT" })
+    })
+    try {
+      const config = yield* Config.use.get()
+      expect(config.username).toBe("user")
+    } finally {
+      userInfo.mockRestore()
+    }
+  }),
+)
+
 it.effect("creates global jsonc config with schema when no global configs exist", () =>
   withGlobalConfig({}, ({ dir }) =>
     Effect.gen(function* () {