aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cmd/go/internal/doc/doc.go8
-rw-r--r--src/cmd/go/internal/doc/pkgsite.go59
-rw-r--r--src/cmd/go/internal/doc/pkgsite_bootstrap.go4
3 files changed, 58 insertions, 13 deletions
diff --git a/src/cmd/go/internal/doc/doc.go b/src/cmd/go/internal/doc/doc.go
index 4376e3344e..d961c2a215 100644
--- a/src/cmd/go/internal/doc/doc.go
+++ b/src/cmd/go/internal/doc/doc.go
@@ -222,16 +222,16 @@ func do(ctx context.Context, writer io.Writer, flagSet *flag.FlagSet, args []str
mod, err := runCmd(append(os.Environ(), "GOWORK=off"), "go", "list", "-m")
if err == nil && mod != "" && mod != "command-line-arguments" {
// If there's a module, go to the module's doc page.
- return doPkgsite(mod, "")
+ return doPkgsite(ctx, mod, "")
}
gowork, err := runCmd(nil, "go", "env", "GOWORK")
if err == nil && gowork != "" {
// Outside a module, but in a workspace, go to the home page
// with links to each of the modules' pages.
- return doPkgsite("", "")
+ return doPkgsite(ctx, "", "")
}
// Outside a module or workspace, go to the documentation for the standard library.
- return doPkgsite("std", "")
+ return doPkgsite(ctx, "std", "")
}
// If args are provided, we need to figure out which page to open on the pkgsite
@@ -296,7 +296,7 @@ func do(ctx context.Context, writer io.Writer, flagSet *flag.FlagSet, args []str
if err != nil {
return err
}
- return doPkgsite(path, fragment)
+ return doPkgsite(ctx, path, fragment)
}
return nil
}
diff --git a/src/cmd/go/internal/doc/pkgsite.go b/src/cmd/go/internal/doc/pkgsite.go
index 2c135cdc34..a2398ef397 100644
--- a/src/cmd/go/internal/doc/pkgsite.go
+++ b/src/cmd/go/internal/doc/pkgsite.go
@@ -7,17 +7,21 @@
package doc
import (
+ "context"
"errors"
"fmt"
"net"
"net/url"
"os"
"os/exec"
- "os/signal"
"path/filepath"
"strings"
+ "cmd/go/internal/base"
"cmd/go/internal/cfg"
+ "cmd/go/internal/load"
+ "cmd/go/internal/modload"
+ "cmd/go/internal/work"
)
// pickUnusedPort finds an unused port by trying to listen on port 0
@@ -36,7 +40,49 @@ func pickUnusedPort() (int, error) {
return port, nil
}
-func doPkgsite(urlPath, fragment string) error {
+// buildPkgsite builds a pkgsite binary whose build may be cached.
+func buildPkgsite(ctx context.Context) string {
+ loader := modload.NewLoader()
+
+ // Set the builder to have no module root so we can build a pkg@version pattern.
+ loader.ForceUseModules = true
+ loader.RootMode = modload.NoRoot
+ loader.AllowMissingModuleImports()
+ modload.Init(loader)
+
+ work.BuildInit(loader)
+ b := work.NewBuilder("", loader.VendorDirOrEmpty)
+ defer func() {
+ if err := b.Close(); err != nil {
+ base.Fatal(err)
+ }
+ }()
+
+ const version = "v0.0.0-20251223195805-1a3bd3c788fe"
+ pkgVers := "golang.org/x/pkgsite/cmd/internal/doc@" + version
+ pkgOpts := load.PackageOpts{MainOnly: true}
+ pkgs, err := load.PackagesAndErrorsOutsideModule(loader, ctx, pkgOpts, []string{pkgVers})
+ if err != nil {
+ base.Fatal(err)
+ }
+ if len(pkgs) == 0 {
+ base.Fatalf("go: internal error: no packages loaded for %s", pkgVers)
+ }
+ if len(pkgs) > 1 {
+ base.Fatalf("go: internal error: pattern %s matches multiple packages", pkgVers)
+ }
+ p := pkgs[0]
+ p.Internal.OmitDebug = true
+ p.Internal.ExeName = p.DefaultExecName()
+ load.CheckPackageErrors([]*load.Package{p})
+
+ a := b.LinkAction(loader, work.ModeBuild, work.ModeBuild, p)
+ a.CacheExecutable = true
+ b.Do(ctx, a)
+ return a.BuiltTarget()
+}
+
+func doPkgsite(ctx context.Context, urlPath, fragment string) error {
port, err := pickUnusedPort()
if err != nil {
return fmt.Errorf("failed to find port for documentation server: %v", err)
@@ -57,7 +103,7 @@ func doPkgsite(urlPath, fragment string) error {
// 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...)
+ base.StartSigHandlers()
// Prepend the local download cache to GOPROXY to get around deprecation checks.
env := os.Environ()
@@ -77,11 +123,8 @@ func doPkgsite(urlPath, fragment string) error {
env = append(env, "GOPROXY="+gomodcache+","+goproxy)
}
- const version = "v0.0.0-20251223195805-1a3bd3c788fe"
- cmd := exec.Command(goCmd(), "run", "golang.org/x/pkgsite/cmd/internal/doc@"+version,
- "-gorepo", cfg.GOROOT,
- "-http", addr,
- "-open", path)
+ pkgsite := buildPkgsite(ctx)
+ cmd := exec.Command(pkgsite, "-gorepo", cfg.GOROOT, "-http", addr, "-open", path)
cmd.Env = env
cmd.Stdout = os.Stderr
cmd.Stderr = os.Stderr
diff --git a/src/cmd/go/internal/doc/pkgsite_bootstrap.go b/src/cmd/go/internal/doc/pkgsite_bootstrap.go
index 3c9f546957..cb72492cb5 100644
--- a/src/cmd/go/internal/doc/pkgsite_bootstrap.go
+++ b/src/cmd/go/internal/doc/pkgsite_bootstrap.go
@@ -8,4 +8,6 @@
package doc
-func doPkgsite(string, string) error { return nil }
+import "context"
+
+func doPkgsite(context.Context, string, string) error { return nil }