Luke Granger-Brown
dd6ee53bfe
This does a bit more than advertised, since this also switches to a different set of Bazel package building infrastructure that I'm hoping will be more extensible than buildBazelPackage as it exists in nixpkgs today. In any case, the FOD here _seems_ to be much more stable than that previously produced by the old approach, but no promises :)
215 lines
8.8 KiB
Diff
215 lines
8.8 KiB
Diff
From ca2df6d7f53441d443d42908e30bf60fbfc15392 Mon Sep 17 00:00:00 2001
|
|
From: Luke Granger-Brown <git@lukegb.com>
|
|
Date: Thu, 2 Jul 2020 23:03:02 +0100
|
|
Subject: [PATCH 3/3] Add titles to CLs over HTTP
|
|
|
|
---
|
|
.../gerrit/httpd/raw/IndexHtmlUtil.java | 12 +++-
|
|
.../google/gerrit/httpd/raw/IndexServlet.java | 8 ++-
|
|
.../google/gerrit/httpd/raw/StaticModule.java | 5 +-
|
|
.../gerrit/httpd/raw/TitleComputer.java | 67 +++++++++++++++++++
|
|
.../gerrit/httpd/raw/PolyGerritIndexHtml.soy | 4 +-
|
|
5 files changed, 88 insertions(+), 8 deletions(-)
|
|
create mode 100644 java/com/google/gerrit/httpd/raw/TitleComputer.java
|
|
|
|
diff --git a/java/com/google/gerrit/httpd/raw/IndexHtmlUtil.java b/java/com/google/gerrit/httpd/raw/IndexHtmlUtil.java
|
|
index a92dd18f04..f87c46d321 100644
|
|
--- a/java/com/google/gerrit/httpd/raw/IndexHtmlUtil.java
|
|
+++ b/java/com/google/gerrit/httpd/raw/IndexHtmlUtil.java
|
|
@@ -41,6 +41,7 @@ import java.util.Collections;
|
|
import java.util.HashMap;
|
|
import java.util.HashSet;
|
|
import java.util.Map;
|
|
+import java.util.Optional;
|
|
import java.util.Set;
|
|
import java.util.function.Function;
|
|
|
|
@@ -63,13 +64,14 @@ public class IndexHtmlUtil {
|
|
String faviconPath,
|
|
Map<String, String[]> urlParameterMap,
|
|
Function<String, SanitizedContent> urlInScriptTagOrdainer,
|
|
- String requestedURL)
|
|
+ String requestedURL,
|
|
+ TitleComputer titleComputer)
|
|
throws URISyntaxException, RestApiException {
|
|
ImmutableMap.Builder<String, Object> data = ImmutableMap.builder();
|
|
data.putAll(
|
|
staticTemplateData(
|
|
canonicalURL, cdnPath, faviconPath, urlParameterMap, urlInScriptTagOrdainer))
|
|
- .putAll(dynamicTemplateData(gerritApi, requestedURL, canonicalURL));
|
|
+ .putAll(dynamicTemplateData(gerritApi, requestedURL, canonicalURL, titleComputer));
|
|
Set<String> enabledExperiments = new HashSet<>();
|
|
enabledExperiments.addAll(experimentFeatures.getEnabledExperimentFeatures());
|
|
// Add all experiments enabled through url
|
|
@@ -82,7 +84,7 @@ public class IndexHtmlUtil {
|
|
|
|
/** Returns dynamic parameters of {@code index.html}. */
|
|
public static ImmutableMap<String, Object> dynamicTemplateData(
|
|
- GerritApi gerritApi, String requestedURL, String canonicalURL)
|
|
+ GerritApi gerritApi, String requestedURL, String canonicalURL, TitleComputer titleComputer)
|
|
throws RestApiException, URISyntaxException {
|
|
ImmutableMap.Builder<String, Object> data = ImmutableMap.builder();
|
|
Map<String, SanitizedContent> initialData = new HashMap<>();
|
|
@@ -141,6 +143,10 @@ public class IndexHtmlUtil {
|
|
}
|
|
|
|
data.put("gerritInitialData", initialData);
|
|
+
|
|
+ Optional<String> title = titleComputer.computeTitle(requestedURL);
|
|
+ title.ifPresent(s -> data.put("title", s));
|
|
+
|
|
return data.build();
|
|
}
|
|
|
|
diff --git a/java/com/google/gerrit/httpd/raw/IndexServlet.java b/java/com/google/gerrit/httpd/raw/IndexServlet.java
|
|
index fcb821e5ae..e1464b992b 100644
|
|
--- a/java/com/google/gerrit/httpd/raw/IndexServlet.java
|
|
+++ b/java/com/google/gerrit/httpd/raw/IndexServlet.java
|
|
@@ -48,13 +48,15 @@ public class IndexServlet extends HttpServlet {
|
|
private final ExperimentFeatures experimentFeatures;
|
|
private final SoySauce soySauce;
|
|
private final Function<String, SanitizedContent> urlOrdainer;
|
|
+ private TitleComputer titleComputer;
|
|
|
|
IndexServlet(
|
|
@Nullable String canonicalUrl,
|
|
@Nullable String cdnPath,
|
|
@Nullable String faviconPath,
|
|
GerritApi gerritApi,
|
|
- ExperimentFeatures experimentFeatures) {
|
|
+ ExperimentFeatures experimentFeatures,
|
|
+ TitleComputer titleComputer) {
|
|
this.canonicalUrl = canonicalUrl;
|
|
this.cdnPath = cdnPath;
|
|
this.faviconPath = faviconPath;
|
|
@@ -69,6 +71,7 @@ public class IndexServlet extends HttpServlet {
|
|
(s) ->
|
|
UnsafeSanitizedContentOrdainer.ordainAsSafe(
|
|
s, SanitizedContent.ContentKind.TRUSTED_RESOURCE_URI);
|
|
+ this.titleComputer = titleComputer;
|
|
}
|
|
|
|
@Override
|
|
@@ -86,7 +89,8 @@ public class IndexServlet extends HttpServlet {
|
|
faviconPath,
|
|
parameterMap,
|
|
urlOrdainer,
|
|
- getRequestUrl(req));
|
|
+ getRequestUrl(req),
|
|
+ titleComputer);
|
|
renderer = soySauce.renderTemplate("com.google.gerrit.httpd.raw.Index").setData(templateData);
|
|
} catch (URISyntaxException | RestApiException e) {
|
|
throw new IOException(e);
|
|
diff --git a/java/com/google/gerrit/httpd/raw/StaticModule.java b/java/com/google/gerrit/httpd/raw/StaticModule.java
|
|
index b00294f73e..f1c1aae12c 100644
|
|
--- a/java/com/google/gerrit/httpd/raw/StaticModule.java
|
|
+++ b/java/com/google/gerrit/httpd/raw/StaticModule.java
|
|
@@ -224,10 +224,11 @@ public class StaticModule extends ServletModule {
|
|
@CanonicalWebUrl @Nullable String canonicalUrl,
|
|
@GerritServerConfig Config cfg,
|
|
GerritApi gerritApi,
|
|
- ExperimentFeatures experimentFeatures) {
|
|
+ ExperimentFeatures experimentFeatures,
|
|
+ TitleComputer titleComputer) {
|
|
String cdnPath = options.devCdn().orElseGet(() -> cfg.getString("gerrit", null, "cdnPath"));
|
|
String faviconPath = cfg.getString("gerrit", null, "faviconPath");
|
|
- return new IndexServlet(canonicalUrl, cdnPath, faviconPath, gerritApi, experimentFeatures);
|
|
+ return new IndexServlet(canonicalUrl, cdnPath, faviconPath, gerritApi, experimentFeatures, titleComputer);
|
|
}
|
|
|
|
@Provides
|
|
diff --git a/java/com/google/gerrit/httpd/raw/TitleComputer.java b/java/com/google/gerrit/httpd/raw/TitleComputer.java
|
|
new file mode 100644
|
|
index 0000000000..8fd2053ad0
|
|
--- /dev/null
|
|
+++ b/java/com/google/gerrit/httpd/raw/TitleComputer.java
|
|
@@ -0,0 +1,67 @@
|
|
+package com.google.gerrit.httpd.raw;
|
|
+
|
|
+import com.google.common.flogger.FluentLogger;
|
|
+import com.google.gerrit.entities.Change;
|
|
+import com.google.gerrit.extensions.restapi.ResourceConflictException;
|
|
+import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
|
|
+import com.google.gerrit.server.change.ChangeResource;
|
|
+import com.google.gerrit.server.permissions.PermissionBackendException;
|
|
+import com.google.gerrit.server.restapi.change.ChangesCollection;
|
|
+import com.google.inject.Inject;
|
|
+import com.google.inject.Provider;
|
|
+import com.google.inject.Singleton;
|
|
+
|
|
+import java.net.MalformedURLException;
|
|
+import java.net.URL;
|
|
+import java.util.Optional;
|
|
+import java.util.regex.Matcher;
|
|
+import java.util.regex.Pattern;
|
|
+
|
|
+@Singleton
|
|
+public class TitleComputer {
|
|
+ private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
|
+
|
|
+ @Inject
|
|
+ public TitleComputer(Provider<ChangesCollection> changes) {
|
|
+ this.changes = changes;
|
|
+ }
|
|
+
|
|
+ public Optional<String> computeTitle(String requestedURI) {
|
|
+ URL url = null;
|
|
+ try {
|
|
+ url = new URL(requestedURI);
|
|
+ } catch (MalformedURLException e) {
|
|
+ logger.atWarning().log("Failed to turn %s into a URL.", requestedURI);
|
|
+ return Optional.empty();
|
|
+ }
|
|
+
|
|
+ // Try to turn this into a change.
|
|
+ Optional<Change.Id> changeId = tryExtractChange(url.getPath());
|
|
+ if (changeId.isPresent()) {
|
|
+ return titleFromChangeId(changeId.get());
|
|
+ }
|
|
+
|
|
+ return Optional.empty();
|
|
+ }
|
|
+
|
|
+ private static final Pattern extractChangeIdRegex = Pattern.compile("^/(?:c/.*/\\+/)?(?<changeId>[0-9]+)(?:/[0-9]+)?(?:/.*)?$");
|
|
+ private final Provider<ChangesCollection> changes;
|
|
+
|
|
+ private Optional<Change.Id> tryExtractChange(String path) {
|
|
+ Matcher m = extractChangeIdRegex.matcher(path);
|
|
+ if (!m.matches()) {
|
|
+ return Optional.empty();
|
|
+ }
|
|
+ return Change.Id.tryParse(m.group("changeId"));
|
|
+ }
|
|
+
|
|
+ private Optional<String> titleFromChangeId(Change.Id changeId) {
|
|
+ ChangesCollection changesCollection = changes.get();
|
|
+ try {
|
|
+ ChangeResource changeResource = changesCollection.parse(changeId);
|
|
+ return Optional.of(changeResource.getChange().getSubject());
|
|
+ } catch (ResourceConflictException | ResourceNotFoundException | PermissionBackendException e) {
|
|
+ return Optional.empty();
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/resources/com/google/gerrit/httpd/raw/PolyGerritIndexHtml.soy b/resources/com/google/gerrit/httpd/raw/PolyGerritIndexHtml.soy
|
|
index 5ff1822cd9..81c3cdf0e1 100644
|
|
--- a/resources/com/google/gerrit/httpd/raw/PolyGerritIndexHtml.soy
|
|
+++ b/resources/com/google/gerrit/httpd/raw/PolyGerritIndexHtml.soy
|
|
@@ -33,10 +33,12 @@
|
|
{@param? defaultDashboardHex: ?}
|
|
{@param? dashboardQuery: ?}
|
|
{@param? userIsAuthenticated: ?}
|
|
+ {@param? title: ?}
|
|
<!DOCTYPE html>{\n}
|
|
<html lang="en">{\n}
|
|
<meta charset="utf-8">{\n}
|
|
- <meta name="description" content="Gerrit Code Review">{\n}
|
|
+ {if $title}<title>{$title} · Gerrit Code Review</title>{\n}{/if}
|
|
+ <meta name="description" content="{if $title}{$title} · {/if}Gerrit Code Review">{\n}
|
|
<meta name="referrer" content="never">{\n}
|
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0">{\n}
|
|
|
|
--
|
|
2.45.1
|
|
|