github.com/go-asm/go@v1.21.1-0.20240213172139-40c5ead50c48/cmd/go/vcweb/fossil.go (about) 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 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 }