• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2017 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package vcweb
6
7import (
8	"fmt"
9	"log"
10	"net/http"
11	"net/http/cgi"
12	"os"
13	"os/exec"
14	"path/filepath"
15	"sync"
16)
17
18type fossilHandler struct {
19	once          sync.Once
20	fossilPath    string
21	fossilPathErr error
22}
23
24func (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
31func (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