diff --git a/cmd/godoc/godoc_test.go b/cmd/godoc/godoc_test.go index b0a4ef0b..39ca16ae 100644 --- a/cmd/godoc/godoc_test.go +++ b/cmd/godoc/godoc_test.go @@ -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) diff --git a/cmd/godoc/main.go b/cmd/godoc/main.go index 46938734..30caa2a0 100644 --- a/cmd/godoc/main.go +++ b/cmd/godoc/main.go @@ -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 != "" diff --git a/cmd/godoc/setup-godoc-app.bash b/cmd/godoc/setup-godoc-app.bash index 1756f4ef..4bc2787b 100755 --- a/cmd/godoc/setup-godoc-app.bash +++ b/cmd/godoc/setup-godoc-app.bash @@ -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. # diff --git a/godoc/analysis/analysis.go b/godoc/analysis/analysis.go index 7bf4dc0f..f426f13f 100644 --- a/godoc/analysis/analysis.go +++ b/godoc/analysis/analysis.go @@ -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 { diff --git a/godoc/cmdline_test.go b/godoc/cmdline_test.go index 0211d0ed..2228a6ae 100644 --- a/godoc/cmdline_test.go +++ b/godoc/cmdline_test.go @@ -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}} diff --git a/godoc/corpus.go b/godoc/corpus.go index e1b4107b..021fb158 100644 --- a/godoc/corpus.go +++ b/godoc/corpus.go @@ -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 diff --git a/godoc/dirtrees.go b/godoc/dirtrees.go index 5d35e10d..c38d3b2c 100644 --- a/godoc/dirtrees.go +++ b/godoc/dirtrees.go @@ -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 diff --git a/godoc/godoc.go b/godoc/godoc.go index dd574dce..8ec731c7 100644 --- a/godoc/godoc.go +++ b/godoc/godoc.go @@ -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 } diff --git a/godoc/godoc_test.go b/godoc/godoc_test.go index 37e1d713..a10a1ab7 100644 --- a/godoc/godoc_test.go +++ b/godoc/godoc_test.go @@ -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) diff --git a/godoc/index_test.go b/godoc/index_test.go index e788b9c4..562c97aa 100644 --- a/godoc/index_test.go +++ b/godoc/index_test.go @@ -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 diff --git a/godoc/pres.go b/godoc/pres.go index 0b1521f6..42c40f02 100644 --- a/godoc/pres.go +++ b/godoc/pres.go @@ -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//. + // The source file argument has the form /src//. 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//. + // The source file argument has the form /src//. 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//. + // The source file argument has the form /src//. // 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) diff --git a/godoc/redirect/redirect.go b/godoc/redirect/redirect.go index aceb666d..4fb58986 100644 --- a/godoc/redirect/redirect.go +++ b/godoc/redirect/redirect.go @@ -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) +} diff --git a/godoc/server.go b/godoc/server.go index 900f9b7c..e81c6737 100644 --- a/godoc/server.go +++ b/godoc/server.go @@ -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("