cmd/golangorg: simplify local vs prod programs

There was too much duplicated code between main.go
and appinit.go and too many build-tagged-out files.

Make main.go the func main for both prod and local.
Introduce local.go, merging dl.go and play.go.
Introduce prod.go, holding the prod-specific bits of appinit.go
(the rest are in main.go).

Rename the build tag to prod instead of golangorg
(the whole program is golangorg; it's very confusing).

Fixes golang/go#41102.

Change-Id: I261ce8e9171110f01798025f8218ce9f8253af81
Reviewed-on: https://go-review.googlesource.com/c/website/+/293413
Trust: Russ Cox <rsc@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
This commit is contained in:
Russ Cox 2021-02-16 21:26:23 -05:00
Родитель fd7d167356
Коммит 66996d0d91
21 изменённых файлов: 107 добавлений и 260 удалений

Просмотреть файл

@ -8,7 +8,7 @@ Content is in _content/. Server code is in cmd/ and internal/.
To run the server to preview local content changes, use:
go run ./cmd/golangorg -a
go run ./cmd/golangorg
The supporting programs cmd/admingolangorg and cmd/googlegolangorg
are the servers for admin.golang.org and google.golang.org.

Просмотреть файл

@ -21,7 +21,7 @@ COPY . /website
WORKDIR /website/cmd/golangorg
RUN go build -o /golangorg -tags=golangorg golang.org/x/website/cmd/golangorg
RUN go build -o /golangorg -tags=prod golang.org/x/website/cmd/golangorg
# Clean up goroot for the final image.
RUN cd /goroot && git clean -xdf

Просмотреть файл

@ -16,10 +16,9 @@ To run in production mode locally, you need:
* Godoc sources inside $GOPATH
(`go get -d golang.org/x/website/cmd/golangorg`)
Build with the `golangorg` tag and run:
Run with the `prod` tag:
go build -tags golangorg
./golangorg
go run -tags prod .
In production mode it serves on localhost:8080 (not 6060).
The port is controlled by $PORT, as in:

Просмотреть файл

@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build go1.16
// +build go1.16
package main
import (

Просмотреть файл

@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build go1.16
// +build go1.16
// The /doc/codewalk/ tree is synthesized from codewalk descriptions,
// files named $GOROOT/doc/codewalk/*.xml.
// For an example and a description of the format, see

Просмотреть файл

@ -1,16 +0,0 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !golangorg
package main
import "net/http"
// Register a redirect handler for /dl/ to the golang.org download page.
// This file will not be included when deploying godoc to golang.org.
func init() {
http.Handle("/dl/", http.RedirectHandler("https://golang.org/dl/", http.StatusFound))
}

Просмотреть файл

@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build !go1.16
// +build !go1.16
package main

Просмотреть файл

@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build go1.16
// +build go1.16
package main
import (

Просмотреть файл

@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build go1.16
// +build go1.16
package main_test
@ -77,14 +78,6 @@ func waitForServerReady(t *testing.T, addr string) {
false)
}
func waitForSearchReady(t *testing.T, addr string) {
waitForServer(t,
fmt.Sprintf("http://%v/search?q=FALLTHROUGH", addr),
"The list of tokens.",
2*time.Minute,
false)
}
func waitUntilScanComplete(t *testing.T, addr string) {
waitForServer(t,
fmt.Sprintf("http://%v/pkg", addr),

Просмотреть файл

@ -1,74 +0,0 @@
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"os"
"path/filepath"
"runtime"
)
// Copies of functions from src/cmd/go/internal/cfg/cfg.go for
// finding the GOROOT.
// Keep them in sync until support is moved to a common place, if ever.
func findGOROOT() string {
if env := os.Getenv("GOROOT"); env != "" {
return filepath.Clean(env)
}
def := filepath.Clean(runtime.GOROOT())
if runtime.Compiler == "gccgo" {
// gccgo has no real GOROOT, and it certainly doesn't
// depend on the executable's location.
return def
}
exe, err := os.Executable()
if err == nil {
exe, err = filepath.Abs(exe)
if err == nil {
if dir := filepath.Join(exe, "../.."); isGOROOT(dir) {
// If def (runtime.GOROOT()) and dir are the same
// directory, prefer the spelling used in def.
if isSameDir(def, dir) {
return def
}
return dir
}
exe, err = filepath.EvalSymlinks(exe)
if err == nil {
if dir := filepath.Join(exe, "../.."); isGOROOT(dir) {
if isSameDir(def, dir) {
return def
}
return dir
}
}
}
}
return def
}
// isGOROOT reports whether path looks like a GOROOT.
//
// It does this by looking for the path/pkg/tool directory,
// which is necessary for useful operation of the cmd/go tool,
// and is not typically present in a GOPATH.
func isGOROOT(path string) bool {
stat, err := os.Stat(filepath.Join(path, "pkg", "tool"))
if err != nil {
return false
}
return stat.IsDir()
}
// isSameDir reports whether dir1 and dir2 are the same directory.
func isSameDir(dir1, dir2 string) bool {
if dir1 == dir2 {
return true
}
info1, err1 := os.Stat(dir1)
info2, err2 := os.Stat(dir2)
return err1 == nil && err2 == nil && os.SameFile(info1, info2)
}

Просмотреть файл

@ -2,13 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// The /doc/codewalk/ tree is synthesized from codewalk descriptions,
// files named $GOROOT/doc/codewalk/*.xml.
// For an example and a description of the format, see
// http://golang.org/doc/codewalk/codewalk or run godoc -http=:6060
// and see http://localhost:6060/doc/codewalk/codewalk .
// That page is itself a codewalk; the source code for it is
// $GOROOT/doc/codewalk/codewalk.xml.
//go:build go1.16
// +build go1.16
package main

40
cmd/golangorg/local.go Normal file
Просмотреть файл

@ -0,0 +1,40 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build go1.16 && !prod
// +build go1.16,!prod
package main
import (
"fmt"
"log"
"net/http"
"os"
"path/filepath"
"runtime"
// This package registers "/compile" and "/share" handlers
// that redirect to the golang.org playground.
_ "golang.org/x/tools/playground"
)
func earlySetup() {
_, file, _, ok := runtime.Caller(0)
if !ok {
fmt.Fprintln(os.Stderr, "runtime.Caller failed: cannot find templates for -a mode.")
os.Exit(2)
}
dir := filepath.Join(file, "../../../_content")
if _, err := os.Stat(filepath.Join(dir, "godoc.html")); err != nil {
log.Printf("warning: cannot find template dir; using embedded copy")
return
}
*templateDir = dir
}
func lateSetup(mux *http.ServeMux) {
// Register a redirect handler for /dl/ to the golang.org download page.
http.Handle("/dl/", http.RedirectHandler("https://golang.org/dl/", http.StatusFound))
}

Просмотреть файл

@ -15,22 +15,16 @@
// https://golang.org/pkg/compress/zlib)
//
// Some pages are being transitioned from $GOROOT to content/doc.
// See golang.org/issue/29206 and golang.org/issue/33637.
//go:build go1.16
// +build go1.16
// +build !golangorg
package main
import (
_ "expvar" // to serve /debug/vars
"flag"
"fmt"
"go/build"
"log"
"net/http"
_ "net/http/pprof" // to serve /debug/pprof/*
"os"
"path/filepath"
"regexp"
@ -42,39 +36,19 @@ import (
"golang.org/x/website"
)
const defaultAddr = "localhost:6060" // default webserver address
var (
// network
httpAddr = flag.String("http", defaultAddr, "HTTP service address")
verbose = flag.Bool("v", false, "verbose mode")
// file system roots
// TODO(gri) consider the invariant that goroot always end in '/'
goroot = flag.String("goroot", findGOROOT(), "Go root directory")
// layout control
autoFlag = flag.Bool("a", false, "update templates automatically")
httpAddr = flag.String("http", "localhost:6060", "HTTP service address")
verbose = flag.Bool("v", false, "verbose mode")
goroot = flag.String("goroot", runtime.GOROOT(), "Go root directory")
showTimestamps = flag.Bool("timestamps", false, "show timestamps with directory listings")
templateDir = flag.String("templates", "", "load templates/JS/CSS from disk in this directory (usually /path-to-website/content)")
showPlayground = flag.Bool("play", false, "enable playground")
showPlayground = flag.Bool("play", true, "enable playground")
declLinks = flag.Bool("links", true, "link identifiers to their declarations")
// source code notes
notesRx = flag.String("notes", "BUG", "regular expression matching note markers to show")
notesRx = flag.String("notes", "BUG", "regular expression matching note markers to show")
)
func getFullPath(relPath string) string {
gopath := os.Getenv("GOPATH")
if gopath == "" {
gopath = build.Default.GOPATH
}
return gopath + relPath
}
func usage() {
fmt.Fprintf(os.Stderr, "usage: golangorg -http="+defaultAddr+"\n")
fmt.Fprintf(os.Stderr, "usage: golangorg\n")
flag.PrintDefaults()
os.Exit(2)
}
@ -86,37 +60,12 @@ func loggingHandler(h http.Handler) http.Handler {
})
}
func initCorpus(corpus *godoc.Corpus) {
err := corpus.Init()
if err != nil {
log.Fatal(err)
}
}
func main() {
earlySetup()
flag.Usage = usage
flag.Parse()
// Find templates in -a mode.
if *autoFlag {
if *templateDir != "" {
fmt.Fprintln(os.Stderr, "Cannot use -a and -templates together.")
usage()
}
_, file, _, ok := runtime.Caller(0)
if !ok {
fmt.Fprintln(os.Stderr, "runtime.Caller failed: cannot find templates for -a mode.")
os.Exit(2)
}
dir := filepath.Join(file, "../../../_content")
if _, err := os.Stat(filepath.Join(dir, "godoc.html")); err != nil {
fmt.Fprintln(os.Stderr, err)
fmt.Fprintln(os.Stderr, "Cannot find templates for -a mode.")
os.Exit(2)
}
*templateDir = dir
}
playEnabled = *showPlayground
// Check usage.
@ -129,14 +78,12 @@ func main() {
usage()
}
// Set the resolved goroot.
vfs.GOROOT = *goroot
fsGate := make(chan bool, 20)
// Determine file system to use.
rootfs := gatefs.New(vfs.OS(*goroot), fsGate)
fs.Bind("/", rootfs, "/", vfs.BindReplace)
// Try serving files in /doc from a local copy before trying the main
// go repository. This lets us update some documentation outside the
// Go release cycle. This includes root.html, which redirects to "/".
@ -144,25 +91,22 @@ func main() {
if *templateDir != "" {
fs.Bind("/doc", vfs.OS(*templateDir), "/doc", vfs.BindBefore)
fs.Bind("/lib/godoc", vfs.OS(*templateDir), "/", vfs.BindBefore)
root := filepath.Join(*templateDir, "..")
fs.Bind("/robots.txt", vfs.OS(root), "/robots.txt", vfs.BindBefore)
fs.Bind("/favicon.ico", vfs.OS(root), "/favicon.ico", vfs.BindBefore)
} else {
fs.Bind("/doc", vfs.FromFS(website.Content), "/doc", vfs.BindBefore)
fs.Bind("/lib/godoc", vfs.FromFS(website.Content), "/", vfs.BindReplace)
fs.Bind("/robots.txt", vfs.FromFS(website.Root), "/robots.txt", vfs.BindBefore)
fs.Bind("/favicon.ico", vfs.FromFS(website.Root), "/favicon.ico", vfs.BindBefore)
}
// Bind $GOPATH trees into Go root.
for _, p := range filepath.SplitList(build.Default.GOPATH) {
fs.Bind("/src", gatefs.New(vfs.OS(p), fsGate), "/src", vfs.BindAfter)
}
webroot := getFullPath("/src/golang.org/x/website")
fs.Bind("/robots.txt", gatefs.New(vfs.OS(webroot), fsGate), "/robots.txt", vfs.BindBefore)
fs.Bind("/favicon.ico", gatefs.New(vfs.OS(webroot), fsGate), "/favicon.ico", vfs.BindBefore)
corpus := godoc.NewCorpus(fs)
corpus.Verbose = *verbose
go initCorpus(corpus)
corpus.IndexEnabled = false
if err := corpus.Init(); err != nil {
log.Fatal(err)
}
// Initialize the version info before readTemplates, which saves
// the map value in a method value.
corpus.InitVersionInfo()
@ -176,7 +120,8 @@ func main() {
}
readTemplates(pres)
registerHandlers(pres)
mux := registerHandlers(pres)
lateSetup(mux)
var handler http.Handler = http.DefaultServeMux
if *verbose {

Просмотреть файл

@ -1,11 +0,0 @@
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !golangorg
package main
// This package registers "/compile" and "/share" handlers
// that redirect to the golang.org playground.
import _ "golang.org/x/tools/playground"

Просмотреть файл

@ -2,29 +2,19 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build go1.16
// +build golangorg
//go:build go1.16 && prod
// +build go1.16,prod
package main
// This file replaces main.go when running golangorg under App Engine.
// See README.md for details.
import (
"context"
"go/build"
"io"
"log"
"net/http"
"os"
"regexp"
"runtime"
"strings"
"golang.org/x/tools/godoc"
"golang.org/x/tools/godoc/vfs"
"golang.org/x/tools/godoc/vfs/gatefs"
"golang.org/x/website"
"golang.org/x/website/internal/dl"
"golang.org/x/website/internal/proxy"
"golang.org/x/website/internal/redirect"
@ -34,51 +24,22 @@ import (
"golang.org/x/website/internal/memcache"
)
func main() {
func earlySetup() {
log.SetFlags(log.Lshortfile | log.LstdFlags)
playEnabled = true
log.Println("initializing golang.org server ...")
fsGate := make(chan bool, 20)
rootfs := gatefs.New(vfs.OS(runtime.GOROOT()), fsGate)
fs.Bind("/", rootfs, "/", vfs.BindReplace)
// Try serving files in /doc from a local copy before trying the main
// go repository. This lets us update some documentation outside the
// Go release cycle. This includes root.html, which redirects to "/".
// See golang.org/issue/29206.
fs.Bind("/doc", vfs.FromFS(website.Content), "/doc", vfs.BindBefore)
fs.Bind("/lib/godoc", vfs.FromFS(website.Content), "/", vfs.BindReplace)
webroot := getFullPath("/src/golang.org/x/website")
fs.Bind("/favicon.ico", gatefs.New(vfs.OS(webroot), fsGate), "/favicon.ico", vfs.BindBefore)
corpus := godoc.NewCorpus(fs)
corpus.Verbose = false
corpus.MaxResults = 10000 // matches flag default in main.go
corpus.IndexEnabled = false
if err := corpus.Init(); err != nil {
log.Fatal(err)
port := "8080"
if p := os.Getenv("PORT"); p != "" {
port = p
}
corpus.InitVersionInfo()
*httpAddr = ":" + port
}
pres = godoc.NewPresentation(corpus)
pres.ShowPlayground = true
pres.DeclLinks = true
pres.NotesRx = regexp.MustCompile("BUG")
func lateSetup(mux *http.ServeMux) {
pres.GoogleAnalytics = os.Getenv("GOLANGORG_ANALYTICS")
readTemplates(pres)
datastoreClient, memcacheClient := getClients()
// NOTE(cbro): registerHandlers registers itself against DefaultServeMux.
// The mux returned has host enforcement, so it's important to register
// against this mux and not DefaultServeMux.
mux := registerHandlers(pres)
dl.RegisterHandlers(mux, datastoreClient, memcacheClient)
short.RegisterHandlers(mux, datastoreClient, memcacheClient)
@ -100,21 +61,6 @@ func main() {
}
log.Println("godoc initialization complete")
// TODO(cbro): add instrumentation via opencensus.
port := "8080"
if p := os.Getenv("PORT"); p != "" { // PORT is set by GAE flex.
port = p
}
log.Fatal(http.ListenAndServe(":"+port, nil))
}
func getFullPath(relPath string) string {
gopath := os.Getenv("GOPATH")
if gopath == "" {
gopath = build.Default.GOPATH
}
return gopath + relPath
}
func getClients() (*datastore.Client, *memcache.Client) {

Просмотреть файл

@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build go1.16
// +build go1.16
package main
import (

Просмотреть файл

@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build go1.16
// +build go1.16
// Regression tests to run against a production instance of godoc.
package main_test

Просмотреть файл

@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build go1.16
// +build go1.16
package main
import (

Просмотреть файл

@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build go1.16
// +build go1.16
// This file contains the handlers that serve go-import redirects for Go
// sub-repositories. It specifies the mapping from import paths like
// "golang.org/x/tools" to the actual repository locations.

Просмотреть файл

@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build go1.16
// +build go1.16
package main
import (

Просмотреть файл

@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build go1.16
// +build go1.16
// Package website exports the static content as an embed.FS.
@ -25,3 +26,7 @@ func subdir(fsys fs.FS, path string) fs.FS {
}
return s
}
// Root is the website root files: favicon.ico and robots.txt.
//go:embed favicon.ico robots.txt
var Root embed.FS