Fix the buck springboard to always work from Eclipse

JettyDaemon invokes buck build to ensure GWT JS is up-to-date before
running the server.  To be completely compatible with the command line
build it uses the same PATH environment variable, ignoring the PATH
that is inherited from Eclipse.

Including the PATH as part of the genrule() command ensures buck will
rewrite the properties file anytime the user modifies the PATH, rather
than only when there are updates to GWT Java sources.

Using a properties file frees us from worrying about double quoting in
shell: once in the genrule, again in the script itself.

Using a single properties file ensures any GWT UI can be computed or
verified by JettyDaemon.  This change simplifies bootstrap for a
developer as they no longer need to build the UI before launching the
server from within Eclipse.  JettyDaemon now takes care of it.

Change-Id: If096a60d9a3f9d6d1502cc947b966109b4458717
This commit is contained in:
Shawn Pearce
2013-05-13 12:48:12 -07:00
parent 4dbb2dbc71
commit 6dec5bf32e
4 changed files with 49 additions and 17 deletions

View File

@@ -17,6 +17,7 @@ package com.google.gerrit.pgm.http.jetty;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
import com.google.common.base.Objects;
import com.google.common.io.ByteStreams;
import com.google.gerrit.extensions.events.LifecycleListener;
import com.google.gerrit.launcher.GerritLauncher;
@@ -54,6 +55,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
@@ -68,6 +70,7 @@ import java.util.EnumSet;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
@@ -488,7 +491,7 @@ public class JettyServer {
String target = targetForBrowser(System.getProperty("gerrit.browser"));
File gen = new File(dir, "gen");
String out = new File(new File(gen, pkg), target).getAbsolutePath();
build(dir.getParentFile(), out + ".rebuild", "//" + pkg + ":" + target);
build(dir.getParentFile(), gen, "//" + pkg + ":" + target);
return unpackWar(new File(out + ".zip"));
} else if ("target".equals(dir.getName())) {
return useMavenDeveloperBuild(dir);
@@ -507,15 +510,19 @@ public class JettyServer {
}
}
private static void build(File root, String cmd, String target)
private static void build(File root, File gen, String target)
throws IOException {
long start = System.currentTimeMillis();
log.info("buck build " + target);
Process rebuild = new ProcessBuilder(cmd, target)
Properties properties = loadBuckProperties(gen);
String buck = Objects.firstNonNull(properties.getProperty("buck"), "buck");
ProcessBuilder proc = new ProcessBuilder(buck, "build", target)
.directory(root)
.redirectErrorStream(true)
.start();
.redirectErrorStream(true);
if (properties.contains("PATH")) {
proc.environment().put("PATH", properties.getProperty("PATH"));
}
long start = System.currentTimeMillis();
Process rebuild = proc.start();
byte[] out;
InputStream in = rebuild.getInputStream();
try {
@@ -529,7 +536,7 @@ public class JettyServer {
try {
status = rebuild.waitFor();
} catch (InterruptedException e) {
throw new InterruptedIOException("interrupted waiting for " + cmd);
throw new InterruptedIOException("interrupted waiting for " + buck);
}
if (status != 0) {
System.err.write(out);
@@ -541,6 +548,19 @@ public class JettyServer {
log.info(String.format("UPDATED %s in %.3fs", target, time / 1000.0));
}
private static Properties loadBuckProperties(File gen)
throws FileNotFoundException, IOException {
Properties properties = new Properties();
InputStream in = new FileInputStream(
new File(new File(gen, "tools"), "buck.properties"));
try {
properties.load(in);
} finally {
in.close();
}
return properties;
}
private Resource useMavenDeveloperBuild(File dir) throws IOException {
dir = dir.getParentFile(); // pop target
dir = dir.getParentFile(); // pop the module we are in

View File

@@ -16,7 +16,7 @@
from __future__ import print_function
from multiprocessing import cpu_count
from os import environ, fchmod, makedirs, mkdir, path
from os import environ, makedirs, mkdir, path
from subprocess import Popen, PIPE
from sys import argv, stderr
@@ -60,11 +60,3 @@ out, err = gwt.communicate()
if gwt.returncode != 0:
print(out + err, file=stderr)
exit(gwt.returncode)
with open(rebuild, 'w') as fd:
def shquote(s):
return s.replace("'", "'\\''")
print('#!/bin/sh', file=fd)
print("PATH='%s'" % shquote(environ['PATH']), file=fd)
print('buck build "$1" || exit', file=fd)
fchmod(fd.fileno(), 0o755)

View File

@@ -9,3 +9,21 @@ python_binary(
main = 'pack_war.py',
visibility = ['PUBLIC'],
)
def shquote(s):
return s.replace("'", "'\\''")
def os_path():
from os import environ
return environ.get('PATH')
genrule(
name = 'buck.properties',
cmd = 'echo buck=`which buck`>$OUT;' +
("echo PATH=\''%s'\' >>$OUT;" % shquote(os_path())),
srcs = [],
deps = [],
out = 'buck.properties',
visibility = ['PUBLIC'],
)

View File

@@ -7,6 +7,7 @@ genrule(
deps = [
':_classpath',
':_project',
'//tools:buck.properties',
],
out = '__fake.eclipse__',
)
@@ -18,6 +19,7 @@ genrule(
deps = [
':_classpath_nocompile',
':_project',
'//tools:buck.properties',
],
out = '__fake.eclipse__',
)