3 files changed,
115 insertions(+),
49 deletions(-)
Author:
Oleksandr Smirnov
olexsmir@gmail.com
Committed at:
2026-02-03 00:54:39 +0200
Authored at:
2026-02-03 00:37:15 +0200
Change ID:
qszlnmvzvqvsxnqrnpuvzuoskmpuortr
Parent:
8417128
jump to
| M | internal/cli/cli.go |
| M | internal/cli/repo.go |
| A | internal/cli/serve.go |
M
internal/cli/cli.go
路路路 2 2 3 3 import ( 4 4 "context" 5 - "log/slog" 6 - "net" 7 - "net/http" 8 - "os" 9 - "os/signal" 10 - "strconv" 11 - "syscall" 5 + "fmt" 12 6 7 + securejoin "github.com/cyphar/filepath-securejoin" 13 8 "github.com/urfave/cli/v3" 14 9 "olexsmir.xyz/mugit/internal/config" 15 - "olexsmir.xyz/mugit/internal/handlers" 16 - "olexsmir.xyz/mugit/internal/mirror" 17 - "olexsmir.xyz/mugit/internal/ssh" 10 + "olexsmir.xyz/mugit/internal/git" 18 11 ) 19 12 20 13 type Cli struct { 路路路 68 61 }, 69 62 }, 70 63 }, 64 + { 65 + Name: "description", 66 + Usage: "get or set repo description", 67 + Action: c.repoDescriptionAction, 68 + Arguments: []cli.Argument{ 69 + &cli.StringArg{Name: "name"}, 70 + }, 71 + }, 71 72 }, 72 73 }, 73 74 }, 路路路 75 76 return cmd.Run(ctx, args) 76 77 } 77 78 78 -func (c *Cli) serveAction(ctx context.Context, cmd *cli.Command) error { 79 - httpServer := &http.Server{ 80 - Addr: net.JoinHostPort(c.cfg.Server.Host, strconv.Itoa(c.cfg.Server.Port)), 81 - Handler: handlers.InitRoutes(c.cfg), 82 - } 83 - go func() { 84 - slog.Info("starting http server", "host", c.cfg.Server.Host, "port", c.cfg.Server.Port) 85 - if err := httpServer.ListenAndServe(); err != nil && err != http.ErrServerClosed { 86 - slog.Error("HTTP server error", "err", err) 87 - } 88 - }() 89 - 90 - if c.cfg.SSH.Enable { 91 - sshServer := ssh.NewServer(c.cfg) 92 - go func() { 93 - slog.Info("starting ssh server", "port", c.cfg.SSH.Port) 94 - if err := sshServer.Start(); err != nil { 95 - slog.Error("ssh server error", "err", err) 96 - } 97 - }() 98 - } 99 - 100 - if c.cfg.Mirror.Enable { 101 - mirrorer := mirror.NewWorker(c.cfg) 102 - go func() { 103 - slog.Info("starting mirroring worker") 104 - mirrorer.Start(context.TODO()) 105 - }() 79 +func (c *Cli) openRepo(name string) (*git.Repo, error) { 80 + path, err := securejoin.SecureJoin(c.cfg.Repo.Dir, name) 81 + if err != nil { 82 + return nil, err 106 83 } 107 84 108 - sigChan := make(chan os.Signal, 1) 109 - signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM) 110 - 111 - sig := <-sigChan 112 - slog.Info("received signal, starting graceful shutdown", "signal", sig) 113 - 114 - if err := httpServer.Shutdown(context.TODO()); err != nil { 115 - slog.Error("HTTP server shutdown error", "err", err) 116 - } else { 117 - slog.Info("HTTP server shutdown complete") 85 + repo, err := git.Open(path, "") 86 + if err != nil { 87 + return nil, fmt.Errorf("failed to open repo: %w", err) 118 88 } 119 89 120 - return nil 90 + return repo, nil 121 91 }
M
internal/cli/repo.go
路路路 48 48 49 49 return nil 50 50 } 51 + 52 +func (c *Cli) repoDescriptionAction(ctx context.Context, cmd *cli.Command) error { 53 + name := cmd.StringArg("name") 54 + if name == "" { 55 + return fmt.Errorf("no name provided") 56 + } 57 + 58 + name = strings.TrimRight(name, ".git") + ".git" 59 + 60 + repo, err := c.openRepo(name) 61 + if err != nil { 62 + return fmt.Errorf("failed to open repo: %w", err) 63 + } 64 + 65 + newDesc := cmd.Args().Get(0) 66 + if newDesc != "" { 67 + if err := repo.SetDescription(newDesc); err != nil { 68 + return fmt.Errorf("failed to set description: %w", err) 69 + } 70 + } 71 + 72 + desc, err := repo.Description() 73 + if err != nil { 74 + return fmt.Errorf("failed to get description: %w", err) 75 + } 76 + 77 + if desc == "" { 78 + fmt.Println("No description set") 79 + } else { 80 + fmt.Println(desc) 81 + } 82 + 83 + return nil 84 +}
A
internal/cli/serve.go
路路路 1 +package cli 2 + 3 +import ( 4 + "context" 5 + "log/slog" 6 + "net" 7 + "net/http" 8 + "os" 9 + "os/signal" 10 + "strconv" 11 + "syscall" 12 + 13 + "github.com/urfave/cli/v3" 14 + "olexsmir.xyz/mugit/internal/handlers" 15 + "olexsmir.xyz/mugit/internal/mirror" 16 + "olexsmir.xyz/mugit/internal/ssh" 17 +) 18 + 19 +func (c *Cli) serveAction(ctx context.Context, cmd *cli.Command) error { 20 + httpServer := &http.Server{ 21 + Addr: net.JoinHostPort(c.cfg.Server.Host, strconv.Itoa(c.cfg.Server.Port)), 22 + Handler: handlers.InitRoutes(c.cfg), 23 + } 24 + go func() { 25 + slog.Info("starting http server", "host", c.cfg.Server.Host, "port", c.cfg.Server.Port) 26 + if err := httpServer.ListenAndServe(); err != nil && err != http.ErrServerClosed { 27 + slog.Error("HTTP server error", "err", err) 28 + } 29 + }() 30 + 31 + if c.cfg.SSH.Enable { 32 + sshServer := ssh.NewServer(c.cfg) 33 + go func() { 34 + slog.Info("starting ssh server", "port", c.cfg.SSH.Port) 35 + if err := sshServer.Start(); err != nil { 36 + slog.Error("ssh server error", "err", err) 37 + } 38 + }() 39 + } 40 + 41 + if c.cfg.Mirror.Enable { 42 + mirrorer := mirror.NewWorker(c.cfg) 43 + go func() { 44 + slog.Info("starting mirroring worker") 45 + mirrorer.Start(context.TODO()) 46 + }() 47 + } 48 + 49 + sigChan := make(chan os.Signal, 1) 50 + signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM) 51 + 52 + sig := <-sigChan 53 + slog.Info("received signal, starting graceful shutdown", "signal", sig) 54 + 55 + if err := httpServer.Shutdown(context.TODO()); err != nil { 56 + slog.Error("HTTP server shutdown error", "err", err) 57 + } else { 58 + slog.Info("HTTP server shutdown complete") 59 + } 60 + 61 + return nil 62 +}