cmd/doc: make local dot-slash path names work

Before, an argument that started ./ or ../ was not treated as
a package relative to the current directory. Thus

	$ cd $GOROOT/src/text
	$ go doc ./template

could find html/template as $GOROOT/src/html/./template
is a valid Go source directory.

Fix this by catching such paths and making them absolute before
processing.

Fixes #23383.

Change-Id: Ic2a92eaa3a6328f728635657f9de72ac3ee82afb
Reviewed-on: https://go-review.googlesource.com/98396
Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
Rob Pike 2018-03-05 16:21:44 +11:00
parent 917e72697e
commit baf3eb1625
2 changed files with 105 additions and 6 deletions

View file

@ -7,6 +7,9 @@ package main
import (
"bytes"
"flag"
"go/build"
"os"
"path/filepath"
"regexp"
"runtime"
"strings"
@ -22,6 +25,39 @@ func maybeSkip(t *testing.T) {
}
}
type isDotSlashTest struct {
str string
result bool
}
var isDotSlashTests = []isDotSlashTest{
{``, false},
{`x`, false},
{`...`, false},
{`.../`, false},
{`...\`, false},
{`.`, true},
{`./`, true},
{`.\`, true},
{`./x`, true},
{`.\x`, true},
{`..`, true},
{`../`, true},
{`..\`, true},
{`../x`, true},
{`..\x`, true},
}
func TestIsDotSlashPath(t *testing.T) {
for _, test := range isDotSlashTests {
if result := isDotSlash(test.str); result != test.result {
t.Errorf("isDotSlash(%q) = %t; expected %t", test.str, result, test.result)
}
}
}
type test struct {
name string
args []string // Arguments to "[go] doc".
@ -603,6 +639,37 @@ func TestTwoArgLookup(t *testing.T) {
}
}
// Test the code to look up packages when the first argument starts with "./".
// Our test case is in effect "cd src/text; doc ./template". This should get
// text/template but before Issue 23383 was fixed would give html/template.
func TestDotSlashLookup(t *testing.T) {
if testing.Short() {
t.Skip("scanning file system takes too long")
}
maybeSkip(t)
where := pwd()
defer func() {
if err := os.Chdir(where); err != nil {
t.Fatal(err)
}
}()
if err := os.Chdir(filepath.Join(build.Default.GOROOT, "src", "text")); err != nil {
t.Fatal(err)
}
var b bytes.Buffer
var flagSet flag.FlagSet
err := do(&b, &flagSet, []string{"./template"})
if err != nil {
t.Errorf("unexpected error %q from ./template", err)
}
// The output should contain information about the text/template package.
const want = `package template // import "text/template"`
output := b.String()
if !strings.HasPrefix(output, want) {
t.Fatalf("wrong package: %.*q...", len(want), output)
}
}
type trimTest struct {
path string
prefix string