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}