diff --git a/internal/web_server/handlers/maintenance_handler.go b/internal/web_server/handlers/maintenance_handler.go index a92e2da..e429128 100644 --- a/internal/web_server/handlers/maintenance_handler.go +++ b/internal/web_server/handlers/maintenance_handler.go @@ -16,6 +16,52 @@ type resetAndReseedReq struct { Confirm string `json:"confirm"` } +func resolveSeedDir(seedDir string) (string, error) { + cleanSeedDir := strings.TrimSpace(seedDir) + if cleanSeedDir == "" { + cleanSeedDir = "db/data" + } + + // If absolute, use directly. + if filepath.IsAbs(cleanSeedDir) { + info, err := os.Stat(cleanSeedDir) + if err != nil { + return "", err + } + if !info.IsDir() { + return "", fmt.Errorf("seed dir is not a directory: %s", cleanSeedDir) + } + return cleanSeedDir, nil + } + + candidates := make([]string, 0, 5) + + // 1) Relative to current working directory. + candidates = append(candidates, filepath.Clean(cleanSeedDir)) + + // 2) Relative to executable directory (and parents). + if exePath, err := os.Executable(); err == nil { + exeDir := filepath.Dir(exePath) + candidates = append(candidates, + filepath.Join(exeDir, cleanSeedDir), + filepath.Join(exeDir, "..", cleanSeedDir), + filepath.Join(exeDir, "..", "..", cleanSeedDir), + ) + } + + for _, candidate := range candidates { + info, err := os.Stat(candidate) + if err != nil { + continue + } + if info.IsDir() { + return candidate, nil + } + } + + return "", fmt.Errorf("seed directory not found (tried: %s)", strings.Join(candidates, ", ")) +} + // ResetAndReseedDatabase godoc // @Summary Reset and reseed database // @Description Dangerous operation: truncates all public tables (except schema_migrations) and reseeds from db/data SQL files. @@ -62,9 +108,12 @@ func (h *Handler) ResetAndReseedDatabase(c *fiber.Ctx) error { } } - seedDir := strings.TrimSpace(h.Cfg.DBSeedDir) - if seedDir == "" { - seedDir = "db/data" + seedDir, err := resolveSeedDir(h.Cfg.DBSeedDir) + if err != nil { + return c.Status(fiber.StatusInternalServerError).JSON(domain.ErrorResponse{ + Message: "Failed to resolve seed directory", + Error: err.Error(), + }) } seedFiles, err := filepath.Glob(filepath.Join(seedDir, "*.sql")) if err != nil {