|
|
@ -25,7 +25,7 @@ import (
|
|
|
|
var (
|
|
|
|
var (
|
|
|
|
port = flag.Int("port", 8000, "Port on which to serve HTTP")
|
|
|
|
port = flag.Int("port", 8000, "Port on which to serve HTTP")
|
|
|
|
|
|
|
|
|
|
|
|
toServe atomic.Value // Always contains valid []byte to serve. May be stale unless wg is zero.
|
|
|
|
toServe atomic.Value // Always contains valid bytesOrErr to serve. May be stale unless wg is zero.
|
|
|
|
wg sync.WaitGroup // Indicates how many updates are pending.
|
|
|
|
wg sync.WaitGroup // Indicates how many updates are pending.
|
|
|
|
mu sync.Mutex // Prevent multiple updates in parallel.
|
|
|
|
mu sync.Mutex // Prevent multiple updates in parallel.
|
|
|
|
)
|
|
|
|
)
|
|
|
@ -112,8 +112,14 @@ func filter(e fsnotify.Event) bool {
|
|
|
|
|
|
|
|
|
|
|
|
func serve(w http.ResponseWriter, req *http.Request) {
|
|
|
|
func serve(w http.ResponseWriter, req *http.Request) {
|
|
|
|
wg.Wait()
|
|
|
|
wg.Wait()
|
|
|
|
b := toServe.Load().([]byte)
|
|
|
|
b := toServe.Load().(bytesOrErr)
|
|
|
|
w.Write(b)
|
|
|
|
if b.err != nil {
|
|
|
|
|
|
|
|
w.Header().Set("Content-Type", "text/plain")
|
|
|
|
|
|
|
|
w.Write([]byte(b.err.Error()))
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
w.Header().Set("Content-Type", "text/html")
|
|
|
|
|
|
|
|
w.Write([]byte(b.bytes))
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func populateOnce(dir string) {
|
|
|
|
func populateOnce(dir string) {
|
|
|
@ -126,15 +132,15 @@ func populateOnce(dir string) {
|
|
|
|
cmd.Stderr = &b
|
|
|
|
cmd.Stderr = &b
|
|
|
|
err := cmd.Run()
|
|
|
|
err := cmd.Run()
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
toServe.Store([]byte(fmt.Errorf("error generating spec: %v\nOutput from gendoc:\n%v", err, b.String()).Error()))
|
|
|
|
toServe.Store(bytesOrErr{nil, fmt.Errorf("error generating spec: %v\nOutput from gendoc:\n%v", err, b.String())})
|
|
|
|
return
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
specBytes, err := ioutil.ReadFile(path.Join(dir, "scripts", "gen", "specification.html"))
|
|
|
|
specBytes, err := ioutil.ReadFile(path.Join(dir, "scripts", "gen", "specification.html"))
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
toServe.Store([]byte(fmt.Errorf("error reading spec: %v", err).Error()))
|
|
|
|
toServe.Store(bytesOrErr{nil, fmt.Errorf("error reading spec: %v", err)})
|
|
|
|
return
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
toServe.Store(specBytes)
|
|
|
|
toServe.Store(bytesOrErr{specBytes, nil})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func doPopulate(ch chan struct{}, dir string) {
|
|
|
|
func doPopulate(ch chan struct{}, dir string) {
|
|
|
@ -159,3 +165,8 @@ func exists(path string) bool {
|
|
|
|
_, err := os.Stat(path)
|
|
|
|
_, err := os.Stat(path)
|
|
|
|
return !os.IsNotExist(err)
|
|
|
|
return !os.IsNotExist(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
type bytesOrErr struct {
|
|
|
|
|
|
|
|
bytes []byte
|
|
|
|
|
|
|
|
err error
|
|
|
|
|
|
|
|
}
|
|
|
|