]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/doc: use golang.org/x/pkgsite/cmd/internal/doc to start server
authorMichael Matloob <matloob@golang.org>
Mon, 19 May 2025 19:31:37 +0000 (15:31 -0400)
committerMichael Matloob <matloob@golang.org>
Tue, 20 May 2025 22:06:58 +0000 (15:06 -0700)
This change switches the pkgsite command invoked to start a pkgsite
server from golang.org/x/pkgsite/cmd/pkgsite to
golang.org/x/pkgsite/cmd/internal/doc. The doc command is a simplified
version of cmd/pkgsite that changes some options to improve the user
experience. For example, it limits logging informational log messages,
doesn't always expect to find modules (for example if we're outside of a
module getting documentation for the standard library), and it takes the
address of the page to open in the browser (which simplifies waiting for
the server to start listening).

Fixes #68106

Change-Id: I667a49d03823242fa1aff333ecb1c0f198e92412
Reviewed-on: https://go-review.googlesource.com/c/go/+/674158
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
Reviewed-by: David Chase <drchase@google.com>
src/cmd/doc/main.go

index c9b0454ea6c9f03f3e68db7b8da4925f54b8d0b8..4c47b4bcfc63b037463bbc5fe79aabaf20b9f98d 100644 (file)
@@ -44,7 +44,6 @@ package main
 
 import (
        "bytes"
-       "context"
        "errors"
        "flag"
        "fmt"
@@ -53,17 +52,13 @@ import (
        "io"
        "log"
        "net"
-       "net/http"
        "os"
        "os/exec"
        "os/signal"
        "path"
        "path/filepath"
        "strings"
-       "time"
 
-       "cmd/internal/browser"
-       "cmd/internal/quoted"
        "cmd/internal/telemetry/counter"
 )
 
@@ -203,36 +198,14 @@ func listUserPath(userPath string) (string, error) {
 }
 
 func doPkgsite(userPath string, pkg *Package, symbol, method string) error {
-       ctx := context.Background()
-
-       cmdline := "go run golang.org/x/pkgsite/cmd/pkgsite@latest -gorepo=" + buildCtx.GOROOT
-       words, err := quoted.Split(cmdline)
        port, err := pickUnusedPort()
        if err != nil {
                return fmt.Errorf("failed to find port for documentation server: %v", err)
        }
        addr := fmt.Sprintf("localhost:%d", port)
-       words = append(words, fmt.Sprintf("-http=%s", addr))
-       cmd := exec.CommandContext(context.Background(), words[0], words[1:]...)
-       cmd.Stdout = os.Stderr
-       cmd.Stderr = os.Stderr
-       // Turn off the default signal handler for SIGINT (and SIGQUIT on Unix)
-       // and instead wait for the child process to handle the signal and
-       // exit before exiting ourselves.
-       signal.Ignore(signalsToIgnore...)
-
-       if err := cmd.Start(); err != nil {
-               return fmt.Errorf("starting pkgsite: %v", err)
-       }
-
-       // Wait for pkgsite to became available.
-       if !waitAvailable(ctx, addr) {
-               cmd.Cancel()
-               cmd.Wait()
-               return errors.New("could not connect to local documentation server")
-       }
 
-       // Open web browser.
+       // Assemble url to open on the browser, to point to documentation of
+       // the requested object.
        importPath := pkg.build.ImportPath
        if importPath == "." {
                // go/build couldn't determine the import path, probably
@@ -251,16 +224,33 @@ func doPkgsite(userPath string, pkg *Package, symbol, method string) error {
        if object != "" {
                path = path + "#" + object
        }
-       if ok := browser.Open(path); !ok {
-               cmd.Cancel()
-               cmd.Wait()
-               return errors.New("failed to open browser")
+
+       // Turn off the default signal handler for SIGINT (and SIGQUIT on Unix)
+       // and instead wait for the child process to handle the signal and
+       // exit before exiting ourselves.
+       signal.Ignore(signalsToIgnore...)
+
+       const version = "v0.0.0-20250520201116-40659211760d"
+       cmd := exec.Command("go", "run", "golang.org/x/pkgsite/cmd/internal/doc@"+version,
+               "-gorepo", buildCtx.GOROOT,
+               "-http", addr,
+               "-open", path)
+       cmd.Stdout = os.Stderr
+       cmd.Stderr = os.Stderr
+
+       if err := cmd.Run(); err != nil {
+               var ee *exec.ExitError
+               if errors.As(err, &ee) {
+                       // Exit with the same exit status as pkgsite to avoid
+                       // printing of "exit status" error messages.
+                       // Any relevant messages have already been printed
+                       // to stdout or stderr.
+                       os.Exit(ee.ExitCode())
+               }
+               return err
        }
 
-       // Wait for child to terminate. We expect the child process to receive signals from
-       // this terminal and terminate in a timely manner, so this process will terminate
-       // soon after.
-       return cmd.Wait()
+       return nil
 }
 
 // pickUnusedPort finds an unused port by trying to listen on port 0
@@ -279,24 +269,6 @@ func pickUnusedPort() (int, error) {
        return port, nil
 }
 
-func waitAvailable(ctx context.Context, addr string) bool {
-       ctx, cancel := context.WithTimeout(ctx, 15*time.Second)
-       defer cancel()
-       for ctx.Err() == nil {
-               req, err := http.NewRequestWithContext(ctx, "HEAD", "http://"+addr, nil)
-               if err != nil {
-                       log.Println(err)
-                       return false
-               }
-               resp, err := http.DefaultClient.Do(req)
-               if err == nil {
-                       resp.Body.Close()
-                       return true
-               }
-       }
-       return false
-}
-
 // failMessage creates a nicely formatted error message when there is no result to show.
 func failMessage(paths []string, symbol, method string) error {
        var b bytes.Buffer