1
2
3
4
5 package vcweb
6
7 import (
8 "log"
9 "net/http"
10 "net/http/cgi"
11 "os/exec"
12 "runtime"
13 "slices"
14 "sync"
15 )
16
17 type gitHandler struct {
18 once sync.Once
19 gitPath string
20 gitPathErr error
21 }
22
23 func (h *gitHandler) Available() bool {
24 if runtime.GOOS == "plan9" {
25
26
27 return false
28 }
29 h.once.Do(func() {
30 h.gitPath, h.gitPathErr = exec.LookPath("git")
31 })
32 return h.gitPathErr == nil
33 }
34
35 func (h *gitHandler) Handler(dir string, env []string, logger *log.Logger) (http.Handler, error) {
36 if !h.Available() {
37 return nil, ServerNotInstalledError{name: "git"}
38 }
39
40 baseEnv := append(slices.Clip(env),
41 "GIT_PROJECT_ROOT="+dir,
42 "GIT_HTTP_EXPORT_ALL=1",
43 )
44
45 handler := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
46
47
48
49
50
51
52
53
54
55 env := slices.Clip(baseEnv)
56 if p := req.Header.Get("Git-Protocol"); p != "" {
57 env = append(env, "GIT_PROTOCOL="+p)
58 }
59
60 h := &cgi.Handler{
61 Path: h.gitPath,
62 Logger: logger,
63 Args: []string{"http-backend"},
64 Dir: dir,
65 Env: env,
66 }
67 h.ServeHTTP(w, req)
68 })
69
70 return handler, nil
71 }
72
View as plain text