1
2
3
4
5 package vcweb
6
7 import (
8 "fmt"
9 "log"
10 "net/http"
11 "net/http/cgi"
12 "os"
13 "os/exec"
14 "path/filepath"
15 "sync"
16 )
17
18 type fossilHandler struct {
19 once sync.Once
20 fossilPath string
21 fossilPathErr error
22 }
23
24 func (h *fossilHandler) Available() bool {
25 h.once.Do(func() {
26 h.fossilPath, h.fossilPathErr = exec.LookPath("fossil")
27 })
28 return h.fossilPathErr == nil
29 }
30
31 func (h *fossilHandler) Handler(dir string, env []string, logger *log.Logger) (http.Handler, error) {
32 if !h.Available() {
33 return nil, ServerNotInstalledError{name: "fossil"}
34 }
35
36 name := filepath.Base(dir)
37 db := filepath.Join(dir, name+".fossil")
38
39 cgiPath := db + ".cgi"
40 cgiScript := fmt.Sprintf("#!%s\nrepository: %s\n", h.fossilPath, db)
41 if err := os.WriteFile(cgiPath, []byte(cgiScript), 0755); err != nil {
42 return nil, err
43 }
44
45 handler := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
46 if _, err := os.Stat(db); err != nil {
47 http.Error(w, err.Error(), http.StatusInternalServerError)
48 return
49 }
50 ch := &cgi.Handler{
51 Env: env,
52 Logger: logger,
53 Path: h.fossilPath,
54 Args: []string{cgiPath},
55 Dir: dir,
56 }
57 ch.ServeHTTP(w, req)
58 })
59
60 return handler, nil
61 }
62
View as plain text