bazel: abstract the build system in static serving.
Provide BazelBuild to stub out the Bazel build.
Tested:
Production use case:
1.) bazel build polygerrit && \
$(bazel info output_base)/external/local_jdk/bin/java \
-jar bazel-bin/polygerrit.war daemon -d ../test_site \
--console-log --show-stack-trace
Development mode use cases:
2.) bazel build polygerrit \
//polygerrit-ui:polygerrit_components.bower_components.zip &&
$(bazel info output_base)/external/local_jdk/bin/java \
-jar bazel-bin/polygerrit.war daemon \
--polygerrit-dev -d ../gerrit_testsite --console-log --show-stack-trace
checked that updates under polygerrit-ui/app/index.html are served
live.
3.) Run tools/eclipse/project.py, started gwt_daemon launcher,
verified that it worked.
4.) Run tools/eclipse/project.py, started gerit_gwt_debug launcher,
verified that GWT SDM worked.
Change-Id: I9d105e00e953b63c78306e9e37d5152673627727
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/BazelBuild.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/BazelBuild.java
new file mode 100644
index 0000000..efa270a
--- /dev/null
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/BazelBuild.java
@@ -0,0 +1,57 @@
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.httpd.raw;
+
+import java.io.IOException;
+import java.nio.file.Path;
+
+public class BazelBuild implements BuildSystem {
+ private final Path sourceRoot;
+
+ public BazelBuild(Path sourceRoot) {
+ this.sourceRoot = sourceRoot;
+ }
+
+ @Override
+ public void build(Label l) throws IOException, BuildFailureException {
+ throw new BuildFailureException("not implemented yet.".getBytes());
+ }
+
+ @Override
+ public String buildCommand(Label l) {
+ return "bazel build " + l.toString();
+ }
+
+ @Override
+ public Path targetPath(Label l) {
+ return sourceRoot.resolve("bazel-bin").resolve(l.pkg).resolve(l.name);
+ }
+
+ @Override
+ public Label gwtZipLabel(String agent) {
+ return new Label("gerrit-gwtui", "ui_" + agent + ".zip");
+ }
+
+ @Override
+ public Label polygerritComponents() {
+ return new Label("polygerrit-ui",
+ "polygerrit_components.bower_components.zip");
+ }
+
+ @Override
+ public Label fontZipLabel() {
+ return new Label("polygerrit-ui", "fonts.zip");
+ }
+}
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/BowerComponentsDevServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/BowerComponentsDevServlet.java
index c214d1f..c79670f 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/BowerComponentsDevServlet.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/BowerComponentsDevServlet.java
@@ -15,9 +15,11 @@
package com.google.gerrit.httpd.raw;
import com.google.common.cache.Cache;
+import com.google.gerrit.httpd.raw.BuildSystem.Label;
import com.google.gerrit.launcher.GerritLauncher;
import java.io.IOException;
+import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Objects;
@@ -26,24 +28,33 @@
private static final long serialVersionUID = 1L;
private final Path bowerComponents;
+ private final String buildCommand;
+ private final Path zip;
- BowerComponentsDevServlet(Cache<Path, Resource> cache, Path buckOut)
- throws IOException {
+ BowerComponentsDevServlet(Cache<Path, Resource> cache,
+ BuildSystem builder) throws IOException {
super(cache, true);
- Objects.requireNonNull(buckOut);
- Path zip = buckOut.resolve("gen")
- .resolve("polygerrit-ui")
- .resolve("polygerrit_components")
- .resolve("polygerrit_components.bower_components.zip");
+ Objects.requireNonNull(builder);
+ Label pgLabel = builder.polygerritComponents();
+ buildCommand = builder.buildCommand(pgLabel);
- bowerComponents = GerritLauncher
- .newZipFileSystem(zip)
- .getPath("/");
+ zip = builder.targetPath(pgLabel);
+ if (zip == null || !Files.exists(zip)) {
+ bowerComponents = null;
+ } else {
+ bowerComponents = GerritLauncher
+ .newZipFileSystem(zip)
+ .getPath("/");
+ }
}
@Override
protected Path getResourcePath(String pathInfo) throws IOException {
+ if (bowerComponents == null) {
+ throw new IOException("No polymer components found: " + zip
+ + ". Run `" + buildCommand + "`?");
+ }
return bowerComponents.resolve(pathInfo);
}
}
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/BuckUtils.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/BuckUtils.java
index 0b4a02e..df95d71 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/BuckUtils.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/BuckUtils.java
@@ -15,41 +15,39 @@
package com.google.gerrit.httpd.raw;
import static com.google.common.base.MoreObjects.firstNonNull;
-import static java.nio.charset.StandardCharsets.UTF_8;
-import com.google.common.escape.Escaper;
-import com.google.common.html.HtmlEscapers;
import com.google.common.io.ByteStreams;
import com.google.gerrit.common.TimeUtil;
-import com.google.gwtexpui.server.CacheHeaders;
-import org.eclipse.jgit.util.RawParseUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
-import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
-import java.nio.file.Paths;
import java.util.Properties;
-import javax.servlet.http.HttpServletResponse;
-
-class BuckUtils {
+class BuckUtils implements BuildSystem {
private static final Logger log =
LoggerFactory.getLogger(BuckUtils.class);
+ private final Path sourceRoot;
- static void build(Path root, Path gen, String target)
+ BuckUtils(Path sourceRoot) {
+ this.sourceRoot = sourceRoot;
+ }
+
+ @Override
+ public void build(Label label)
throws IOException, BuildFailureException {
- log.info("buck build " + target);
- Properties properties = loadBuckProperties(gen);
+ log.info("buck build " + label.fullName());
+ Properties properties = loadBuckProperties(
+ sourceRoot.resolve("buck-out/gen/tools/buck/buck.properties"));
String buck = firstNonNull(properties.getProperty("buck"), "buck");
- ProcessBuilder proc = new ProcessBuilder(buck, "build", target)
- .directory(root.toFile())
+ ProcessBuilder proc = new ProcessBuilder(buck, "build", label.fullName())
+ .directory(sourceRoot.toFile())
.redirectErrorStream(true);
if (properties.containsKey("PATH")) {
proc.environment().put("PATH", properties.getProperty("PATH"));
@@ -74,13 +72,14 @@
}
long time = TimeUtil.nowMs() - start;
- log.info(String.format("UPDATED %s in %.3fs", target, time / 1000.0));
+ log.info(String.format("UPDATED %s in %.3fs", label.fullName(),
+ time / 1000.0));
}
- private static Properties loadBuckProperties(Path gen) throws IOException {
+ private static Properties loadBuckProperties(Path propPath)
+ throws IOException {
Properties properties = new Properties();
- Path p = gen.resolve(Paths.get("tools/buck/buck.properties"));
- try (InputStream in = Files.newInputStream(p)) {
+ try (InputStream in = Files.newInputStream(propPath)) {
properties.load(in);
} catch (NoSuchFileException e) {
// Ignore; will be run from PATH, with a descriptive error if it fails.
@@ -88,31 +87,38 @@
return properties;
}
- static void displayFailure(String rule, byte[] why, HttpServletResponse res)
- throws IOException {
- res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
- res.setContentType("text/html");
- res.setCharacterEncoding(UTF_8.name());
- CacheHeaders.setNotCacheable(res);
-
- Escaper html = HtmlEscapers.htmlEscaper();
- try (PrintWriter w = res.getWriter()) {
- w.write("<html><title>BUILD FAILED</title><body>");
- w.format("<h1>%s FAILED</h1>", html.escape(rule));
- w.write("<pre>");
- w.write(html.escape(RawParseUtils.decode(why)));
- w.write("</pre>");
- w.write("</body></html>");
- }
+ @Override
+ public Path targetPath(Label label) {
+ return sourceRoot.resolve("buck-out")
+ .resolve("gen").resolve(label.artifact);
}
- static class BuildFailureException extends Exception {
- private static final long serialVersionUID = 1L;
+ @Override
+ public String buildCommand(Label l) {
+ return "buck build " + l.toString();
+ }
- final byte[] why;
+ @Override
+ public Label gwtZipLabel(String agent) {
+ // TODO(davido): instead of assuming specific Buck's internal
+ // target directory for gwt_binary() artifacts, ask Buck for
+ // the location of user agent permutation GWT zip, e. g.:
+ // $ buck targets --show_output //gerrit-gwtui:ui_safari \
+ // | awk '{print $2}'
+ String t = "ui_" + agent;
+ return new BuildSystem.Label("gerrit-gwtui", t,
+ String.format("gerrit-gwtui/__gwt_binary_%s__/%s.zip", t, t));
+ }
- BuildFailureException(byte[] why) {
- this.why = why;
- }
+ @Override
+ public Label polygerritComponents() {
+ return new Label("polygerrit-ui", "polygerrit_components",
+ "polygerrit-ui/polygerrit_components/" +
+ "polygerrit_components.bower_components.zip");
+ }
+
+ @Override
+ public Label fontZipLabel() {
+ return new Label("polygerrit-ui", "fonts", "polygerrit-ui/fonts/fonts.zip");
}
}
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/BuildSystem.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/BuildSystem.java
new file mode 100644
index 0000000..d51d8c0
--- /dev/null
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/BuildSystem.java
@@ -0,0 +1,114 @@
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.httpd.raw;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+import com.google.common.escape.Escaper;
+import com.google.common.html.HtmlEscapers;
+import com.google.gwtexpui.server.CacheHeaders;
+
+import org.eclipse.jgit.util.RawParseUtils;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.nio.file.Path;
+
+import javax.servlet.http.HttpServletResponse;
+
+public interface BuildSystem {
+
+ // Represents a label in either buck or bazel.
+ class Label {
+ protected final String pkg;
+ protected final String name;
+
+ // Regrettably, buck confounds rule names and artifact names,
+ // and so we have to lug this along. Non-null only for Buck; in that case,
+ // holds the path relative to buck-out/gen/
+ protected final String artifact;
+
+ public String fullName() {
+ return "//" + pkg + ":" + name;
+ }
+
+ @Override
+ public String toString() {
+ String s = fullName();
+ if (!name.equals(artifact)) {
+ s += "(" + artifact + ")";
+ }
+ return s;
+ }
+
+ // Label in Buck style.
+ Label(String pkg, String name, String artifact) {
+ this.name = name;
+ this.pkg = pkg;
+ this.artifact = artifact;
+ }
+
+ // Label in Bazel style.
+ Label(String pkg, String name) {
+ this(pkg, name, name);
+ }
+ }
+
+ class BuildFailureException extends Exception {
+ private static final long serialVersionUID = 1L;
+
+ final byte[] why;
+
+ BuildFailureException(byte[] why) {
+ this.why = why;
+ }
+
+ public void display(String rule, HttpServletResponse res)
+ throws IOException {
+ res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+ res.setContentType("text/html");
+ res.setCharacterEncoding(UTF_8.name());
+ CacheHeaders.setNotCacheable(res);
+
+ Escaper html = HtmlEscapers.htmlEscaper();
+ try (PrintWriter w = res.getWriter()) {
+ w.write("<html><title>BUILD FAILED</title><body>");
+ w.format("<h1>%s FAILED</h1>", html.escape(rule));
+ w.write("<pre>");
+ w.write(html.escape(RawParseUtils.decode(why)));
+ w.write("</pre>");
+ w.write("</body></html>");
+ }
+ }
+ }
+
+ /** returns the command to build given target */
+ String buildCommand(Label l);
+
+ /** builds the given label. */
+ void build(Label l) throws IOException, BuildFailureException;
+
+ /** returns the root relative path to the artifact for the given label */
+ Path targetPath(Label l);
+
+ /** Label for the agent specific GWT zip. */
+ Label gwtZipLabel(String agent);
+
+ /** Label for the polygerrit component zip. */
+ Label polygerritComponents();
+
+ /** Label for the fonts zip file. */
+ Label fontZipLabel();
+}
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/FontsDevServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/FontsDevServlet.java
index 9925c49..a9fb35ff 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/FontsDevServlet.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/FontsDevServlet.java
@@ -27,18 +27,15 @@
private final Path fonts;
- FontsDevServlet(Cache<Path, Resource> cache, Path buckOut)
+ FontsDevServlet(Cache<Path, Resource> cache, BuildSystem builder)
throws IOException {
super(cache, true);
- Objects.requireNonNull(buckOut);
+ Objects.requireNonNull(builder);
- Path zip = buckOut.resolve("gen")
- .resolve("polygerrit-ui")
- .resolve("fonts")
- .resolve("fonts.zip");
- fonts = GerritLauncher
- .newZipFileSystem(zip)
- .getPath("/");
+ Path zip = builder.targetPath(builder.fontZipLabel());
+ Objects.requireNonNull(zip);
+
+ fonts = GerritLauncher.newZipFileSystem(zip).getPath("/");
}
@Override
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/RecompileGwtUiFilter.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/RecompileGwtUiFilter.java
index 1984cbb..c36d257 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/RecompileGwtUiFilter.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/RecompileGwtUiFilter.java
@@ -14,7 +14,7 @@
package com.google.gerrit.httpd.raw;
-import com.google.gerrit.httpd.raw.BuckUtils.BuildFailureException;
+import com.google.gerrit.httpd.raw.BuildSystem.Label;
import com.google.gwtexpui.linker.server.UserAgentRule;
import java.io.File;
@@ -43,48 +43,40 @@
private final UserAgentRule rule = new UserAgentRule();
private final Set<String> uaInitialized = new HashSet<>();
private final Path unpackedWar;
- private final Path gen;
- private final Path root;
+ private final BuildSystem builder;
- private String lastTarget;
+ private String lastAgent;
private long lastTime;
- RecompileGwtUiFilter(Path buckOut, Path unpackedWar) {
+ RecompileGwtUiFilter(BuildSystem builder, Path unpackedWar) {
+ this.builder = builder;
this.unpackedWar = unpackedWar;
- gen = buckOut.resolve("gen");
- root = buckOut.getParent();
}
@Override
public void doFilter(ServletRequest request, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
- String pkg = "gerrit-gwtui";
- String target = "ui_" + rule.select((HttpServletRequest) request);
- if (gwtuiRecompile || !uaInitialized.contains(target)) {
- String rule = "//" + pkg + ":" + target;
- // TODO(davido): instead of assuming specific Buck's internal
- // target directory for gwt_binary() artifacts, ask Buck for
- // the location of user agent permutation GWT zip, e. g.:
- // $ buck targets --show_output //gerrit-gwtui:ui_safari \
- // | awk '{print $2}'
- String child = String.format("%s/__gwt_binary_%s__", pkg, target);
- File zip = gen.resolve(child).resolve(target + ".zip").toFile();
+ String agent = rule.select((HttpServletRequest) request);
+ if (unpackedWar != null
+ && (gwtuiRecompile || !uaInitialized.contains(agent))) {
+ Label label = builder.gwtZipLabel(agent);
+ File zip = builder.targetPath(label).toFile();
synchronized (this) {
try {
- BuckUtils.build(root, gen, rule);
- } catch (BuildFailureException e) {
- BuckUtils.displayFailure(rule, e.why, (HttpServletResponse) res);
+ builder.build(label);
+ } catch (BuildSystem.BuildFailureException e) {
+ e.display(label.toString(), (HttpServletResponse) res);
return;
}
- if (!target.equals(lastTarget) || lastTime != zip.lastModified()) {
- lastTarget = target;
+ if (!agent.equals(lastAgent) || lastTime != zip.lastModified()) {
+ lastAgent = agent;
lastTime = zip.lastModified();
unpack(zip, unpackedWar.toFile());
}
}
- uaInitialized.add(target);
+ uaInitialized.add(agent);
}
chain.doFilter(request, res);
}
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/StaticModule.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/StaticModule.java
index 3770469..d1070fc 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/StaticModule.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/StaticModule.java
@@ -221,8 +221,7 @@
if (p.unpackedWar != null) {
return p.unpackedWar.resolve(name);
}
- return p.buckOut.resolveSibling("gerrit-war").resolve("src")
- .resolve("main").resolve("webapp").resolve(name);
+ return p.sourceRoot.resolve("gerrit-war/src/main/webapp/" + name);
}
}
@@ -233,7 +232,7 @@
.with(Key.get(HttpServlet.class, Names.named(GWT_UI_SERVLET)));
Paths p = getPaths();
if (p.isDev()) {
- filter("/").through(new RecompileGwtUiFilter(p.buckOut, p.unpackedWar));
+ filter("/").through(new RecompileGwtUiFilter(p.builder, p.unpackedWar));
}
}
@@ -286,7 +285,7 @@
BowerComponentsDevServlet getBowerComponentsServlet(
@Named(CACHE) Cache<Path, Resource> cache) throws IOException {
return getPaths().isDev()
- ? new BowerComponentsDevServlet(cache, getPaths().buckOut)
+ ? new BowerComponentsDevServlet(cache, getPaths().builder)
: null;
}
@@ -295,19 +294,19 @@
FontsDevServlet getFontsServlet(
@Named(CACHE) Cache<Path, Resource> cache) throws IOException {
return getPaths().isDev()
- ? new FontsDevServlet(cache, getPaths().buckOut)
+ ? new FontsDevServlet(cache, getPaths().builder)
: null;
}
private Path polyGerritBasePath() {
Paths p = getPaths();
if (options.forcePolyGerritDev()) {
- checkArgument(p.buckOut != null,
- "no buck-out directory found for PolyGerrit developer mode");
+ checkArgument(p.sourceRoot != null,
+ "no source root directory found for PolyGerrit developer mode");
}
if (p.isDev()) {
- return p.buckOut.getParent().resolve("polygerrit-ui").resolve("app");
+ return p.sourceRoot.resolve("polygerrit-ui").resolve("app");
}
return p.warFs != null
@@ -318,7 +317,8 @@
private static class Paths {
private final FileSystem warFs;
- private final Path buckOut;
+ private final BuildSystem builder;
+ private final Path sourceRoot;
private final Path unpackedWar;
private final boolean development;
@@ -338,28 +338,42 @@
.getParentFile()
.getParentFile()
.toURI());
- buckOut = null;
+ sourceRoot = null;
development = false;
+ builder = null;
return;
}
warFs = getDistributionArchive(launcherLoadedFrom);
if (warFs == null) {
- buckOut = getDeveloperBuckOut();
unpackedWar = makeWarTempDir();
development = true;
} else if (options.forcePolyGerritDev()) {
- buckOut = getDeveloperBuckOut();
unpackedWar = null;
development = true;
} else {
- buckOut = null;
unpackedWar = null;
development = false;
+ sourceRoot = null;
+ builder = null;
+ return;
}
} catch (IOException e) {
throw new ProvisionException(
"Error initializing static content paths", e);
}
+
+ sourceRoot = getSourseRootOrNull();
+ builder = GerritLauncher.isBazel()
+ ? new BazelBuild(sourceRoot)
+ : new BuckUtils(sourceRoot);
+ }
+
+ private static Path getSourseRootOrNull() {
+ try {
+ return GerritLauncher.resolveInSourceRoot(".");
+ } catch (FileNotFoundException e) {
+ return null;
+ }
}
private FileSystem getDistributionArchive(File war) throws IOException {
@@ -390,14 +404,6 @@
return development;
}
- private Path getDeveloperBuckOut() {
- try {
- return GerritLauncher.getDeveloperBuckOut();
- } catch (FileNotFoundException e) {
- return null;
- }
- }
-
private Path makeWarTempDir() {
// Obtain our local temporary directory, but it comes back as a file
// so we have to switch it to be a directory post creation.
diff --git a/gerrit-launcher/BUILD b/gerrit-launcher/BUILD
index ced3447..cf1e788 100644
--- a/gerrit-launcher/BUILD
+++ b/gerrit-launcher/BUILD
@@ -3,5 +3,17 @@
java_library(
name = 'launcher',
srcs = ['src/main/java/com/google/gerrit/launcher/GerritLauncher.java'],
+ resources = [':workspace-root.txt'],
+ visibility = ['//visibility:public'],
+)
+
+# The root of the workspace is non-hermetic, but we need it for
+# on-the-fly GWT recompiles and PolyGerrit updates.
+genrule(
+ name = 'gen_root',
+ stamp = 1,
+ cmd = ("cat bazel-out/stable-status.txt | " +
+ "grep STABLE_WORKSPACE_ROOT | cut -d ' ' -f 2 > $@"),
+ outs = ['workspace-root.txt'],
visibility = ['//visibility:public'],
)
diff --git a/gerrit-launcher/src/main/java/com/google/gerrit/launcher/GerritLauncher.java b/gerrit-launcher/src/main/java/com/google/gerrit/launcher/GerritLauncher.java
index 27f885d..19bf51d 100644
--- a/gerrit-launcher/src/main/java/com/google/gerrit/launcher/GerritLauncher.java
+++ b/gerrit-launcher/src/main/java/com/google/gerrit/launcher/GerritLauncher.java
@@ -16,6 +16,7 @@
import static java.util.concurrent.TimeUnit.DAYS;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static java.nio.charset.StandardCharsets.UTF_8;
import java.io.File;
import java.io.FileNotFoundException;
@@ -42,6 +43,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Scanner;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.jar.Attributes;
@@ -622,20 +624,47 @@
return resolveInSourceRoot("eclipse-out");
}
- /**
- * Locate the path of the {@code buck-out} directory in a source tree.
- *
- * @return local path of the {@code buck-out} directory in a source tree.
- * @throws FileNotFoundException if the directory cannot be found.
- */
- public static Path getDeveloperBuckOut() throws FileNotFoundException {
- return resolveInSourceRoot("buck-out");
+ static String SOURCE_ROOT_RESOURCE = "/gerrit-launcher/workspace-root.txt";
+
+ /** returns whether we're running out of a bazel build. */
+ public static boolean isBazel() {
+ Class<GerritLauncher> self = GerritLauncher.class;
+ URL rootURL = self.getResource(SOURCE_ROOT_RESOURCE);
+ return rootURL != null;
}
- private static Path resolveInSourceRoot(String name)
+ /**
+ * Locate a path in the source tree.
+ *
+ * @return local path of the {@code name} directory in a source tree.
+ * @throws FileNotFoundException if the directory cannot be found.
+ */
+ public static Path resolveInSourceRoot(String name)
throws FileNotFoundException {
+
// Find ourselves in the classpath, as a loose class file or jar.
Class<GerritLauncher> self = GerritLauncher.class;
+
+ // If the build system provides us with a source root, use that.
+ try (InputStream stream = self.getResourceAsStream(SOURCE_ROOT_RESOURCE)) {
+ System.err.println("URL: " + stream);
+ if (stream != null) {
+ try (Scanner scan =
+ new Scanner(stream, UTF_8.name()).useDelimiter("\n")) {
+ if (scan.hasNext()) {
+ Path p = Paths.get(scan.next());
+ if (!Files.exists(p)) {
+ throw new FileNotFoundException(
+ "source root not found: " + p);
+ }
+ return p;
+ }
+ }
+ }
+ } catch (IOException e) {
+ // not Bazel, then.
+ }
+
URL u = self.getResource(self.getSimpleName() + ".class");
if (u == null) {
throw new FileNotFoundException("Cannot find class " + self.getName());
@@ -674,7 +703,7 @@
private static ClassLoader useDevClasspath()
throws MalformedURLException, FileNotFoundException {
- Path out = getDeveloperEclipseOut();
+ Path out = resolveInSourceRoot("eclipse-out");
List<URL> dirs = new ArrayList<>();
dirs.add(out.resolve("classes").toUri().toURL());
ClassLoader cl = GerritLauncher.class.getClassLoader();
diff --git a/polygerrit-ui/BUILD b/polygerrit-ui/BUILD
index 4cc6899..0124f93 100644
--- a/polygerrit-ui/BUILD
+++ b/polygerrit-ui/BUILD
@@ -6,7 +6,7 @@
load('//tools/bzl:genrule2.bzl', 'genrule2')
bower_component_bundle(
- name = "polygerrit_components",
+ name = "polygerrit_components.bower_components",
deps = [
'//lib/js:es6-promise',
'//lib/js:fetch',
diff --git a/polygerrit-ui/app/BUILD b/polygerrit-ui/app/BUILD
index 95ca5b2..331f912 100644
--- a/polygerrit-ui/app/BUILD
+++ b/polygerrit-ui/app/BUILD
@@ -18,7 +18,7 @@
'test/**',
'**/*_test.html',
]),
- deps = [ "//polygerrit-ui:polygerrit_components"],
+ deps = [ "//polygerrit-ui:polygerrit_components.bower_components"],
)
filegroup(
@@ -65,7 +65,7 @@
name = 'test_components',
testonly = 1,
deps = [
- '//polygerrit-ui:polygerrit_components',
+ '//polygerrit-ui:polygerrit_components.bower_components',
'//lib/js:iron-test-helpers',
'//lib/js:test-fixture',
'//lib/js:web-component-tester',
diff --git a/tools/workspace-status.sh b/tools/workspace-status.sh
index cbc263e..cd48a30 100755
--- a/tools/workspace-status.sh
+++ b/tools/workspace-status.sh
@@ -19,3 +19,4 @@
test -d "$p" || continue
echo STABLE_BUILD_$(echo $(basename $p)_LABEL|tr [a-z] [A-Z]) $(rev $p)
done
+echo "STABLE_WORKSPACE_ROOT ${PWD}"