all: remove toFS usage
The toFS calls were a stop-gap to convert from old code that wasn't
strict about path forms to the io/fs routines that are more strict.
Arrange to pass io/fs-compatible paths everywhere and remove toFS.
Change-Id: Id69c0f23074ebd3a6dfef2255b2f8185ad1d1249
Reviewed-on: https://go-review.googlesource.com/c/website/+/317659
Trust: Russ Cox <rsc@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
diff --git a/_content/lib/godoc/package.html b/_content/lib/godoc/package.html
index 3d6e8ba..7efdea1 100644
--- a/_content/lib/godoc/package.html
+++ b/_content/lib/godoc/package.html
@@ -95,7 +95,7 @@
<p>
<span style="font-size:90%">
{{range .}}
- <a href="/src/{{.}}">{{basename .}}</a>
+ <a href="/{{.}}">{{basename .}}</a>
{{end}}
</span>
</p>
diff --git a/cmd/golangorg/codewalk.go b/cmd/golangorg/codewalk.go
index 52deb29..d3e5cbd 100644
--- a/cmd/golangorg/codewalk.go
+++ b/cmd/golangorg/codewalk.go
@@ -25,6 +25,7 @@
"log"
"net/http"
"os"
+ "path"
pathpkg "path"
"regexp"
"sort"
@@ -37,8 +38,7 @@
// Handler for /doc/codewalk/ and below.
func codewalk(w http.ResponseWriter, r *http.Request) {
- relpath := r.URL.Path[len("/doc/codewalk/"):]
- abspath := r.URL.Path
+ relpath := path.Clean(r.URL.Path[1:])
r.ParseForm()
if f := r.FormValue("fileprint"); f != "" {
@@ -47,9 +47,9 @@
}
// If directory exists, serve list of code walks.
- dir, err := fs.Stat(fsys, toFS(abspath))
+ dir, err := fs.Stat(fsys, relpath)
if err == nil && dir.IsDir() {
- codewalkDir(w, r, relpath, abspath)
+ codewalkDir(w, r, relpath)
return
}
@@ -62,8 +62,7 @@
// Otherwise append .xml and hope to find
// a codewalk description, but before trim
// the trailing /.
- abspath = strings.TrimRight(abspath, "/")
- cw, err := loadCodewalk(abspath + ".xml")
+ cw, err := loadCodewalk(relpath + ".xml")
if err != nil {
log.Print(err)
site.ServeError(w, r, err)
@@ -140,7 +139,7 @@
// loadCodewalk reads a codewalk from the named XML file.
func loadCodewalk(filename string) (*Codewalk, error) {
- f, err := fsys.Open(toFS(filename))
+ f, err := fsys.Open(filename)
if err != nil {
return nil, err
}
@@ -161,7 +160,7 @@
i = len(st.Src)
}
filename := st.Src[0:i]
- data, err := fs.ReadFile(fsys, toFS(filename))
+ data, err := fs.ReadFile(fsys, filename)
if err != nil {
st.Err = err
continue
@@ -202,13 +201,13 @@
// codewalkDir serves the codewalk directory listing.
// It scans the directory for subdirectories or files named *.xml
// and prepares a table.
-func codewalkDir(w http.ResponseWriter, r *http.Request, relpath, abspath string) {
+func codewalkDir(w http.ResponseWriter, r *http.Request, relpath string) {
type elem struct {
Name string
Title string
}
- dir, err := fs.ReadDir(fsys, toFS(abspath))
+ dir, err := fs.ReadDir(fsys, relpath)
if err != nil {
log.Print(err)
site.ServeError(w, r, err)
@@ -220,7 +219,7 @@
if fi.IsDir() {
v = append(v, &elem{name + "/", ""})
} else if strings.HasSuffix(name, ".xml") {
- cw, err := loadCodewalk(abspath + "/" + name)
+ cw, err := loadCodewalk(relpath + "/" + name)
if err != nil {
continue
}
@@ -242,8 +241,8 @@
// of the codewalk pages. It is a separate iframe and does not get
// the usual godoc HTML wrapper.
func codewalkFileprint(w http.ResponseWriter, r *http.Request, f string) {
- abspath := f
- data, err := fs.ReadFile(fsys, toFS(abspath))
+ relpath := strings.Trim(path.Clean(f), "/")
+ data, err := fs.ReadFile(fsys, relpath)
if err != nil {
log.Print(err)
site.ServeError(w, r, err)
diff --git a/cmd/golangorg/handlers.go b/cmd/golangorg/handlers.go
index 1ea8478..ee2cb77 100644
--- a/cmd/golangorg/handlers.go
+++ b/cmd/golangorg/handlers.go
@@ -12,7 +12,6 @@
"go/format"
"io/fs"
"net/http"
- pathpkg "path"
"strings"
"golang.org/x/website/internal/env"
@@ -25,14 +24,6 @@
fsys fs.FS
)
-// toFS returns the io/fs name for path (no leading slash).
-func toFS(path string) string {
- if path == "/" {
- return "."
- }
- return pathpkg.Clean(strings.TrimPrefix(path, "/"))
-}
-
// hostEnforcerHandler redirects requests to "http://foo.golang.org/bar"
// to "https://golang.org/bar".
// It permits requests to the host "godoc-test.golang.org" for testing and
diff --git a/cmd/golangorg/main.go b/cmd/golangorg/main.go
index 7e832d5..37d9d8b 100644
--- a/cmd/golangorg/main.go
+++ b/cmd/golangorg/main.go
@@ -137,7 +137,7 @@
var seen map[string]bool // seen[name] is true if name is listed in all; lazily initialized
var errOut error
for _, sub := range fsys {
- list, err := fs.ReadDir(sub, toFS(name))
+ list, err := fs.ReadDir(sub, name)
if err != nil {
errOut = err
}
diff --git a/internal/pkgdoc/dir.go b/internal/pkgdoc/dir.go
index e8b2c61..fe995e2 100644
--- a/internal/pkgdoc/dir.go
+++ b/internal/pkgdoc/dir.go
@@ -22,14 +22,6 @@
"strings"
)
-// toFS returns the io/fs name for path (no leading slash).
-func toFS(name string) string {
- if name == "/" {
- return "."
- }
- return path.Clean(strings.TrimPrefix(name, "/"))
-}
-
type Dir struct {
Path string // directory path
HasPkg bool // true if the directory contains at least one package
@@ -65,17 +57,15 @@
if name == dir.Path {
return dir
}
- dirPathLen := len(dir.Path)
- if dir.Path == "/" {
- dirPathLen = 0 // so path[dirPathLen] is a slash
- }
- if !strings.HasPrefix(name, dir.Path) || name[dirPathLen] != '/' {
- println("NO", name, dir.Path)
- return nil
+ if dir.Path != "." {
+ if !strings.HasPrefix(name, dir.Path) || name[len(dir.Path)] != '/' {
+ return nil
+ }
+ name = name[len(dir.Path)+1:]
}
d := dir
Walk:
- for i := dirPathLen + 1; i <= len(name); i++ {
+ for i := 0; i <= len(name); i++ {
if i == len(name) || name[i] == '/' {
// Find next child along path.
for _, sub := range d.Dirs {
@@ -84,7 +74,6 @@
continue Walk
}
}
- println("LOST", name[:i])
return nil
}
}
@@ -126,16 +115,16 @@
return &DirList{list}
}
-func newDir(fsys fs.FS, fset *token.FileSet, abspath string) *Dir {
+func newDir(fsys fs.FS, fset *token.FileSet, dirpath string) *Dir {
var synopses [3]string // prioritized package documentation (0 == highest priority)
hasPkgFiles := false
haveSummary := false
- list, err := fs.ReadDir(fsys, toFS(abspath))
+ list, err := fs.ReadDir(fsys, dirpath)
if err != nil {
// TODO: propagate more. See golang.org/issue/14252.
- log.Printf("newDirTree reading %s: %v", abspath, err)
+ log.Printf("newDirTree reading %s: %v", dirpath, err)
}
// determine number of subdirectories and if there are package files
@@ -143,7 +132,7 @@
var dirs []*Dir
for _, d := range list {
- filename := path.Join(abspath, d.Name())
+ filename := path.Join(dirpath, d.Name())
switch {
case isPkgDir(d):
dir := newDir(fsys, fset, filename)
@@ -168,7 +157,7 @@
// prioritize documentation
i := -1
switch file.Name.Name {
- case path.Base(abspath):
+ case path.Base(dirpath):
i = 0 // normal case: directory name matches package name
case "main":
i = 1 // directory contains a main package
@@ -211,7 +200,7 @@
}
return &Dir{
- Path: abspath,
+ Path: dirpath,
HasPkg: hasPkgFiles,
Synopsis: synopsis,
Dirs: dirs,
@@ -247,7 +236,7 @@
}
func parseFile(fsys fs.FS, fset *token.FileSet, filename string, mode parser.Mode) (*ast.File, error) {
- src, err := fs.ReadFile(fsys, toFS(filename))
+ src, err := fs.ReadFile(fsys, filename)
if err != nil {
return nil, err
}
@@ -259,15 +248,15 @@
return parser.ParseFile(fset, filename, src, mode)
}
-func parseFiles(fsys fs.FS, fset *token.FileSet, relpath string, abspath string, localnames []string) (map[string]*ast.File, error) {
+func parseFiles(fsys fs.FS, fset *token.FileSet, dirname string, localnames []string) (map[string]*ast.File, error) {
files := make(map[string]*ast.File)
for _, f := range localnames {
- absname := path.Join(abspath, f)
- file, err := parseFile(fsys, fset, absname, parser.ParseComments)
+ filename := path.Join(dirname, f)
+ file, err := parseFile(fsys, fset, filename, parser.ParseComments)
if err != nil {
return nil, err
}
- files[path.Join(relpath, f)] = file
+ files[filename] = file
}
return files, nil
diff --git a/internal/pkgdoc/dir_test.go b/internal/pkgdoc/dir_test.go
index 9441274..db1c782 100644
--- a/internal/pkgdoc/dir_test.go
+++ b/internal/pkgdoc/dir_test.go
@@ -17,7 +17,7 @@
)
func TestNewDirTree(t *testing.T) {
- dir := newDir(os.DirFS(runtime.GOROOT()), token.NewFileSet(), "/src")
+ dir := newDir(os.DirFS(runtime.GOROOT()), token.NewFileSet(), "src")
processDir(t, dir)
}
@@ -62,6 +62,6 @@
b.ResetTimer()
b.ReportAllocs()
for tries := 0; tries < b.N; tries++ {
- newDir(fs, token.NewFileSet(), "/src")
+ newDir(fs, token.NewFileSet(), "src")
}
}
diff --git a/internal/pkgdoc/doc.go b/internal/pkgdoc/doc.go
index 02e7b5b..218228e 100644
--- a/internal/pkgdoc/doc.go
+++ b/internal/pkgdoc/doc.go
@@ -32,9 +32,9 @@
}
func NewDocs(fsys fs.FS) *Docs {
- src := newDir(fsys, token.NewFileSet(), "/src")
+ src := newDir(fsys, token.NewFileSet(), "src")
root := &Dir{
- Path: "/",
+ Path: ".",
Dirs: []*Dir{src},
}
return &Docs{
@@ -112,14 +112,15 @@
return mode
}
-// Doc returns the Page for a package directory abspath.
+// Doc returns the Page for a package directory dir.
// Package documentation (Page.PDoc) is extracted from the AST.
// If there is no corresponding package in the
// directory, Page.PDoc is nil. If there are no sub-
// directories, Page.Dirs is nil. If an error occurred, PageInfo.Err is
// set to the respective error but the error is not logged.
-func Doc(d *Docs, abspath, relpath string, mode Mode, goos, goarch string) *Page {
- info := &Page{Dirname: abspath, Mode: mode}
+func Doc(d *Docs, dir string, mode Mode, goos, goarch string) *Page {
+ dir = path.Clean(dir)
+ info := &Page{Dirname: dir, Mode: mode}
// Restrict to the package files that would be used when building
// the package on this system. This makes sure that if there are
@@ -130,11 +131,11 @@
ctxt := build.Default
ctxt.IsAbsPath = path.IsAbs
ctxt.IsDir = func(path string) bool {
- fi, err := fs.Stat(d.fs, toFS(filepath.ToSlash(path)))
+ fi, err := fs.Stat(d.fs, filepath.ToSlash(path))
return err == nil && fi.IsDir()
}
ctxt.ReadDir = func(dir string) ([]os.FileInfo, error) {
- f, err := fs.ReadDir(d.fs, toFS(filepath.ToSlash(dir)))
+ f, err := fs.ReadDir(d.fs, filepath.ToSlash(dir))
filtered := make([]os.FileInfo, 0, len(f))
for _, i := range f {
if mode&ModeAll != 0 || i.Name() != "internal" {
@@ -147,7 +148,7 @@
return filtered, err
}
ctxt.OpenFile = func(name string) (r io.ReadCloser, err error) {
- data, err := fs.ReadFile(d.fs, toFS(filepath.ToSlash(name)))
+ data, err := fs.ReadFile(d.fs, filepath.ToSlash(name))
if err != nil {
return nil, err
}
@@ -159,7 +160,7 @@
// linux/amd64 means the wasm syscall/js package was blank.
// And you can't run godoc on js/wasm anyway, so host defaults
// don't make sense here.
- if goos == "" && goarch == "" && relpath == "syscall/js" {
+ if goos == "" && goarch == "" && dir == "syscall/js" {
goos, goarch = "js", "wasm"
}
if goos != "" {
@@ -169,7 +170,7 @@
ctxt.GOARCH = goarch
}
- pkginfo, err := ctxt.ImportDir(abspath, 0)
+ pkginfo, err := ctxt.ImportDir(dir, 0)
// continue if there are no Go source files; we still want the directory info
if _, nogo := err.(*build.NoGoError); err != nil && !nogo {
info.Err = err
@@ -193,7 +194,7 @@
if len(pkgfiles) > 0 {
// build package AST
fset := token.NewFileSet()
- files, err := parseFiles(d.fs, fset, relpath, abspath, pkgfiles)
+ files, err := parseFiles(d.fs, fset, dir, pkgfiles)
if err != nil {
info.Err = err
return info
@@ -213,7 +214,7 @@
if mode&ModeMethods != 0 {
m |= doc.AllMethods
}
- info.PDoc = doc.New(pkg, path.Clean(relpath), m) // no trailing '/' in importpath
+ info.PDoc = doc.New(pkg, strings.TrimPrefix(dir, "src/"), m)
if mode&ModeBuiltin != 0 {
for _, t := range info.PDoc.Types {
info.PDoc.Consts = append(info.PDoc.Consts, t.Consts...)
@@ -230,7 +231,7 @@
// collect examples
testfiles := append(pkginfo.TestGoFiles, pkginfo.XTestGoFiles...)
- files, err = parseFiles(d.fs, fset, relpath, abspath, testfiles)
+ files, err = parseFiles(d.fs, fset, dir, testfiles)
if err != nil {
log.Println("parsing examples:", err)
}
@@ -238,7 +239,7 @@
info.Bugs = info.PDoc.Notes["BUG"]
}
- info.Dirs = d.root.Lookup(abspath).List(func(path string) bool { return d.includePath(path, mode) })
+ info.Dirs = d.root.Lookup(dir).List(func(path string) bool { return d.includePath(path, mode) })
info.DirFlat = mode&ModeFlat != 0
return info
diff --git a/internal/pkgdoc/doc_test.go b/internal/pkgdoc/doc_test.go
index c82d042..1ac4f0a 100644
--- a/internal/pkgdoc/doc_test.go
+++ b/internal/pkgdoc/doc_test.go
@@ -25,7 +25,7 @@
package main`)},
}
d := NewDocs(fs)
- pInfo := Doc(d, "/src/"+packagePath, packagePath, ModeAll, "linux", "amd64")
+ pInfo := Doc(d, "src/"+packagePath, ModeAll, "linux", "amd64")
if pInfo.PDoc == nil {
t.Error("pInfo.PDoc = nil; want non-nil.")
@@ -58,7 +58,7 @@
}
d := NewDocs(fs)
- pInfo := Doc(d, "/src/"+packagePath, packagePath, 0, "linux", "amd64")
+ pInfo := Doc(d, "src/"+packagePath, 0, "linux", "amd64")
if got, want := pInfo.PDoc.Funcs[0].Doc, "F doc //line 1 should appear\nline 2 should appear\n"; got != want {
t.Errorf("pInfo.PDoc.Funcs[0].Doc = %q; want %q", got, want)
}
diff --git a/internal/web/docfuncs.go b/internal/web/docfuncs.go
index a11190f..1f7850e 100644
--- a/internal/web/docfuncs.go
+++ b/internal/web/docfuncs.go
@@ -13,6 +13,7 @@
"html/template"
"io/fs"
"log"
+ "path"
"regexp"
"strings"
@@ -34,7 +35,12 @@
}
}()
- text := s.contents(file)
+ file = path.Clean(strings.TrimPrefix(file, "/"))
+ btext, err := fs.ReadFile(s.fs, file)
+ if err != nil {
+ return "", err
+ }
+ text := string(btext)
var command string
switch len(arg) {
case 0:
@@ -64,16 +70,6 @@
// Functions in this file panic on error, but the panic is recovered
// to an error by 'code'.
-// contents reads and returns the content of the named file
-// (from the virtual file system, so for example /doc refers to $GOROOT/doc).
-func (s *Site) contents(name string) string {
- file, err := fs.ReadFile(s.fs, toFS(name))
- if err != nil {
- log.Panic(err)
- }
- return string(file)
-}
-
// stringFor returns a textual representation of the arg, formatted according to its nature.
func stringFor(arg interface{}) string {
switch arg := arg.(type) {
@@ -92,7 +88,7 @@
// oneLine returns the single line generated by a two-argument code invocation.
func (s *Site) oneLine(file, text string, arg interface{}) string {
- lines := strings.SplitAfter(s.contents(file), "\n")
+ lines := strings.SplitAfter(text, "\n")
line, pattern, isInt := parseArg(arg, file, len(lines))
if isInt {
return lines[line-1]
@@ -102,7 +98,7 @@
// multipleLines returns the text generated by a three-argument code invocation.
func (s *Site) multipleLines(file, text string, arg1, arg2 interface{}) string {
- lines := strings.SplitAfter(s.contents(file), "\n")
+ lines := strings.SplitAfter(text, "\n")
line1, pattern1, isInt1 := parseArg(arg1, file, len(lines))
line2, pattern2, isInt2 := parseArg(arg2, file, len(lines))
if !isInt1 {
@@ -111,7 +107,7 @@
if !isInt2 {
line2 = match(file, line1, lines, pattern2)
} else if line2 < line1 {
- log.Panicf("lines out of order for %q: %d %d", text, line1, line2)
+ log.Panicf("lines out of order for %q: %d %d", file, line1, line2)
}
for k := line1 - 1; k < line2; k++ {
if strings.HasSuffix(lines[k], "OMIT\n") {
diff --git a/internal/web/file.go b/internal/web/file.go
index f2ff605..c82ff85 100644
--- a/internal/web/file.go
+++ b/internal/web/file.go
@@ -34,25 +34,23 @@
Redirect string // if set, redirect to other URL
}
-var join = path.Join
-
-// open returns the file for a given absolute path or nil if none exists.
-func open(fsys fs.FS, path string) *file {
+// open returns the *file for a given relative path or nil if none exists.
+func open(fsys fs.FS, relpath string) *file {
// Strip trailing .html or .md or /; it all names the same page.
- if strings.HasSuffix(path, ".html") {
- path = strings.TrimSuffix(path, ".html")
- } else if strings.HasSuffix(path, ".md") {
- path = strings.TrimSuffix(path, ".md")
- } else if path != "/" && strings.HasSuffix(path, "/") {
- path = strings.TrimSuffix(path, "/")
+ if strings.HasSuffix(relpath, ".html") {
+ relpath = strings.TrimSuffix(relpath, ".html")
+ } else if strings.HasSuffix(relpath, ".md") {
+ relpath = strings.TrimSuffix(relpath, ".md")
+ } else if strings.HasSuffix(relpath, "/") {
+ relpath = strings.TrimSuffix(relpath, "/")
}
- files := []string{path + ".html", path + ".md", join(path, "index.html"), join(path, "index.md")}
+ files := []string{relpath + ".html", relpath + ".md", path.Join(relpath, "index.html"), path.Join(relpath, "index.md")}
var filePath string
var b []byte
var err error
for _, filePath = range files {
- b, err = fs.ReadFile(fsys, toFS(filePath))
+ b, err = fs.ReadFile(fsys, filePath)
if err == nil {
break
}
@@ -60,14 +58,14 @@
// Special case for memory model and spec, which live
// in the main Go repo's doc directory and therefore have not
- // been renamed to their serving paths.
+ // been renamed to their serving relpaths.
// We wait until the ReadFiles above have failed so that the
// code works if these are ever moved to /ref/spec and /ref/mem.
- if err != nil && path == "/ref/spec" {
- return open(fsys, "/doc/go_spec")
+ if err != nil && relpath == "ref/spec" {
+ return open(fsys, "doc/go_spec")
}
- if err != nil && path == "/ref/mem" {
- return open(fsys, "/doc/go_mem")
+ if err != nil && relpath == "ref/mem" {
+ return open(fsys, "doc/go_mem")
}
if err != nil {
@@ -75,21 +73,21 @@
}
// Special case for memory model and spec, continued.
- switch path {
- case "/doc/go_spec":
- path = "/ref/spec"
- case "/doc/go_mem":
- path = "/ref/mem"
+ switch relpath {
+ case "doc/go_spec":
+ relpath = "ref/spec"
+ case "doc/go_mem":
+ relpath = "ref/mem"
}
- // If we read an index.md or index.html, the canonical path is without the index.md/index.html suffix.
- if strings.HasSuffix(filePath, "/index.md") || strings.HasSuffix(filePath, "/index.html") {
- path = filePath[:strings.LastIndex(filePath, "/")+1]
+ // If we read an index.md or index.html, the canonical relpath is without the index.md/index.html suffix.
+ if name := path.Base(filePath); name == "index.html" || name == "index.md" {
+ relpath, _ = path.Split(filePath)
}
js, body, err := parseFile(b)
if err != nil {
- log.Printf("extractMetadata %s: %v", path, err)
+ log.Printf("extractMetadata %s: %v", relpath, err)
return nil
}
@@ -97,7 +95,7 @@
Title: js.Title,
Subtitle: js.Subtitle,
Template: js.Template,
- Path: path,
+ Path: "/" + relpath,
FilePath: filePath,
Body: body,
}
diff --git a/internal/web/pkgdoc.go b/internal/web/pkgdoc.go
index c0b5e91..32949f4 100644
--- a/internal/web/pkgdoc.go
+++ b/internal/web/pkgdoc.go
@@ -31,7 +31,6 @@
relpath := path.Clean(strings.TrimPrefix(r.URL.Path, "/pkg"))
relpath = strings.TrimPrefix(relpath, "/")
- abspath := path.Join("/src", relpath)
mode := pkgdoc.ParseMode(r.FormValue("m"))
if relpath == "builtin" {
// The fake built-in package contains unexported identifiers,
@@ -39,7 +38,7 @@
// since it's not helpful for this fake package (see issue 6645).
mode |= pkgdoc.ModeAll | pkgdoc.ModeBuiltin
}
- info := pkgdoc.Doc(h.d, abspath, relpath, mode, r.FormValue("GOOS"), r.FormValue("GOARCH"))
+ info := pkgdoc.Doc(h.d, "src/"+relpath, mode, r.FormValue("GOOS"), r.FormValue("GOARCH"))
if info.Err != nil {
log.Print(info.Err)
h.p.ServeError(w, r, info.Err)
@@ -76,7 +75,7 @@
}
name := "package.html"
- if info.Dirname == "/src" {
+ if info.Dirname == "src" {
name = "packageroot.html"
}
h.p.ServePage(w, r, Page{
diff --git a/internal/web/site.go b/internal/web/site.go
index 5756714..1ad8948 100644
--- a/internal/web/site.go
+++ b/internal/web/site.go
@@ -28,14 +28,6 @@
"golang.org/x/website/internal/texthtml"
)
-// toFS returns the io/fs name for path (no leading slash).
-func toFS(name string) string {
- if name == "/" {
- return "."
- }
- return path.Clean(strings.TrimPrefix(name, "/"))
-}
-
// Site is a website served from a file system.
type Site struct {
fs fs.FS
@@ -204,7 +196,8 @@
// Check to see if we need to redirect or serve another file.
abspath := r.URL.Path
- if f := open(s.fs, abspath); f != nil {
+ relpath := path.Clean(strings.TrimPrefix(abspath, "/"))
+ if f := open(s.fs, relpath); f != nil {
if f.Path != abspath {
// Redirect to canonical path.
http.Redirect(w, r, f.Path, http.StatusMovedPermanently)
@@ -215,16 +208,14 @@
return
}
- relpath := abspath[1:] // strip leading slash
-
- dir, err := fs.Stat(s.fs, toFS(abspath))
+ dir, err := fs.Stat(s.fs, relpath)
if err != nil {
// Check for spurious trailing slash.
if strings.HasSuffix(abspath, "/") {
- trimmed := abspath[:len(abspath)-1]
- if _, err := fs.Stat(s.fs, toFS(trimmed)); err == nil ||
+ trimmed := relpath[:len(relpath)-1]
+ if _, err := fs.Stat(s.fs, trimmed); err == nil ||
open(s.fs, trimmed) != nil {
- http.Redirect(w, r, trimmed, http.StatusMovedPermanently)
+ http.Redirect(w, r, "/"+trimmed, http.StatusMovedPermanently)
return
}
}
@@ -232,20 +223,19 @@
return
}
- fsPath := toFS(abspath)
if dir != nil && dir.IsDir() {
if maybeRedirect(w, r) {
return
}
- s.serveDir(w, r, abspath, relpath)
+ s.serveDir(w, r, relpath)
return
}
- if isTextFile(s.fs, fsPath) {
+ if isTextFile(s.fs, relpath) {
if maybeRedirectFile(w, r) {
return
}
- s.serveText(w, r, abspath, relpath)
+ s.serveText(w, r, relpath)
return
}
@@ -337,12 +327,12 @@
s.ServePage(w, r, page)
}
-func (s *Site) serveDir(w http.ResponseWriter, r *http.Request, abspath, relpath string) {
+func (s *Site) serveDir(w http.ResponseWriter, r *http.Request, relpath string) {
if maybeRedirect(w, r) {
return
}
- list, err := fs.ReadDir(s.fs, toFS(abspath))
+ list, err := fs.ReadDir(s.fs, relpath)
if err != nil {
s.ServeError(w, r, err)
return
@@ -365,8 +355,8 @@
})
}
-func (s *Site) serveText(w http.ResponseWriter, r *http.Request, abspath, relpath string) {
- src, err := fs.ReadFile(s.fs, toFS(abspath))
+func (s *Site) serveText(w http.ResponseWriter, r *http.Request, relpath string) {
+ src, err := fs.ReadFile(s.fs, relpath)
if err != nil {
log.Printf("ReadFile: %s", err)
s.ServeError(w, r, err)
@@ -379,7 +369,7 @@
}
cfg := texthtml.Config{
- GoComments: path.Ext(abspath) == ".go",
+ GoComments: path.Ext(relpath) == ".go",
Highlight: r.FormValue("h"),
Selection: rangeSelection(r.FormValue("s")),
Line: 1,