Merge "ChangeScreen2: Fix enter when setting topic"
diff --git a/gerrit-acceptance-tests/BUCK b/gerrit-acceptance-tests/BUCK
index 756450f..0fc7fbc 100644
--- a/gerrit-acceptance-tests/BUCK
+++ b/gerrit-acceptance-tests/BUCK
@@ -1,5 +1,3 @@
-include_defs('//gerrit-acceptance-tests/tests.defs')
-
 java_library(
   name = 'lib',
   srcs = glob(['src/test/java/com/google/gerrit/acceptance/*.java']),
@@ -42,3 +40,14 @@
     '//gerrit-acceptance-tests/...',
   ],
 )
+
+java_library(
+  name = 'configs',
+  resources = glob([
+    'src/test/resources/com/google/gerrit/acceptance/config/*.config',
+  ]),
+  visibility = [
+    '//tools/eclipse:classpath',
+    '//gerrit-acceptance-tests/...',
+  ],
+)
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/AbstractDaemonTest.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
index 8a06f15..0105897 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
@@ -17,12 +17,15 @@
 import com.google.gerrit.server.OutputFormat;
 import com.google.gson.Gson;
 
+import org.eclipse.jgit.errors.ConfigInvalidException;
 import org.eclipse.jgit.lib.Config;
 import org.junit.Rule;
 import org.junit.rules.TestRule;
 import org.junit.runner.Description;
 import org.junit.runners.model.Statement;
 
+import java.io.IOException;
+
 public abstract class AbstractDaemonTest {
   protected GerritServer server;
 
@@ -42,18 +45,20 @@
     }
   };
 
