// Copyright 2017 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package vcweb import ( "fmt" "log" "net/http" "net/http/cgi" "os" "os/exec" "path/filepath" "sync" ) type fossilHandler struct { once sync.Once fossilPath string fossilPathErr error } func (h *fossilHandler) Available() bool { h.once.Do(func() { h.fossilPath, h.fossilPathErr = exec.LookPath("fossil") }) return h.fossilPathErr == nil } func (h *fossilHandler) Handler(dir string, env []string, logger *log.Logger) (http.Handler, error) { if !h.Available() { return nil, ServerNotInstalledError{name: "fossil"} } name := filepath.Base(dir) db := filepath.Join(dir, name+".fossil") cgiPath := db + ".cgi" cgiScript := fmt.Sprintf("#!%s\nrepository: %s\n", h.fossilPath, db) if err := os.WriteFile(cgiPath, []byte(cgiScript), 0755); err != nil { return nil, err } handler := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { if _, err := os.Stat(db); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } ch := &cgi.Handler{ Env: env, Logger: logger, Path: h.fossilPath, Args: []string{cgiPath}, Dir: dir, } ch.ServeHTTP(w, req) }) return handler, nil }