all repos — elgit @ e538f32279a29426c6fcffa039f0c08279de0532

fork of legit: web frontend for git, written in go

routes/handler.go (view raw)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
package routes

import (
	"fmt"
	"io/fs"
	"log"
	"net"
	"path/filepath"
	"strconv"
	"strings"
	"time"

	"github.com/fsnotify/fsnotify"
	"github.com/savsgio/atreugo/v11"

	"alin.ovh/elgit/config"
)

var ErrMethodNotAllowed = fmt.Errorf("that's not possible")
var ErrNotFound = fmt.Errorf("nothing like that here")

func Handlers(c *config.Config, staticFiles fs.FS) *atreugo.Atreugo {
	d := deps{
		c: c,
	}

	addr := net.JoinHostPort(c.Server.Host, strconv.FormatInt(c.Server.Port, 10))
	cfg := atreugo.Config{
		Addr:                         addr,
		Name:                         c.Server.Name,
		Compress:                     c.Server.Compress,
		Logger:                       log.Default(),
		NotFoundView:                 d.NotFound,
		MethodNotAllowedView:         nil,
		ErrorView:                    d.Error,
		PanicView:                    d.Panic,
		ReadTimeout:                  5 * time.Second,
		DisablePreParseMultipartForm: true,
		GracefulShutdown:             !c.Server.Development,
		CloseOnShutdown:              !c.Server.Development,
		StreamRequestBody:            true,
	}
	if strings.Contains(c.Server.Host, ":") {
		cfg.Network = "tcp6"
	}
	if c.Server.Development {
		cfg.PanicView = nil
	}
	srv := atreugo.New(cfg)

	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		log.Fatal(err)
	}

	plist := filepath.Join(c.Repo.Root, "projects.list")

	d.projects, err = ReadProjectsList(plist)
	if err != nil {
		log.Fatal(err)
	}

	err = watcher.Add(plist)
	if err != nil {
		log.Fatal(err)
	}

	go func() {
		for {
			select {
			case event, ok := <-watcher.Events:
				if !ok {
					continue
				}
				if event.Op.Has(fsnotify.Write) {
					d.projects, err = ReadProjectsList(plist)
					if err != nil {
						log.Println(err)
					}
				}
			case err, ok := <-watcher.Errors:
				if !ok {
					continue
				}
				log.Println("error:", err)
			}
		}
	}()

	go func() {
		d.UpdateRepos()
		for range time.Tick(time.Minute) {
			d.UpdateRepos()
		}
	}()

	d.mountRepoPaths(srv.NewGroupPath("/{name}"))
	d.mountRepoPaths(srv.NewGroupPath("/{category}/{name}"))

	srv.StaticFS("/static/", staticFiles)
	srv.GET("/", d.Index)

	return srv
}

func (d deps) mountRepoPaths(router *atreugo.Router) {
	router.GET("/tree/{ref}/{rest:*}", d.RepoTree)
	router.GET("/blob/{ref}/{rest:*}", d.FileContent)
	router.GET("/tree/{ref}/", d.RepoTree)
	router.GET("/log/{ref}/", d.Log)
	router.GET("/archive/{file}", d.Archive)
	router.GET("/commit/{ref}", d.Diff)
	router.GET("/commit/{ref}/{file:*}", d.FileDiff)
	router.GET("/refs/", d.Refs)
	router.GET("/info/refs", d.InfoRefs)
	router.POST("/git-upload-pack", d.UploadPack)
	router.GET("/", d.RepoIndex)
}