github.com/bir3/gocompiler@v0.3.205/src/cmd/gocmd/internal/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  	"io/ioutil"
    10  	"log"
    11  	"net/http"
    12  	"net/http/cgi"
    13  	"os"
    14  	"os/exec"
    15  	"path/filepath"
    16  	"sync"
    17  )
    18  
    19  type fossilHandler struct {
    20  	once          sync.Once
    21  	fossilPath    string
    22  	fossilPathErr error
    23  }
    24  
    25  func (h *fossilHandler) Available() bool {
    26  	h.once.Do(func() {
    27  		h.fossilPath, h.fossilPathErr = exec.LookPath("fossil")
    28  	})
    29  	return h.fossilPathErr == nil
    30  }
    31  
    32  func (h *fossilHandler) Handler(dir string, env []string, logger *log.Logger) (http.Handler, error) {
    33  	if !h.Available() {
    34  		return nil, ServerNotInstalledError{name: "fossil"}
    35  	}
    36  
    37  	name := filepath.Base(dir)
    38  	db := filepath.Join(dir, name+".fossil")
    39  
    40  	cgiPath := db + ".cgi"
    41  	cgiScript := fmt.Sprintf("#!%s\nrepository: %s\n", h.fossilPath, db)
    42  	if err := ioutil.WriteFile(cgiPath, []byte(cgiScript), 0755); err != nil {
    43  		return nil, err
    44  	}
    45  
    46  	handler := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
    47  		if _, err := os.Stat(db); err != nil {
    48  			http.Error(w, err.Error(), http.StatusInternalServerError)
    49  			return
    50  		}
    51  		ch := &cgi.Handler{
    52  			Env:    env,
    53  			Logger: logger,
    54  			Path:   h.fossilPath,
    55  			Args:   []string{cgiPath},
    56  			Dir:    dir,
    57  		}
    58  		ch.ServeHTTP(w, req)
    59  	})
    60  
    61  	return handler, nil
    62  }