Merge branch 'stable'

* stable:
  Support different color pallete when not signed in
  Send new patchset event after its available
  Enable git:// download URLs if canonicalGitUrl set
  Fix NPE on Gerrit startup if mail.from doesn't include a name
  Add config setting to only suggest users which are in a visible group

Change-Id: I2bc9ca40e616c7f7b0c12de41f631c916439289c
diff --git a/Documentation/config-gerrit.txt b/Documentation/config-gerrit.txt
index 09b3f50..b288c89 100644
--- a/Documentation/config-gerrit.txt
+++ b/Documentation/config-gerrit.txt
@@ -1779,6 +1779,9 @@
 If `SAME_GROUP`, only users who are also members of a group the
 current user is a member of will be offered.
 +
+If `VISIBLE_GROUP`, only users who are members of at least one group
+that is visible to the current user will be offered.
++
 If `OFF`, no account suggestions are given.
 +
 Default is `ALL`.
@@ -1792,7 +1795,8 @@
 open changes table or the account dashboard. The value must be a
 valid HTML hex color code, or standard color name.
 +
-By default white, `FFFFFF`.
+By default white, `FFFFFF` for signed-out theme and `FCFEEF` (creme)
+for signed-in theme.
 
 [[theme.topMenuColor]]theme.topMenuColor::
 +
@@ -1827,6 +1831,19 @@
 +
 By default a shade of yellow, `FFFFCC`.
 
+A different theme may be used for signed-in vs. signed-out user status
+by using the "signed-in" and "signed-out" theme sections. Variables
+not specified in a section are inherited from the default theme.
+
+----
+[theme]
+  backgroundColor = FFFFFF
+[theme "signed-in"]
+  backgroundColor = C0C0C0
+[theme "signed-out"]
+  backgroundColor = 00FFFF
+----
+
 [[trackingid]] Section trackingid
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/GerritConfig.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/GerritConfig.java
index 2e6be7e..9bb87ab 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/GerritConfig.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/GerritConfig.java
@@ -42,12 +42,6 @@
   protected List<RegexFindReplace> commentLinks;
   protected boolean documentationAvailable;
 
-  protected String backgroundColor;
-  protected String topMenuColor;
-  protected String textColor;
-  protected String trimColor;
-  protected String selectionColor;
-
   public String getRegisterUrl() {
     return registerUrl;
   }
@@ -166,44 +160,4 @@
   public void setDocumentationAvailable(final boolean available) {
     documentationAvailable = available;
   }
-
-  public String getBackgroundColor() {
-    return backgroundColor;
-  }
-
-  public void setBackgroundColor(String color) {
-    backgroundColor = color;
-  }
-
-  public String getTopMenuColor() {
-    return topMenuColor;
-  }
-
-  public void setTopMenuColor(String color) {
-    topMenuColor = color;
-  }
-
-  public String getTextColor() {
-    return textColor;
-  }
-
-  public void setTextColor(String color) {
-    textColor = color;
-  }
-
-  public String getTrimColor() {
-    return trimColor;
-  }
-
-  public void setTrimColor(String color) {
-    trimColor = color;
-  }
-
-  public String getSelectionColor() {
-    return selectionColor;
-  }
-
-  public void setSelectionColor(String color) {
-    selectionColor = color;
-  }
 }
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/HostPageData.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/HostPageData.java
index 717a492..66b0c3b 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/HostPageData.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/HostPageData.java
@@ -22,4 +22,13 @@
   public Account account;
   public AccountDiffPreference accountDiffPref;
   public GerritConfig config;
+  public Theme theme;
+
+  public static class Theme {
+    public String backgroundColor;
+    public String topMenuColor;
+    public String textColor;
+    public String trimColor;
+    public String selectionColor;
+  }
 }
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/errors/NoSuchGroupException.java b/gerrit-common/src/main/java/com/google/gerrit/common/errors/NoSuchGroupException.java
index 4e117b1..179bc3a 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/errors/NoSuchGroupException.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/errors/NoSuchGroupException.java
@@ -26,10 +26,18 @@
     this(key, null);
   }
 
