From 40951c103f709cd47f520cee2db36b9dc597a631 Mon Sep 17 00:00:00 2001
From: mpl
Date: Fri, 16 Aug 2013 18:25:14 +0200
Subject: [PATCH] appengine: fix the UI
-dev-appengine populates the default sourceRoot.
-app.yaml filters out the go files from the static
resources
-the UI handler warns that sourceRoot is required
Change-Id: I816456a882ff4b0573bc8962cce85139d8a0f611
---
dev-appengine | 21 +++++++++++++++++++-
pkg/server/publish.go | 1 +
pkg/server/ui.go | 19 +++++++++++++++++-
server/camlistored/ui/fileembed.go | 7 ++++++-
server/camlistored/ui/fileembed_appengine.go | 13 ++----------
website/content/docs/server-config | 15 ++++++++++++++
6 files changed, 62 insertions(+), 14 deletions(-)
diff --git a/dev-appengine b/dev-appengine
index 18f0c6fc7..0e2da15cb 100755
--- a/dev-appengine
+++ b/dev-appengine
@@ -38,8 +38,27 @@ if ($opt_port) {
push @args, @ARGV;
chdir "$Bin/server/appengine" or die "$!";
-push @args, ".";
+my $sourceRoot = "$Bin/server/appengine/source_root";
+# import in the appengine dir all the static files, so they get uploaded
+# TODO(mpl): do a smarter mirroring when we convert this to go
+unless (-d $sourceRoot) {
+ # copy ui files
+ system("mkdir", "-p", $sourceRoot) and die "Failed to create $sourceRoot.\n";
+ my $dest = "$sourceRoot/server/camlistored";
+ system("mkdir", "-p", $dest) and die "Failed to create uiDir.\n";
+ system("cp", "-a", "$Bin/server/camlistored/ui", $dest) and die "Failed to cp uiDir.\n";
+ # copy closure files
+ $dest = "$sourceRoot/third_party/closure/lib";
+ system("mkdir", "-p", $dest) and die "Failed to create closureDir.\n";
+ system("cp", "-a", "$Bin/third_party/closure/lib/closure", $dest) and die "Failed to cp uiDir.\n";
+ # copy favicon.ico
+ $dest = "$sourceRoot/pkg/server";
+ system("mkdir", "-p", $dest) and die "Failed to create pkg/server.\n";
+ system("cp", "$Bin/pkg/server/favicon.ico", $dest) and die "Failed to cp favicon.ico.\n";
+}
+
+push @args, ".";
print "\$ @args\n";
exec(@args);
diff --git a/pkg/server/publish.go b/pkg/server/publish.go
index bf76d2bd5..8f29ef732 100644
--- a/pkg/server/publish.go
+++ b/pkg/server/publish.go
@@ -159,6 +159,7 @@ func newPublishFromConfig(ld blobserver.Loader, conf jsonconfig.Obj) (h http.Han
}
}
+ // TODO(mpl): check that it works on appengine too.
if ph.sourceRoot == "" {
ph.sourceRoot = os.Getenv("CAMLI_DEV_CAMLI_ROOT")
}
diff --git a/pkg/server/ui.go b/pkg/server/ui.go
index 01f48b026..3498d1477 100644
--- a/pkg/server/ui.go
+++ b/pkg/server/ui.go
@@ -158,6 +158,19 @@ func uiFromConfig(ld blobserver.Loader, conf jsonconfig.Obj) (h http.Handler, er
if ui.sourceRoot == "" {
ui.sourceRoot = os.Getenv("CAMLI_DEV_CAMLI_ROOT")
+ if uistatic.IsAppEngine {
+ if _, err = os.Stat(filepath.Join(uistatic.GaeSourceRoot,
+ filepath.FromSlash("server/camlistored/ui/index.html"))); err != nil {
+ hint := fmt.Sprintf("\"sourceRoot\" was not specified in the config,"+
+ " and the default sourceRoot dir %v does not exist or does not contain"+
+ " \"server/camlistored/ui/index.html\". dev-appengine can do that for you.",
+ uistatic.GaeSourceRoot)
+ log.Print(hint)
+ return nil, errors.New("No sourceRoot found; UI not available.")
+ }
+ log.Printf("Using the default \"%v\" as the sourceRoot for AppEngine", uistatic.GaeSourceRoot)
+ ui.sourceRoot = uistatic.GaeSourceRoot
+ }
}
if ui.sourceRoot != "" {
ui.uiDir = filepath.Join(ui.sourceRoot, filepath.FromSlash("server/camlistored/ui"))
@@ -168,6 +181,10 @@ func uiFromConfig(ld blobserver.Loader, conf jsonconfig.Obj) (h http.Handler, er
uistatic.Files = &fileembed.Files{
DirFallback: ui.uiDir,
Listable: true,
+ // In dev_appserver, allow edit-and-reload without
+ // restarting. In production, though, it's faster to just
+ // slurp it in.
+ SlurpToMemory: uistatic.IsProdAppEngine,
}
}
@@ -202,7 +219,7 @@ func (ui *UIHandler) makeClosureHandler(root string) (http.Handler, error) {
// 3) a path on disk to the root of camlistore's source (which
// contains the necessary subset of Closure files)
func makeClosureHandler(root, handlerName string) (http.Handler, error) {
- // devcam server environment variable takes precendence:
+ // devcam server environment variable takes precedence:
if d := os.Getenv("CAMLI_DEV_CLOSURE_DIR"); d != "" {
log.Printf("%v: serving Closure from devcam server's $CAMLI_DEV_CLOSURE_DIR: %v", handlerName, d)
return http.FileServer(http.Dir(d)), nil
diff --git a/server/camlistored/ui/fileembed.go b/server/camlistored/ui/fileembed.go
index 237e21af2..7b5c15e80 100644
--- a/server/camlistored/ui/fileembed.go
+++ b/server/camlistored/ui/fileembed.go
@@ -23,4 +23,9 @@ import (
"camlistore.org/pkg/fileembed"
)
-var Files *fileembed.Files
+const GaeSourceRoot = "source_root"
+
+var (
+ Files *fileembed.Files
+ IsAppEngine, IsProdAppEngine bool
+)
diff --git a/server/camlistored/ui/fileembed_appengine.go b/server/camlistored/ui/fileembed_appengine.go
index 78d514c3c..de57dbbb5 100644
--- a/server/camlistored/ui/fileembed_appengine.go
+++ b/server/camlistored/ui/fileembed_appengine.go
@@ -19,19 +19,10 @@ limitations under the License.
package ui
import (
- "camlistore.org/pkg/fileembed"
-
"appengine"
)
func init() {
- Files = &fileembed.Files{
- DirFallback: "uistatic",
-
- // In dev_appserver, allow edit-and-reload without
- // restarting. In production, though, it's faster to just
- // slurp it in.
- SlurpToMemory: !appengine.IsDevAppServer(),
- Listable: true,
- }
+ IsAppEngine = true
+ IsProdAppEngine = !appengine.IsDevAppServer()
}
diff --git a/website/content/docs/server-config b/website/content/docs/server-config
index 168d187a3..8935d2bd3 100644
--- a/website/content/docs/server-config
+++ b/website/content/docs/server-config
@@ -84,3 +84,18 @@ to use the App Engine Blobstore and Datastore, as well as App Engine's
user auth mechanisms. But as of 2013-06-12 we don't yet recommend running
on App Engine; there are still some sharp corners.
+
+
+The UI requires some static resources that are not included by default in the App Engine application directory (server/appengine/
). You can define that directory in the server configuration file (server/appengine/config.json
), with the sourceRoot
parameter, like so:
+
+ "/ui/": {
+ "handler": "ui",
+ "handlerArgs": {
+ "sourceRoot": "dir_name",
+ "jsonSignRoot": "/sighelper/"
+ }
+ },
+
+You will then have to populate that directory with all the necessary resources (UI static files and closure library files).
+Alternatively, you can run ./dev-appengine
once, which will create and populate the default directory (server/appengine/source_root
).
+