Commit 8604e180 authored by Robert Griesemer's avatar Robert Griesemer

- added goroutine to automatically p4 sync the current workspace

- set "Updated" timestamp on served pages to p4 sync time

R=rsc
DELTA=72  (66 added, 3 deleted, 3 changed)
OCL=29959
CL=29959
parent 031bf2c8
...@@ -42,6 +42,8 @@ import ( ...@@ -42,6 +42,8 @@ import (
pathutil "path"; pathutil "path";
"sort"; "sort";
"strings"; "strings";
"sync";
"syscall";
"tabwriter"; "tabwriter";
"template"; "template";
"time"; "time";
...@@ -53,6 +55,26 @@ import ( ...@@ -53,6 +55,26 @@ import (
const Pkg = "/pkg/" // name for auto-generated package documentation tree const Pkg = "/pkg/" // name for auto-generated package documentation tree
type timeStamp struct {
mutex sync.RWMutex;
seconds int64;
}
func (ts *timeStamp) set() {
ts.mutex.Lock();
ts.seconds = time.Seconds();
ts.mutex.Unlock();
}
func (ts *timeStamp) get() int64 {
ts.mutex.RLock();
defer ts.mutex.RUnlock();
return ts.seconds;
}
var ( var (
verbose = flag.Bool("v", false, "verbose mode"); verbose = flag.Bool("v", false, "verbose mode");
...@@ -62,6 +84,11 @@ var ( ...@@ -62,6 +84,11 @@ var (
pkgroot = flag.String("pkgroot", "src/lib", "root package source directory (if unrooted, relative to goroot)"); pkgroot = flag.String("pkgroot", "src/lib", "root package source directory (if unrooted, relative to goroot)");
tmplroot = flag.String("tmplroot", "usr/gri/pretty", "root template directory (if unrooted, relative to goroot)"); tmplroot = flag.String("tmplroot", "usr/gri/pretty", "root template directory (if unrooted, relative to goroot)");
// workspace control
p4binary = flag.String("p4", "/usr/local/scripts/p4", "p4 binary");
syncSleep = flag.Int("sync", 10, "p4 sync interval in minutes; disabled if <= 0");
syncTime timeStamp; // time of last p4 sync
// layout control // layout control
tabwidth = flag.Int("tabwidth", 4, "tab width"); tabwidth = flag.Int("tabwidth", 4, "tab width");
usetabs = flag.Bool("tabs", false, "align with tabs instead of spaces"); usetabs = flag.Bool("tabs", false, "align with tabs instead of spaces");
...@@ -319,7 +346,7 @@ func servePage(c *http.Conn, title, content interface{}) { ...@@ -319,7 +346,7 @@ func servePage(c *http.Conn, title, content interface{}) {
var d Data; var d Data;
d.title = title; d.title = title;
d.header = title; d.header = title;
d.timestamp = time.UTC().String(); d.timestamp = time.SecondsToLocalTime(syncTime.get()).String();
d.content = content; d.content = content;
godocHtml.Execute(&d, c); godocHtml.Execute(&d, c);
} }
...@@ -578,12 +605,25 @@ func loggingHandler(h http.Handler) http.Handler { ...@@ -578,12 +605,25 @@ func loggingHandler(h http.Handler) http.Handler {
} }
func p4sync() bool {
if *verbose {
log.Stderrf("p4 sync");
}
args := []string{*p4binary, "sync"};
pid, err := os.ForkExec(*p4binary, args, os.Environ(), "", []*os.File{os.Stdin, os.Stdout, os.Stderr});
if err != nil {
log.Stderrf("os.ForkExec(%s): %v", *p4binary, err);
return false;
}
os.Wait(pid, 0);
syncTime.set();
return true;
}
func restartGodoc(c *http.Conn, r *http.Request) { func restartGodoc(c *http.Conn, r *http.Request) {
binary := os.Args[0]; binary := os.Args[0];
if len(binary) > 0 && binary[0] != '/' { pid, err := os.ForkExec(binary, os.Args, os.Environ(), launchdir, []*os.File{os.Stdin, os.Stdout, os.Stderr});
binary = pathutil.Join(launchdir, binary);
}
pid, err := os.ForkExec(binary, os.Args, os.Environ(), "", []*os.File{os.Stdin, os.Stdout, os.Stderr});
if err != nil { if err != nil {
log.Stderrf("os.ForkExec(%s): %v", binary, err); log.Stderrf("os.ForkExec(%s): %v", binary, err);
return; // do not terminate return; // do not terminate
...@@ -642,7 +682,11 @@ func main() { ...@@ -642,7 +682,11 @@ func main() {
} }
http.Handle(Pkg, http.HandlerFunc(servePkg)); http.Handle(Pkg, http.HandlerFunc(servePkg));
http.Handle("/debug/restart", http.HandlerFunc(restartGodoc)); if syscall.OS != "darwin" {
http.Handle("/debug/restart", http.HandlerFunc(restartGodoc));
} else {
log.Stderrf("warning: debug/restart disabled (running on darwin)\n");
}
http.Handle("/", http.HandlerFunc(serveFile)); http.Handle("/", http.HandlerFunc(serveFile));
// The server may have been restarted; always wait 1sec to // The server may have been restarted; always wait 1sec to
...@@ -651,6 +695,25 @@ func main() { ...@@ -651,6 +695,25 @@ func main() {
// won't work if there are more than one thread running.) // won't work if there are more than one thread running.)
time.Sleep(1e9); time.Sleep(1e9);
// Start p4 sync goroutine, if enabled.
if syscall.OS != "darwin" {
if *syncSleep > 0 {
go func() {
if *verbose {
log.Stderrf("p4 sync every %dmin", *syncSleep);
}
for p4sync() {
time.Sleep(int64(*syncSleep) * (60 * 1e9));
}
if *verbose {
log.Stderrf("periodic p4 sync stopped");
}
}();
}
} else {
log.Stderrf("warning: sync disabled (running on darwin)\n");
}
if err := http.ListenAndServe(*httpaddr, handler); err != nil { if err := http.ListenAndServe(*httpaddr, handler); err != nil {
log.Exitf("ListenAndServe %s: %v", *httpaddr, err) log.Exitf("ListenAndServe %s: %v", *httpaddr, err)
} }
......
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