+  public NoSuchGroupException(final AccountGroup.UUID key) {
+    this(key, null);
+  }
+
   public NoSuchGroupException(final AccountGroup.Id key, final Throwable why) {
     super(MESSAGE + key.toString(), why);
   }
 
+  public NoSuchGroupException(final AccountGroup.UUID key, final Throwable why) {
+    super(MESSAGE + key.toString(), why);
+  }
+
   public NoSuchGroupException(final AccountGroup.NameKey k) {
     this(k, null);
   }
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java
index c2afb84..d0e5192 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java
@@ -72,6 +72,7 @@
 
   private static String myHost;
   private static GerritConfig myConfig;
+  private static HostPageData.Theme myTheme;
   private static Account myAccount;
   private static AccountDiffPreference myAccountDiffPref;
 
@@ -183,6 +184,11 @@
     return myConfig;
   }
 
+  /** Site theme information (site specific colors)/ */
+  public static HostPageData.Theme getTheme() {
+    return myTheme;
+  }
+
   /** @return the currently signed in user's account data; null if no account */
   public static Account getUserAccount() {
     return myAccount;
@@ -264,6 +270,7 @@
     hpd.load(new GerritCallback<HostPageData>() {
       public void onSuccess(final HostPageData result) {
         myConfig = result.config;
+        myTheme = result.theme;
         if (result.account != null) {
           myAccount = result.account;
         }
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AccessSectionEditor.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AccessSectionEditor.ui.xml
index 541ffc3..fdae4ed 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AccessSectionEditor.ui.xml
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AccessSectionEditor.ui.xml
@@ -25,8 +25,8 @@
   >
 <ui:with field='res' type='com.google.gerrit.client.admin.AdminResources'/>
 <ui:style>
-  @eval selectionColor com.google.gerrit.client.Gerrit.getConfig().getSelectionColor();
-  @eval trimColor com.google.gerrit.client.Gerrit.getConfig().getTrimColor();
+  @eval selectionColor com.google.gerrit.client.Gerrit.getTheme().selectionColor;
+  @eval trimColor com.google.gerrit.client.Gerrit.getTheme().trimColor;
 
   .panel {
     position: relative;
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/PermissionEditor.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/PermissionEditor.ui.xml
index 35a6dc0..25995d9 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/PermissionEditor.ui.xml
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/PermissionEditor.ui.xml
@@ -25,8 +25,8 @@
   >
 <ui:with field='res' type='com.google.gerrit.client.admin.AdminResources'/>
 <ui:style>
-  @eval selectionColor com.google.gerrit.client.Gerrit.getConfig().getSelectionColor();
-  @eval backgroundColor com.google.gerrit.client.Gerrit.getConfig().getBackgroundColor();
+  @eval selectionColor com.google.gerrit.client.Gerrit.getTheme().selectionColor;
+  @eval backgroundColor com.google.gerrit.client.Gerrit.getTheme().backgroundColor;
 
   .panel {
     position: relative;
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/PermissionRuleEditor.ui.xml b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/PermissionRuleEditor.ui.xml
index 7524bde..447c99f 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/PermissionRuleEditor.ui.xml
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/PermissionRuleEditor.ui.xml
@@ -26,7 +26,7 @@
   >
 <ui:with field='res' type='com.google.gerrit.client.admin.AdminResources'/>
 <ui:style>
-  @eval selectionColor com.google.gerrit.client.Gerrit.getConfig().getSelectionColor();
+  @eval selectionColor com.google.gerrit.client.Gerrit.getTheme().selectionColor;
 
   .panel {
     position: relative;
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/admin.css b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/admin.css
index 2570b2c..eca4823 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/admin.css
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/admin.css
@@ -13,8 +13,8 @@
  * limitations under the License.
  */
 
-@eval selectionColor com.google.gerrit.client.Gerrit.getConfig().getSelectionColor();
-@eval textColor com.google.gerrit.client.Gerrit.getConfig().getTextColor();
+@eval selectionColor com.google.gerrit.client.Gerrit.getTheme().selectionColor;
+@eval textColor com.google.gerrit.client.Gerrit.getTheme().textColor;
 @def deletedBackground #a9a9a9;
 
 @sprite .deleteIcon {
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PatchSetComplexDisclosurePanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PatchSetComplexDisclosurePanel.java
index 4561208..4caf8f8 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PatchSetComplexDisclosurePanel.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PatchSetComplexDisclosurePanel.java
@@ -189,7 +189,8 @@
 
     if (changeDetail.isAllowsAnonymous()
         && Gerrit.getConfig().getGitDaemonUrl() != null
-        && allowedSchemes.contains(DownloadScheme.ANON_GIT)) {
+        && (allowedSchemes.contains(DownloadScheme.ANON_GIT) ||
+            allowedSchemes.contains(DownloadScheme.DEFAULT_DOWNLOADS))) {
       StringBuilder r = new StringBuilder();
       r.append(Gerrit.getConfig().getGitDaemonUrl());
       r.append(projectName);
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/gerrit.css b/gerrit-gwtui/src/main/java/com/google/gerrit/client/gerrit.css
index c81920d..a281393 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/gerrit.css
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/gerrit.css
@@ -38,11 +38,11 @@
 @def norm-font  Arial Unicode MS, Arial, sans-serif;
 @def mono-font 'Lucida Console', 'Lucida Sans Typewriter', Monaco, monospace;
 
-@eval backgroundColor com.google.gerrit.client.Gerrit.getConfig().getBackgroundColor();
-@eval topMenuColor com.google.gerrit.client.Gerrit.getConfig().getTopMenuColor();
-@eval textColor com.google.gerrit.client.Gerrit.getConfig().getTextColor();;
-@eval trimColor com.google.gerrit.client.Gerrit.getConfig().getTrimColor();
-@eval selectionColor com.google.gerrit.client.Gerrit.getConfig().getSelectionColor();
+@eval backgroundColor com.google.gerrit.client.Gerrit.getTheme().backgroundColor;
+@eval topMenuColor com.google.gerrit.client.Gerrit.getTheme().topMenuColor;
+@eval textColor com.google.gerrit.client.Gerrit.getTheme().textColor;
+@eval trimColor com.google.gerrit.client.Gerrit.getTheme().trimColor;
+@eval selectionColor com.google.gerrit.client.Gerrit.getTheme().selectionColor;
 
 
 @sprite .greenCheckClass {
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/gwt_override.css b/gerrit-gwtui/src/main/java/com/google/gerrit/client/gwt_override.css
index b238292..ed0b32c 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/gwt_override.css
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/gwt_override.css
@@ -23,10 +23,10 @@
 @external .gwt-TabPanel;
 @external .gwt-TabPanelBottom;
 
-@eval backgroundColor com.google.gerrit.client.Gerrit.getConfig().getBackgroundColor();
-@eval textColor com.google.gerrit.client.Gerrit.getConfig().getTextColor();;
-@eval trimColor com.google.gerrit.client.Gerrit.getConfig().getTrimColor();
-@eval selectionColor com.google.gerrit.client.Gerrit.getConfig().getSelectionColor();
+@eval backgroundColor com.google.gerrit.client.Gerrit.getTheme().backgroundColor;
+@eval textColor com.google.gerrit.client.Gerrit.getTheme().textColor;
+@eval trimColor com.google.gerrit.client.Gerrit.getTheme().trimColor;
+@eval selectionColor com.google.gerrit.client.Gerrit.getTheme().selectionColor;
 
 body {
   background: backgroundColor;
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GerritConfigProvider.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GerritConfigProvider.java
index e51731d..dd2ef69 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GerritConfigProvider.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GerritConfigProvider.java
@@ -149,28 +149,9 @@
     }
     config.setCommentLinks(links);
 
-    config.setBackgroundColor(getThemeColor("backgroundColor", "#FFFFFF"));
-    config.setTextColor(getThemeColor("textColor", "#000000"));
-    config.setTrimColor(getThemeColor("trimColor", "#D4E9A9"));
-    config.setSelectionColor(getThemeColor("selectionColor", "#FFFFCC"));
-
-    config
-        .setTopMenuColor(getThemeColor("topMenuColor", config.getTrimColor()));
-
     return config;
   }
 
-  private String getThemeColor(String name, String defaultValue) {
-    String v = cfg.getString("theme", null, name);
-    if (v == null || v.isEmpty()) {
-      v = defaultValue;
-    }
-    if (!v.startsWith("#") && v.matches("^[0-9a-fA-F]{2,6}$")) {
-      v = "#" + v;
-    }
-    return v;
-  }
-
   @Override
   public GerritConfig get() {
     try {
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/HostPageServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/HostPageServlet.java
index 4521348..1c2e5b8 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/HostPageServlet.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/HostPageServlet.java
@@ -62,6 +62,8 @@
 
   private final Provider<CurrentUser> currentUser;
   private final GerritConfig config;
+  private final HostPageData.Theme signedOutTheme;
+  private final HostPageData.Theme signedInTheme;
   private final SitePaths site;
   private final Document template;
   private final String noCacheName;
@@ -70,10 +72,12 @@
 
   @Inject
   HostPageServlet(final Provider<CurrentUser> cu, final SitePaths sp,
-      final GerritConfig gc, final ServletContext servletContext)
-      throws IOException, ServletException {
+      final ThemeFactory themeFactory, final GerritConfig gc,
+      final ServletContext servletContext) throws IOException, ServletException {
     currentUser = cu;
     config = gc;
+    signedOutTheme = themeFactory.getSignedOutTheme();
+    signedInTheme = themeFactory.getSignedInTheme();
     site = sp;
 
     final String pageName = "HostPage.html";
@@ -158,12 +162,16 @@
       w.write(HPD_ID + ".account=");
       json(((IdentifiedUser) user).getAccount(), w);
       w.write(";");
+
       w.write(HPD_ID + ".accountDiffPref=");
       json(((IdentifiedUser) user).getAccountDiffPreference(), w);
       w.write(";");
 
-      final byte[] userData = w.toString().getBytes("UTF-8");
+      w.write(HPD_ID + ".theme=");
+      json(signedInTheme, w);
+      w.write(";");
 
+      final byte[] userData = w.toString().getBytes("UTF-8");
       raw = concat(page.part1, userData, page.part2);
     } else {
       raw = page.full;
@@ -303,7 +311,14 @@
         }
         part1 = raw.substring(0, p).getBytes("UTF-8");
         part2 = raw.substring(raw.indexOf('>', p) + 1).getBytes("UTF-8");
-        full = concat(part1, part2, new byte[0]);
+
+        final StringWriter w = new StringWriter();
+        w.write(HPD_ID + ".theme=");
+        json(signedOutTheme, w);
+        w.write(";");
+
+        final byte[] themeData = w.toString().getBytes("UTF-8");
+        full = concat(part1, themeData, part2);
         full_gz = HtmlDomUtil.compress(full);
       }
     }
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/ThemeFactory.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/ThemeFactory.java
new file mode 100644
index 0000000..a1e09f9
--- /dev/null
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/ThemeFactory.java
@@ -0,0 +1,66 @@
+// Copyright (C) 2011 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 com.google.gerrit.common.data.HostPageData;
+import com.google.gerrit.server.config.GerritServerConfig;
+import com.google.inject.Inject;
+
+import org.eclipse.jgit.lib.Config;
+
+class ThemeFactory {
+  private final Config cfg;
+
+  @Inject
+  ThemeFactory(@GerritServerConfig Config cfg) {
+    this.cfg = cfg;
+  }
+
+  HostPageData.Theme getSignedOutTheme() {
+    return getTheme("signed-out");
+  }
+
+  HostPageData.Theme getSignedInTheme() {
+    return getTheme("signed-in");
+  }
+
+  private HostPageData.Theme getTheme(String name) {
+    HostPageData.Theme theme = new HostPageData.Theme();
+    theme.backgroundColor = color(name, "backgroundColor", "#FFFFFF");
+    theme.textColor = color(name, "textColor", "#000000");
+    theme.trimColor = color(name, "trimColor", "#D4E9A9");
+    theme.selectionColor = color(name, "selectionColor", "#FFFFCC");
+    theme.topMenuColor = color(name, "topMenuColor", theme.trimColor);
+    return theme;
+  }
+
+  private String color(String section, String name, String defaultValue) {
+    String v = cfg.getString("theme", section, name);
+    if (v == null || v.isEmpty()) {
+      v = cfg.getString("theme", null, name);
+      if (v == null || v.isEmpty()) {
+        if ("signed-in".equals(section) && "backgroundColor".equals(name)) {
+          v = "#FCFEEF";
+        } else {
+          v = defaultValue;
+        }
+      }
+    }
+    if (!v.startsWith("#") && v.matches("^[0-9a-fA-F]{2,6}$")) {
+      v = "#" + v;
+    }
+    return v;
+  }
+}
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/SuggestAccountsEnum.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/SuggestAccountsEnum.java
index 0cd21ef..2ef2d44 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/SuggestAccountsEnum.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/SuggestAccountsEnum.java
@@ -17,5 +17,6 @@
 public enum SuggestAccountsEnum {
   ALL,
   SAME_GROUP,
+  VISIBLE_GROUP,
   OFF;
 }
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/SuggestServiceImpl.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/SuggestServiceImpl.java
index 6dc3623..adc48f8 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/SuggestServiceImpl.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/SuggestServiceImpl.java
@@ -174,6 +174,23 @@
         }
         break;
       }
+      case VISIBLE_GROUP: {
+        Set<AccountGroup.UUID> usersGroups = groupsOf(account);
+        usersGroups.remove(AccountGroup.ANONYMOUS_USERS);
+        usersGroups.remove(AccountGroup.REGISTERED_USERS);
+        usersGroups.remove(authConfig.getBatchUsersGroup());
+        for (AccountGroup.UUID usersGroup : usersGroups) {
+          try {
+            if (groupControlFactory.controlFor(usersGroup).isVisible()) {
+              map.put(account.getId(), info);
+              break;
+            }
+          } catch (NoSuchGroupException e) {
+            continue;
+          }
+        }
+        break;
+      }
       case OFF:
         break;
       default:
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupControl.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupControl.java
index 602b593..96c8df9 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupControl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupControl.java
@@ -42,6 +42,15 @@
       return new GroupControl(user.get(), group);
     }
 
+    public GroupControl controlFor(final AccountGroup.UUID groupId)
+        throws NoSuchGroupException {
+      final AccountGroup group = groupCache.get(groupId);
+      if (group == null) {
+        throw new NoSuchGroupException(groupId);
+      }
+      return new GroupControl(user.get(), group);
+    }
+
     public GroupControl controlFor(final AccountGroup group) {
       return new GroupControl(user.get(), group);
     }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java
index 724d11f..97ad546 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java
@@ -1435,8 +1435,6 @@
           insertDummyApproval(result, reviewer, catId, db);
         }
       }
-
-      hooks.doPatchsetCreatedHook(result.change, ps);
     }
 
     final RefUpdate ru = repo.updateRef(ps.getRefName());
@@ -1447,6 +1445,7 @@
           + repo.getDirectory() + ": " + ru.getResult());
     }
     replication.scheduleUpdate(project.getNameKey(), ru.getName());
+    hooks.doPatchsetCreatedHook(result.change, ps);
     request.cmd.setResult(ReceiveCommand.Result.OK);
 
     try {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/mail/FromAddressGeneratorProvider.java b/gerrit-server/src/main/java/com/google/gerrit/server/mail/FromAddressGeneratorProvider.java
index 2d739ea..afcfccd 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/mail/FromAddressGeneratorProvider.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/mail/FromAddressGeneratorProvider.java
@@ -52,8 +52,8 @@
 
     } else {
       final Address a = Address.parse(from);
-      final ParamertizedString name = new ParamertizedString(a.name);
-      if (name.getParameterNames().isEmpty()) {
+      final ParamertizedString name = a.name != null ? new ParamertizedString(a.name) : null;
+      if (name == null || name.getParameterNames().isEmpty()) {
         generator = new ServerGen(a);
       } else {
         generator = new PatternGen(srvAddr, accountCache, name, a.email);