diff options
author | Gabriel A. Giovanini <mail@gabrielgio.me> | 2024-05-27 22:36:50 +0200 |
---|---|---|
committer | Gabriel A. Giovanini <mail@gabrielgio.me> | 2024-05-27 22:42:16 +0200 |
commit | 2dd4cf35aab8324608a83d337459fd8354521b92 (patch) | |
tree | b65ecc803260bc268332fb2fbce83ab5dd209dbc | |
parent | 60e8e751c76d949a28eefe0c5462e0cf17337217 (diff) | |
download | cerrado-2dd4cf35aab8324608a83d337459fd8354521b92.tar.gz cerrado-2dd4cf35aab8324608a83d337459fd8354521b92.tar.bz2 cerrado-2dd4cf35aab8324608a83d337459fd8354521b92.zip |
feat: Wraps handler into its own package
Although this creates more complex folder structure will allow in the
feature for a easier testing of those given handlers.
-rw-r--r-- | main.go | 30 | ||||
-rw-r--r-- | pkg/config/config.go | 115 | ||||
-rw-r--r-- | pkg/config/config_test.go | 14 | ||||
-rw-r--r-- | pkg/git/git.go | 42 | ||||
-rw-r--r-- | pkg/handler/about/handler.go (renamed from pkg/handler/about.go) | 18 | ||||
-rw-r--r-- | pkg/handler/config/handler.go (renamed from pkg/handler/status.go) | 29 | ||||
-rw-r--r-- | pkg/handler/git/handler.go (renamed from pkg/handler/git.go) | 20 | ||||
-rw-r--r-- | pkg/handler/router.go | 38 | ||||
-rw-r--r-- | pkg/handler/static/handler.go (renamed from pkg/handler/static.go) | 2 | ||||
-rw-r--r-- | pkg/service/git.go | 26 |
10 files changed, 220 insertions, 114 deletions
@@ -10,7 +10,6 @@ import ( "time" "git.gabrielgio.me/cerrado/pkg/config" - "git.gabrielgio.me/cerrado/pkg/git" "git.gabrielgio.me/cerrado/pkg/handler" "git.gabrielgio.me/cerrado/pkg/service" "git.gabrielgio.me/cerrado/pkg/worker" @@ -33,38 +32,21 @@ func run(ctx context.Context) error { flag.Parse() - mux := http.NewServeMux() - - staticHandler, err := handler.NewStaticHander("/static/") + // repositorie + configRepo, err := config.LoadConfigurationRepository(*configPath) if err != nil { return err } - f, err := os.Open(*configPath) - if err != nil { - return err - } + // services + gitService := service.NewGitService(configRepo) - config, err := config.Parse(f) + handler, err := handler.MountHandler(gitService, configRepo) if err != nil { return err } - // repositories - gitServer := git.NewGitServerRepository(config.Scan.Path) - - // services - gitService := service.NewGitService(gitServer) - - //handlers - gitHandler := handler.NewGitHandler(gitService) - aboutHandler := handler.NewAboutHandler(config.RootReadme) - - mux.Handle("/static/", staticHandler) - mux.HandleFunc("/config", handler.ConfigFile(*configPath)) - mux.HandleFunc("/about", aboutHandler.About) - mux.HandleFunc("/", gitHandler.List) - serverTask := worker.NewServerTask(&http.Server{Handler: mux, Addr: "0.0.0.0:8080"}) + serverTask := worker.NewServerTask(&http.Server{Handler: handler, Addr: "0.0.0.0:8080"}) pool := worker.NewTaskPool() pool.AddTask("http-server", 5*time.Second, serverTask) diff --git a/pkg/config/config.go b/pkg/config/config.go index 9b6acce..419d49d 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -1,27 +1,126 @@ package config import ( + "errors" "fmt" "io" + "os" + "path" "strconv" "git.gabrielgio.me/cerrado/pkg/u" "git.sr.ht/~emersion/go-scfg" ) +var ( + ScanPathErr = errors.New("Scan path does not exist") + RepoPathErr = errors.New("Repository path does not exist") +) + type ( - Scan struct { + + // scan represents piece of the scan from the configuration file. + scan struct { Path string Public bool } - Configuration struct { - Scan *Scan + // configuration represents file configuration. + configuration struct { + Scan *scan RootReadme string } + + // This is a per repository configuration. + GitRepositoryConfiguration struct { + Name string + Path string + Public bool + } + + // ConfigurationRepository represents the configuration repository (as in + // database repositories). + // This holds all the function necessary to ask for configuration + // information. + ConfigurationRepository struct { + rootReadme string + repositories []*GitRepositoryConfiguration + } ) -func Parse(r io.Reader) (*Configuration, error) { +func LoadConfigurationRepository(configPath string) (*ConfigurationRepository, error) { + f, err := os.Open(configPath) + if err != nil { + return nil, err + } + + config, err := parse(f) + if err != nil { + return nil, err + } + + repo := &ConfigurationRepository{ + rootReadme: config.RootReadme, + } + + err = repo.expandOnScanPath(config.Scan.Path, config.Scan.Public) + if err != nil { + return nil, err + } + return repo, nil + +} + +// GetRootReadme returns root read path +func (c *ConfigurationRepository) GetRootReadme() string { + return c.rootReadme +} + +// GetByName returns configuration of repository for a given name. +// It returns nil if there is not match for it. +func (c *ConfigurationRepository) GetByName(name string) *GitRepositoryConfiguration { + for _, r := range c.repositories { + if r.Name == name { + return r + } + } + return nil +} + +// List returns all the configuration for all repositories. +func (c *ConfigurationRepository) List() []*GitRepositoryConfiguration { + return c.repositories +} + +// expandOnScanPath scans the scanPath for folders taking them as repositories +// and applying them default configuration. +func (c *ConfigurationRepository) expandOnScanPath(scanPath string, public bool) error { + if !u.FileExist(scanPath) { + return ScanPathErr + } + + entries, err := os.ReadDir(scanPath) + if err != nil { + return err + } + + c.repositories = make([]*GitRepositoryConfiguration, 0) + for _, e := range entries { + if !e.IsDir() { + continue + } + + fullPath := path.Join(scanPath, e.Name()) + c.repositories = append(c.repositories, &GitRepositoryConfiguration{ + Name: e.Name(), + Path: fullPath, + Public: public, + }) + } + return nil +} + +func parse(r io.Reader) (*configuration, error) { block, err := scfg.Read(r) if err != nil { return nil, err @@ -42,9 +141,9 @@ func Parse(r io.Reader) (*Configuration, error) { return config, nil } -func defaultConfiguration() *Configuration { - return &Configuration{ - Scan: &Scan{ +func defaultConfiguration() *configuration { + return &configuration{ + Scan: &scan{ Public: true, Path: "", }, @@ -57,7 +156,7 @@ func setRootReadme(block scfg.Block, readme *string) error { return setString(scanDir, readme) } -func setScan(block scfg.Block, scan *Scan) error { +func setScan(block scfg.Block, scan *scan) error { scanDir := block.Get("scan") err := setString(scanDir, &scan.Path) if err != nil { diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go index c8cd887..7afbaef 100644 --- a/pkg/config/config_test.go +++ b/pkg/config/config_test.go @@ -8,17 +8,17 @@ import ( "github.com/google/go-cmp/cmp" ) -func TestConfig(t *testing.T) { +func TestFileParsing(t *testing.T) { testCases := []struct { name string config string - expectedConfig *Configuration + expectedConfig *configuration }{ { name: "minimal scan", config: `scan "/srv/git"`, - expectedConfig: &Configuration{ - Scan: &Scan{ + expectedConfig: &configuration{ + Scan: &scan{ Public: true, Path: "/srv/git", }, @@ -29,8 +29,8 @@ func TestConfig(t *testing.T) { config: `scan "/srv/git" { public false }`, - expectedConfig: &Configuration{ - Scan: &Scan{ + expectedConfig: &configuration{ + Scan: &scan{ Public: false, Path: "/srv/git", }, @@ -41,7 +41,7 @@ func TestConfig(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { r := strings.NewReader(tc.config) - config, err := Parse(r) + config, err := parse(r) if err != nil { t.Fatalf("Error parsing config %s", err.Error()) } diff --git a/pkg/git/git.go b/pkg/git/git.go index 85a3b95..b9ab235 100644 --- a/pkg/git/git.go +++ b/pkg/git/git.go @@ -2,63 +2,29 @@ package git import ( "errors" - "os" - "path" - "git.gabrielgio.me/cerrado/pkg/u" "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/plumbing/object" ) +var () + var ( - ScanPathErr = errors.New("Scan path does not exist") - RepoPathErr = errors.New("Repository path does not exist") - missingHeadErr = errors.New("Head not found") + MissingHeadErr = errors.New("Head not found") ) type ( - GitServerRepository struct { - scanPath string - } - GitRepository struct { path string } ) -func NewGitServerRepository(scanPath string) *GitServerRepository { - return &GitServerRepository{scanPath} -} - func NewGitRepository(dir string) *GitRepository { return &GitRepository{ path: dir, } } -func (g *GitServerRepository) List() ([]*GitRepository, error) { - if !u.FileExist(g.scanPath) { - return nil, ScanPathErr - } - - entries, err := os.ReadDir(g.scanPath) - if err != nil { - return nil, err - } - - repos := make([]*GitRepository, 0) - for _, e := range entries { - if !e.IsDir() { - continue - } - - fullPath := path.Join(g.scanPath, e.Name()) - repos = append(repos, NewGitRepository(fullPath)) - } - - return repos, nil -} - func (g *GitRepository) Path() string { return g.path } @@ -71,7 +37,7 @@ func (g *GitRepository) LastCommit() (*object.Commit, error) { ref, err := repo.Head() if err != nil { - return nil, errors.Join(missingHeadErr, err) + return nil, errors.Join(MissingHeadErr, err) } c, err := repo.CommitObject(ref.Hash()) diff --git a/pkg/handler/about.go b/pkg/handler/about/handler.go index 3ab2de8..a2caa4e 100644 --- a/pkg/handler/about.go +++ b/pkg/handler/about/handler.go @@ -1,4 +1,4 @@ -package handler +package about import ( "io" @@ -13,12 +13,18 @@ import ( "git.gabrielgio.me/cerrado/templates" ) -type AboutHandler struct { - readmePath string -} +type ( + AboutHandler struct { + readmePath string + } + + configurationRepository interface { + GetRootReadme() string + } +) -func NewAboutHandler(readmePath string) *AboutHandler { - return &AboutHandler{readmePath} +func NewAboutHandler(configRepo configurationRepository) *AboutHandler { + return &AboutHandler{configRepo.GetRootReadme()} } func (g *AboutHandler) About(w http.ResponseWriter, _ *http.Request) { diff --git a/pkg/handler/status.go b/pkg/handler/config/handler.go index 9baac2c..c278e35 100644 --- a/pkg/handler/status.go +++ b/pkg/handler/config/handler.go @@ -1,11 +1,10 @@ -package handler +package config import ( "bytes" "encoding/json" "log/slog" "net/http" - "os" "github.com/alecthomas/chroma/v2/formatters/html" "github.com/alecthomas/chroma/v2/lexers" @@ -15,21 +14,25 @@ import ( "git.gabrielgio.me/cerrado/templates" ) -func ConfigFile(configPath string) func(http.ResponseWriter, *http.Request) { +type ( + configurationRepository interface { + GetRootReadme() string + List() []*config.GitRepositoryConfiguration + } +) + +func ConfigFile(configRepo configurationRepository) func(http.ResponseWriter, *http.Request) { return func(w http.ResponseWriter, _ *http.Request) { - f, err := os.Open(configPath) - if err != nil { - slog.Error("Error openning config file", "error", err, "path", configPath) - return - } - c, err := config.Parse(f) - if err != nil { - slog.Error("Error parsing config", "error", err, "path", configPath) - return + config := struct { + RootReadme string + Repositories []*config.GitRepositoryConfiguration + }{ + RootReadme: configRepo.GetRootReadme(), + Repositories: configRepo.List(), } - b, err := json.MarshalIndent(c, "", " ") + b, err := json.MarshalIndent(config, "", " ") if err != nil { slog.Error("Error parsing json", "error", err) return diff --git a/pkg/handler/git.go b/pkg/handler/git/handler.go index 1ed2c49..236ac41 100644 --- a/pkg/handler/git.go +++ b/pkg/handler/git/handler.go @@ -1,4 +1,4 @@ -package handler +package git import ( "log/slog" @@ -8,12 +8,20 @@ import ( "git.gabrielgio.me/cerrado/templates" ) -type GitHandler struct { - gitService *service.GitService -} +type ( + GitHandler struct { + gitService gitService + } + + gitService interface { + ListRepositories() ([]*service.Repository, error) + } +) -func NewGitHandler(gitService *service.GitService) *GitHandler { - return &GitHandler{gitService} +func NewGitHandler(gitService gitService) *GitHandler { + return &GitHandler{ + gitService: gitService, + } } func (g *GitHandler) List(w http.ResponseWriter, _ *http.Request) { diff --git a/pkg/handler/router.go b/pkg/handler/router.go new file mode 100644 index 0000000..a8c9c6f --- /dev/null +++ b/pkg/handler/router.go @@ -0,0 +1,38 @@ +package handler + +import ( + "net/http" + + serverconfig "git.gabrielgio.me/cerrado/pkg/config" + "git.gabrielgio.me/cerrado/pkg/handler/about" + "git.gabrielgio.me/cerrado/pkg/handler/config" + "git.gabrielgio.me/cerrado/pkg/handler/git" + "git.gabrielgio.me/cerrado/pkg/handler/static" + "git.gabrielgio.me/cerrado/pkg/service" +) + +// Mount handler gets the requires service and repository to build the handlers +// This functons wraps the whole handler package and wraps it into one part so +// its sub package don't leak in other places. +func MountHandler( + gitService *service.GitService, + configRepo *serverconfig.ConfigurationRepository, +) (http.Handler, error) { + var ( + gitHandler = git.NewGitHandler(gitService) + aboutHandler = about.NewAboutHandler(configRepo) + configHander = config.ConfigFile(configRepo) + ) + + staticHandler, err := static.NewStaticHander("/static/") + if err != nil { + return nil, err + } + + mux := http.NewServeMux() + mux.Handle("/static/", staticHandler) + mux.HandleFunc("/config", configHander) + mux.HandleFunc("/about", aboutHandler.About) + mux.HandleFunc("/", gitHandler.List) + return mux, nil +} diff --git a/pkg/handler/static.go b/pkg/handler/static/handler.go index 9f312f4..6a826cc 100644 --- a/pkg/handler/static.go +++ b/pkg/handler/static/handler.go @@ -1,4 +1,4 @@ -package handler +package static import ( "io/fs" diff --git a/pkg/service/git.go b/pkg/service/git.go index 94ca75e..2b1fe25 100644 --- a/pkg/service/git.go +++ b/pkg/service/git.go @@ -3,44 +3,48 @@ package service import ( "path" + "git.gabrielgio.me/cerrado/pkg/config" "git.gabrielgio.me/cerrado/pkg/git" ) type ( - GitService struct { - server *git.GitServerRepository - } Repository struct { Name string Title string LastCommitMessage string LastCommitDate string } + + GitService struct { + configRepo configurationRepository + } + + configurationRepository interface { + List() []*config.GitRepositoryConfiguration + } ) // TODO: make it configurable const timeFormat = "2006.01.02 15:04:05" -func NewGitService(server *git.GitServerRepository) *GitService { +func NewGitService(configRepo configurationRepository) *GitService { return &GitService{ - server: server, + configRepo: configRepo, } } func (g *GitService) ListRepositories() ([]*Repository, error) { - rs, err := g.server.List() - if err != nil { - return nil, err - } + rs := g.configRepo.List() repos := make([]*Repository, len(rs)) for i, r := range rs { - obj, err := r.LastCommit() + repo := git.NewGitRepository(r.Path) + obj, err := repo.LastCommit() if err != nil { return nil, err } - baseName := path.Base(r.Path()) + baseName := path.Base(r.Path) repos[i] = &Repository{ Name: baseName, Title: baseName, |