Commit 5883c6ef authored by Robert Griesemer's avatar Robert Griesemer

godoc support for directories outside $GOROOT

Example use: godoc -path=/home/user1:/home/build/foo -http=:6666
will start a local godoc that maps urls starting with /pkg/user1 or
/pkg/foo to the respective roots specified in the path.

Missing: Handling of overlapping package directories, multiple
packages per directory.

R=rsc
CC=golang-dev
https://golang.org/cl/206078
parent 85498cbc
......@@ -4,10 +4,6 @@
license that can be found in the LICENSE file.
-->
{.section Error}
<p>
<span class="alert" style="font-size:120%">{@|html}</span>
</p>
{.or}
<pre>{Source|html}</pre>
{.end}
<p>
<span class="alert" style="font-size:120%">{@|html-esc}</span>
</p>
......@@ -94,6 +94,9 @@
<li><a href="/doc/code.html">How to write code</a></li>
<li><a href="/cmd">Command documentation</a></li>
<li><a href="/pkg">Package documentation</a></li>
{.repeated section PkgRoots}
<li><a href="/pkg/{@|html-esc}">Package documentation for {@|html-esc}</a></li>
{.end}
<li><a href="/src">Source files</a></li>
<li><a href="/doc/devel/">The Go project</a></li>
......
......@@ -16,7 +16,7 @@
<h4>Package files</h4>
<span style="font-size:90%">
{.repeated section @}
<a href="/{FilePath|html-esc}/{@|html-esc}">{@|html}</a>
<a href="{@|url-src}">{@|localname}</a>
{.end}
</span>
</p>
......@@ -38,14 +38,14 @@
{.end}
{.section Funcs}
{.repeated section @}
<h2 id="{Name|html-esc}">func <a href="{Decl|link}">{Name|html}</a></h2>
<h2 id="{Name|html-esc}">func <a href="{Decl|url-pos}">{Name|html}</a></h2>
<p><code>{Decl|html}</code></p>
{Doc|html-comment}
{.end}
{.end}
{.section Types}
{.repeated section @}
<h2 id="{Type.Name|html-esc}">type <a href="{Decl|link}">{Type.Name|html}</a></h2>
<h2 id="{Type.Name|html-esc}">type <a href="{Decl|url-pos}">{Type.Name|html}</a></h2>
{Doc|html-comment}
<p><pre>{Decl|html}</pre></p>
{.repeated section Consts}
......@@ -57,12 +57,12 @@
<pre>{Decl|html}</pre>
{.end}
{.repeated section Factories}
<h3 id="{Type.Name|html-esc}.{Name|html-esc}">func <a href="{Decl|link}">{Name|html}</a></h3>
<h3 id="{Type.Name|html-esc}.{Name|html-esc}">func <a href="{Decl|url-pos}">{Name|html}</a></h3>
<p><code>{Decl|html}</code></p>
{Doc|html-comment}
{.end}
{.repeated section Methods}
<h3 id="{Type.Name|html-esc}.{Name|html-esc}">func ({Recv|html}) <a href="{Decl|link}">{Name|html}</a></h3>
<h3 id="{Type.Name|html-esc}.{Name|html-esc}">func ({Recv|html}) <a href="{Decl|url-pos}">{Name|html}</a></h3>
<p><code>{Decl|html}</code></p>
{Doc|html-comment}
{.end}
......
......@@ -22,11 +22,11 @@
{.section Decls}
<h2 id="Global">Package-level declarations</h2>
{.repeated section @}
<h3 id="Global_{Pak.Path|path}">package <a href="{Pak.Path|path}">{Pak.Name|html}</a></h3>
<h3 id="Global_{Pak.Path|url-pkg}">package <a href="{Pak.Path|url-pkg}">{Pak.Name|html}</a></h3>
{.repeated section Files}
{.repeated section Groups}
{.repeated section Infos}
<a href="{File.Path|html-esc}?h={Query|html-esc}#L{@|infoLine}">{File.Path|html}:{@|infoLine}</a>
<a href="{File.Path|url-src}?h={Query|html-esc}#L{@|infoLine}">{File.Path|html}:{@|infoLine}</a>
<pre>{@|infoSnippet}</pre>
{.end}
{.end}
......@@ -36,9 +36,9 @@
{.section Others}
<h2 id="Local">Local declarations and uses</h2>
{.repeated section @}
<h3 id="Local_{Pak.Path|path}">package <a href="{Pak.Path|path}">{Pak.Name|html}</a></h3>
<h3 id="Local_{Pak.Path|url-pkg}">package <a href="{Pak.Path|url-pkg}">{Pak.Name|html}</a></h3>
{.repeated section Files}
<a href="{File.Path|html-esc}?h={Query|html-esc}">{File.Path|html}</a>
<a href="{File.Path|url-src}?h={Query|html-esc}">{File.Path|html}</a>
<table class="layout">
{.repeated section Groups}
<tr>
......@@ -47,7 +47,7 @@
<td align="left" width="4"></td>
<td>
{.repeated section Infos}
<a href="{File.Path|html-esc}?h={Query|html-esc}#L{@|infoLine}">{@|infoLine}</a>
<a href="{File.Path|url-src}?h={Query|html-esc}#L{@|infoLine}">{@|infoLine}</a>
{.end}
</td>
</tr>
......
......@@ -9,6 +9,7 @@ GOFILES=\
godoc.go\
index.go\
main.go\
mapping.go\
snippet.go\
spec.go\
......
This diff is collapsed.
......@@ -47,9 +47,6 @@ var (
// layout control
html = flag.Bool("html", false, "print HTML in command-line mode")
// --- Hack to remember current directory
workingDir string
)
......@@ -112,7 +109,7 @@ func dosync(c *http.Conn, r *http.Request) {
// TODO(gri): The directory tree may be temporarily out-of-sync.
// Consider keeping separate time stamps so the web-
// page can indicate this discrepancy.
fsTree.set(newDirectory(".", maxDirDepth))
fsTree.set(newDirectory(goroot, maxDirDepth))
fallthrough
case 1:
// sync failed because no files changed;
......@@ -155,17 +152,7 @@ func main() {
log.Exitf("negative tabwidth %d", *tabwidth)
}
// --- Start of hack.
// Remember where we were, so "." works as a directory name.
// Error's not worth worrying about; we just check for empty string
// when we need it.
workingDir, _ = os.Getwd()
// --- End of hack.
if err := os.Chdir(goroot); err != nil {
log.Exitf("chdir %s: %v", goroot, err)
}
initRoots()
readTemplates()
if *httpaddr != "" {
......@@ -175,10 +162,14 @@ func main() {
log.Stderrf("Go Documentation Server\n")
log.Stderrf("address = %s\n", *httpaddr)
log.Stderrf("goroot = %s\n", goroot)
log.Stderrf("cmdroot = %s\n", *cmdroot)
log.Stderrf("pkgroot = %s\n", *pkgroot)
log.Stderrf("tmplroot = %s\n", *tmplroot)
log.Stderrf("cmdroot = %s\n", cmdroot)
log.Stderrf("pkgroot = %s\n", pkgroot)
log.Stderrf("tmplroot = %s\n", tmplroot)
log.Stderrf("tabwidth = %d\n", *tabwidth)
if !fsMap.IsEmpty() {
log.Stderr("user-defined mapping:")
fsMap.Fprint(os.Stderr)
}
handler = loggingHandler(handler)
}
......@@ -192,7 +183,7 @@ func main() {
// 1) set timestamp right away so that the indexer is kicked on
fsTree.set(nil)
// 2) compute initial directory tree in a goroutine so that launch is quick
go func() { fsTree.set(newDirectory(".", maxDirDepth)) }()
go func() { fsTree.set(newDirectory(goroot, maxDirDepth)) }()
// Start sync goroutine, if enabled.
if *syncCmd != "" && *syncMin > 0 {
......
......@@ -27,13 +27,13 @@ import (
// until a valid mapping is found. For instance, for the mapping:
//
// user -> /home/user
// public -> /home/user/public
// public -> /home/user/public
// public -> /home/build/public
//
// the relative paths below are mapped to absolute paths as follows:
//
// user/foo -> /home/user/foo
// public/net/rpc/file1.go -> /home/user/public/net/rpc/file1.go
// public/net/rpc/file1.go -> /home/user/public/net/rpc/file1.go
//
// If there is no /home/user/public/net/rpc/file2.go, the next public
// mapping entry is used to map the relative path to:
......@@ -43,7 +43,8 @@ import (
// (assuming that file exists).
//
type Mapping struct {
list []mapping
list []mapping
prefixes []string
}
......@@ -71,7 +72,7 @@ type mapping struct {
// leads to the following mapping:
//
// user -> /home/user
// public -> /home/build/public
// public -> /home/build/public
//
func (m *Mapping) Init(paths string) {
cwd, _ := os.Getwd() // ignore errors
......@@ -105,7 +106,7 @@ func (m *Mapping) Init(paths string) {
// add mapping if it is new
if i >= n {
_, prefix := pathutil.Split(path)
list[i] = mapping{prefix, path}
list[n] = mapping{prefix, path}
n++
}
}
......@@ -118,6 +119,45 @@ func (m *Mapping) Init(paths string) {
func (m *Mapping) IsEmpty() bool { return len(m.list) == 0 }
// PrefixList returns a list of all prefixes, with duplicates removed.
// For instance, for the mapping:
//
// user -> /home/user
// public -> /home/user/public
// public -> /home/build/public
//
// the prefix list is:
//
// user, public
//
func (m *Mapping) PrefixList() []string {
// compute the list lazily
if m.prefixes == nil {
list := make([]string, len(m.list))
n := 0 // nuber of prefixes
for _, e := range m.list {
// check if prefix exists already
var i int
for i = 0; i < n; i++ {
if e.prefix == list[i] {
break
}
}
// add prefix if it is new
if i >= n {
list[n] = e.prefix
n++
}
}
m.prefixes = list[0:n]
}
return m.prefixes
}
// Fprint prints the mapping.
func (m *Mapping) Fprint(w io.Writer) {
for _, e := range m.list {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment