rin
Public Open-source lightweight git hosting.
main.go · 97 lines · 2.3 KB
Raw
1 package main
2
3 import (
4 "context"
5 "flag"
6 "log/slog"
7 "os"
8 "os/signal"
9 "runtime/debug"
10 "syscall"
11 "time"
12
13 "polar/internal/auth"
14 "polar/internal/config"
15 "polar/internal/db"
16 "polar/internal/repo"
17 "polar/internal/user"
18 "polar/internal/web/handlers"
19 "polar/internal/web/views"
20
21 "github.com/gofiber/fiber/v2"
22 )
23
24 func main() {
25 configPath := flag.String("config", "", "path to polar.toml configuration file")
26 flag.Parse()
27
28 logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
29 Level: slog.LevelInfo,
30 }))
31 slog.SetDefault(logger)
32
33 cfg, err := config.Load(*configPath)
34 if err != nil {
35 logger.Error("failed to load configuration", "err", err)
36 os.Exit(1)
37 }
38
39 if err := os.MkdirAll(cfg.ReposDir(), 0o755); err != nil {
40 logger.Error("failed to create repositories directory", "path", cfg.ReposDir(), "err", err)
41 os.Exit(1)
42 }
43
44 ctx := context.Background()
45 database, err := db.Open(ctx, cfg.DBPath(), cfg.Auth.RegistrationEnabled)
46 if err != nil {
47 logger.Error("failed to initialize database", "path", cfg.DBPath(), "err", err)
48 os.Exit(1)
49 }
50 defer func() { _ = database.Close() }()
51
52 authSvc := auth.NewService(database)
53 userSvc := user.NewService(database)
54 repoSvc := repo.NewService(database, cfg.ReposDir())
55
56 viewsEngine, err := views.NewEngine()
57 if err != nil {
58 logger.Error("failed to initialize template engine", "err", err)
59 os.Exit(1)
60 }
61
62 app := fiber.New(fiber.Config{
63 AppName: "Polar Git Server",
64 DisableStartupMessage: true,
65 BodyLimit: 100 * 1024 * 1024, // 100 MB for git pack pushes
66 ReadTimeout: 60 * time.Second,
67 WriteTimeout: 120 * time.Second,
68 })
69
70 h := handlers.New(cfg, database, authSvc, userSvc, repoSvc, viewsEngine, logger)
71 h.RegisterRoutes(app)
72 debug.FreeOSMemory()
73
74 errCh := make(chan error, 1)
75 go func() {
76 logger.Info("Polar server starting",
77 "addr", cfg.Addr(),
78 "base_url", cfg.Server.BaseURL,
79 "data_dir", cfg.Storage.DataDir,
80 )
81 if err := app.Listen(cfg.Addr()); err != nil {
82 errCh <- err
83 }
84 }()
85
86 sigCh := make(chan os.Signal, 1)
87 signal.Notify(sigCh, os.Interrupt, syscall.SIGTERM)
88
89 select {
90 case sig := <-sigCh:
91 logger.Info("shutting down gracefully", "signal", sig.String())
92 _ = app.ShutdownWithTimeout(10 * time.Second)
93 case err := <-errCh:
94 logger.Error("server exited with error", "err", err)
95 os.Exit(1)
96 }
97 }
98