-  private static Config config(Description description) {
+  private static Config config(Description description)
+      throws IOException, ConfigInvalidException {
+    Config base = ConfigAnnotationParser.parseFromSystemProperty();
     GerritConfigs cfgs = description.getAnnotation(GerritConfigs.class);
     GerritConfig cfg = description.getAnnotation(GerritConfig.class);
     if (cfgs != null && cfg != null) {
       throw new IllegalStateException("Use either @GerritConfigs or @GerritConfig not both");
     }
     if (cfgs != null) {
-      return ConfigAnnotationParser.parse(cfgs);
+      return ConfigAnnotationParser.parse(base, cfgs);
     } else if (cfg != null) {
-      return ConfigAnnotationParser.parse(cfg);
+      return ConfigAnnotationParser.parse(base, cfg);
     } else {
-      return null;
+      return base;
     }
   }
 
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/ConfigAnnotationParser.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/ConfigAnnotationParser.java
index cf60fb4..a1285b5 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/ConfigAnnotationParser.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/ConfigAnnotationParser.java
@@ -14,36 +14,59 @@
 
 package com.google.gerrit.acceptance;
 
-import com.google.common.base.Splitter;
-import com.google.common.collect.Lists;
+import static com.google.common.base.Preconditions.checkNotNull;
 
+import com.google.common.base.Charsets;
+import com.google.common.base.Splitter;
+import com.google.common.base.Strings;
+import com.google.common.collect.Lists;
+import com.google.common.io.Resources;
+
+import org.eclipse.jgit.errors.ConfigInvalidException;
 import org.eclipse.jgit.lib.Config;
 
+import java.io.IOException;
+import java.net.URL;
 import java.util.ArrayList;
 
 class ConfigAnnotationParser {
-
+  private static final String CONFIG_PKG =
+      "com.google.gerrit.acceptance.config.";
+  private static final String CONFIG_DIR = "/" + CONFIG_PKG.replace('.', '/');
   private static Splitter splitter = Splitter.on(".").trimResults();
 
-  static Config parse(GerritConfigs annotation) {
+  static Config parseFromSystemProperty()
+      throws ConfigInvalidException, IOException {
+    Config cfg = new Config();
+    String name = System.getProperty(CONFIG_PKG + "BaseConfig");
+    if (!Strings.isNullOrEmpty(name)) {
+      String resource = CONFIG_DIR + name + ".config";
+      URL url = checkNotNull(ConfigAnnotationParser.class.getResource(resource),
+          "test config resource not found: %s", resource);
+      cfg.fromText(Resources.toString(url, Charsets.UTF_8));
+    }
+    return cfg;
+  }
+
+  static Config parse(Config base, GerritConfigs annotation) {
     if (annotation == null) {
       return null;
     }
 
-    Config cfg = new Config();
+    Config cfg = new Config(base);
     for (GerritConfig c : annotation.value()) {
-      parse(cfg, c);
+      parseAnnotation(cfg, c);
     }
     return cfg;
   }
 
-  static Config parse(GerritConfig annotation) {
-    Config cfg = new Config();
-    parse(cfg, annotation);
+  static Config parse(Config base, GerritConfig annotation) {
+    Config cfg = new Config(base);
+    parseAnnotation(cfg, annotation);
     return cfg;
   }
 
-  static private void parse(Config cfg, GerritConfig c) {
+  static private void parseAnnotation(Config cfg, GerritConfig c) {
     ArrayList<String> l = Lists.newArrayList(splitter.split(c.name()));
     if (l.size() == 2) {
       cfg.setString(l.get(0), null, l.get(1), c.value());
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/GerritServer.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/GerritServer.java
index 6caa2a6..272b5ab 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/GerritServer.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/GerritServer.java
@@ -49,7 +49,7 @@
 public class GerritServer {
 
   /** Returns fully started Gerrit server */
-  static GerritServer start(Config base, boolean memory) throws Exception {
+  static GerritServer start(Config cfg, boolean memory) throws Exception {
     final CyclicBarrier serverStarted = new CyclicBarrier(2);
     final Daemon daemon = new Daemon(new Runnable() {
       public void run() {
@@ -67,7 +67,6 @@
     ExecutorService daemonService = null;
     if (memory) {
       site = null;
-      Config cfg = base != null ? base : new Config();
       mergeTestConfig(cfg);
       cfg.setBoolean("httpd", null, "requestLog", false);
       cfg.setBoolean("sshd", null, "requestLog", false);
@@ -79,7 +78,6 @@
           new InMemoryTestingDatabaseModule(cfg)));
       daemon.start();
     } else {
-      Config cfg = base != null ? base : new Config();
       site = initSite(cfg);
       daemonService = Executors.newSingleThreadExecutor();
       daemonService.submit(new Callable<Void>() {
diff --git a/gerrit-acceptance-tests/tests.defs b/gerrit-acceptance-tests/tests.defs
index 3c8b4d5..c682e7b 100644
--- a/gerrit-acceptance-tests/tests.defs
+++ b/gerrit-acceptance-tests/tests.defs
@@ -1,20 +1,36 @@
 def acceptance_tests(
     srcs,
     deps = [],
+    configs = [],
     vm_args = ['-Xmx256m']):
   for j in srcs:
-    java_test(
-      name = j[:-len('.java')],
-      srcs = [j],
-      deps = ['//gerrit-acceptance-tests:lib'] + deps,
-      source_under_test = [
-        '//gerrit-httpd:httpd',
-        '//gerrit-sshd:sshd',
-        '//gerrit-server:server',
-      ],
+    for config in [None] + configs:
+      name = j[:-len('.java')]
       labels = [
         'acceptance',
         'slow',
-      ],
-      vm_args = vm_args,
-    )
+      ]
+      curr_vm_args = list(vm_args)
+
+      if config:
+        curr_vm_args.append(
+          '-Dcom.google.gerrit.acceptance.config.BaseConfig=' + config)
+        name += '_' + config
+        labels.append('acceptance_config')
+        labels.append('config_' + config)
+
+      java_test(
+        name = name,
+        srcs = [j],
+        deps = deps + [
+          '//gerrit-acceptance-tests:configs',
+          '//gerrit-acceptance-tests:lib',
+        ],
+        source_under_test = [
+          '//gerrit-httpd:httpd',
+          '//gerrit-sshd:sshd',
+          '//gerrit-server:server',
+        ],
+        labels = labels,
+        vm_args = curr_vm_args,
+      )
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/UpToChangeCommand.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/UpToChangeCommand.java
index 72318dd..970e33d3 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/UpToChangeCommand.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/UpToChangeCommand.java
@@ -15,7 +15,6 @@
 package com.google.gerrit.client.patches;
 
 import com.google.gerrit.client.Gerrit;
-import com.google.gerrit.client.changes.ChangeScreen;
 import com.google.gerrit.common.PageLinks;
 import com.google.gerrit.reviewdb.client.PatchSet;
 import com.google.gwt.event.dom.client.KeyPressEvent;
@@ -31,6 +30,6 @@
 
   @Override
   public void onKeyPress(final KeyPressEvent event) {
-    Gerrit.display(PageLinks.toChange(patchSetId), new ChangeScreen(patchSetId));
+    Gerrit.display(PageLinks.toChange(patchSetId));
   }
 }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/ApprovalsUtil.java b/gerrit-server/src/main/java/com/google/gerrit/server/ApprovalsUtil.java
index 9714e84..d563591 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/ApprovalsUtil.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/ApprovalsUtil.java
@@ -254,7 +254,7 @@
     }
     PatchSetApproval submitter = null;
     for (PatchSetApproval a : approvals) {
-      if (a.getValue() > 0 && a.isSubmit()) {
+      if (a.getPatchSetId().equals(c) && a.getValue() > 0 && a.isSubmit()) {
         if (submitter == null
             || a.getGranted().compareTo(submitter.getGranted()) > 0) {
           submitter = a;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeInserter.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeInserter.java
index 42f5c23..c208bb6 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeInserter.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/ChangeInserter.java
@@ -28,7 +28,6 @@
 import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.ApprovalsUtil;
 import com.google.gerrit.server.ChangeUtil;
-import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
 import com.google.gerrit.server.mail.CreateChangeSender;
 import com.google.gerrit.server.notedb.ChangeUpdate;
@@ -159,8 +158,9 @@
 
   public Change insert() throws OrmException, IOException {
     ReviewDb db = dbProvider.get();
-    ChangeUpdate update = updateFactory.create(change, change.getCreatedOn(),
-        (IdentifiedUser) refControl.getCurrentUser());
+    ChangeUpdate update = updateFactory.create(
+        refControl.getProjectControl().controlFor(change),
+        change.getCreatedOn());
     db.changes().beginTransaction(change.getId());
     try {
       ChangeUtil.insertAncestors(db, patchSet.getId(), commit);
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteReviewer.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteReviewer.java
index c396eaa..9aa9a83 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteReviewer.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteReviewer.java
@@ -72,7 +72,7 @@
     ChangeControl control = rsrc.getControl();
     Change.Id changeId = rsrc.getChange().getId();
     ReviewDb db = dbProvider.get();
-    ChangeUpdate update = updateFactory.create(rsrc.getChange());
+    ChangeUpdate update = updateFactory.create(rsrc.getControl());
 
     StringBuilder msg = new StringBuilder();
     db.changes().beginTransaction(changeId);
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/PatchSetInserter.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/PatchSetInserter.java
index 945c201..dd5101d 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/PatchSetInserter.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/PatchSetInserter.java
@@ -225,8 +225,7 @@
 
     final PatchSet.Id currentPatchSetId = c.currentPatchSetId();
 
-    ChangeUpdate update = updateFactory.create(c, patchSet.getCreatedOn(),
-        (IdentifiedUser) ctl.getCurrentUser());
+    ChangeUpdate update = updateFactory.create(ctl, patchSet.getCreatedOn());
 
     db.changes().beginTransaction(c.getId());
     try {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/PostReview.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/PostReview.java
index 4828558..a975c9c 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/PostReview.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/PostReview.java
@@ -135,7 +135,7 @@
       ChangeUtil.updated(change);
       timestamp = change.getLastUpdatedOn();
 
-      update = updateFactory.create(change, timestamp, revision.getUser());
+      update = updateFactory.create(revision.getControl(), timestamp);
       dirty |= insertComments(revision, input.comments, input.drafts);
       dirty |= updateLabels(revision, update, input.labels);
       dirty |= insertMessage(revision, input.message);
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/PostReviewers.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/PostReviewers.java
index 16a65b2..50bbc73 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/PostReviewers.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/PostReviewers.java
@@ -221,7 +221,7 @@
       Map<Account.Id, ChangeControl> reviewers)
       throws OrmException, EmailException, IOException {
     ReviewDb db = dbProvider.get();
-    ChangeUpdate update = updateFactory.create(rsrc.getChange());
+    ChangeUpdate update = updateFactory.create(rsrc.getControl());
     List<PatchSetApproval> added;
     db.changes().beginTransaction(rsrc.getChange().getId());
     try {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/Publish.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/Publish.java
index 2f33ae7..00c9d60 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/Publish.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/Publish.java
@@ -76,7 +76,7 @@
 
     PatchSet updatedPatchSet = updateDraftPatchSet(rsrc);
     Change updatedChange = updateDraftChange(rsrc);
-    ChangeUpdate update = updateFactory.create(rsrc.getChange(),
+    ChangeUpdate update = updateFactory.create(rsrc.getControl(),
         updatedChange.getLastUpdatedOn());
 
     try {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/Submit.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/Submit.java
index f37650e..d9d51f7 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/Submit.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/Submit.java
@@ -20,6 +20,7 @@
 import com.google.common.base.Predicate;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
 import com.google.gerrit.common.data.SubmitRecord;
 import com.google.gerrit.extensions.api.changes.SubmitInput;
 import com.google.gerrit.extensions.restapi.AuthException;
@@ -55,6 +56,7 @@
 import java.sql.Timestamp;
 import java.util.Collection;
 import java.util.List;
+import java.util.Map;
 
 public class Submit implements RestModifyView<RevisionResource, SubmitInput>,
     UiAction<RevisionResource> {
@@ -191,7 +193,7 @@
       throws OrmException, IOException {
     final Timestamp timestamp = TimeUtil.nowTs();
     Change change = rsrc.getChange();
-    ChangeUpdate update = updateFactory.create(change, timestamp, caller);
+    ChangeUpdate update = updateFactory.create(rsrc.getControl(), timestamp);
     ReviewDb db = dbProvider.get();
     db.changes().beginTransaction(change.getId());
     try {
@@ -224,9 +226,18 @@
   private void approve(RevisionResource rsrc, ChangeUpdate update,
       IdentifiedUser caller, Timestamp timestamp) throws OrmException {
     PatchSet.Id psId = rsrc.getPatchSet().getId();
-    List<PatchSetApproval> approvals = Lists.newArrayList(
-        approvalsUtil.byPatchSet(dbProvider.get(), rsrc.getNotes(), psId));
-    PatchSetApproval submit = ApprovalsUtil.getSubmitter(psId, approvals);
+    List<PatchSetApproval> approvals =
+        approvalsUtil.byPatchSet(dbProvider.get(), rsrc.getNotes(), psId);
+
+    Map<PatchSetApproval.Key, PatchSetApproval> byKey =
+        Maps.newHashMapWithExpectedSize(approvals.size());
+    for (PatchSetApproval psa : approvals) {
+      if (!byKey.containsKey(psa.getKey())) {
+        byKey.put(psa.getKey(), psa);
+      }
+    }
+
+    PatchSetApproval submit = ApprovalsUtil.getSubmitter(psId, byKey.values());
     if (submit == null || submit.getAccountId() != caller.getAccountId()) {
       submit = new PatchSetApproval(
           new PatchSetApproval.Key(
@@ -234,7 +245,7 @@
               caller.getAccountId(),
               LabelId.SUBMIT),
           (short) 1, TimeUtil.nowTs());
-      approvals.add(submit);
+      byKey.put(submit.getKey(), submit);
     }
     submit.setValue((short) 1);
     submit.setGranted(timestamp);
@@ -244,7 +255,7 @@
     // presentation view time, except for zero votes used to indicate a reviewer
     // was added. So we need to make sure votes are accurate now. This way if
     // permissions get modified in the future, historical records stay accurate.
-    approvals = labelNormalizer.normalize(rsrc.getControl(), approvals);
+    approvals = labelNormalizer.normalize(rsrc.getControl(), byKey.values());
 
     // TODO(dborowitz): Don't use a label in notedb; just check when status
     // change happened.
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 a27ea40..3b55a19 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
@@ -1842,7 +1842,7 @@
       recipients.add(getRecipientsFromFooters(accountResolver, newPatchSet, footerLines));
       recipients.remove(me);
 
-      ChangeUpdate update = updateFactory.create(change, newPatchSet.getCreatedOn());
+      ChangeUpdate update = updateFactory.create(changeCtl, newPatchSet.getCreatedOn());
       db.changes().beginTransaction(change.getId());
       try {
         change = db.changes().get(change.getId());
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/notedb/ChangeUpdate.java b/gerrit-server/src/main/java/com/google/gerrit/server/notedb/ChangeUpdate.java
index d16ae4c..a8f470d 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/notedb/ChangeUpdate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/notedb/ChangeUpdate.java
@@ -27,12 +27,15 @@
 import com.google.gerrit.reviewdb.client.Account;
 import com.google.gerrit.reviewdb.client.Change;
 import com.google.gerrit.reviewdb.client.PatchSet;
+
+import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.GerritPersonIdent;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.account.AccountCache;
 import com.google.gerrit.server.git.GitRepositoryManager;
 import com.google.gerrit.server.git.MetaDataUpdate;
 import com.google.gerrit.server.git.VersionedMetaData;
+import com.google.gerrit.server.project.ChangeControl;
 import com.google.gerrit.server.project.ProjectCache;
 import com.google.gerrit.server.util.LabelVote;
 import com.google.inject.assistedinject.Assisted;
@@ -63,9 +66,8 @@
  */
 public class ChangeUpdate extends VersionedMetaData {
   public interface Factory {
-    ChangeUpdate create(Change change);
-    ChangeUpdate create(Change change, Date when);
-    ChangeUpdate create(Change change, Date when, IdentifiedUser user);
+    ChangeUpdate create(ChangeControl ctl);
+    ChangeUpdate create(ChangeControl ctl, Date when);
   }
 
   private final NotesMigration migration;
@@ -73,8 +75,7 @@
   private final AccountCache accountCache;
   private final MetaDataUpdate.User updateFactory;
   private final LabelTypes labelTypes;
-  private final Change change;
-  private final IdentifiedUser user;
+  private final ChangeControl ctl;
   private final Date when;
   private final TimeZone tz;
   private final Map<String, Short> approvals;
@@ -90,10 +91,9 @@
       AccountCache accountCache,
       MetaDataUpdate.User updateFactory,
       ProjectCache projectCache,
-      IdentifiedUser user,
-      @Assisted Change change) {
+      @Assisted ChangeControl ctl) {
     this(serverIdent, repoManager, migration, accountCache, updateFactory,
-        projectCache, user, change, serverIdent.getWhen());
+        projectCache, ctl, serverIdent.getWhen());
   }
 
   @AssistedInject
@@ -104,27 +104,15 @@
       AccountCache accountCache,
       MetaDataUpdate.User updateFactory,
       ProjectCache projectCache,
-      IdentifiedUser user,
-      @Assisted Change change,
+      @Assisted ChangeControl ctl,
       @Assisted Date when) {
     this(serverIdent, repoManager, migration, accountCache, updateFactory,
-        projectCache, change, when, user);
+        projectCache.get(getProjectName(ctl)).getLabelTypes(),
+        ctl, when);
   }
 
-  @AssistedInject
-  ChangeUpdate(
-      @GerritPersonIdent PersonIdent serverIdent,
-      GitRepositoryManager repoManager,
-      NotesMigration migration,
-      AccountCache accountCache,
-      MetaDataUpdate.User updateFactory,
-      ProjectCache projectCache,
-      @Assisted Change change,
-      @Assisted Date when,
-      @Assisted IdentifiedUser user) {
-    this(serverIdent, repoManager, migration, accountCache, updateFactory,
-        projectCache.get(change.getDest().getParentKey()).getLabelTypes(),
-        change, when, user);
+  private static Project.NameKey getProjectName(ChangeControl ctl) {
+    return ctl.getChange().getDest().getParentKey();
   }
 
   @VisibleForTesting
@@ -135,16 +123,14 @@
       AccountCache accountCache,
       MetaDataUpdate.User updateFactory,
       LabelTypes labelTypes,
-      Change change,
-      Date when,
-      IdentifiedUser user) {
+      ChangeControl ctl,
+      Date when) {
     this.repoManager = repoManager;
     this.migration = migration;
     this.accountCache = accountCache;
     this.updateFactory = updateFactory;
     this.labelTypes = labelTypes;
-    this.change = change;
-    this.user = user;
+    this.ctl = ctl;
     this.when = when;
     this.tz = serverIdent.getTimeZone();
     this.approvals = Maps.newTreeMap(labelTypes.nameComparator());
@@ -152,11 +138,11 @@
   }
 
   public Change getChange() {
-    return change;
+    return ctl.getChange();
   }
 
   public IdentifiedUser getUser() {
-    return user;
+    return (IdentifiedUser) ctl.getCurrentUser();
   }
 
   public Date getWhen() {
@@ -172,7 +158,8 @@
   }
 
   public void setPatchSetId(PatchSet.Id psId) {
-    checkArgument(psId == null || psId.getParentKey().equals(change.getKey()));
+    checkArgument(psId == null
+        || psId.getParentKey().equals(getChange().getKey()));
     this.psId = psId;
   }
 
@@ -187,7 +174,7 @@
 
   public RevCommit commit() throws IOException {
     return commit(checkNotNull(updateFactory, "MetaDataUpdate.Factory")
-        .create(change.getProject(), user));
+        .create(getChange().getProject(), getUser()));
   }
 
   @Override
@@ -195,7 +182,7 @@
     if (!migration.write()) {
       return null;
     }
-    Repository repo = repoManager.openRepository(change.getProject());
+    Repository repo = repoManager.openRepository(getChange().getProject());
     try {
       load(repo);
     } catch (ConfigInvalidException e) {
@@ -218,7 +205,7 @@
   }
 
   public PersonIdent newCommitter() {
-    return newIdent(user.getAccount());
+    return newIdent(getUser().getAccount());
   }
 
   @Override
@@ -261,7 +248,7 @@
 
   @Override
   protected String getRefName() {
-    return ChangeNoteUtil.changeRefName(change.getId());
+    return ChangeNoteUtil.changeRefName(getChange().getId());
   }
 
   @Override
@@ -269,7 +256,7 @@
     if (approvals.isEmpty() && reviewers.isEmpty()) {
       return false;
     }
-    int ps = psId != null ? psId.get() : change.currentPatchSetId().get();
+    int ps = psId != null ? psId.get() : getChange().currentPatchSetId().get();
     StringBuilder msg = new StringBuilder();
     if (subject != null) {
       msg.append(subject);
diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/notedb/ChangeNotesTest.java b/gerrit-server/src/test/java/com/google/gerrit/server/notedb/ChangeNotesTest.java
index 1e4bf59..bdbacd8 100644
--- a/gerrit-server/src/test/java/com/google/gerrit/server/notedb/ChangeNotesTest.java
+++ b/gerrit-server/src/test/java/com/google/gerrit/server/notedb/ChangeNotesTest.java
@@ -19,10 +19,13 @@
 import static com.google.gerrit.server.project.Util.category;
 import static com.google.gerrit.server.project.Util.value;
 import static com.google.inject.Scopes.SINGLETON;
+
 import static java.util.concurrent.TimeUnit.DAYS;
 import static java.util.concurrent.TimeUnit.MILLISECONDS;
 import static java.util.concurrent.TimeUnit.MINUTES;
 import static java.util.concurrent.TimeUnit.SECONDS;
+
+import static org.easymock.EasyMock.expect;
 import static org.junit.Assert.assertEquals;
 
 import com.google.common.collect.ImmutableList;
@@ -50,6 +53,7 @@
 import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
 import com.google.gerrit.server.git.MetaDataUpdate;
 import com.google.gerrit.server.group.SystemGroupBackend;
+import com.google.gerrit.server.project.ChangeControl;
 import com.google.gerrit.server.util.TimeUtil;
 import com.google.gerrit.testutil.FakeAccountCache;
 import com.google.gerrit.testutil.FakeRealm;
@@ -60,7 +64,7 @@
 import com.google.inject.Injector;
 import com.google.inject.util.Providers;
 
-import org.eclipse.jgit.errors.ConfigInvalidException;
+import org.easymock.EasyMock;
 import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
 import org.eclipse.jgit.lib.Config;
 import org.eclipse.jgit.lib.PersonIdent;
@@ -414,10 +418,11 @@
   }
 
   private ChangeUpdate newUpdate(Change c, IdentifiedUser user)
-      throws ConfigInvalidException, IOException {
+      throws Exception {
     return new ChangeUpdate(SERVER_IDENT, repoManager,
-        NotesMigration.allEnabled(), accountCache, null, LABEL_TYPES, c,
-        TimeUtil.nowTs(), user);
+        NotesMigration.allEnabled(), accountCache, null, LABEL_TYPES,
+        stubChangeControl(c, user),
+        TimeUtil.nowTs());
   }
 
   private ChangeNotes newNotes(Change c) throws OrmException {
@@ -447,4 +452,12 @@
         update.getUser().newCommitterIdent(update.getWhen(), TZ));
     return update.commit(md);
   }
+
+  private ChangeControl stubChangeControl(Change c, IdentifiedUser user) {
+    ChangeControl ctl = EasyMock.createNiceMock(ChangeControl.class);
+    expect(ctl.getChange()).andStubReturn(c);
+    expect(ctl.getCurrentUser()).andStubReturn(user);
+    EasyMock.replay(ctl);
+    return ctl;
+  }
 }
diff --git a/tools/eclipse/BUCK b/tools/eclipse/BUCK
index c60d9f2..c2a8fa8 100644
--- a/tools/eclipse/BUCK
+++ b/tools/eclipse/BUCK
@@ -3,6 +3,7 @@
 java_library(
   name = 'classpath',
   deps = LIBS + PGMLIBS + [
+    '//gerrit-acceptance-tests:configs',
     '//gerrit-acceptance-tests:lib',
     '//gerrit-gwtdebug:gwtdebug',
     '//gerrit-gwtui:ui_module',