cmd/godoc: bake templates and scripts into godoc binary
Add godoc/vfs/mapfs package for serving baked files. Fixes golang/go#6010. R=golang-dev, bradfitz, r, arnehormann, rsc CC=golang-dev https://golang.org/cl/12978043
This commit is contained in:
parent
dfa65ded17
commit
562e4faeca
|
|
@ -0,0 +1,64 @@
|
||||||
|
// Copyright 2013 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.
|
||||||
|
|
||||||
|
// +build ignore
|
||||||
|
|
||||||
|
// Command bake takes a list of file names and writes a Go source file to
|
||||||
|
// standard output that declares a map of string constants containing the input files.
|
||||||
|
//
|
||||||
|
// For example, the command
|
||||||
|
// bake foo.html bar.txt
|
||||||
|
// produces a source file in package main that declares the variable bakedFiles
|
||||||
|
// that is a map with keys "foo.html" and "bar.txt" that contain the contents
|
||||||
|
// of foo.html and bar.txt.
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"unicode/utf8"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
if err := bake(os.Args[1:]); err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func bake(files []string) error {
|
||||||
|
w := bufio.NewWriter(os.Stdout)
|
||||||
|
fmt.Fprintf(w, "%v\n\npackage main\n\n", warning)
|
||||||
|
fmt.Fprintf(w, "var bakedFiles = map[string]string{\n")
|
||||||
|
for _, fn := range files {
|
||||||
|
b, err := ioutil.ReadFile(fn)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !utf8.Valid(b) {
|
||||||
|
return fmt.Errorf("file %s is not valid UTF-8", fn)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(w, "\t%q: `%s`,\n", filepath.Base(fn), sanitize(b))
|
||||||
|
}
|
||||||
|
fmt.Fprintln(w, "}")
|
||||||
|
return w.Flush()
|
||||||
|
}
|
||||||
|
|
||||||
|
// sanitize prepares a string as a raw string constant.
|
||||||
|
func sanitize(b []byte) []byte {
|
||||||
|
// Replace ` with `+"`"+`
|
||||||
|
b = bytes.Replace(b, []byte("`"), []byte("`+\"`\"+`"), -1)
|
||||||
|
|
||||||
|
// Replace BOM with `+"\xEF\xBB\xBF"+`
|
||||||
|
// (A BOM is valid UTF-8 but not permitted in Go source files.
|
||||||
|
// I wouldn't bother handling this, but for some insane reason
|
||||||
|
// jquery.js has a BOM somewhere in the middle.)
|
||||||
|
return bytes.Replace(b, []byte("\xEF\xBB\xBF"), []byte("`+\"\\xEF\\xBB\\xBF\"+`"), -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
const warning = "// DO NOT EDIT ** This file was generated with the bake tool ** DO NOT EDIT //"
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# Copyright 2013 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.
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
go run bake.go template/* | gofmt > template.go
|
||||||
|
|
||||||
|
|
@ -50,6 +50,7 @@ import (
|
||||||
|
|
||||||
"code.google.com/p/go.tools/godoc"
|
"code.google.com/p/go.tools/godoc"
|
||||||
"code.google.com/p/go.tools/godoc/vfs"
|
"code.google.com/p/go.tools/godoc/vfs"
|
||||||
|
"code.google.com/p/go.tools/godoc/vfs/mapfs"
|
||||||
"code.google.com/p/go.tools/godoc/vfs/zipfs"
|
"code.google.com/p/go.tools/godoc/vfs/zipfs"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -196,13 +197,7 @@ func main() {
|
||||||
if *templateDir != "" {
|
if *templateDir != "" {
|
||||||
fs.Bind("/lib/godoc", vfs.OS(*templateDir), "/", vfs.BindBefore)
|
fs.Bind("/lib/godoc", vfs.OS(*templateDir), "/", vfs.BindBefore)
|
||||||
} else {
|
} else {
|
||||||
// Read templates from go.tools repository; if not
|
fs.Bind("/lib/godoc", mapfs.New(bakedFiles), "/", vfs.BindReplace)
|
||||||
// found there, fall back on $GOROOT/lib/godoc
|
|
||||||
// which will be present in binary distributions.
|
|
||||||
pkg, err := build.Import(templatePath, "", build.FindOnly)
|
|
||||||
if err == nil {
|
|
||||||
fs.Bind("/lib/godoc", vfs.OS(pkg.Dir), "/", vfs.BindReplace)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// use file system specified via .zip file (path separator must be '/')
|
// use file system specified via .zip file (path separator must be '/')
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,81 @@
|
||||||
|
// Copyright 2013 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 mapfs file provides an implementation of the FileSystem
|
||||||
|
// interface based on the contents of a map[string]string.
|
||||||
|
package mapfs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"code.google.com/p/go.tools/godoc/vfs"
|
||||||
|
)
|
||||||
|
|
||||||
|
func New(m map[string]string) vfs.FileSystem {
|
||||||
|
return mapFS(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// mapFS is the map based implementation of FileSystem
|
||||||
|
type mapFS map[string]string
|
||||||
|
|
||||||
|
func (fs mapFS) String() string { return "mapfs" }
|
||||||
|
|
||||||
|
func (fs mapFS) Close() error { return nil }
|
||||||
|
|
||||||
|
func filename(p string) string {
|
||||||
|
if len(p) > 0 && p[0] == '/' {
|
||||||
|
p = p[1:]
|
||||||
|
}
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fs mapFS) Open(p string) (vfs.ReadSeekCloser, error) {
|
||||||
|
b, ok := fs[filename(p)]
|
||||||
|
if !ok {
|
||||||
|
return nil, os.ErrNotExist
|
||||||
|
}
|
||||||
|
return nopCloser{strings.NewReader(b)}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fs mapFS) Lstat(p string) (os.FileInfo, error) {
|
||||||
|
b, ok := fs[filename(p)]
|
||||||
|
if !ok {
|
||||||
|
return nil, os.ErrNotExist
|
||||||
|
}
|
||||||
|
return mapFI{name: p, size: int64(len(b))}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fs mapFS) Stat(p string) (os.FileInfo, error) {
|
||||||
|
return fs.Lstat(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fs mapFS) ReadDir(p string) ([]os.FileInfo, error) {
|
||||||
|
var list []os.FileInfo
|
||||||
|
for fn, b := range fs {
|
||||||
|
list = append(list, mapFI{name: fn, size: int64(len(b))})
|
||||||
|
}
|
||||||
|
return list, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// mapFI is the map-based implementation of FileInfo.
|
||||||
|
type mapFI struct {
|
||||||
|
name string
|
||||||
|
size int64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fi mapFI) IsDir() bool { return false }
|
||||||
|
func (fi mapFI) ModTime() time.Time { return time.Time{} }
|
||||||
|
func (fi mapFI) Mode() os.FileMode { return 0444 }
|
||||||
|
func (fi mapFI) Name() string { return fi.name }
|
||||||
|
func (fi mapFI) Size() int64 { return fi.size }
|
||||||
|
func (fi mapFI) Sys() interface{} { return nil }
|
||||||
|
|
||||||
|
type nopCloser struct {
|
||||||
|
io.ReadSeeker
|
||||||
|
}
|
||||||
|
|
||||||
|
func (nc nopCloser) Close() error { return nil }
|
||||||
Loading…
Reference in New Issue