fierj
PublicTiny personal git forge
package main
import (
"context"
"embed"
"html/template"
"log/slog"
"net/http"
"os"
"os/signal"
"syscall"
"time"
)
//go:embed templates/*.html
var templateFS embed.FS
func main() {
cfgPath := "config.json"
if len(os.Args) > 1 {
cfgPath = os.Args[1]
}
cfg := LoadConfig(cfgPath)
os.MkdirAll(cfg.Dir, 0755)
tmpl := template.Must(template.New("").Funcs(funcMap).ParseFS(templateFS, "templates/*.html"))
mux := http.NewServeMux()
mux.HandleFunc("GET /", Repos(cfg, tmpl))
mux.HandleFunc("GET /new", NewRepoGet(tmpl))
mux.HandleFunc("POST /new", NewRepoPost(cfg, tmpl))
mux.HandleFunc("GET /{repo}", Tree(cfg, tmpl))
mux.HandleFunc("GET /{repo}/tree/{ref}/{path...}", Tree(cfg, tmpl))
mux.HandleFunc("GET /{repo}/blob/{ref}/{path...}", Blob(cfg, tmpl))
mux.HandleFunc("GET /{repo}/log/{ref}", Log(cfg, tmpl))
mux.HandleFunc("GET /{repo}/commit/{ref}", Diff(cfg, tmpl))
mux.HandleFunc("GET /{repo}/refs/", Refs(cfg, tmpl))
srv := &http.Server{
Addr: cfg.Addr,
Handler: mux,
}
// Start SSH server if configured
if cfg.SSHAddr != "" {
sshSrv, err := NewSSHServer(cfg.Dir, cfg.SSHHostKey)
if err != nil {
slog.Error("failed to create SSH server", "error", err)
os.Exit(1)
}
go func() {
if err := sshSrv.ListenAndServe(cfg.SSHAddr); err != nil {
slog.Error("ssh server failed", "error", err)
}
}()
}
go func() {
sig := make(chan os.Signal, 1)
signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM)
<-sig
slog.Info("shutting down...")
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
srv.Shutdown(ctx)
}()
slog.Info("fierj started", "addr", cfg.Addr, "host", cfg.Host, "repos", cfg.Dir)
if err := srv.ListenAndServe(); err != http.ErrServerClosed {
slog.Error("failed to start server", "error", err)
}
slog.Info("stopped")
}