1package main
2
3import (
4 "flag"
5 "fmt"
6 "io/fs"
7 "log"
8 "net/http"
9 "os"
10 "os/signal"
11 "syscall"
12 "time"
13)
14
15const Version = "0.1.0"
16
17type loggingResponseWriter struct {
18 http.ResponseWriter
19 statusCode int
20}
21
22func (lrw *loggingResponseWriter) WriteHeader(code int) {
23 lrw.statusCode = code
24 lrw.ResponseWriter.WriteHeader(code)
25}
26
27func loggingMiddleware(next http.Handler) http.Handler {
28 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
29 start := time.Now()
30 lrw := &loggingResponseWriter{w, http.StatusOK}
31 next.ServeHTTP(lrw, r)
32 log.Printf("%s %s %d %v", r.Method, r.URL.Path, lrw.statusCode, time.Since(start))
33 })
34}
35
36var (
37 GlobalConfig *Config
38)
39
40func main() {
41 var showVersion bool
42 flag.StringVar(&ConfigPath, "c", "config.yaml", "custom config path")
43 flag.BoolVar(&showVersion, "v", false, "show version")
44 flag.Parse()
45
46 if showVersion {
47 fmt.Printf("bbgit version %s\n", Version)
48 return
49 }
50
51 var err error
52 GlobalConfig, err = loadConfig(ConfigPath)
53 if err != nil {
54 log.Fatalf("Error loading config: %v", err)
55 }
56
57 LoadCache()
58 StartSaver()
59
60 mux := http.NewServeMux()
61
62 staticSub, _ := fs.Sub(staticFS, "static")
63 mux.Handle("GET /static/", http.StripPrefix("/static/", http.FileServer(http.FS(staticSub))))
64 mux.HandleFunc("GET /{$}", homeHandler)
65 mux.HandleFunc("GET /r/{name}", repoHandler)
66 mux.HandleFunc("GET /r/{name}/readme", readmeHandler)
67 mux.HandleFunc("GET /r/{name}/license", licenseHandler)
68 mux.HandleFunc("GET /r/{name}/markers", markersHandler)
69 mux.HandleFunc("GET /r/{name}/commits.rss", repoCommitsRSSHandler)
70 mux.HandleFunc("GET /r/{name}/tags.rss", repoTagsRSSHandler)
71 mux.HandleFunc("GET /r/{name}/files/{path...}", filesHandler)
72 mux.HandleFunc("GET /r/{name}/blob/{path...}", blobHandler)
73 mux.HandleFunc("GET /r/{name}/raw/{path...}", rawHandler)
74 mux.HandleFunc("GET /r/{name}/archive/{path...}", archiveHandler)
75 mux.HandleFunc("GET /r/{name}/c/{hash}", commitHandler)
76 mux.HandleFunc("GET /r/{name}/c/{hash}/patch", patchHandler)
77
78 go func() {
79 sigChan := make(chan os.Signal, 1)
80 signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
81 <-sigChan
82 log.Println("Shutting down... saving cache.")
83 if err := SaveCache(); err != nil {
84 log.Printf("Error saving cache on shutdown: %v", err)
85 }
86 os.Exit(0)
87 }()
88
89 fmt.Printf("Server starting on :8080 (config: %s)...\n", ConfigPath)
90 if err := http.ListenAndServe(":8080", loggingMiddleware(mux)); err != nil {
91 log.Fatalf("Error starting server: %v", err)
92 }
93}