--- /dev/null
+// 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"
+)
--- /dev/null
+// 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: <hostname>: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")
+}
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.
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
"io"
"log"
"os"
+ "path"
"path/filepath"
"regexp"
"runtime"
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)
}
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