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
This commit is contained in:
mpl 2013-08-16 18:25:14 +02:00
parent 7364fd6110
commit 40951c103f
6 changed files with 62 additions and 14 deletions

View File

@ -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);

View File

@ -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")
}

View File

@ -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

View File

@ -23,4 +23,9 @@ import (
"camlistore.org/pkg/fileembed"
)
var Files *fileembed.Files
const GaeSourceRoot = "source_root"
var (
Files *fileembed.Files
IsAppEngine, IsProdAppEngine bool
)

View File

@ -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()
}

View File

@ -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.
</p>
<p>
The UI requires some static resources that are not included by default in the App Engine application directory (<code>server/appengine/</code>). You can define that directory in the server configuration file (<code>server/appengine/config.json</code>), with the <b><code>sourceRoot</code></b> parameter, like so:
<pre>
"/ui/": {
"handler": "ui",
"handlerArgs": {
"sourceRoot": "dir_name",
"jsonSignRoot": "/sighelper/"
}
},
</pre>
You will then have to populate that directory with all the necessary resources (UI static files and closure library files).</br>
Alternatively, you can run <b><code>./dev-appengine</code></b> once, which will create and populate the default directory (<code>server/appengine/source_root</code>).
</p>