go.tools/godoc: deal with fallout from $GOROOT/src/pkg -> $GOROOT/src renaming.

To avoid breaking URLs, we redirect /src/pkg/* to /src/*.

The URL /pkg is now the "directory" /src, which triggers the
"Packages" index.

All other references to "src/pkg" are now gone,
except a number in the namespace documentation which are
probably still illustrative.

Tested: go test cmd/godoc godoc
        Manual inspection of src and src/pkg pages.
        with GOROOT and GOPATH packages
        -analysis
        /AUTHORS file URL still works

LGTM=bradfitz, adg
R=bradfitz, adg
CC=golang-codereviews
https://golang.org/cl/141770044
This commit is contained in:
Alan Donovan 2014-09-10 09:02:54 -04:00
Родитель 3cded4a933
Коммит 6c93dbff3e
15 изменённых файлов: 74 добавлений и 66 удалений

Просмотреть файл

@ -155,8 +155,8 @@ func TestWeb(t *testing.T) {
tests := []struct{ path, substr string }{
{"/", "Go is an open source programming language"},
{"/pkg/fmt/", "Package fmt implements formatted I/O"},
{"/src/pkg/fmt/", "scan_test.go"},
{"/src/pkg/fmt/print.go", "// Println formats using"},
{"/src/fmt/", "scan_test.go"},
{"/src/fmt/print.go", "// Println formats using"},
}
for _, test := range tests {
url := fmt.Sprintf("http://%s%s", addr, test.path)
@ -186,7 +186,7 @@ func TestTypeAnalysis(t *testing.T) {
}
defer os.RemoveAll(tmpdir)
for _, f := range []struct{ file, content string }{
{"goroot/src/pkg/lib/lib.go", `
{"goroot/src/lib/lib.go", `
package lib
type T struct{}
const C = 3
@ -237,14 +237,14 @@ func main() { print(lib.V) }
// has been annotated onto the source view.
tryagain:
for _, test := range []struct{ url, pattern string }{
{"/src/pkg/lib/lib.go", "L2.*package .*Package docs for lib.*/pkg/lib"},
{"/src/pkg/lib/lib.go", "L3.*type .*type info for T.*struct"},
{"/src/pkg/lib/lib.go", "L5.*var V .*type T struct"},
{"/src/pkg/lib/lib.go", "L6.*func .*type T struct.*T.*return .*const C untyped int.*C"},
{"/src/lib/lib.go", "L2.*package .*Package docs for lib.*/lib"},
{"/src/lib/lib.go", "L3.*type .*type info for T.*struct"},
{"/src/lib/lib.go", "L5.*var V .*type T struct"},
{"/src/lib/lib.go", "L6.*func .*type T struct.*T.*return .*const C untyped int.*C"},
{"/src/pkg/app/main.go", "L2.*package .*Package docs for app"},
{"/src/pkg/app/main.go", "L3.*import .*Package docs for lib.*lib"},
{"/src/pkg/app/main.go", "L4.*func main.*package lib.*lib.*var lib.V lib.T.*V"},
{"/src/app/main.go", "L2.*package .*Package docs for app"},
{"/src/app/main.go", "L3.*import .*Package docs for lib.*lib"},
{"/src/app/main.go", "L4.*func main.*package lib.*lib.*var lib.V lib.T.*V"},
} {
url := fmt.Sprintf("http://%s%s", addr, test.url)
resp, err := http.Get(url)

Просмотреть файл

@ -173,7 +173,8 @@ func main() {
// Determine file system to use.
if *zipfile == "" {
// use file system of underlying OS
fs.Bind("/", gatefs.New(vfs.OS(*goroot), fsGate), "/", vfs.BindReplace)
rootfs := gatefs.New(vfs.OS(*goroot), fsGate)
fs.Bind("/", rootfs, "/", vfs.BindReplace)
} else {
// use file system specified via .zip file (path separator must be '/')
rc, err := zip.OpenReader(*zipfile)
@ -191,7 +192,7 @@ func main() {
// Bind $GOPATH trees into Go root.
for _, p := range filepath.SplitList(build.Default.GOPATH) {
fs.Bind("/src/pkg", gatefs.New(vfs.OS(p), fsGate), "/src", vfs.BindAfter)
fs.Bind("/src", gatefs.New(vfs.OS(p), fsGate), "/src", vfs.BindAfter)
}
httpMode := *httpAddr != ""

Просмотреть файл

@ -5,7 +5,7 @@
# license that can be found in the LICENSE file.
# This script creates a complete godoc app in $APPDIR.
# It copies the cmd/godoc and src/pkg/go/... sources from GOROOT,
# It copies the cmd/godoc and src/go/... sources from GOROOT,
# synthesizes an app.yaml file, and creates the .zip, index, and
# configuration files.
#

Просмотреть файл

@ -11,7 +11,7 @@
// progressively populated as analysis facts are derived.
//
// The Result is a mapping from each godoc file URL
// (e.g. /src/pkg/fmt/print.go) to information about that file. The
// (e.g. /src/fmt/print.go) to information about that file. The
// information is a list of HTML markup links and a JSON array of
// structured data values. Some of the links call client-side
// JavaScript functions that index this array.
@ -302,7 +302,7 @@ type analysis struct {
ops []chanOp // all channel ops in program
allNamed []*types.Named // all named types in the program
ptaConfig pointer.Config
path2url map[string]string // maps openable path to godoc file URL (/src/pkg/fmt/print.go)
path2url map[string]string // maps openable path to godoc file URL (/src/fmt/print.go)
pcgs map[*ssa.Package]*packageCallGraph
}
@ -345,7 +345,7 @@ func Run(pta bool, result *Result) {
var roots, args []string // roots[i] ends with os.PathSeparator
// Enumerate packages in $GOROOT.
root := filepath.Join(runtime.GOROOT(), "src", "pkg") + string(os.PathSeparator)
root := filepath.Join(runtime.GOROOT(), "src") + string(os.PathSeparator)
roots = append(roots, root)
args = allPackages(root)
log.Printf("GOROOT=%s: %s\n", root, args)
@ -408,7 +408,7 @@ func Run(pta bool, result *Result) {
}
// Build a mapping from openable filenames to godoc file URLs,
// i.e. "/src/pkg/" plus path relative to GOROOT/src/pkg or GOPATH[i]/src.
// i.e. "/src/" plus path relative to GOROOT/src or GOPATH[i]/src.
a.path2url = make(map[string]string)
for _, info := range iprog.AllPackages {
nextfile:
@ -421,7 +421,7 @@ func Run(pta bool, result *Result) {
for _, root := range roots {
rel := strings.TrimPrefix(abs, root)
if len(rel) < len(abs) {
a.path2url[abs] = "/src/pkg/" + filepath.ToSlash(rel)
a.path2url[abs] = "/src/" + filepath.ToSlash(rel)
continue nextfile
}
}
@ -572,7 +572,7 @@ func (a linksByStart) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a linksByStart) Len() int { return len(a) }
// allPackages returns a new sorted slice of all packages beneath the
// specified package root directory, e.g. $GOROOT/src/pkg or $GOPATH/src.
// specified package root directory, e.g. $GOROOT/src or $GOPATH/src.
// Derived from from go/ssa/stdlib_test.go
// root must end with os.PathSeparator.
func allPackages(root string) []string {

Просмотреть файл

@ -23,7 +23,7 @@ import (
// the temporary directory.
func setupGoroot(t *testing.T) (cleanup func()) {
var stdLib = map[string]string{
"src/pkg/fmt/fmt.go": `// Package fmt implements formatted I/O.
"src/fmt/fmt.go": `// Package fmt implements formatted I/O.
package fmt
type Stringer interface {
@ -155,10 +155,10 @@ func TestCommandLine(t *testing.T) {
cleanup := setupGoroot(t)
defer cleanup()
mfs := mapfs.New(map[string]string{
"src/pkg/bar/bar.go": `// Package bar is an example.
"src/bar/bar.go": `// Package bar is an example.
package bar
`,
"src/pkg/foo/foo.go": `// Package foo.
"src/foo/foo.go": `// Package foo.
package foo
// First function is first.
@ -169,7 +169,7 @@ func First() {
func Second() {
}
`,
"src/pkg/gen/gen.go": `// Package gen
"src/gen/gen.go": `// Package gen
package gen
//line notgen.go:3
@ -177,7 +177,7 @@ package gen
// line 2 should appear
func F()
//line foo.go:100`, // no newline on end to check corner cases!
"src/pkg/vet/vet.go": `// Package vet
"src/vet/vet.go": `// Package vet
package vet
`,
"src/cmd/go/doc.go": `// The go command
@ -195,7 +195,7 @@ package main
c := NewCorpus(fs)
p := &Presentation{Corpus: c}
p.cmdHandler = handlerServer{p, c, "/cmd/", "/src/cmd"}
p.pkgHandler = handlerServer{p, c, "/pkg/", "/src/pkg"}
p.pkgHandler = handlerServer{p, c, "/pkg/", "/src"}
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}}:
{{node $ $ast}}{{end}}{{end}}{{end}}{{with .PDoc}}{{if $.IsMain}}COMMAND {{.Doc}}{{else}}PACKAGE {{.Doc}}{{end}}{{with .Funcs}}

Просмотреть файл

@ -82,7 +82,7 @@ type Corpus struct {
// IndexDirectory optionally specifies a function to determine
// whether the provided directory should be indexed. The dir
// will be of the form "/src/cmd/6a", "/doc/play",
// "/src/pkg/io", etc.
// "/src/io", etc.
// If nil, all directories are indexed if indexing is enabled.
IndexDirectory func(dir string) bool

Просмотреть файл

@ -77,7 +77,7 @@ func (b *treeBuilder) newDirTree(fset *token.FileSet, path, name string, depth i
haveSummary := false
if hook := b.c.SummarizePackage; hook != nil {
if summary, show0, ok := hook(strings.TrimPrefix(path, "/src/pkg/")); ok {
if summary, show0, ok := hook(strings.TrimPrefix(path, "/src/")); ok {
hasPkgFiles = true
show = show0
synopses[0] = summary

Просмотреть файл

@ -369,9 +369,8 @@ func srcPosLinkFunc(s string, line, low, high int) string {
func srcLinkFunc(s string) string {
s = pathpkg.Clean("/" + s)
// TODO(bgarcia): Once the /src/pkg -> /src transition occurs, update this function.
if !strings.HasPrefix(s, "/src/pkg/") {
s = "/src/pkg" + s
if !strings.HasPrefix(s, "/src/") {
s = "/src" + s
}
return s
}

Просмотреть файл

@ -13,8 +13,8 @@ func TestPkgLinkFunc(t *testing.T) {
path string
want string
}{
{"/src/pkg/fmt", "pkg/fmt"},
{"src/pkg/fmt", "pkg/fmt"},
{"/src/fmt", "pkg/fmt"},
{"src/fmt", "pkg/fmt"},
{"/fmt", "pkg/fmt"},
{"fmt", "pkg/fmt"},
} {
@ -32,13 +32,13 @@ func TestSrcPosLinkFunc(t *testing.T) {
high int
want string
}{
{"/src/pkg/fmt/print.go", 42, 30, 50, "/src/pkg/fmt/print.go?s=30:50#L32"},
{"/src/pkg/fmt/print.go", 2, 1, 5, "/src/pkg/fmt/print.go?s=1:5#L1"},
{"/src/pkg/fmt/print.go", 2, 0, 0, "/src/pkg/fmt/print.go#L2"},
{"/src/pkg/fmt/print.go", 0, 0, 0, "/src/pkg/fmt/print.go"},
{"/src/pkg/fmt/print.go", 0, 1, 5, "/src/pkg/fmt/print.go?s=1:5#L1"},
{"fmt/print.go", 0, 0, 0, "/src/pkg/fmt/print.go"},
{"fmt/print.go", 0, 1, 5, "/src/pkg/fmt/print.go?s=1:5#L1"},
{"/src/fmt/print.go", 42, 30, 50, "/src/fmt/print.go?s=30:50#L32"},
{"/src/fmt/print.go", 2, 1, 5, "/src/fmt/print.go?s=1:5#L1"},
{"/src/fmt/print.go", 2, 0, 0, "/src/fmt/print.go#L2"},
{"/src/fmt/print.go", 0, 0, 0, "/src/fmt/print.go"},
{"/src/fmt/print.go", 0, 1, 5, "/src/fmt/print.go?s=1:5#L1"},
{"fmt/print.go", 0, 0, 0, "/src/fmt/print.go"},
{"fmt/print.go", 0, 1, 5, "/src/fmt/print.go?s=1:5#L1"},
} {
if got := srcPosLinkFunc(tc.src, tc.line, tc.low, tc.high); got != tc.want {
t.Errorf("srcLinkFunc(%v, %v, %v, %v) = %v; want %v", tc.src, tc.line, tc.low, tc.high, got, tc.want)
@ -51,10 +51,10 @@ func TestSrcLinkFunc(t *testing.T) {
src string
want string
}{
{"/src/pkg/fmt/print.go", "/src/pkg/fmt/print.go"},
{"src/pkg/fmt/print.go", "/src/pkg/fmt/print.go"},
{"/fmt/print.go", "/src/pkg/fmt/print.go"},
{"fmt/print.go", "/src/pkg/fmt/print.go"},
{"/src/fmt/print.go", "/src/fmt/print.go"},
{"src/fmt/print.go", "/src/fmt/print.go"},
{"/fmt/print.go", "/src/fmt/print.go"},
{"fmt/print.go", "/src/fmt/print.go"},
} {
if got := srcLinkFunc(tc.src); got != tc.want {
t.Errorf("srcLinkFunc(%v) = %v; want %v", tc.src, got, tc.want)
@ -69,10 +69,10 @@ func TestQueryLinkFunc(t *testing.T) {
line int
want string
}{
{"/src/pkg/fmt/print.go", "Sprintf", 33, "/src/pkg/fmt/print.go?h=Sprintf#L33"},
{"/src/pkg/fmt/print.go", "Sprintf", 0, "/src/pkg/fmt/print.go?h=Sprintf"},
{"src/pkg/fmt/print.go", "EOF", 33, "/src/pkg/fmt/print.go?h=EOF#L33"},
{"src/pkg/fmt/print.go", "a%3f+%26b", 1, "/src/pkg/fmt/print.go?h=a%3f+%26b#L1"},
{"/src/fmt/print.go", "Sprintf", 33, "/src/fmt/print.go?h=Sprintf#L33"},
{"/src/fmt/print.go", "Sprintf", 0, "/src/fmt/print.go?h=Sprintf"},
{"src/fmt/print.go", "EOF", 33, "/src/fmt/print.go?h=EOF#L33"},
{"src/fmt/print.go", "a%3f+%26b", 1, "/src/fmt/print.go?h=a%3f+%26b#L1"},
} {
if got := queryLinkFunc(tc.src, tc.query, tc.line); got != tc.want {
t.Errorf("queryLinkFunc(%v, %v, %v) = %v; want %v", tc.src, tc.query, tc.line, got, tc.want)

Просмотреть файл

@ -16,7 +16,7 @@ import (
func newCorpus(t *testing.T) *Corpus {
c := NewCorpus(mapfs.New(map[string]string{
"src/pkg/foo/foo.go": `// Package foo is an example.
"src/foo/foo.go": `// Package foo is an example.
package foo
import "bar"
@ -32,20 +32,20 @@ func New() *Foo {
return new(Foo)
}
`,
"src/pkg/bar/bar.go": `// Package bar is another example to test races.
"src/bar/bar.go": `// Package bar is another example to test races.
package bar
`,
"src/pkg/other/bar/bar.go": `// Package bar is another bar package.
"src/other/bar/bar.go": `// Package bar is another bar package.
package bar
func X() {}
`,
"src/pkg/skip/skip.go": `// Package skip should be skipped.
"src/skip/skip.go": `// Package skip should be skipped.
package skip
func Skip() {}
`,
"src/pkg/bar/readme.txt": `Whitelisted text file.
"src/bar/readme.txt": `Whitelisted text file.
`,
"src/pkg/bar/baz.zzz": `Text file not whitelisted.
"src/bar/baz.zzz": `Text file not whitelisted.
`,
}))
c.IndexEnabled = true

Просмотреть файл

@ -65,7 +65,7 @@ type Presentation struct {
// URLForSrc optionally specifies a function that takes a source file and
// returns a URL for it.
// The source file argument has the form /src/pkg/<path>/<filename>.
// The source file argument has the form /src/<path>/<filename>.
URLForSrc func(src string) string
// URLForSrcPos optionally specifies a function to create a URL given a
@ -73,12 +73,12 @@ type Presentation struct {
// positions (0-based, bytes from beginning of file). Ideally, the returned
// URL will be for the specified line of the file, while the high & low
// positions will be used to highlight a section of the file.
// The source file argument has the form /src/pkg/<path>/<filename>.
// The source file argument has the form /src/<path>/<filename>.
URLForSrcPos func(src string, line, low, high int) string
// URLForSrcQuery optionally specifies a function to create a URL given a
// source file, a query string, and a line from the source file (1-based).
// The source file argument has the form /src/pkg/<path>/<filename>.
// The source file argument has the form /src/<path>/<filename>.
// The query argument will be escaped for the purposes of embedding in a URL
// query parameter.
// Ideally, the returned URL will be for the specified line of the file with
@ -116,7 +116,7 @@ func NewPresentation(c *Corpus) *Presentation {
},
}
p.cmdHandler = handlerServer{p, c, "/cmd/", "/src/cmd"}
p.pkgHandler = handlerServer{p, c, "/pkg/", "/src/pkg"}
p.pkgHandler = handlerServer{p, c, "/pkg/", "/src"}
p.cmdHandler.registerWithMux(p.mux)
p.pkgHandler.registerWithMux(p.mux)
p.mux.HandleFunc("/", p.ServeFile)

Просмотреть файл

@ -28,6 +28,8 @@ func Register(mux *http.ServeMux) {
for path, redirect := range redirects {
mux.Handle(path, Handler(redirect))
}
// NB: /src/pkg (sans trailing slash) is the index of packages.
http.HandleFunc("/src/pkg/", srcPkgHandler)
}
func handlePathRedirects(mux *http.ServeMux, redirects map[string]string, prefix string) {
@ -155,3 +157,10 @@ func PrefixHandler(prefix, baseURL string) http.Handler {
http.Redirect(w, r, target, http.StatusFound)
})
}
// Redirect requests from the old "/src/pkg/foo" to the new "/src/foo".
// See http://golang.org/s/go14nopkg
func srcPkgHandler(w http.ResponseWriter, r *http.Request) {
r.URL.Path = "/src/" + r.URL.Path[len("/src/pkg/"):]
http.Redirect(w, r, r.URL.String(), http.StatusMovedPermanently)
}

Просмотреть файл

@ -253,7 +253,7 @@ func (h *handlerServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// special cases for top-level package/command directories
switch tabtitle {
case "/src/pkg":
case "/src":
title = "Packages"
tabtitle = "Packages"
case "/src/cmd":
@ -262,7 +262,6 @@ func (h *handlerServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
}
// Emit JSON array for type information.
// TODO(adonovan): display the h.c.Analysis.Status() message in the UI.
pi := h.c.Analysis.PackageInfo(relpath)
info.CallGraphIndex = pi.CallGraphIndex
info.CallGraph = htmltemplate.JS(marshalJSON(pi.CallGraph))
@ -501,7 +500,7 @@ func (p *Presentation) serveTextFile(w http.ResponseWriter, r *http.Request, abs
var buf bytes.Buffer
if pathpkg.Ext(abspath) == ".go" {
// Find markup links for this file (e.g. "/src/pkg/fmt/print.go").
// Find markup links for this file (e.g. "/src/fmt/print.go").
fi := p.Corpus.Analysis.FileInfo(abspath)
buf.WriteString("<script type='text/javascript'>document.ANALYSIS_DATA = ")
buf.Write(marshalJSON(fi.Data))

Просмотреть файл

@ -237,7 +237,7 @@
{{if $.PDoc}}
<h2 id="pkg-subdirectories">Subdirectories</h2>
{{end}}
{{if eq $.Dirname "/src/pkg"}}
{{if eq $.Dirname "/src"}}
<div id="manual-nav">
<dl>
<dt><a href="#stdlib">Standard library</a></dt>
@ -255,7 +255,7 @@
<th>&nbsp;&nbsp;&nbsp;&nbsp;</th>
<th style="text-align: left; width: auto">Synopsis</th>
</tr>
{{if not (or (eq $.Dirname "/src/pkg") (eq $.Dirname "/src/cmd") $.DirFlat)}}
{{if not (or (eq $.Dirname "/src") (eq $.Dirname "/src/cmd") $.DirFlat)}}
<tr>
<td><a href="..">..</a></td>
</tr>
@ -279,7 +279,7 @@
{{end}}
</table>
{{if eq $.Dirname "/src/pkg"}}
{{if eq $.Dirname "/src"}}
<h2 id="other">Other packages</h2>
<h3 id="subrepo">Sub-repositories</h3>

Просмотреть файл

@ -1748,7 +1748,7 @@ function cgAddChild(tree, ul, cgn) {
{{if $.PDoc}}
<h2 id="pkg-subdirectories">Subdirectories</h2>
{{end}}
{{if eq $.Dirname "/src/pkg"}}
{{if eq $.Dirname "/src"}}
<div id="manual-nav">
<dl>
<dt><a href="#stdlib">Standard library</a></dt>
@ -1766,7 +1766,7 @@ function cgAddChild(tree, ul, cgn) {
<th>&nbsp;&nbsp;&nbsp;&nbsp;</th>
<th style="text-align: left; width: auto">Synopsis</th>
</tr>
{{if not (or (eq $.Dirname "/src/pkg") (eq $.Dirname "/src/cmd") $.DirFlat)}}
{{if not (or (eq $.Dirname "/src") (eq $.Dirname "/src/cmd") $.DirFlat)}}
<tr>
<td><a href="..">..</a></td>
</tr>
@ -1790,7 +1790,7 @@ function cgAddChild(tree, ul, cgn) {
{{end}}
</table>
{{if eq $.Dirname "/src/pkg"}}
{{if eq $.Dirname "/src"}}
<h2 id="other">Other packages</h2>
<h3 id="subrepo">Sub-repositories</h3>