From d7a0e0e6a2b20f945329feec2fcb1b5c559fcbc7 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 27 Jul 2011 15:14:12 -0700 Subject: [PATCH] godoc: app engine configuration and updated documentation Also: Fixed an error message in zip.go. R=r, dsymonds CC=golang-dev https://golang.org/cl/4816053 --- src/cmd/godoc/appconfig.go | 19 +++++++++ src/cmd/godoc/appinit.go | 86 ++++++++++++++++++++++++++++++++++++++ src/cmd/godoc/doc.go | 25 +++++++++-- src/cmd/godoc/main.go | 8 ++-- src/cmd/godoc/zip.go | 3 +- 5 files changed, 132 insertions(+), 9 deletions(-) create mode 100644 src/cmd/godoc/appconfig.go create mode 100644 src/cmd/godoc/appinit.go diff --git a/src/cmd/godoc/appconfig.go b/src/cmd/godoc/appconfig.go new file mode 100644 index 0000000000..9cbe7a4434 --- /dev/null +++ b/src/cmd/godoc/appconfig.go @@ -0,0 +1,19 @@ +// Copyright 2011 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. + +// This file contains configuration information used by +// godoc when running on app engine. Adjust as needed +// (typically when the .zip file changes). + +package main + +const ( + // zipFilename is the name of the .zip file + // containing the file system served by godoc. + zipFilename = "go.zip" + + // zipGoroot is the path of the goroot directory + // in the .zip file. + zipGoroot = "/home/username/go" +) diff --git a/src/cmd/godoc/appinit.go b/src/cmd/godoc/appinit.go new file mode 100644 index 0000000000..9b89872232 --- /dev/null +++ b/src/cmd/godoc/appinit.go @@ -0,0 +1,86 @@ +// Copyright 2011 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. + +// To run godoc under app engine, substitute main.go with +// this file (appinit.go), provide a .zip file containing +// the file system to serve, and adjust the configuration +// parameters in appconfig.go accordingly. +// +// The current app engine SDK may be based on an older Go +// release version. To correct for version skew, copy newer +// packages into the alt directory (e.g. alt/strings) and +// adjust the imports in the godoc source files (e.g. from +// `import "strings"` to `import "alt/strings"`). Both old +// and new packages may be used simultaneously as long as +// there is no package global state that needs to be shared. +// +// The directory structure should look as follows: +// +// godoc // directory containing the app engine app +// alt // alternative packages directory to +// // correct for version skew +// strings // never version of the strings package +// ... // +// app.yaml // app engine control file +// go.zip // zip file containing the file system to serve +// godoc // contains godoc sources +// appinit.go // this file instead of godoc/main.go +// appconfig.go // godoc for app engine configuration +// ... // +// +// To run app the engine emulator locally: +// +// dev_appserver.py -a 0 godoc +// +// godoc is the top-level "goroot" directory. +// The godoc home page is served at: :8080 and localhost:8080. + +package main + +import ( + "alt/archive/zip" + "http" + "log" + "os" +) + +func serveError(w http.ResponseWriter, r *http.Request, relpath string, err os.Error) { + contents := applyTemplate(errorHTML, "errorHTML", err) // err may contain an absolute path! + w.WriteHeader(http.StatusNotFound) + servePage(w, "File "+relpath, "", "", contents) +} + +func init() { + log.Println("initializing godoc ...") + *goroot = path.Join("/", zipGoroot) // fsHttp paths are relative to '/' + + // read .zip file and set up file systems + const zipfile = zipFilename + rc, err := zip.OpenReader(zipfile) + if err != nil { + log.Fatalf("%s: %s\n", zipfile, err) + } + fs = NewZipFS(rc) + fsHttp = NewHttpZipFS(rc, *goroot) + + // initialize http handlers + initHandlers() + readTemplates() + registerPublicHandlers(http.DefaultServeMux) + + // initialize default directory tree with corresponding timestamp. + initFSTree() + + // initialize directory trees for user-defined file systems (-path flag). + initDirTrees() + + // create search index + // TODO(gri) Disabled for now as it takes too long. Find a solution for this. + /* + *indexEnabled = true + go indexer() + */ + + log.Println("godoc initialization complete") +} diff --git a/src/cmd/godoc/doc.go b/src/cmd/godoc/doc.go index a8fcd22d64..dc98b0eca5 100644 --- a/src/cmd/godoc/doc.go +++ b/src/cmd/godoc/doc.go @@ -97,10 +97,9 @@ may be provided with the -filter flag; if it exists, only directories on those paths are considered. If -filter_minutes is set, the filter_file is updated regularly by walking the entire directory tree. -When godoc runs as a web server, it creates a search index from all .go files -under -goroot (excluding files starting with .). The index is created at startup -and is automatically updated every time the -sync command terminates with exit -status 0, indicating that files have changed. +When godoc runs as a web server and -index is set, a search index is maintained. +The index is created at startup and is automatically updated every time the +-sync command terminates with exit status 0, indicating that files have changed. If the sync exit status is 1, godoc assumes that it succeeded without errors but that no files changed; the index is not updated in this case. @@ -109,5 +108,23 @@ In all other cases, sync is assumed to have failed and godoc backs off running sync exponentially (up to 1 day). As soon as sync succeeds again (exit status 0 or 1), the normal sync rhythm is re-established. +The index contains both identifier and full text search information (searchable +via regular expressions). The maximum number of full text search results shown +can be set with the -maxresults flag; if set to 0, no full text results are +shown, and only an identifier index but no full text search index is created. + +By default, godoc serves files from the file system of the underlying OS. +Instead, a .zip file may be provided via the -zip flag, which contains +the file system to serve. The file paths stored in the .zip file must use +slash ('/') as path separator; and they must be unrooted. $GOROOT (or -goroot) +must be set to the .zip file directory path containing the Go root directory. +For instance, for a .zip file created by the command: + + zip go.zip $HOME/go + +one may run godoc as follows: + + godoc -http=:6060 -zip=go.zip -goroot=$HOME/go + */ package documentation diff --git a/src/cmd/godoc/main.go b/src/cmd/godoc/main.go index 6f7d9d78dc..943c81cfb5 100644 --- a/src/cmd/godoc/main.go +++ b/src/cmd/godoc/main.go @@ -38,6 +38,7 @@ import ( "io" "log" "os" + "path" "path/filepath" "regexp" "runtime" @@ -228,23 +229,22 @@ func main() { log.Fatalf("negative tabwidth %d", *tabwidth) } - // Clean goroot: normalize path separator. - *goroot = filepath.Clean(*goroot) - // Determine file system to use. // TODO(gri) - fs and fsHttp should really be the same. Try to unify. // - fsHttp doesn't need to be set up in command-line mode, // same is true for the http handlers in initHandlers. if *zipfile == "" { // use file system of underlying OS + *goroot = filepath.Clean(*goroot) // normalize path separator fs = OS fsHttp = http.Dir(*goroot) } else { - // use file system specified via .zip file + // use file system specified via .zip file (path separator must be '/') rc, err := zip.OpenReader(*zipfile) if err != nil { log.Fatalf("%s: %s\n", *zipfile, err) } + *goroot = path.Join("/", *goroot) // fsHttp paths are relative to '/' fs = NewZipFS(rc) fsHttp = NewHttpZipFS(rc, *goroot) } diff --git a/src/cmd/godoc/zip.go b/src/cmd/godoc/zip.go index 868aa1f02f..27dc142f54 100644 --- a/src/cmd/godoc/zip.go +++ b/src/cmd/godoc/zip.go @@ -83,7 +83,8 @@ func zipPath(name string) string { func (fs *zipFS) stat(abspath string) (int, zipFI, os.Error) { i, exact := fs.list.lookup(abspath) if i < 0 { - return -1, zipFI{}, fmt.Errorf("file not found: %s", abspath) + // abspath has leading '/' stripped - print it explicitly + return -1, zipFI{}, fmt.Errorf("file not found: /%s", abspath) } _, name := path.Split(abspath) var file *zip.File