Skip to content

Commit 2a5ac1a

Browse files
committed
cmd/doc: allow go doc -http without package in current directory
go doc tries to find a package to display documentation for. In the case that no package is provided, it uses "." just like go list does. So if go doc -http is run without any arguments, it tries to show the documentation for the package in the current directory. As a special case, if no arguments are provided, allow no package to match the current directory and just open the root pkgsite page. For #68106 Change-Id: I6d65b160a838591db953fac630eced6b09106877 Reviewed-on: https://go-review.googlesource.com/c/go/+/675075 Reviewed-by: Alan Donovan <adonovan@google.com> Reviewed-by: Michael Matloob <matloob@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
1 parent 8b45a3f commit 2a5ac1a

File tree

1 file changed

+40
-20
lines changed

1 file changed

+40
-20
lines changed

src/cmd/doc/main.go

Lines changed: 40 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,21 @@ func do(writer io.Writer, flagSet *flag.FlagSet, args []string) (err error) {
122122
}
123123
}
124124
if serveHTTP {
125-
// We want to run the logic below to determine a match for a symbol, method,
126-
// or field, but not actually print the documentation to the output.
125+
// Special case: if there are no arguments to go doc -http, allow
126+
// there to be no package in the current directory. We'll still try
127+
// to open the page for the documentation of the package in the current
128+
// directory, but if one doesn't exist, fall back to opening the home page.
129+
if len(flagSet.Args()) == 0 {
130+
var path string
131+
if importPath, err := runCmd("go", "list"); err == nil {
132+
path = importPath
133+
}
134+
return doPkgsite(path)
135+
}
136+
137+
// If args are provided, we need to figure out which page to open on the pkgsite
138+
// instance. Run the logic below to determine a match for a symbol, method,
139+
// or field, but don't actually print the documentation to the output.
127140
writer = io.Discard
128141
}
129142
var paths []string
@@ -179,51 +192,58 @@ func do(writer io.Writer, flagSet *flag.FlagSet, args []string) (err error) {
179192
}
180193
if found {
181194
if serveHTTP {
182-
return doPkgsite(userPath, pkg, symbol, method)
195+
path, err := objectPath(userPath, pkg, symbol, method)
196+
if err != nil {
197+
return err
198+
}
199+
return doPkgsite(path)
183200
}
184201
return nil
185202
}
186203
}
187204
}
188205

189-
func listUserPath(userPath string) (string, error) {
206+
func runCmd(cmdline ...string) (string, error) {
190207
var stdout, stderr strings.Builder
191-
cmd := exec.Command("go", "list", userPath)
208+
cmd := exec.Command(cmdline[0], cmdline[1:]...)
192209
cmd.Stdout = &stdout
193210
cmd.Stderr = &stderr
194211
if err := cmd.Run(); err != nil {
195-
return "", fmt.Errorf("go doc: go list %s: %v\n%s\n", userPath, err, stderr.String())
212+
return "", fmt.Errorf("go doc: %s: %v\n%s\n", strings.Join(cmdline, " "), err, stderr.String())
196213
}
197214
return strings.TrimSpace(stdout.String()), nil
198215
}
199216

200-
func doPkgsite(userPath string, pkg *Package, symbol, method string) error {
201-
port, err := pickUnusedPort()
202-
if err != nil {
203-
return fmt.Errorf("failed to find port for documentation server: %v", err)
204-
}
205-
addr := fmt.Sprintf("localhost:%d", port)
206-
207-
// Assemble url to open on the browser, to point to documentation of
208-
// the requested object.
209-
importPath := pkg.build.ImportPath
210-
if importPath == "." {
217+
func objectPath(userPath string, pkg *Package, symbol, method string) (string, error) {
218+
var err error
219+
path := pkg.build.ImportPath
220+
if path == "." {
211221
// go/build couldn't determine the import path, probably
212222
// because this was a relative path into a module. Use
213223
// go list to get the import path.
214-
importPath, err = listUserPath(userPath)
224+
path, err = runCmd("go", "list", userPath)
215225
if err != nil {
216-
return err
226+
return "", err
217227
}
218228
}
219-
path := path.Join("http://"+addr, importPath)
229+
220230
object := symbol
221231
if symbol != "" && method != "" {
222232
object = symbol + "." + method
223233
}
224234
if object != "" {
225235
path = path + "#" + object
226236
}
237+
return path, nil
238+
}
239+
240+
func doPkgsite(urlPath string) error {
241+
port, err := pickUnusedPort()
242+
if err != nil {
243+
return fmt.Errorf("failed to find port for documentation server: %v", err)
244+
}
245+
addr := fmt.Sprintf("localhost:%d", port)
246+
path := path.Join("http://"+addr, urlPath)
227247

228248
// Turn off the default signal handler for SIGINT (and SIGQUIT on Unix)
229249
// and instead wait for the child process to handle the signal and

0 commit comments

Comments
 (0)