package server import ( "fmt" "os" "path/filepath" "strings" "github.com/google/uuid" "github.com/zzet/gortex/internal/platform" ) // DefaultServerIDPath returns the default persistence path for the // per-machine server id. Callers that want a process-local id (e.g. // tests, custom cache dirs) should pass their own dir to // LoadOrCreateServerID instead of calling this. // // An absolute $XDG_CACHE_HOME is honoured; otherwise the id stays under // os.UserCacheDir() — the historical location, kept so an existing // server id is not orphaned. func DefaultServerIDPath() (string, error) { if v := os.Getenv("XDG_CACHE_HOME"); v == "" || !filepath.IsAbs(v) { if _, err := os.UserCacheDir(); err != nil { return "", fmt.Errorf("resolve user cache dir: %w", err) } } return filepath.Join(platform.OSCacheDir(), "server.id"), nil } // LoadOrCreateServerID returns a stable UUID for this server // instance. If path already holds a valid UUID, it's returned as-is; // otherwise a fresh UUID is generated and persisted. Intermediate // directories are created as needed (0o755). // // A malformed existing file is replaced — the file is advisory // state, not authoritative, so there's no reason to fail loudly // when it gets corrupted. func LoadOrCreateServerID(path string) (string, error) { if data, err := os.ReadFile(path); err == nil { id := strings.TrimSpace(string(data)) if _, err := uuid.Parse(id); err == nil { return id, nil } // Fall through — we'll regenerate below. } else if !os.IsNotExist(err) { return "", fmt.Errorf("read server id: %w", err) } id := uuid.NewString() if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil { return "", fmt.Errorf("create server id dir: %w", err) } if err := os.WriteFile(path, []byte(id+"\n"), 0o600); err != nil { return "", fmt.Errorf("write server id: %w", err) } return id, nil }