Polygerrit: Decouple bower components rebuild from dev workflow

According to the polygerrit "development story", any changes related
to polymer components (aka bower_components) involves buck invocations:

  buck run //tools/js:bower2buck -- -o /tmp/newbuck

That why it doesn't really make sense to try to optimize for this use
case and to refresh polymer components in running container. This only
makes polygerrit development unnecessary slow. We are getting the main
use case to refresh the polygerrit sources in running container for
granted due to mounting the PolyGerritUiServlet to the source path.

Remove bower components rebuild filter and store zip file system in
bower component own servlet instead of leaking it to GerritLauncher
instance. Eclipse project generation depends now also on polymer
components.

Test Plan:

* Run:

  buck build polygerrit && \
      java -jar buck-out/gen/polygerrit/polygerrit.war daemon \
      --polygerrit-dev -d ../gerrit_testsite

* Change polygerrit sources, refresh the browser window and observe
that the changes are reflected and that there is no delay for
unnecessary `buck build //polygerrit-ui:polygerrit_components`
invocations, every time browser window is refreshed.

Change-Id: If86bbbe14b9ddf0fa5001b2bbb9a39629e9b383f
This commit is contained in:
David Ostrovsky 2016-01-09 14:46:57 +01:00 committed by Dave Borowitz
parent 29101927ba
commit d383d114c4
5 changed files with 30 additions and 125 deletions

View File

@ -18,12 +18,38 @@ import com.google.common.cache.Cache;
import com.google.gerrit.launcher.GerritLauncher;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
class BowerComponentsServlet extends ResourceServlet {
private static final long serialVersionUID = 1L;
static Path getZipPath(Path buckOut) {
private final Path zip;
private final Path bowerComponents;
BowerComponentsServlet(Cache<Path, Resource> cache, Path buckOut)
throws IOException {
super(cache, true);
zip = getZipPath(buckOut);
if (zip == null || !Files.exists(zip)) {
bowerComponents = null;
} else {
bowerComponents = GerritLauncher
.newZipFileSystem(zip)
.getPath("bower_components/");
}
}
@Override
protected Path getResourcePath(String pathInfo) throws IOException {
if (bowerComponents == null) {
throw new IOException("No polymer components found: " + zip
+ ". Run `buck build //polygerrit-ui:polygerrit_components`?");
}
return bowerComponents.resolve(pathInfo);
}
private static Path getZipPath(Path buckOut) {
if (buckOut == null) {
return null;
}
@ -32,17 +58,4 @@ class BowerComponentsServlet extends ResourceServlet {
.resolve("polygerrit_components")
.resolve("polygerrit_components.bower_components.zip");
}
private final Path zip;
BowerComponentsServlet(Cache<Path, Resource> cache, Path buckOut) {
super(cache, true);
this.zip = getZipPath(buckOut);
}
@Override
protected Path getResourcePath(String pathInfo) throws IOException {
return GerritLauncher.getZipFileSystem(zip)
.getPath("bower_components/" + pathInfo);
}
}

View File

@ -1,74 +0,0 @@
// Copyright (C) 2015 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.gerrit.httpd.raw.BuckUtils.BuildFailureException;
import com.google.gerrit.launcher.GerritLauncher;
import com.google.inject.Singleton;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
@Singleton
class RebuildBowerComponentsFilter implements Filter {
private static final String TARGET = "//polygerrit-ui:polygerrit_components";
private final Path gen;
private final Path root;
private final Path zip;
RebuildBowerComponentsFilter(Path buckOut) {
gen = buckOut.resolve("gen");
root = buckOut.getParent();
zip = BowerComponentsServlet.getZipPath(buckOut);
}
@Override
public synchronized void doFilter(ServletRequest sreq, ServletResponse sres,
FilterChain chain) throws IOException, ServletException {
HttpServletResponse res = (HttpServletResponse) sres;
try {
BuckUtils.build(root, gen, TARGET);
} catch (BuildFailureException e) {
BuckUtils.displayFailure(TARGET, e.why, res);
return;
}
if (!Files.exists(zip)) {
String msg = "`buck build` did not produce " + zip.toAbsolutePath();
BuckUtils.displayFailure(TARGET, msg.getBytes(UTF_8), res);
}
GerritLauncher.reloadZipFileSystem(zip);
chain.doFilter(sreq, sres);
}
@Override
public void init(FilterConfig config) throws ServletException {
}
@Override
public void destroy() {
}
}

View File

@ -218,15 +218,6 @@ public class StaticModule extends ServletModule {
public void configureServlets() {
Path buckOut = getPaths().buckOut;
if (buckOut != null) {
RebuildBowerComponentsFilter rebuildFilter =
new RebuildBowerComponentsFilter(buckOut);
for (String p : POLYGERRIT_INDEX_PATHS) {
// Rebuilding bower_components once per load on the index request,
// is sufficient, since it will finish building before attempting to
// access any bower_components resources. Plus it saves contention and
// extraneous buck builds.
filter(p).through(rebuildFilter);
}
serve("/bower_components/*").with(BowerComponentsServlet.class);
} else {
// In the war case, bower_components are either inlined by vulcanize, or
@ -262,7 +253,7 @@ public class StaticModule extends ServletModule {
@Provides
@Singleton
BowerComponentsServlet getBowerComponentsServlet(
@Named(CACHE) Cache<Path, Resource> cache) {
@Named(CACHE) Cache<Path, Resource> cache) throws IOException {
return new BowerComponentsServlet(cache, getPaths().buckOut);
}

View File

@ -341,33 +341,7 @@ public final class GerritLauncher {
return zipFs;
}
/**
* Reload the zip {@link FileSystem} for a path.
* <p>
* <strong>Warning</strong>: This calls {@link FileSystem#close()} on any
* previously open instance of the filesystem at this path, which may cause
* {@code IOException}s in any open path handles created with the old
* filesystem. Use with caution.
*
* @param zip path to zip file.
* @return reloaded filesystem instance.
* @throws IOException if there was an error reading the zip file.
*/
public static synchronized FileSystem reloadZipFileSystem(Path zip)
throws IOException {
// FileSystems canonicalizes the path, so we should too.
zip = zip.toRealPath();
@SuppressWarnings("resource") // Caching resource for later use.
FileSystem zipFs = zipFileSystems.get(zip);
if (zipFs != null) {
zipFs.close();
}
zipFs = newZipFileSystem(zip);
zipFileSystems.put(zip, zipFs);
return zipFs;
}
private static FileSystem newZipFileSystem(Path zip) throws IOException {
public static FileSystem newZipFileSystem(Path zip) throws IOException {
return FileSystems.newFileSystem(
URI.create("jar:" + zip.toUri()),
Collections.<String, String> emptyMap());

View File

@ -25,6 +25,7 @@ java_library(
'//lib/gwt:javax-validation_src',
'//lib/jetty:servlets',
'//lib/prolog:compiler_lib',
'//polygerrit-ui:polygerrit_components',
'//Documentation:index_lib',
] + scan_plugins(),
)