godoc: exclude internal packages and cmd from packages page.
Internal packages are now only included with ?m=all Fixes golang/go#8879 LGTM=bradfitz R=golang-codereviews, bradfitz CC=golang-codereviews https://golang.org/cl/155910044
This commit is contained in:
parent
0513cb08b6
commit
13837d25ef
|
|
@ -152,11 +152,49 @@ func TestWeb(t *testing.T) {
|
||||||
}
|
}
|
||||||
defer cmd.Process.Kill()
|
defer cmd.Process.Kill()
|
||||||
waitForServer(t, addr)
|
waitForServer(t, addr)
|
||||||
tests := []struct{ path, substr string }{
|
tests := []struct {
|
||||||
{"/", "Go is an open source programming language"},
|
path string
|
||||||
{"/pkg/fmt/", "Package fmt implements formatted I/O"},
|
match []string
|
||||||
{"/src/fmt/", "scan_test.go"},
|
dontmatch []string
|
||||||
{"/src/fmt/print.go", "// Println formats using"},
|
}{
|
||||||
|
{
|
||||||
|
path: "/",
|
||||||
|
match: []string{"Go is an open source programming language"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/pkg/fmt/",
|
||||||
|
match: []string{"Package fmt implements formatted I/O"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/src/fmt/",
|
||||||
|
match: []string{"scan_test.go"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/src/fmt/print.go",
|
||||||
|
match: []string{"// Println formats using"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/pkg",
|
||||||
|
match: []string{
|
||||||
|
"Standard library",
|
||||||
|
"Package fmt implements formatted I/O",
|
||||||
|
},
|
||||||
|
dontmatch: []string{
|
||||||
|
"internal/syscall",
|
||||||
|
"cmd/gc",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/pkg/?m=all",
|
||||||
|
match: []string{
|
||||||
|
"Standard library",
|
||||||
|
"Package fmt implements formatted I/O",
|
||||||
|
"internal/syscall",
|
||||||
|
},
|
||||||
|
dontmatch: []string{
|
||||||
|
"cmd/gc",
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
url := fmt.Sprintf("http://%s%s", addr, test.path)
|
url := fmt.Sprintf("http://%s%s", addr, test.path)
|
||||||
|
|
@ -170,9 +208,21 @@ func TestWeb(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("GET %s: failed to read body: %s (response: %v)", url, err, resp)
|
t.Errorf("GET %s: failed to read body: %s (response: %v)", url, err, resp)
|
||||||
}
|
}
|
||||||
if bytes.Index(body, []byte(test.substr)) < 0 {
|
isErr := false
|
||||||
t.Errorf("GET %s: want substring %q in body, got:\n%s",
|
for _, substr := range test.match {
|
||||||
url, test.substr, string(body))
|
if !bytes.Contains(body, []byte(substr)) {
|
||||||
|
t.Errorf("GET %s: wanted substring %q in body", url, substr)
|
||||||
|
isErr = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, substr := range test.dontmatch {
|
||||||
|
if bytes.Contains(body, []byte(substr)) {
|
||||||
|
t.Errorf("GET %s: didn't want substring %q in body", url, substr)
|
||||||
|
isErr = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if isErr {
|
||||||
|
t.Errorf("GET %s: got:\n%s", url, body)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -194,8 +194,19 @@ package main
|
||||||
fs.Bind("/", mfs, "/", vfs.BindReplace)
|
fs.Bind("/", mfs, "/", vfs.BindReplace)
|
||||||
c := NewCorpus(fs)
|
c := NewCorpus(fs)
|
||||||
p := &Presentation{Corpus: c}
|
p := &Presentation{Corpus: c}
|
||||||
p.cmdHandler = handlerServer{p, c, "/cmd/", "/src/cmd"}
|
p.cmdHandler = handlerServer{
|
||||||
p.pkgHandler = handlerServer{p, c, "/pkg/", "/src"}
|
p: p,
|
||||||
|
c: c,
|
||||||
|
pattern: "/cmd/",
|
||||||
|
fsRoot: "/src/cmd",
|
||||||
|
}
|
||||||
|
p.pkgHandler = handlerServer{
|
||||||
|
p: p,
|
||||||
|
c: c,
|
||||||
|
pattern: "/pkg/",
|
||||||
|
fsRoot: "/src",
|
||||||
|
exclude: []string{"/src/cmd"},
|
||||||
|
}
|
||||||
p.initFuncMap()
|
p.initFuncMap()
|
||||||
p.PackageText = template.Must(template.New("PackageText").Funcs(p.FuncMap()).Parse(`{{$info := .}}{{$filtered := .IsFiltered}}{{if $filtered}}{{range .PAst}}{{range .Decls}}{{node $info .}}{{end}}{{end}}{{else}}{{with .PAst}}{{range $filename, $ast := .}}{{$filename}}:
|
p.PackageText = template.Must(template.New("PackageText").Funcs(p.FuncMap()).Parse(`{{$info := .}}{{$filtered := .IsFiltered}}{{if $filtered}}{{range .PAst}}{{range .Decls}}{{node $info .}}{{end}}{{end}}{{else}}{{with .PAst}}{{range $filename, $ast := .}}{{$filename}}:
|
||||||
{{node $ $ast}}{{end}}{{end}}{{end}}{{with .PDoc}}{{if $.IsMain}}COMMAND {{.Doc}}{{else}}PACKAGE {{.Doc}}{{end}}{{with .Funcs}}
|
{{node $ $ast}}{{end}}{{end}}{{end}}{{with .PDoc}}{{if $.IsMain}}COMMAND {{.Doc}}{{else}}PACKAGE {{.Doc}}{{end}}{{with .Funcs}}
|
||||||
|
|
|
||||||
|
|
@ -280,8 +280,10 @@ type DirList struct {
|
||||||
|
|
||||||
// listing creates a (linear) directory listing from a directory tree.
|
// listing creates a (linear) directory listing from a directory tree.
|
||||||
// If skipRoot is set, the root directory itself is excluded from the list.
|
// If skipRoot is set, the root directory itself is excluded from the list.
|
||||||
|
// If filter is set, only the directory entries whose paths match the filter
|
||||||
|
// are included.
|
||||||
//
|
//
|
||||||
func (root *Directory) listing(skipRoot bool) *DirList {
|
func (root *Directory) listing(skipRoot bool, filter func(string) bool) *DirList {
|
||||||
if root == nil {
|
if root == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -306,10 +308,12 @@ func (root *Directory) listing(skipRoot bool) *DirList {
|
||||||
}
|
}
|
||||||
|
|
||||||
// create list
|
// create list
|
||||||
list := make([]DirEntry, n)
|
list := make([]DirEntry, 0, n)
|
||||||
i := 0
|
|
||||||
for d := range root.iter(skipRoot) {
|
for d := range root.iter(skipRoot) {
|
||||||
p := &list[i]
|
if filter != nil && !filter(d.Path) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
var p DirEntry
|
||||||
p.Depth = d.Depth - minDepth
|
p.Depth = d.Depth - minDepth
|
||||||
p.Height = maxHeight - p.Depth
|
p.Height = maxHeight - p.Depth
|
||||||
// the path is relative to root.Path - remove the root.Path
|
// the path is relative to root.Path - remove the root.Path
|
||||||
|
|
@ -322,7 +326,7 @@ func (root *Directory) listing(skipRoot bool) *DirList {
|
||||||
p.Name = d.Name
|
p.Name = d.Name
|
||||||
p.HasPkg = d.HasPkg
|
p.HasPkg = d.HasPkg
|
||||||
p.Synopsis = d.Synopsis
|
p.Synopsis = d.Synopsis
|
||||||
i++
|
list = append(list, p)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &DirList{maxHeight, list}
|
return &DirList{maxHeight, list}
|
||||||
|
|
|
||||||
|
|
@ -115,8 +115,19 @@ func NewPresentation(c *Corpus) *Presentation {
|
||||||
(*Presentation).SearchResultTxt,
|
(*Presentation).SearchResultTxt,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
p.cmdHandler = handlerServer{p, c, "/cmd/", "/src/cmd"}
|
p.cmdHandler = handlerServer{
|
||||||
p.pkgHandler = handlerServer{p, c, "/pkg/", "/src"}
|
p: p,
|
||||||
|
c: c,
|
||||||
|
pattern: "/cmd/",
|
||||||
|
fsRoot: "/src/cmd",
|
||||||
|
}
|
||||||
|
p.pkgHandler = handlerServer{
|
||||||
|
p: p,
|
||||||
|
c: c,
|
||||||
|
pattern: "/pkg/",
|
||||||
|
fsRoot: "/src",
|
||||||
|
exclude: []string{"/src/cmd"},
|
||||||
|
}
|
||||||
p.cmdHandler.registerWithMux(p.mux)
|
p.cmdHandler.registerWithMux(p.mux)
|
||||||
p.pkgHandler.registerWithMux(p.mux)
|
p.pkgHandler.registerWithMux(p.mux)
|
||||||
p.mux.HandleFunc("/", p.ServeFile)
|
p.mux.HandleFunc("/", p.ServeFile)
|
||||||
|
|
|
||||||
|
|
@ -36,9 +36,10 @@ import (
|
||||||
// This should probably merge into something else.
|
// This should probably merge into something else.
|
||||||
type handlerServer struct {
|
type handlerServer struct {
|
||||||
p *Presentation
|
p *Presentation
|
||||||
c *Corpus // copy of p.Corpus
|
c *Corpus // copy of p.Corpus
|
||||||
pattern string // url pattern; e.g. "/pkg/"
|
pattern string // url pattern; e.g. "/pkg/"
|
||||||
fsRoot string // file system root to which the pattern is mapped
|
fsRoot string // file system root to which the pattern is mapped; e.g. "/src"
|
||||||
|
exclude []string // file system paths to exclude; e.g. "/src/cmd"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *handlerServer) registerWithMux(mux *http.ServeMux) {
|
func (s *handlerServer) registerWithMux(mux *http.ServeMux) {
|
||||||
|
|
@ -66,7 +67,14 @@ func (h *handlerServer) GetPageInfo(abspath, relpath string, mode PageInfoMode)
|
||||||
ctxt := build.Default
|
ctxt := build.Default
|
||||||
ctxt.IsAbsPath = pathpkg.IsAbs
|
ctxt.IsAbsPath = pathpkg.IsAbs
|
||||||
ctxt.ReadDir = func(dir string) ([]os.FileInfo, error) {
|
ctxt.ReadDir = func(dir string) ([]os.FileInfo, error) {
|
||||||
return h.c.fs.ReadDir(filepath.ToSlash(dir))
|
f, err := h.c.fs.ReadDir(filepath.ToSlash(dir))
|
||||||
|
filtered := make([]os.FileInfo, 0, len(f))
|
||||||
|
for _, i := range f {
|
||||||
|
if mode&NoFiltering != 0 || i.Name() != "internal" {
|
||||||
|
filtered = append(filtered, i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return filtered, err
|
||||||
}
|
}
|
||||||
ctxt.OpenFile = func(name string) (r io.ReadCloser, err error) {
|
ctxt.OpenFile = func(name string) (r io.ReadCloser, err error) {
|
||||||
data, err := vfs.ReadFile(h.c.fs, filepath.ToSlash(name))
|
data, err := vfs.ReadFile(h.c.fs, filepath.ToSlash(name))
|
||||||
|
|
@ -188,13 +196,35 @@ func (h *handlerServer) GetPageInfo(abspath, relpath string, mode PageInfoMode)
|
||||||
dir = h.c.newDirectory(abspath, 1)
|
dir = h.c.newDirectory(abspath, 1)
|
||||||
timestamp = time.Now()
|
timestamp = time.Now()
|
||||||
}
|
}
|
||||||
info.Dirs = dir.listing(true)
|
info.Dirs = dir.listing(true, func(path string) bool { return h.includePath(path, mode) })
|
||||||
info.DirTime = timestamp
|
info.DirTime = timestamp
|
||||||
info.DirFlat = mode&FlatDir != 0
|
info.DirFlat = mode&FlatDir != 0
|
||||||
|
|
||||||
return info
|
return info
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *handlerServer) includePath(path string, mode PageInfoMode) (r bool) {
|
||||||
|
// if the path is under one of the exclusion paths, don't list.
|
||||||
|
for _, e := range h.exclude {
|
||||||
|
if strings.HasPrefix(path, e) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the path includes 'internal', don't list unless we are in the NoFiltering mode.
|
||||||
|
if mode&NoFiltering != 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if strings.Contains(path, "internal") {
|
||||||
|
for _, c := range strings.Split(path, string(os.PathSeparator)) {
|
||||||
|
if c == "internal" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
type funcsByName []*doc.Func
|
type funcsByName []*doc.Func
|
||||||
|
|
||||||
func (s funcsByName) Len() int { return len(s) }
|
func (s funcsByName) Len() int { return len(s) }
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue