Merge "Disable submit button if merge will fail"
diff --git a/Documentation/config-gerrit.txt b/Documentation/config-gerrit.txt
index 79373b0..6f93920 100644
--- a/Documentation/config-gerrit.txt
+++ b/Documentation/config-gerrit.txt
@@ -1973,7 +1973,9 @@
 [[trackingid.name.footer]]trackingid.<name>.footer::
 +
 A prefix tag that identify the footer line to parse for tracking ids.
-Several trakingid entries can have the same footer tag.
+Several trackingid entries can have the same footer tag. A single
+trackingid entry can have multiple footer tags. If multiple footer
+tags are specified, each tag will be parsed separately.
 (the trailing ":" is optional)
 
 [[trackingid.name.match]]trackingid.<name>.match::
diff --git a/Documentation/config-replication.txt b/Documentation/config-replication.txt
index d8390e6..3768b6d 100644
--- a/Documentation/config-replication.txt
+++ b/Documentation/config-replication.txt
@@ -201,6 +201,14 @@
 +
 By default, true, replicating everything.
 
+[[remote.name.mirror]]remote.<name>.mirror::
++
+If true, replication will remove remote branches that absent locally
+or invisible to the replication (i.e. read access denied via 'authGroup'
+option).
++
+By default, false, do not remove remote branches.
+
 
 [[secure_config]]File `secure.config`
 -----------------------------------------------
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/AccountSecurity.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/AccountSecurity.java
index 1117455..0b76558 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/AccountSecurity.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/AccountSecurity.java
@@ -72,7 +72,7 @@
       AsyncCallback<VoidResult> callback);
 
   @SignInRequired
-  void registerEmail(String address, AsyncCallback<VoidResult> callback);
+  void registerEmail(String address, AsyncCallback<Account> callback);
 
   @SignInRequired
   void validateEmail(String token, AsyncCallback<VoidResult> callback);
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/ParameterizedString.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/ParameterizedString.java
index f9b0dad..68676cf 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/ParameterizedString.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/ParameterizedString.java
@@ -63,20 +63,27 @@
       ops.add(new Constant(pattern.substring(i, b)));
 
       String expr = pattern.substring(b + 2, e);
-      Function function;
-      int lastDot = expr.lastIndexOf('.');
-      if (lastDot < 0) {
-        function = NOOP;
+      String parameterName = "";
+      List<Function> functions = new ArrayList<Function>();
+      if (!expr.contains(".")) {
+        parameterName = expr;
       } else {
-        function = FUNCTIONS.get(expr.substring(lastDot + 1));
-        if (function == null) {
-          function = NOOP;
-        } else {
-          expr = expr.substring(0, lastDot);
+        int firstDot = expr.indexOf('.');
+        parameterName = expr.substring(0, firstDot);
+        String actionsStr = expr.substring(firstDot + 1);
+        String[] actions = actionsStr.split("\\.");
+
+        for (String action : actions) {
+          Function function = FUNCTIONS.get(action);
+          if (function == null) {
+            function = NOOP;
+          }
+          functions.add(function);
         }
       }
 
-      final Parameter p = new Parameter(expr, function);
+      final Parameter p =
+          new Parameter(parameterName, Collections.unmodifiableList(functions));
       raw.append("{" + prs.size() + "}");
       prs.add(p);
       ops.add(p);
@@ -175,11 +182,11 @@
 
   private static class Parameter extends Format {
     private final String name;
-    private final Function function;
+    private final List<Function> functions;
 
-    Parameter(final String name, final Function function) {
+    Parameter(final String name, final List<Function> functions) {
       this.name = name;
-      this.function = function;
+      this.functions = functions;
     }
 
     @Override
@@ -188,7 +195,10 @@
       if (v == null) {
         v = "";
       }
-      b.append(function.apply(v));
+      for (Function function : functions) {
+        v = function.apply(v);
+      }
+      b.append(v);
     }
   }
 
diff --git a/gerrit-common/src/test/java/com/google/gerrit/common/data/ParameterizedStringTest.java b/gerrit-common/src/test/java/com/google/gerrit/common/data/ParameterizedStringTest.java
index 4fe3365..a2d1279 100644
--- a/gerrit-common/src/test/java/com/google/gerrit/common/data/ParameterizedStringTest.java
+++ b/gerrit-common/src/test/java/com/google/gerrit/common/data/ParameterizedStringTest.java
@@ -165,8 +165,210 @@
   }
 
   public void testUndefinedFunctionName() {
-    ParameterizedString p = new ParameterizedString("${a.anUndefinedMethod}");
+    ParameterizedString p =
+        new ParameterizedString(
+            "hi, ${userName.toUpperCase},your eamil address is '${email.toLowerCase.localPart}'.right?");
+    assertEquals(2, p.getParameterNames().size());
+    assertTrue(p.getParameterNames().contains("userName"));
+    assertTrue(p.getParameterNames().contains("email"));
+
+    final Map<String, String> a = new HashMap<String, String>();
+    a.put("userName", "firstName lastName");
+    a.put("email", "FIRSTNAME.LASTNAME@EXAMPLE.COM");
+    assertNotNull(p.bind(a));
+    assertEquals(2, p.bind(a).length);
+
+    assertEquals("FIRSTNAME LASTNAME", p.bind(a)[0]);
+    assertEquals("firstname.lastname", p.bind(a)[1]);
+    assertEquals("hi, FIRSTNAME LASTNAME,your eamil address is 'firstname.lastname'.right?", p.replace(a));
+  }
+
+  public void testReplaceToUpperCaseToLowerCase() {
+    final ParameterizedString p =
+        new ParameterizedString("${a.toUpperCase.toLowerCase}");
     assertEquals(1, p.getParameterNames().size());
-    assertTrue(p.getParameterNames().contains("a.anUndefinedMethod"));
+    assertTrue(p.getParameterNames().contains("a"));
+
+    final Map<String, String> a = new HashMap<String, String>();
+
+    a.put("a", "FOO@EXAMPLE.COM");
+    assertNotNull(p.bind(a));
+    assertEquals(1, p.bind(a).length);
+    assertEquals("foo@example.com", p.bind(a)[0]);
+    assertEquals("foo@example.com", p.replace(a));
+
+    a.put("a", "foo@example.com");
+    assertNotNull(p.bind(a));
+    assertEquals(1, p.bind(a).length);
+    assertEquals("foo@example.com", p.bind(a)[0]);
+    assertEquals("foo@example.com", p.replace(a));
+  }
+
+  public void testReplaceToUpperCaseLocalName() {
+    final ParameterizedString p =
+        new ParameterizedString("${a.toUpperCase.localPart}");
+    assertEquals(1, p.getParameterNames().size());
+    assertTrue(p.getParameterNames().contains("a"));
+
+    final Map<String, String> a = new HashMap<String, String>();
+
+    a.put("a", "foo@example.com");
+    assertNotNull(p.bind(a));
+    assertEquals(1, p.bind(a).length);
+    assertEquals("FOO", p.bind(a)[0]);
+    assertEquals("FOO", p.replace(a));
+
+    a.put("a", "FOO@EXAMPLE.COM");
+    assertNotNull(p.bind(a));
+    assertEquals(1, p.bind(a).length);
+    assertEquals("FOO", p.bind(a)[0]);
+    assertEquals("FOO", p.replace(a));
+  }
+
+  public void testReplaceToUpperCaseAnUndefinedMethod() {
+    final ParameterizedString p =
+        new ParameterizedString("${a.toUpperCase.anUndefinedMethod}");
+    assertEquals(1, p.getParameterNames().size());
+    assertTrue(p.getParameterNames().contains("a"));
+
+    final Map<String, String> a = new HashMap<String, String>();
+
+    a.put("a", "foo@example.com");
+    assertNotNull(p.bind(a));
+    assertEquals(1, p.bind(a).length);
+    assertEquals("FOO@EXAMPLE.COM", p.bind(a)[0]);
+    assertEquals("FOO@EXAMPLE.COM", p.replace(a));
+
+    a.put("a", "FOO@EXAMPLE.COM");
+    assertNotNull(p.bind(a));
+    assertEquals(1, p.bind(a).length);
+    assertEquals("FOO@EXAMPLE.COM", p.bind(a)[0]);
+    assertEquals("FOO@EXAMPLE.COM", p.replace(a));
+  }
+
+  public void testReplaceLocalNameToUpperCase() {
+    final ParameterizedString p =
+        new ParameterizedString("${a.localPart.toUpperCase}");
+    assertEquals(1, p.getParameterNames().size());
+    assertTrue(p.getParameterNames().contains("a"));
+
+    final Map<String, String> a = new HashMap<String, String>();
+
+    a.put("a", "foo@example.com");
+    assertNotNull(p.bind(a));
+    assertEquals(1, p.bind(a).length);
+    assertEquals("FOO", p.bind(a)[0]);
+    assertEquals("FOO", p.replace(a));
+
+    a.put("a", "FOO@EXAMPLE.COM");
+    assertNotNull(p.bind(a));
+    assertEquals(1, p.bind(a).length);
+    assertEquals("FOO", p.bind(a)[0]);
+    assertEquals("FOO", p.replace(a));
+  }
+
+  public void testReplaceLocalNameToLowerCase() {
+    final ParameterizedString p =
+        new ParameterizedString("${a.localPart.toLowerCase}");
+    assertEquals(1, p.getParameterNames().size());
+    assertTrue(p.getParameterNames().contains("a"));
+
+    final Map<String, String> a = new HashMap<String, String>();
+
+    a.put("a", "FOO@EXAMPLE.COM");
+    assertNotNull(p.bind(a));
+    assertEquals(1, p.bind(a).length);
+    assertEquals("foo", p.bind(a)[0]);
+    assertEquals("foo", p.replace(a));
+
+    a.put("a", "foo@example.com");
+    assertNotNull(p.bind(a));
+    assertEquals(1, p.bind(a).length);
+    assertEquals("foo", p.bind(a)[0]);
+    assertEquals("foo", p.replace(a));
+  }
+
+  public void testReplaceLocalNameAnUndefinedMethod() {
+    final ParameterizedString p =
+        new ParameterizedString("${a.localPart.anUndefinedMethod}");
+    assertEquals(1, p.getParameterNames().size());
+    assertTrue(p.getParameterNames().contains("a"));
+
+    final Map<String, String> a = new HashMap<String, String>();
+
+    a.put("a", "FOO@EXAMPLE.COM");
+    assertNotNull(p.bind(a));
+    assertEquals(1, p.bind(a).length);
+    assertEquals("FOO", p.bind(a)[0]);
+    assertEquals("FOO", p.replace(a));
+
+    a.put("a", "foo@example.com");
+    assertNotNull(p.bind(a));
+    assertEquals(1, p.bind(a).length);
+    assertEquals("foo", p.bind(a)[0]);
+    assertEquals("foo", p.replace(a));
+  }
+
+  public void testReplaceToLowerCaseToUpperCase() {
+    final ParameterizedString p =
+        new ParameterizedString("${a.toLowerCase.toUpperCase}");
+    assertEquals(1, p.getParameterNames().size());
+    assertTrue(p.getParameterNames().contains("a"));
+
+    final Map<String, String> a = new HashMap<String, String>();
+
+    a.put("a", "FOO@EXAMPLE.COM");
+    assertNotNull(p.bind(a));
+    assertEquals(1, p.bind(a).length);
+    assertEquals("FOO@EXAMPLE.COM", p.bind(a)[0]);
+    assertEquals("FOO@EXAMPLE.COM", p.replace(a));
+
+    a.put("a", "foo@example.com");
+    assertNotNull(p.bind(a));
+    assertEquals(1, p.bind(a).length);
+    assertEquals("FOO@EXAMPLE.COM", p.bind(a)[0]);
+    assertEquals("FOO@EXAMPLE.COM", p.replace(a));
+  }
+
+  public void testReplaceToLowerCaseLocalName() {
+    final ParameterizedString p =
+        new ParameterizedString("${a.toLowerCase.localPart}");
+    assertEquals(1, p.getParameterNames().size());
+    assertTrue(p.getParameterNames().contains("a"));
+
+    final Map<String, String> a = new HashMap<String, String>();
+
+    a.put("a", "FOO@EXAMPLE.COM");
+    assertNotNull(p.bind(a));
+    assertEquals(1, p.bind(a).length);
+    assertEquals("foo", p.bind(a)[0]);
+    assertEquals("foo", p.replace(a));
+
+    a.put("a", "foo@example.com");
+    assertNotNull(p.bind(a));
+    assertEquals(1, p.bind(a).length);
+    assertEquals("foo", p.bind(a)[0]);
+    assertEquals("foo", p.replace(a));
+  }
+
+  public void testReplaceToLowerCaseAnUndefinedMethod() {
+    final ParameterizedString p =
+        new ParameterizedString("${a.toLowerCase.anUndefinedMethod}");
+    assertEquals(1, p.getParameterNames().size());
+    assertTrue(p.getParameterNames().contains("a"));
+
+    final Map<String, String> a = new HashMap<String, String>();
+
+    a.put("a", "foo@example.com");
+    assertNotNull(p.bind(a));
+    assertEquals(1, p.bind(a).length);
+    assertEquals("foo@example.com", p.bind(a)[0]);
+    assertEquals("foo@example.com", p.replace(a));
+
+    a.put("a", "FOO@EXAMPLE.COM");
+    assertNotNull(p.bind(a));
+    assertEquals(1, p.bind(a).length);
+    assertEquals("foo@example.com", p.bind(a)[0]);
+    assertEquals("foo@example.com", p.replace(a));
   }
 }
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountConstants.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountConstants.java
index 1d4aeca..53a2b58 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountConstants.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountConstants.java
@@ -57,6 +57,7 @@
   String buttonClearPassword();
   String buttonGeneratePassword();
   String invalidUserName();
+  String invalidUserEmail();
 
   String sshKeyInvalid();
   String sshKeyAlgorithm();
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountConstants.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountConstants.properties
index a1c96c7..ffc5218 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountConstants.properties
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountConstants.properties
@@ -38,7 +38,7 @@
 buttonClearPassword = Clear Password
 buttonGeneratePassword = Generate Password
 invalidUserName = Username must contain only letters, numbers, _, - or .
-
+invalidUserEmail = Email format is wrong.
 sshKeyInvalid = Invalid Key
 sshKeyAlgorithm = Algorithm
 sshKeyKey = Key
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/ContactPanelShort.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/ContactPanelShort.java
index 8fe4d5f..aa179ab 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/ContactPanelShort.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/ContactPanelShort.java
@@ -14,6 +14,7 @@
 
 package com.google.gerrit.client.account;
 
+import com.google.gerrit.client.ErrorDialog;
 import com.google.gerrit.client.Gerrit;
 import com.google.gerrit.client.rpc.GerritCallback;
 import com.google.gerrit.client.ui.OnEditEnabler;
@@ -21,6 +22,7 @@
 import com.google.gerrit.reviewdb.AccountExternalId;
 import com.google.gerrit.reviewdb.ContactInformation;
 import com.google.gerrit.reviewdb.Account.FieldName;
+import com.google.gerrit.reviewdb.AuthType;
 import com.google.gwt.event.dom.client.ChangeEvent;
 import com.google.gwt.event.dom.client.ChangeHandler;
 import com.google.gwt.event.dom.client.ClickEvent;
@@ -38,7 +40,6 @@
 import com.google.gwt.user.client.ui.FormPanel.SubmitEvent;
 import com.google.gwtexpui.globalkey.client.NpTextBox;
 import com.google.gwtexpui.user.client.AutoCenterDialogBox;
-import com.google.gwtjsonrpc.client.VoidResult;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -205,30 +206,7 @@
 
   private void postLoad() {
     if (haveAccount && haveEmails) {
-      if (currentEmail != null) {
-        boolean found = false;
-        for (int i = 0; i < emailPick.getItemCount(); i++) {
-          if (currentEmail.equals(emailPick.getValue(i))) {
-            emailPick.setSelectedIndex(i);
-            found = true;
-            break;
-          }
-        }
-        if (!found) {
-          emailPick.addItem(currentEmail);
-          emailPick.setSelectedIndex(emailPick.getItemCount() - 1);
-        }
-      }
-      if (emailPick.getItemCount() > 0) {
-        emailPick.setVisible(true);
-        emailPick.setEnabled(true);
-        if (canRegisterNewEmail()) {
-          final String t = Util.C.buttonOpenRegisterNewEmail();
-          emailPick.addItem("... " + t + "  ", t);
-        }
-      } else {
-        emailPick.setVisible(false);
-      }
+      updateEmailList();
       registerNewEmail.setEnabled(true);
     }
     display();
@@ -270,14 +248,24 @@
         event.cancel();
         final String addr = inEmail.getText().trim();
         if (!addr.contains("@")) {
+          new ErrorDialog(Util.C.invalidUserEmail()).center();
           return;
         }
 
         inEmail.setEnabled(false);
         register.setEnabled(false);
-        Util.ACCOUNT_SEC.registerEmail(addr, new GerritCallback<VoidResult>() {
-          public void onSuccess(VoidResult result) {
+        Util.ACCOUNT_SEC.registerEmail(addr, new GerritCallback<Account>() {
+          public void onSuccess(Account currentUser) {
             box.hide();
+            if (Gerrit.getConfig().getAuthType() == AuthType.DEVELOPMENT_BECOME_ANY_ACCOUNT) {
+              currentEmail = addr;
+              if (emailPick.getItemCount() == 0) {
+                onSaveSuccess(currentUser);
+              } else {
+                save.setEnabled(true);
+              }
+              updateEmailList();
+            }
           }
 
           @Override
@@ -309,7 +297,9 @@
     buttons.add(register);
     buttons.add(cancel);
 
-    body.add(new HTML(Util.C.descRegisterNewEmail()));
+    if (Gerrit.getConfig().getAuthType() != AuthType.DEVELOPMENT_BECOME_ANY_ACCOUNT) {
+      body.add(new HTML(Util.C.descRegisterNewEmail()));
+    }
     body.add(inEmail);
     body.add(buttons);
 
@@ -367,4 +357,39 @@
   ContactInformation toContactInformation() {
     return null;
   }
+
+  private int emailListIndexOf(String value) {
+    for (int i = 0; i < emailPick.getItemCount(); i++) {
+      if (value.equalsIgnoreCase(emailPick.getValue(i))) {
+        return i;
+      }
+    }
+    return -1;
+  }
+
+  private void updateEmailList() {
+    if (currentEmail != null) {
+      int index = emailListIndexOf(currentEmail);
+      if (index == -1) {
+        emailPick.addItem(currentEmail);
+        emailPick.setSelectedIndex(emailPick.getItemCount() - 1);
+      } else {
+        emailPick.setSelectedIndex(index);
+      }
+    }
+    if (emailPick.getItemCount() > 0) {
+      emailPick.setVisible(true);
+      emailPick.setEnabled(true);
+      if (canRegisterNewEmail()) {
+        final String t = Util.C.buttonOpenRegisterNewEmail();
+        int index = emailListIndexOf(t);
+        if (index != -1) {
+          emailPick.removeItem(index);
+        }
+        emailPick.addItem("... " + t + "  ", t);
+      }
+    } else {
+      emailPick.setVisible(false);
+    }
+  }
 }
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/AccountSecurityImpl.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/AccountSecurityImpl.java
index 77662a1..df71700 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/AccountSecurityImpl.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/AccountSecurityImpl.java
@@ -26,6 +26,7 @@
 import com.google.gerrit.reviewdb.AccountExternalId;
 import com.google.gerrit.reviewdb.AccountGroup;
 import com.google.gerrit.reviewdb.AccountSshKey;
+import com.google.gerrit.reviewdb.AuthType;
 import com.google.gerrit.reviewdb.ContactInformation;
 import com.google.gerrit.reviewdb.ContributorAgreement;
 import com.google.gerrit.reviewdb.ReviewDb;
@@ -270,18 +271,27 @@
   }
 
   public void registerEmail(final String address,
-      final AsyncCallback<VoidResult> cb) {
-    try {
-      final RegisterNewEmailSender sender;
-      sender = registerNewEmailFactory.create(address);
-      sender.send();
-      cb.onSuccess(VoidResult.INSTANCE);
-    } catch (EmailException e) {
-      log.error("Cannot send email verification message to " + address, e);
-      cb.onFailure(e);
-    } catch (RuntimeException e) {
-      log.error("Cannot send email verification message to " + address, e);
-      cb.onFailure(e);
+      final AsyncCallback<Account> cb) {
+    if (authConfig.getAuthType() == AuthType.DEVELOPMENT_BECOME_ANY_ACCOUNT) {
+      try {
+        accountManager.link(user.get().getAccountId(),
+            AuthRequest.forEmail(address));
+        cb.onSuccess(user.get().getAccount());
+      } catch (AccountException e) {
+        cb.onFailure(e);
+      }
+    } else {
+      try {
+        final RegisterNewEmailSender sender;
+        sender = registerNewEmailFactory.create(address);
+        sender.send();
+      } catch (EmailException e) {
+        log.error("Cannot send email verification message to " + address, e);
+        cb.onFailure(e);
+      } catch (RuntimeException e) {
+        log.error("Cannot send email verification message to " + address, e);
+        cb.onFailure(e);
+      }
     }
   }
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/PushOp.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/PushOp.java
index 5e13ade..4bff8eb 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/PushOp.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/PushOp.java
@@ -65,7 +65,7 @@
   }
 
   private static final Logger log = PushReplication.log;
-  static final String MIRROR_ALL = "..all..";
+  static final String ALL_REFS = "..all..";
 
   private final GitRepositoryManager repoManager;
   private final SchemaFactory<ReviewDb> schema;
@@ -77,7 +77,7 @@
   private final Set<String> delta = new HashSet<String>();
   private final Project.NameKey projectName;
   private final URIish uri;
-  private boolean mirror;
+  private boolean pushAllRefs;
 
   private Repository db;
 
@@ -125,10 +125,10 @@
   }
 
   void addRef(final String ref) {
-    if (MIRROR_ALL.equals(ref)) {
+    if (ALL_REFS.equals(ref)) {
       delta.clear();
-      mirror = true;
-    } else if (!mirror) {
+      pushAllRefs = true;
+    } else if (!pushAllRefs) {
       delta.add(ref);
     }
   }
@@ -136,9 +136,9 @@
   public Set<String> getRefs() {
     final Set<String> refs;
 
-    if (mirror) {
+    if (pushAllRefs) {
       refs = new HashSet<String>(1);
-      refs.add(MIRROR_ALL);
+      refs.add(ALL_REFS);
     } else {
       refs = delta;
     }
@@ -147,7 +147,7 @@
   }
 
   public void addRefs(Set<String> refs) {
-    if (!mirror) {
+    if (!pushAllRefs) {
       for (String ref : refs) {
         addRef(ref);
       }
@@ -216,7 +216,7 @@
 
   @Override
   public String toString() {
-    return (mirror ? "mirror " : "push ") + uri;
+    return "push " + uri;
   }
 
   private void runImpl() throws IOException {
@@ -292,7 +292,7 @@
 
     Map<String, Ref> local = db.getAllRefs();
     if (!pc.allRefsAreVisible()) {
-      if (!mirror) {
+      if (!pushAllRefs) {
         // If we aren't mirroring, reduce the space we need to filter
         // to only the references we will update during this operation.
         //
@@ -322,7 +322,7 @@
 
     final boolean noPerms = !pool.isReplicatePermissions();
     final List<RemoteRefUpdate> cmds = new ArrayList<RemoteRefUpdate>();
-    if (mirror) {
+    if (pushAllRefs) {
       final Map<String, Ref> remote = listRemote(tn);
 
       for (final Ref src : local.values()) {
@@ -341,17 +341,19 @@
         }
       }
 
-      for (final Ref ref : remote.values()) {
-        if (noPerms && GitRepositoryManager.REF_CONFIG.equals(ref.getName())) {
-          continue;
-        }
+      if (config.isMirror()) {
+        for (final Ref ref : remote.values()) {
+          if (noPerms && GitRepositoryManager.REF_CONFIG.equals(ref.getName())) {
+            continue;
+          }
 
-        if (!Constants.HEAD.equals(ref.getName())) {
-          final RefSpec spec = matchDst(ref.getName());
-          if (spec != null && !local.containsKey(spec.getSource())) {
-            // No longer on local side, request removal.
-            //
-            delete(cmds, spec);
+          if (!Constants.HEAD.equals(ref.getName())) {
+            final RefSpec spec = matchDst(ref.getName());
+            if (spec != null && !local.containsKey(spec.getSource())) {
+              // No longer on local side, request removal.
+              //
+              delete(cmds, spec);
+            }
           }
         }
       }
@@ -369,7 +371,7 @@
           Ref srcRef = local.get(src);
           if (srcRef != null) {
             send(cmds, spec, srcRef);
-          } else {
+          } else if (config.isMirror()) {
             delete(cmds, spec);
           }
         }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/PushReplication.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/PushReplication.java
index d89ad7d..a3d327a 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/PushReplication.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/PushReplication.java
@@ -114,7 +114,7 @@
       final String urlMatch) {
     for (final ReplicationConfig cfg : configs) {
       for (final URIish uri : cfg.getURIs(project, urlMatch)) {
-        cfg.schedule(project, PushOp.MIRROR_ALL, uri);
+        cfg.schedule(project, PushOp.ALL_REFS, uri);
       }
     }
   }