From 9406ffda0143797060ea0de378b1986ee31fcbb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lie=20DELHAIE?= Date: Sun, 26 Oct 2025 22:35:52 +0100 Subject: [PATCH] fix (wip) --- cmd/server/api/responses.go | 2 +- cmd/server/core/storage/storage.go | 21 ++++++++++++--------- go.mod | 1 + go.sum | 2 ++ pkg/client/client.go | 11 +++++++---- pkg/project/file.go | 30 +++++++++++++++++++++++++++--- pkg/remote/obj/obj.go | 4 ++-- 7 files changed, 52 insertions(+), 19 deletions(-) diff --git a/cmd/server/api/responses.go b/cmd/server/api/responses.go index a5a6b4f..40f2d98 100644 --- a/cmd/server/api/responses.go +++ b/cmd/server/api/responses.go @@ -87,7 +87,7 @@ func unauthorized(w http.ResponseWriter, r *http.Request) { } func ok(o interface{}, w http.ResponseWriter, r *http.Request) { - payload := obj.HTTPObject{ + payload := obj.HTTPObject[any]{ HTTPCore: obj.HTTPCore{ Status: http.StatusOK, Path: r.RequestURI, diff --git a/cmd/server/core/storage/storage.go b/cmd/server/core/storage/storage.go index b8414b8..d3840af 100644 --- a/cmd/server/core/storage/storage.go +++ b/cmd/server/core/storage/storage.go @@ -227,13 +227,13 @@ func (r *Repository) Update(pr project.Project) error { func (r *Repository) List() ([]project.Project, error) { var prs []project.Project - rows, err := r.db.Query("SELECT uuid, name WHERE Projects") + rows, err := r.db.Query("SELECT uuid, name FROM Projects") if err != nil { return nil, fmt.Errorf("failed to get the list of projects: %w", err) } defer rows.Close() - stmt, err := r.db.Prepare("SELECT name, schedule, source, destination FROM Repositories WHERE uuid = ?") + stmt, err := r.db.Prepare("SELECT name, schedule, source, destination FROM Repositories WHERE project = ?") if err != nil { return nil, fmt.Errorf("invalid syntax: %w", err) } @@ -244,18 +244,21 @@ func (r *Repository) List() ([]project.Project, error) { return nil, fmt.Errorf("failed to scan project name: %w", err) } - for rows.Next() { + repoRows, err := stmt.Query(prUUID) + if err != nil { + return nil, fmt.Errorf("failed to query repositories for the project %s: %w", prUUID, err) + } + + for repoRows.Next() { var repo project.Repository - rows, err := stmt.Query(prUUID) - if err != nil { - return nil, fmt.Errorf("failed to get the list of projects: %w", err) - } - if err := rows.Scan(&repo.Name, &repo.Schedule, &repo.Source, &repo.Destination); err != nil { + if err := repoRows.Scan(&repo.Name, &repo.Schedule, &repo.Source, &repo.Destination); err != nil { + repoRows.Close() return nil, fmt.Errorf("failed to scan repository entry: %w", err) } - pr.Repositories = append(pr.Repositories, repo) } + + repoRows.Close() prs = append(prs, pr) } diff --git a/go.mod b/go.mod index 850a216..63167b1 100644 --- a/go.mod +++ b/go.mod @@ -10,6 +10,7 @@ require ( github.com/google/subcommands v1.2.0 github.com/google/uuid v1.6.0 github.com/pressly/goose/v3 v3.26.0 + github.com/robfig/cron/v3 v3.0.1 ) require ( diff --git a/go.sum b/go.sum index 024bbcd..7eeb8a5 100644 --- a/go.sum +++ b/go.sum @@ -64,6 +64,8 @@ github.com/pressly/goose/v3 v3.26.0 h1:KJakav68jdH0WDvoAcj8+n61WqOIaPGgH0bJWS6jp github.com/pressly/goose/v3 v3.26.0/go.mod h1:4hC1KrritdCxtuFsqgs1R4AU5bWtTAf+cnWvfhf2DNY= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= +github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw= github.com/sergi/go-diff v1.4.0/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= github.com/sethvargo/go-retry v0.3.0 h1:EEt31A35QhrcRZtrYFDTBg91cqZVnFL2navjDrah2SE= diff --git a/pkg/client/client.go b/pkg/client/client.go index efed382..7a76392 100644 --- a/pkg/client/client.go +++ b/pkg/client/client.go @@ -6,6 +6,7 @@ import ( "fmt" "io" "mirror-sync/pkg/project" + "mirror-sync/pkg/remote/obj" "net/http" "net/url" ) @@ -71,16 +72,18 @@ func (c *Client) List() ([]project.Project, error) { } defer res.Body.Close() - if res.StatusCode != 201 { + if res.StatusCode != 200 { return nil, fmt.Errorf("failed to send the request to the server: %s: %s", res.Status, toError(res.Body)) } - var prs []project.Project + var payload obj.HTTPObject[[]project.Project] d := json.NewDecoder(res.Body) - if err := d.Decode(&prs); err != nil { - return nil, fmt.Errorf("failed to parse the server response, is the client you up-to-date? (reason: %s)", err) + if err := d.Decode(&payload); err != nil { + return nil, fmt.Errorf("failed to parse the server response, is your client up-to-date? (reason: %s)", err) } + prs := payload.Data + for i, pr := range prs { pr.ServerURL = c.url prs[i] = pr diff --git a/pkg/project/file.go b/pkg/project/file.go index c9147e9..b468c7c 100644 --- a/pkg/project/file.go +++ b/pkg/project/file.go @@ -8,6 +8,7 @@ import ( "strings" "github.com/goccy/go-yaml" + "github.com/robfig/cron/v3" ) type ( @@ -29,8 +30,8 @@ type ( } GitStorage struct { - Source string `yaml:"source"` - Destination string `yaml:"destination"` + Source string `yaml:"source"` + Mirror string `yaml:"mirror"` } ) @@ -58,6 +59,10 @@ func LoadCurrent() (Project, error) { return Project{}, fmt.Errorf("%w: %s", ErrParsing, err) } + if err := checkConfig(mainFile); err != nil { + return Project{}, fmt.Errorf("failed to validate configuration: %w", err) + } + pr := Project{ Name: filepath.Base(wd), ServerURL: "http://localhost:8080", @@ -83,10 +88,29 @@ func LoadCurrent() (Project, error) { pr.Repositories = append(pr.Repositories, Repository{ Name: fmt.Sprintf("%s-%s", pr.Name, strings.ToLower(repoName)), Source: repo.Storage.Source, - Destination: repo.Storage.Destination, + Destination: repo.Storage.Mirror, Schedule: repo.Schedule, }) } return pr, nil } + +func checkConfig(mf MainFile) error { + for _, r := range mf.Repositories { + if len(strings.TrimSpace(r.Storage.Source)) == 0 { + return fmt.Errorf("source is empty") + } + if len(strings.TrimSpace(r.Storage.Mirror)) == 0 { + return fmt.Errorf("mirror is empty") + } + if len(strings.TrimSpace(r.Schedule)) == 0 { + return fmt.Errorf("schedule is empty") + } + if _, err := cron.ParseStandard(r.Schedule); err != nil { + return fmt.Errorf("failed to validate schedule: %w", err) + } + } + + return nil +} diff --git a/pkg/remote/obj/obj.go b/pkg/remote/obj/obj.go index fed64c0..01cdc0d 100644 --- a/pkg/remote/obj/obj.go +++ b/pkg/remote/obj/obj.go @@ -15,9 +15,9 @@ type ( Message string `json:"message"` } - HTTPObject struct { + HTTPObject[T any] struct { HTTPCore - Data any `json:"data"` + Data T `json:"data"` } SystemInformation struct {