package api import ( "errors" "net/http" "strconv" "time" "github.com/go-chi/chi/v5" "github.com/syonad/clonepack/internal/core" "github.com/syonad/clonepack/internal/store" ) type CloneHandler struct { svc *core.CloneService } func NewCloneHandler(svc *core.CloneService) *CloneHandler { return &CloneHandler{svc: svc} } func (h *CloneHandler) StartClone(w http.ResponseWriter, r *http.Request) { repoID, err := strconv.ParseInt(chi.URLParam(r, "id"), 10, 64) if err != nil { Error(w, http.StatusBadRequest, "invalid id") return } jobID, err := h.svc.StartClone(r.Context(), repoID) if errors.Is(err, store.ErrNotFound) { Error(w, http.StatusNotFound, "repo not found") return } if errors.Is(err, core.ErrCloneAlreadyRunning) { Error(w, http.StatusConflict, err.Error()) return } if err != nil { Error(w, http.StatusUnprocessableEntity, err.Error()) return } JSON(w, http.StatusAccepted, StartCloneResponse{JobID: jobID, Status: "running"}) } func (h *CloneHandler) GetStatus(w http.ResponseWriter, r *http.Request) { repoID, err := strconv.ParseInt(chi.URLParam(r, "id"), 10, 64) if err != nil { Error(w, http.StatusBadRequest, "invalid id") return } job, err := h.svc.GetLatestCloneJob(r.Context(), repoID) if errors.Is(err, store.ErrNotFound) { Error(w, http.StatusNotFound, "no clone job found for this repo") return } if err != nil { Error(w, http.StatusInternalServerError, err.Error()) return } JSON(w, http.StatusOK, cloneJobToResponse(job)) } func cloneJobToResponse(j *store.CloneJob) CloneStatusResponse { resp := CloneStatusResponse{ JobID: j.ID, RepoID: j.RepoID, Status: string(j.Status), Error: j.Error, CreatedAt: j.CreatedAt.Format(time.RFC3339), } if j.StartedAt != nil { s := j.StartedAt.Format(time.RFC3339) resp.StartedAt = &s } if j.FinishedAt != nil { f := j.FinishedAt.Format(time.RFC3339) resp.FinishedAt = &f } return resp }