summaryrefslogtreecommitdiff
path: root/src/cmd/godoc
diff options
context:
space:
mode:
authorOndřej Surý <ondrej@sury.org>2011-04-20 15:44:41 +0200
committerOndřej Surý <ondrej@sury.org>2011-04-20 15:44:41 +0200
commit50104cc32a498f7517a51c8dc93106c51c7a54b4 (patch)
tree47af80be259cc7c45d0eaec7d42e61fa38c8e4fb /src/cmd/godoc
parentc072558b90f1bbedc2022b0f30c8b1ac4712538e (diff)
downloadgolang-50104cc32a498f7517a51c8dc93106c51c7a54b4.tar.gz
Imported Upstream version 2011.03.07.1upstream/2011.03.07.1
Diffstat (limited to 'src/cmd/godoc')
-rw-r--r--src/cmd/godoc/dirtrees.go29
-rw-r--r--src/cmd/godoc/godoc.go82
-rw-r--r--src/cmd/godoc/index.go8
-rw-r--r--src/cmd/godoc/main.go10
-rw-r--r--src/cmd/godoc/mapping.go47
-rw-r--r--src/cmd/godoc/utils.go12
6 files changed, 108 insertions, 80 deletions
diff --git a/src/cmd/godoc/dirtrees.go b/src/cmd/godoc/dirtrees.go
index edb4a169d..3ad7c8cfc 100644
--- a/src/cmd/godoc/dirtrees.go
+++ b/src/cmd/godoc/dirtrees.go
@@ -12,8 +12,9 @@ import (
"go/parser"
"go/token"
"io/ioutil"
+ "log"
"os"
- pathutil "path"
+ "path/filepath"
"strings"
"unicode"
)
@@ -31,7 +32,7 @@ type Directory struct {
func isGoFile(f *os.FileInfo) bool {
return f.IsRegular() &&
!strings.HasPrefix(f.Name, ".") && // ignore .files
- pathutil.Ext(f.Name) == ".go"
+ filepath.Ext(f.Name) == ".go"
}
@@ -100,7 +101,13 @@ func (b *treeBuilder) newDirTree(fset *token.FileSet, path, name string, depth i
return &Directory{depth, path, name, "", nil}
}
- list, _ := ioutil.ReadDir(path) // ignore errors
+ list, err := ioutil.ReadDir(path)
+ if err != nil {
+ // newDirTree is called with a path that should be a package
+ // directory; errors here should not happen, but if they do,
+ // we want to know about them
+ log.Printf("ioutil.ReadDir(%s): %s", path, err)
+ }
// determine number of subdirectories and if there are package files
ndirs := 0
@@ -116,7 +123,7 @@ func (b *treeBuilder) newDirTree(fset *token.FileSet, path, name string, depth i
// though the directory doesn't contain any real package files - was bug)
if synopses[0] == "" {
// no "optimal" package synopsis yet; continue to collect synopses
- file, err := parser.ParseFile(fset, pathutil.Join(path, d.Name), nil,
+ file, err := parser.ParseFile(fset, filepath.Join(path, d.Name), nil,
parser.ParseComments|parser.PackageClauseOnly)
if err == nil {
hasPkgFiles = true
@@ -149,7 +156,7 @@ func (b *treeBuilder) newDirTree(fset *token.FileSet, path, name string, depth i
i := 0
for _, d := range list {
if isPkgDir(d) {
- dd := b.newDirTree(fset, pathutil.Join(path, d.Name), d.Name, depth+1)
+ dd := b.newDirTree(fset, filepath.Join(path, d.Name), d.Name, depth+1)
if dd != nil {
dirs[i] = dd
i++
@@ -188,8 +195,16 @@ func (b *treeBuilder) newDirTree(fset *token.FileSet, path, name string, depth i
// (i.e., in this case the tree may contain directories w/o any package files).
//
func newDirectory(root string, pathFilter func(string) bool, maxDepth int) *Directory {
- d, err := os.Lstat(root)
- if err != nil || !isPkgDir(d) {
+ // The root could be a symbolic link so use os.Stat not os.Lstat.
+ d, err := os.Stat(root)
+ // If we fail here, report detailed error messages; otherwise
+ // is is hard to see why a directory tree was not built.
+ switch {
+ case err != nil:
+ log.Printf("newDirectory(%s): %s", root, err)
+ return nil
+ case !isPkgDir(d):
+ log.Printf("newDirectory(%s): not a package directory", root)
return nil
}
if maxDepth < 0 {
diff --git a/src/cmd/godoc/godoc.go b/src/cmd/godoc/godoc.go
index c91dc33db..9dce5edf9 100644
--- a/src/cmd/godoc/godoc.go
+++ b/src/cmd/godoc/godoc.go
@@ -18,7 +18,8 @@ import (
"io/ioutil"
"log"
"os"
- pathutil "path"
+ "path"
+ "path/filepath"
"regexp"
"runtime"
"sort"
@@ -81,8 +82,8 @@ var (
func initHandlers() {
fsMap.Init(*pkgPath)
fileServer = http.FileServer(*goroot, "")
- cmdHandler = httpHandler{"/cmd/", pathutil.Join(*goroot, "src/cmd"), false}
- pkgHandler = httpHandler{"/pkg/", pathutil.Join(*goroot, "src/pkg"), true}
+ cmdHandler = httpHandler{"/cmd/", filepath.Join(*goroot, "src", "cmd"), false}
+ pkgHandler = httpHandler{"/pkg/", filepath.Join(*goroot, "src", "pkg"), true}
}
@@ -91,12 +92,13 @@ func registerPublicHandlers(mux *http.ServeMux) {
mux.Handle(pkgHandler.pattern, &pkgHandler)
mux.HandleFunc("/doc/codewalk/", codewalk)
mux.HandleFunc("/search", search)
+ mux.Handle("/robots.txt", fileServer)
mux.HandleFunc("/", serveFile)
}
func initFSTree() {
- fsTree.set(newDirectory(pathutil.Join(*goroot, *testDir), nil, -1))
+ fsTree.set(newDirectory(filepath.Join(*goroot, *testDir), nil, -1))
invalidateIndex()
}
@@ -147,8 +149,13 @@ func readDirList(filename string) ([]string, os.Error) {
}
// create a sorted list of valid directory names
filter := func(path string) bool {
- d, err := os.Lstat(path)
- return err == nil && isPkgDir(d)
+ d, e := os.Lstat(path)
+ if e != nil && err == nil {
+ // remember first error and return it from readDirList
+ // so we have at least some information if things go bad
+ err = e
+ }
+ return e == nil && isPkgDir(d)
}
list := canonicalizePaths(strings.Split(string(contents), "\n", -1), filter)
// for each parent path, remove all it's children q
@@ -160,7 +167,7 @@ func readDirList(filename string) ([]string, os.Error) {
i++
}
}
- return list[0:i], nil
+ return list[0:i], err
}
@@ -207,9 +214,10 @@ func initDirTrees() {
if *filter != "" {
list, err := readDirList(*filter)
if err != nil {
- log.Printf("%s", err)
- } else if len(list) == 0 {
- log.Printf("no directory paths in file %s", *filter)
+ log.Printf("readDirList(%s): %s", *filter, err)
+ }
+ if *verbose || len(list) == 0 {
+ log.Printf("found %d directory paths in file %s", len(list), *filter)
}
setPathFilter(list)
}
@@ -239,27 +247,30 @@ func initDirTrees() {
// ----------------------------------------------------------------------------
// Path mapping
-func absolutePath(path, defaultRoot string) string {
- abspath := fsMap.ToAbsolute(path)
+// Absolute paths are file system paths (backslash-separated on Windows),
+// but relative paths are always slash-separated.
+
+func absolutePath(relpath, defaultRoot string) string {
+ abspath := fsMap.ToAbsolute(relpath)
if abspath == "" {
// no user-defined mapping found; use default mapping
- abspath = pathutil.Join(defaultRoot, path)
+ abspath = filepath.Join(defaultRoot, filepath.FromSlash(relpath))
}
return abspath
}
-func relativePath(path string) string {
- relpath := fsMap.ToRelative(path)
+func relativeURL(abspath string) string {
+ relpath := fsMap.ToRelative(abspath)
if relpath == "" {
- // prefix must end in '/'
+ // prefix must end in a path separator
prefix := *goroot
- if len(prefix) > 0 && prefix[len(prefix)-1] != '/' {
- prefix += "/"
+ if len(prefix) > 0 && prefix[len(prefix)-1] != filepath.Separator {
+ prefix += string(filepath.Separator)
}
- if strings.HasPrefix(path, prefix) {
+ if strings.HasPrefix(abspath, prefix) {
// no user-defined mapping found; use default mapping
- relpath = path[len(prefix):]
+ relpath = filepath.ToSlash(abspath[len(prefix):])
}
}
// Only if path is an invalid absolute path is relpath == ""
@@ -474,7 +485,7 @@ func urlFmt(w io.Writer, format string, x ...interface{}) {
}
// map path
- relpath := relativePath(path)
+ relpath := relativeURL(path)
// convert to relative URLs so that they can also
// be used as relative file names in .txt templates
@@ -591,7 +602,7 @@ func dirslashFmt(w io.Writer, format string, x ...interface{}) {
// Template formatter for "localname" format.
func localnameFmt(w io.Writer, format string, x ...interface{}) {
- _, localname := pathutil.Split(x[0].(string))
+ _, localname := filepath.Split(x[0].(string))
template.HTMLEscape(w, []byte(localname))
}
@@ -623,7 +634,7 @@ var fmap = template.FormatterMap{
func readTemplate(name string) *template.Template {
- path := pathutil.Join(*goroot, "lib/godoc/"+name)
+ path := filepath.Join(*goroot, "lib", "godoc", name)
data, err := ioutil.ReadFile(path)
if err != nil {
log.Fatalf("ReadFile %s: %v", path, err)
@@ -760,14 +771,13 @@ func applyTemplate(t *template.Template, name string, data interface{}) []byte {
func redirect(w http.ResponseWriter, r *http.Request) (redirected bool) {
- if canonical := pathutil.Clean(r.URL.Path) + "/"; r.URL.Path != canonical {
+ if canonical := path.Clean(r.URL.Path) + "/"; r.URL.Path != canonical {
http.Redirect(w, r, canonical, http.StatusMovedPermanently)
redirected = true
}
return
}
-
func serveTextFile(w http.ResponseWriter, r *http.Request, abspath, relpath, title string) {
src, err := ioutil.ReadFile(abspath)
if err != nil {
@@ -778,7 +788,7 @@ func serveTextFile(w http.ResponseWriter, r *http.Request, abspath, relpath, tit
var buf bytes.Buffer
buf.WriteString("<pre>")
- FormatText(&buf, src, 1, pathutil.Ext(abspath) == ".go", r.FormValue("h"), rangeSelection(r.FormValue("s")))
+ FormatText(&buf, src, 1, filepath.Ext(abspath) == ".go", r.FormValue("h"), rangeSelection(r.FormValue("s")))
buf.WriteString("</pre>")
servePage(w, title+" "+relpath, "", "", buf.Bytes())
@@ -815,7 +825,7 @@ func serveFile(w http.ResponseWriter, r *http.Request) {
// pick off special cases and hand the rest to the standard file server
switch r.URL.Path {
case "/":
- serveHTMLDoc(w, r, pathutil.Join(*goroot, "doc/root.html"), "doc/root.html")
+ serveHTMLDoc(w, r, filepath.Join(*goroot, "doc", "root.html"), "doc/root.html")
return
case "/doc/root.html":
@@ -824,9 +834,9 @@ func serveFile(w http.ResponseWriter, r *http.Request) {
return
}
- switch pathutil.Ext(abspath) {
+ switch path.Ext(relpath) {
case ".html":
- if strings.HasSuffix(abspath, "/index.html") {
+ if strings.HasSuffix(relpath, "/index.html") {
// We'll show index.html for the directory.
// Use the dir/ version as canonical instead of dir/index.html.
http.Redirect(w, r, r.URL.Path[0:len(r.URL.Path)-len("index.html")], http.StatusMovedPermanently)
@@ -851,8 +861,8 @@ func serveFile(w http.ResponseWriter, r *http.Request) {
if redirect(w, r) {
return
}
- if index := abspath + "/index.html"; isTextFile(index) {
- serveHTMLDoc(w, r, index, relativePath(index))
+ if index := filepath.Join(abspath, "index.html"); isTextFile(index) {
+ serveHTMLDoc(w, r, index, relativeURL(index))
return
}
serveDirectory(w, r, abspath, relpath)
@@ -948,13 +958,13 @@ func (h *httpHandler) getPageInfo(abspath, relpath, pkgname string, mode PageInf
// the package with dirname, and the 3rd choice is a package
// that is not called "main" if there is exactly one such
// package. Otherwise, don't select a package.
- dirpath, dirname := pathutil.Split(abspath)
+ dirpath, dirname := filepath.Split(abspath)
// If the dirname is "go" we might be in a sub-directory for
// .go files - use the outer directory name instead for better
// results.
if dirname == "go" {
- _, dirname = pathutil.Split(pathutil.Clean(dirpath))
+ _, dirname = filepath.Split(filepath.Clean(dirpath))
}
var choice3 *ast.Package
@@ -995,7 +1005,7 @@ func (h *httpHandler) getPageInfo(abspath, relpath, pkgname string, mode PageInf
ast.PackageExports(pkg)
}
if mode&genDoc != 0 {
- pdoc = doc.NewPackageDoc(pkg, pathutil.Clean(relpath)) // no trailing '/' in importpath
+ pdoc = doc.NewPackageDoc(pkg, path.Clean(relpath)) // no trailing '/' in importpath
} else {
past = ast.MergePackageFiles(pkg, ast.FilterUnassociatedComments)
}
@@ -1081,13 +1091,13 @@ func (h *httpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
title = "Package " + info.PDoc.PackageName
case info.PDoc.PackageName == fakePkgName:
// assume that the directory name is the command name
- _, pkgname := pathutil.Split(pathutil.Clean(relpath))
+ _, pkgname := path.Split(path.Clean(relpath))
title = "Command " + pkgname
default:
title = "Command " + info.PDoc.PackageName
}
default:
- title = "Directory " + relativePath(info.Dirname)
+ title = "Directory " + relativeURL(info.Dirname)
if *showTimestamps {
subtitle = "Last update: " + time.SecondsToLocalTime(info.DirTime).String()
}
diff --git a/src/cmd/godoc/index.go b/src/cmd/godoc/index.go
index 56f31f5cf..5af4d15cb 100644
--- a/src/cmd/godoc/index.go
+++ b/src/cmd/godoc/index.go
@@ -47,7 +47,7 @@ import (
"index/suffixarray"
"io/ioutil"
"os"
- "path"
+ "path/filepath"
"regexp"
"sort"
"strings"
@@ -718,7 +718,7 @@ var whitelisted = map[string]bool{
// of "permitted" files for indexing. The filename must
// be the directory-local name of the file.
func isWhitelisted(filename string) bool {
- key := path.Ext(filename)
+ key := filepath.Ext(filename)
if key == "" {
// file has no extension - use entire filename
key = filename
@@ -732,7 +732,7 @@ func (x *Indexer) visitFile(dirname string, f *os.FileInfo, fulltextIndex bool)
return
}
- filename := path.Join(dirname, f.Name)
+ filename := filepath.Join(dirname, f.Name)
goFile := false
switch {
@@ -757,7 +757,7 @@ func (x *Indexer) visitFile(dirname string, f *os.FileInfo, fulltextIndex bool)
if fast != nil {
// we've got a Go file to index
x.current = file
- dir, _ := path.Split(filename)
+ dir, _ := filepath.Split(filename)
pak := Pak{dir, fast.Name.Name}
x.file = &File{filename, pak}
ast.Walk(x, fast)
diff --git a/src/cmd/godoc/main.go b/src/cmd/godoc/main.go
index ea1e3c42e..1ebb80279 100644
--- a/src/cmd/godoc/main.go
+++ b/src/cmd/godoc/main.go
@@ -36,7 +36,7 @@ import (
"io"
"log"
"os"
- pathutil "path"
+ "path/filepath"
"regexp"
"runtime"
"strings"
@@ -314,14 +314,14 @@ func main() {
if len(path) > 0 && path[0] == '.' {
// assume cwd; don't assume -goroot
cwd, _ := os.Getwd() // ignore errors
- path = pathutil.Join(cwd, path)
+ path = filepath.Join(cwd, path)
}
relpath := path
abspath := path
- if !pathutil.IsAbs(path) {
+ if !filepath.IsAbs(path) {
abspath = absolutePath(path, pkgHandler.fsRoot)
} else {
- relpath = relativePath(path)
+ relpath = relativeURL(path)
}
var mode PageInfoMode
@@ -339,7 +339,7 @@ func main() {
if info.IsEmpty() {
// try again, this time assume it's a command
- if !pathutil.IsAbs(path) {
+ if !filepath.IsAbs(path) {
abspath = absolutePath(path, cmdHandler.fsRoot)
}
cmdInfo := cmdHandler.getPageInfo(abspath, relpath, "", mode)
diff --git a/src/cmd/godoc/mapping.go b/src/cmd/godoc/mapping.go
index 1d87bbc76..6ae9032e4 100644
--- a/src/cmd/godoc/mapping.go
+++ b/src/cmd/godoc/mapping.go
@@ -10,7 +10,8 @@ import (
"fmt"
"io"
"os"
- pathutil "path"
+ "path"
+ "path/filepath"
"sort"
"strings"
)
@@ -59,10 +60,10 @@ type mapping struct {
}
-// Init initializes the Mapping from a list of ':'-separated
-// paths. Empty paths are ignored; relative paths are assumed
-// to be relative to the current working directory and converted
-// to absolute paths. For each path of the form:
+// Init initializes the Mapping from a list of paths separated by
+// filepath.ListSeparator. Empty paths are ignored; relative paths
+// are assumed to be relative to the current working directory and
+// converted to absolute paths. For each path of the form:
//
// dirname/localname
//
@@ -71,7 +72,7 @@ type mapping struct {
// localname -> path
//
// is added to the Mapping object, in the order of occurrence.
-// For instance, the argument:
+// For instance, under Unix, the argument:
//
// /home/user:/home/build/public
//
@@ -81,12 +82,12 @@ type mapping struct {
// public -> /home/build/public
//
func (m *Mapping) Init(paths string) {
- pathlist := canonicalizePaths(strings.Split(paths, ":", -1), nil)
+ pathlist := canonicalizePaths(filepath.SplitList(paths), nil)
list := make([]mapping, len(pathlist))
// create mapping list
for i, path := range pathlist {
- _, prefix := pathutil.Split(path)
+ _, prefix := filepath.Split(path)
list[i] = mapping{prefix, path, new(RWValue)}
}
@@ -147,7 +148,7 @@ func (m *Mapping) Fprint(w io.Writer) {
func splitFirst(path string) (head, tail string) {
- i := strings.Index(path, "/")
+ i := strings.Index(path, string(filepath.Separator))
if i > 0 {
// 0 < i < len(path)
return path[0:i], path[i+1:]
@@ -156,22 +157,23 @@ func splitFirst(path string) (head, tail string) {
}
-// ToAbsolute maps a relative path to an absolute path using the Mapping
-// specified by the receiver. If the path cannot be mapped, the empty
-// string is returned.
+// ToAbsolute maps a slash-separated relative path to an absolute filesystem
+// path using the Mapping specified by the receiver. If the path cannot
+// be mapped, the empty string is returned.
//
-func (m *Mapping) ToAbsolute(path string) string {
- prefix, tail := splitFirst(path)
+func (m *Mapping) ToAbsolute(spath string) string {
+ fpath := filepath.FromSlash(spath)
+ prefix, tail := splitFirst(fpath)
for _, e := range m.list {
switch {
case e.prefix == prefix:
// use tail
case e.prefix == "":
- tail = path
+ tail = fpath
default:
continue // no match
}
- abspath := pathutil.Join(e.path, tail)
+ abspath := filepath.Join(e.path, tail)
if _, err := os.Stat(abspath); err == nil {
return abspath
}
@@ -181,15 +183,16 @@ func (m *Mapping) ToAbsolute(path string) string {
}
-// ToRelative maps an absolute path to a relative path using the Mapping
-// specified by the receiver. If the path cannot be mapped, the empty
-// string is returned.
+// ToRelative maps an absolute filesystem path to a relative slash-separated
+// path using the Mapping specified by the receiver. If the path cannot
+// be mapped, the empty string is returned.
//
-func (m *Mapping) ToRelative(path string) string {
+func (m *Mapping) ToRelative(fpath string) string {
for _, e := range m.list {
- if strings.HasPrefix(path, e.path) {
+ if strings.HasPrefix(fpath, e.path) {
+ spath := filepath.ToSlash(fpath)
// /absolute/prefix/foo -> prefix/foo
- return pathutil.Join(e.prefix, path[len(e.path):]) // Join will remove a trailing '/'
+ return path.Join(e.prefix, spath[len(e.path):]) // Join will remove a trailing '/'
}
}
return "" // no match
diff --git a/src/cmd/godoc/utils.go b/src/cmd/godoc/utils.go
index cc028cc4d..9517aee7a 100644
--- a/src/cmd/godoc/utils.go
+++ b/src/cmd/godoc/utils.go
@@ -10,7 +10,7 @@ import (
"io"
"io/ioutil"
"os"
- pathutil "path"
+ "path/filepath"
"sort"
"strings"
"sync"
@@ -60,10 +60,10 @@ func canonicalizePaths(list []string, filter func(path string) bool) []string {
continue // ignore empty paths (don't assume ".")
}
// len(path) > 0: normalize path
- if pathutil.IsAbs(path) {
- path = pathutil.Clean(path)
+ if filepath.IsAbs(path) {
+ path = filepath.Clean(path)
} else {
- path = pathutil.Join(cwd, path)
+ path = filepath.Join(cwd, path)
}
// we have a non-empty absolute path
if filter != nil && !filter(path) {
@@ -95,7 +95,7 @@ func canonicalizePaths(list []string, filter func(path string) bool) []string {
// atomically renames that file to the file named by filename.
//
func writeFileAtomically(filename string, data []byte) os.Error {
- f, err := ioutil.TempFile(cwd, filename)
+ f, err := ioutil.TempFile(filepath.Split(filename))
if err != nil {
return err
}
@@ -149,7 +149,7 @@ var textExt = map[string]bool{
//
func isTextFile(filename string) bool {
// if the extension is known, use it for decision making
- if isText, found := textExt[pathutil.Ext(filename)]; found {
+ if isText, found := textExt[filepath.Ext(filename)]; found {
return isText
}