Merge branch 'stable-2.14' into stable-2.15

* stable-2.14:
  Change equality comparison for consistency
  Handle sub-patch versioning
  Handle changes in refs/meta
  Handle file comment
  Fix inline comment position
  Use latest bazlets

Change-Id: I917ad34fbc711e78f02302eaf03c75b8e12b7e1e
diff --git a/WORKSPACE b/WORKSPACE
index 76635ed..57d536f 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -3,7 +3,7 @@
 load("//:bazlets.bzl", "load_bazlets")
 
 load_bazlets(
-    commit = "e57da7c1ddde1389c15c86154a2ac4019099b050",
+    commit = "d9abef15db0f934bfe9adcb40b0c475807fd12bf",
     # local_path = "/home/<user>/projects/bazlets",
 )
 
diff --git a/src/main/java/com/googlesource/gerrit/plugins/importer/AddApprovalsStep.java b/src/main/java/com/googlesource/gerrit/plugins/importer/AddApprovalsStep.java
index b541966..267925f 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/importer/AddApprovalsStep.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/importer/AddApprovalsStep.java
@@ -18,7 +18,6 @@
 import com.google.gerrit.common.TimeUtil;
 import com.google.gerrit.common.data.LabelType;
 import com.google.gerrit.common.errors.NoSuchAccountException;
-import com.google.gerrit.extensions.common.AccountInfo;
 import com.google.gerrit.extensions.common.ApprovalInfo;
 import com.google.gerrit.extensions.common.ChangeInfo;
 import com.google.gerrit.extensions.common.LabelInfo;
@@ -29,8 +28,8 @@
 import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.notedb.ChangeUpdate;
-import com.google.gerrit.server.project.ChangeControl;
 import com.google.gerrit.server.project.NoSuchChangeException;
+import com.google.gerrit.server.query.change.ChangeData;
 import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
@@ -57,7 +56,7 @@
   private final ChangeUpdate.Factory updateFactory;
   private final ReviewDb db;
   private final IdentifiedUser.GenericFactory genericUserFactory;
-  private final ChangeControl.GenericFactory changeControlFactory;
+  private final ChangeData.Factory changeDataFactory;
   private final Change change;
   private final ChangeInfo changeInfo;
   private final boolean resume;
@@ -67,7 +66,7 @@
       ChangeUpdate.Factory updateFactory,
       ReviewDb db,
       IdentifiedUser.GenericFactory genericUserFactory,
-      ChangeControl.GenericFactory changeControlFactory,
+      ChangeData.Factory changeDataFactory,
       @Assisted Change change,
       @Assisted ChangeInfo changeInfo,
       @Assisted boolean resume) {
@@ -75,7 +74,7 @@
     this.updateFactory = updateFactory;
     this.db = db;
     this.genericUserFactory = genericUserFactory;
-    this.changeControlFactory = changeControlFactory;
+    this.changeDataFactory = changeDataFactory;
     this.change = change;
     this.changeInfo = changeInfo;
     this.resume = resume;
@@ -96,8 +95,8 @@
       if (label.all != null) {
         for (ApprovalInfo a : label.all) {
           Account.Id user = accountUtil.resolveUser(api, a);
-          ChangeControl ctrl = control(change, a);
-          LabelType labelType = ctrl.getLabelTypes().byLabel(labelName);
+          ChangeData cd = changeDataFactory.create(db, change);
+          LabelType labelType = cd.getLabelTypes().byLabel(labelName);
           if(labelType == null) {
             log.warn(String.format("Label '%s' not found in target system."
                 + " This label was referenced by an approval provided from '%s'"
@@ -112,7 +111,7 @@
           approvals.add(new PatchSetApproval(new PatchSetApproval.Key(change
               .currentPatchSetId(), user, labelType.getLabelId()), shortValue,
               MoreObjects.firstNonNull(a.date, TimeUtil.nowTs())));
-          ChangeUpdate update = updateFactory.create(ctrl);
+          ChangeUpdate update = updateFactory.create(cd.notes(), genericUserFactory.create(user));
           if (shortValue != 0) {
             update.putApproval(labelName, shortValue);
           } else {
@@ -124,19 +123,4 @@
     }
     db.patchSetApprovals().insert(approvals);
   }
-
-  private ChangeControl control(Change change, AccountInfo acc)
-      throws NoSuchChangeException {
-    return control(change, new Account.Id(acc._accountId));
-  }
-
-  private ChangeControl control(Change change, Account.Id id)
-      throws NoSuchChangeException {
-    try {
-      return changeControlFactory.controlFor(db, change,
-          genericUserFactory.create(id));
-    } catch (OrmException e) {
-      throw new NoSuchChangeException(change.getId());
-    }
-  }
 }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/importer/CompleteProjectImport.java b/src/main/java/com/googlesource/gerrit/plugins/importer/CompleteProjectImport.java
index 2df913f..f5cabb9 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/importer/CompleteProjectImport.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/importer/CompleteProjectImport.java
@@ -14,8 +14,11 @@
 
 package com.googlesource.gerrit.plugins.importer;
 
+import static com.google.gerrit.server.permissions.GlobalPermission.ADMINISTRATE_SERVER;
+
 import com.google.gerrit.extensions.annotations.PluginName;
 import com.google.gerrit.extensions.annotations.RequiresCapability;
+import com.google.gerrit.extensions.api.access.PluginPermission;
 import com.google.gerrit.extensions.restapi.IdString;
 import com.google.gerrit.extensions.restapi.ResourceConflictException;
 import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
@@ -24,9 +27,9 @@
 import com.google.gerrit.extensions.webui.UiAction;
 import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.CurrentUser;
-import com.google.gerrit.server.account.CapabilityControl;
 import com.google.gerrit.server.config.ConfigResource;
 import com.google.gerrit.server.git.GitRepositoryManager;
+import com.google.gerrit.server.permissions.PermissionBackend;
 import com.google.gerrit.server.project.ProjectResource;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
@@ -109,6 +112,8 @@
           case REJECTED:
           case REJECTED_CURRENT_BRANCH:
           case RENAMED:
+          case REJECTED_MISSING_OBJECT:
+          case REJECTED_OTHER_REASON:
           default:
             throw new IOException(String.format(
                 "Failed to delete %s, RefUpdate.Result = %s", ref, result));
@@ -123,16 +128,19 @@
     private final CompleteProjectImport completeProjectImport;
     private final Provider<CurrentUser> currentUserProvider;
     private final String pluginName;
+    private final PermissionBackend permissionBackend;
 
     @Inject
     public OnProjects(ProjectsCollection projectsCollection,
         CompleteProjectImport completeProjectImport,
         Provider<CurrentUser> currentUserProvider,
-        @PluginName String pluginName) {
+        @PluginName String pluginName,
+        PermissionBackend permissionBackend) {
       this.projectsCollection = projectsCollection;
       this.completeProjectImport = completeProjectImport;
       this.currentUserProvider = currentUserProvider;
       this.pluginName = pluginName;
+      this.permissionBackend = permissionBackend;
     }
 
     @Override
@@ -170,10 +178,10 @@
     }
 
     private boolean canCompleteImport(ProjectResource rsrc) {
-      CapabilityControl ctl = currentUserProvider.get().getCapabilities();
-      return ctl.canAdministrateServer()
-          || (ctl.canPerform(pluginName + "-" + ImportCapability.ID)
-              && rsrc.getControl().isOwner());
+      return permissionBackend.user(currentUserProvider).testOrFalse(ADMINISTRATE_SERVER) ||
+        (permissionBackend.user(currentUserProvider).testOrFalse(
+          new PluginPermission(pluginName, ImportCapability.ID))
+            && rsrc.getControl().isOwner());
     }
   }
 }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/importer/CopyProject.java b/src/main/java/com/googlesource/gerrit/plugins/importer/CopyProject.java
index 579d684..7d9f712 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/importer/CopyProject.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/importer/CopyProject.java
@@ -14,26 +14,29 @@
 
 package com.googlesource.gerrit.plugins.importer;
 
+import static com.google.gerrit.server.permissions.GlobalPermission.ADMINISTRATE_SERVER;
+
 import com.google.common.base.Strings;
 import com.google.gerrit.common.errors.NoSuchAccountException;
 import com.google.gerrit.extensions.annotations.PluginName;
 import com.google.gerrit.extensions.annotations.RequiresCapability;
+import com.google.gerrit.extensions.api.access.PluginPermission;
 import com.google.gerrit.extensions.restapi.BadRequestException;
 import com.google.gerrit.extensions.restapi.RestApiException;
 import com.google.gerrit.extensions.restapi.RestModifyView;
 import com.google.gerrit.extensions.webui.UiAction;
 import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.CurrentUser;
-import com.google.gerrit.server.account.CapabilityControl;
 import com.google.gerrit.server.config.ConfigResource;
 import com.google.gerrit.server.update.UpdateException;
+import com.google.gerrit.server.permissions.PermissionBackend;
+import com.google.gerrit.server.permissions.PermissionBackendException;
 import com.google.gerrit.server.project.NoSuchChangeException;
 import com.google.gerrit.server.project.ProjectResource;
 import com.google.gerrit.server.validators.ValidationException;
 import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
-import com.google.inject.Singleton;
 
 import com.googlesource.gerrit.plugins.importer.CopyProject.Input;
 
@@ -44,7 +47,6 @@
 import java.io.PrintWriter;
 import java.io.Writer;
 
-@Singleton
 @RequiresCapability(CopyProjectCapability.ID)
 class CopyProject implements RestModifyView<ProjectResource, Input>,
     UiAction<ProjectResource> {
@@ -55,24 +57,26 @@
   private final ImportProject.Factory importProjectFactory;
   private final Provider<CurrentUser> currentUserProvider;
   private final String pluginName;
-
+  private final PermissionBackend permissionBackend;
   private Writer err;
 
   @Inject
   CopyProject(
       ImportProject.Factory importProjectFactory,
       Provider<CurrentUser> currentUserProvider,
-      @PluginName String pluginName) {
+      @PluginName String pluginName,
+      PermissionBackend permissionBackend) {
     this.importProjectFactory = importProjectFactory;
     this.currentUserProvider = currentUserProvider;
     this.pluginName = pluginName;
+    this.permissionBackend = permissionBackend;
   }
 
   @Override
   public ImportStatistic apply(ProjectResource rsrc, Input input)
       throws RestApiException, OrmException, IOException, ValidationException,
       GitAPIException, NoSuchChangeException, NoSuchAccountException,
-      UpdateException, ConfigInvalidException {
+      UpdateException, ConfigInvalidException, PermissionBackendException {
     if (Strings.isNullOrEmpty(input.name)) {
       throw new BadRequestException("name is required");
     }
@@ -95,9 +99,9 @@
   }
 
   private boolean canCopy() {
-    CapabilityControl ctl = currentUserProvider.get().getCapabilities();
-    return ctl.canAdministrateServer()
-        || ctl.canPerform(pluginName + "-" + CopyProjectCapability.ID);
+    return permissionBackend.user(currentUserProvider).testOrFalse(ADMINISTRATE_SERVER) ||
+      permissionBackend.user(currentUserProvider).testOrFalse(
+      new PluginPermission(pluginName, CopyProjectCapability.ID));
   }
 
   void setErr(PrintWriter err) {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/importer/GitFetchStep.java b/src/main/java/com/googlesource/gerrit/plugins/importer/GitFetchStep.java
index 132a36c..a3421d1 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/importer/GitFetchStep.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/importer/GitFetchStep.java
@@ -83,6 +83,8 @@
         case REJECTED:
         case REJECTED_CURRENT_BRANCH:
         case RENAMED:
+        case REJECTED_MISSING_OBJECT:
+        case REJECTED_OTHER_REASON:
         default:
           throw new IOException(String.format(
               "Failed to update %s, RefUpdate.Result = %s", targetRef, result));
diff --git a/src/main/java/com/googlesource/gerrit/plugins/importer/GroupsCollection.java b/src/main/java/com/googlesource/gerrit/plugins/importer/GroupsCollection.java
index bb692cd..c25f5b5 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/importer/GroupsCollection.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/importer/GroupsCollection.java
@@ -60,7 +60,6 @@
   }
 
   @Override
-  @SuppressWarnings("unchecked")
   public ImportGroup create(ConfigResource parent, IdString id)
       throws RestApiException {
     return importGroupFactory.create(new AccountGroup.NameKey(id.get()));
diff --git a/src/main/java/com/googlesource/gerrit/plugins/importer/ImportGroup.java b/src/main/java/com/googlesource/gerrit/plugins/importer/ImportGroup.java
index c4bdd7e..6c64783 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/importer/ImportGroup.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/importer/ImportGroup.java
@@ -16,6 +16,7 @@
 
 import static com.google.gerrit.reviewdb.client.AccountGroup.isInternalGroup;
 
+import com.google.gerrit.common.TimeUtil;
 import com.google.gerrit.common.errors.NoSuchAccountException;
 import com.google.gerrit.extensions.annotations.RequiresCapability;
 import com.google.gerrit.extensions.common.AccountInfo;
@@ -40,6 +41,7 @@
 import com.google.gerrit.server.account.GroupIncludeCache;
 import com.google.gerrit.server.config.ConfigResource;
 import com.google.gerrit.server.config.GerritServerConfig;
+import com.google.gerrit.server.group.InternalGroup;
 import com.google.gerrit.server.validators.GroupCreationValidationListener;
 import com.google.gerrit.server.validators.ValidationException;
 import com.google.gwtorm.server.OrmDuplicateKeyException;
@@ -59,6 +61,7 @@
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Optional;
 import java.util.Set;
 
 @RequiresCapability(ImportCapability.ID)
@@ -174,11 +177,11 @@
     }
   }
 
-  private AccountGroup getGroupByName(String groupName) {
+  private Optional<InternalGroup> getGroupByName(String groupName) {
     return groupCache.get(new AccountGroup.NameKey(groupName));
   }
 
-  private AccountGroup getGroupByUUID(String uuid) {
+  private Optional<InternalGroup> getGroupByUUID(String uuid) {
     return groupCache.get(new AccountGroup.UUID(uuid));
   }
 
@@ -190,7 +193,7 @@
     args.groupDescription = groupInfo.description;
     args.visibleToAll = cfg.getBoolean("groups", "newGroupsVisibleToAll", false);
     if (!groupInfo.ownerId.equals(groupInfo.id)) {
-      args.ownerGroupId = getGroupByUUID(groupInfo.ownerId).getId();
+      args.ownerGroupId = getGroupByUUID(groupInfo.ownerId).get().getId();
     }
     Set<Account.Id> initialMembers = new HashSet<>();
     for (AccountInfo member : groupInfo.members) {
@@ -220,7 +223,7 @@
       throw new ResourceConflictException(info.name);
     }
     db.accountGroups().insert(Collections.singleton(group));
-    groupCache.evict(group);
+    groupCache.evict(group.getGroupUUID(), group.getId(), group.getNameKey());
 
     if (!info.id.equals(info.ownerId)) {
       if (getGroupByUUID(info.ownerId) == null) {
@@ -243,7 +246,7 @@
     addMembers(group.getId(), info.members);
     addGroups(input, group.getId(), info.name, info.includes);
 
-    groupCache.evict(group);
+    groupCache.evict(group.getGroupUUID(), group.getId(), group.getNameKey());
 
     return group;
   }
@@ -272,7 +275,8 @@
     AccountGroup.Id groupId = new AccountGroup.Id(db.nextAccountGroupId());
     AccountGroup.UUID uuid = new AccountGroup.UUID(info.id);
     AccountGroup group =
-        new AccountGroup(new AccountGroup.NameKey(info.name), groupId, uuid);
+        new AccountGroup(new AccountGroup.NameKey(info.name), groupId, uuid,
+            TimeUtil.nowTs());
     group.setVisibleToAll(cfg.getBoolean("groups", "newGroupsVisibleToAll",
         false));
     group.setDescription(info.description);
diff --git a/src/main/java/com/googlesource/gerrit/plugins/importer/ImportMenu.java b/src/main/java/com/googlesource/gerrit/plugins/importer/ImportMenu.java
index f0b0976..2edfdc1 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/importer/ImportMenu.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/importer/ImportMenu.java
@@ -14,12 +14,15 @@
 
 package com.googlesource.gerrit.plugins.importer;
 
+import static com.google.gerrit.server.permissions.GlobalPermission.ADMINISTRATE_SERVER;
+
 import com.google.common.collect.Lists;
 import com.google.gerrit.extensions.annotations.PluginName;
+import com.google.gerrit.extensions.api.access.PluginPermission;
 import com.google.gerrit.extensions.client.MenuItem;
 import com.google.gerrit.extensions.webui.TopMenu;
 import com.google.gerrit.server.CurrentUser;
-import com.google.gerrit.server.account.CapabilityControl;
+import com.google.gerrit.server.permissions.PermissionBackend;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
@@ -29,13 +32,16 @@
   private final String pluginName;
   private final Provider<CurrentUser> userProvider;
   private final List<MenuEntry> menuEntries;
+  private final PermissionBackend permissionBackend;
 
   @Inject
   ImportMenu(
       @PluginName String pluginName,
-      Provider<CurrentUser> userProvider) {
+      Provider<CurrentUser> userProvider,
+      PermissionBackend permissionBackend) {
     this.pluginName = pluginName;
     this.userProvider = userProvider;
+    this.permissionBackend = permissionBackend;
     menuEntries = Lists.newArrayList();
 
     List<MenuItem> projectItems = Lists.newArrayListWithExpectedSize(2);
@@ -54,9 +60,9 @@
   }
 
   private boolean canImport() {
-    CapabilityControl ctl = userProvider.get().getCapabilities();
-    return ctl.canAdministrateServer()
-        || ctl.canPerform(pluginName + "-" + ImportCapability.ID);
+    return permissionBackend.user(userProvider).testOrFalse(
+      new PluginPermission(pluginName, ImportCapability.ID)) ||
+      permissionBackend.user(userProvider).testOrFalse(ADMINISTRATE_SERVER);
   }
 
   @Override
diff --git a/src/main/java/com/googlesource/gerrit/plugins/importer/ImportProject.java b/src/main/java/com/googlesource/gerrit/plugins/importer/ImportProject.java
index ea00a2d..9e7c61b 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/importer/ImportProject.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/importer/ImportProject.java
@@ -29,6 +29,7 @@
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.config.ConfigResource;
 import com.google.gerrit.server.update.UpdateException;
+import com.google.gerrit.server.permissions.PermissionBackendException;
 import com.google.gerrit.server.project.NoSuchChangeException;
 import com.google.gerrit.server.project.ProjectCache;
 import com.google.gerrit.server.project.ProjectState;
@@ -166,7 +167,7 @@
   public ImportStatistic apply(ConfigResource rsrc, Input input)
       throws RestApiException, OrmException, IOException, ValidationException,
       GitAPIException, NoSuchChangeException, NoSuchAccountException,
-      UpdateException, ConfigInvalidException {
+      UpdateException, ConfigInvalidException, PermissionBackendException {
     if (input == null) {
       input = new Input();
     }
@@ -182,7 +183,7 @@
   public ResumeImportStatistic resume(String user, String pass, boolean force,
       File importStatus) throws RestApiException, OrmException, IOException,
       GitAPIException, NoSuchChangeException, NoSuchAccountException,
-      UpdateException, ConfigInvalidException {
+      UpdateException, ConfigInvalidException, PermissionBackendException {
     LockFile lockFile = lockForImport();
     try {
       ImportProjectInfo info = ImportJson.parse(importStatus);
@@ -205,7 +206,8 @@
   private ResumeImportStatistic apply(LockFile lockFile, Input input,
       ImportProjectInfo info) throws RestApiException, OrmException,
       IOException, GitAPIException, NoSuchChangeException,
-      NoSuchAccountException, UpdateException, ConfigInvalidException {
+      NoSuchAccountException, UpdateException, ConfigInvalidException,
+      PermissionBackendException {
     boolean resume = info != null;
     api = apiFactory.create(input.from, input.user, input.pass);
 
diff --git a/src/main/java/com/googlesource/gerrit/plugins/importer/InsertLinkToOriginalChangeStep.java b/src/main/java/com/googlesource/gerrit/plugins/importer/InsertLinkToOriginalChangeStep.java
index ba25273..eb3dbe9 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/importer/InsertLinkToOriginalChangeStep.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/importer/InsertLinkToOriginalChangeStep.java
@@ -28,8 +28,8 @@
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.config.CanonicalWebUrl;
 import com.google.gerrit.server.notedb.ChangeUpdate;
-import com.google.gerrit.server.project.ChangeControl;
 import com.google.gerrit.server.project.NoSuchChangeException;
+import com.google.gerrit.server.query.change.ChangeData;
 import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
@@ -41,7 +41,7 @@
   private final CurrentUser currentUser;
   private final ChangeUpdate.Factory updateFactory;
   private final IdentifiedUser.GenericFactory genericUserFactory;
-  private final ChangeControl.GenericFactory changeControlFactory;
+  private final ChangeData.Factory changeDataFactory;
   private final ReviewDb db;
   private final ChangeMessagesUtil cmUtil;
   private final String canonicalWebUrl;
@@ -62,7 +62,7 @@
   InsertLinkToOriginalChangeStep(CurrentUser currentUser,
       ChangeUpdate.Factory updateFactory,
       IdentifiedUser.GenericFactory genericUserFactory,
-      ChangeControl.GenericFactory changeControlFactory,
+      ChangeData.Factory changeDataFactory,
       ReviewDb db,
       ChangeMessagesUtil cmUtil,
       @CanonicalWebUrl String canonicalWebUrl,
@@ -73,7 +73,7 @@
     this.currentUser = currentUser;
     this.updateFactory = updateFactory;
     this.genericUserFactory = genericUserFactory;
-    this.changeControlFactory = changeControlFactory;
+    this.changeDataFactory = changeDataFactory;
     this.db = db;
     this.cmUtil = cmUtil;
     this.canonicalWebUrl = canonicalWebUrl;
@@ -99,7 +99,8 @@
   private void insertMessage(Change change, String message)
       throws NoSuchChangeException, OrmException, IOException {
     Account.Id userId = ((IdentifiedUser) currentUser).getAccountId();
-    ChangeUpdate update = updateFactory.create(control(change, userId));
+    ChangeData cd = changeDataFactory.create(db, change);
+    ChangeUpdate update = updateFactory.create(cd.notes(), genericUserFactory.create(userId));
     ChangeMessage cmsg =
         new ChangeMessage(new ChangeMessage.Key(change.getId(),
             ChangeUtil.messageUuid()), userId, TimeUtil.nowTs(),
@@ -109,16 +110,6 @@
     update.commit();
   }
 
-  private ChangeControl control(Change change, Account.Id id)
-      throws NoSuchChangeException {
-    try {
-      return changeControlFactory.controlFor(db, change,
-          genericUserFactory.create(id));
-    } catch (OrmException e) {
-      throw new NoSuchChangeException(change.getId());
-    }
-  }
-
   private static String ensureSlash(String in) {
     if (in != null && !in.endsWith("/")) {
       return in + "/";
diff --git a/src/main/java/com/googlesource/gerrit/plugins/importer/LocalApi.java b/src/main/java/com/googlesource/gerrit/plugins/importer/LocalApi.java
index a5dd841..9248b8c 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/importer/LocalApi.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/importer/LocalApi.java
@@ -31,6 +31,7 @@
 import com.google.gerrit.server.account.AccountResource;
 import com.google.gerrit.server.account.AccountsCollection;
 import com.google.gerrit.server.account.GetSshKeys;
+import com.google.gerrit.server.permissions.PermissionBackendException;
 import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 
@@ -128,7 +129,7 @@
           accounts.parse(TopLevelResource.INSTANCE,
               IdString.fromDecoded(userId));
       return getSshKeys.apply(rsrc);
-    } catch (ResourceNotFoundException | AuthException e) {
+    } catch (ResourceNotFoundException | AuthException | PermissionBackendException e) {
       throw new BadRequestException(e.getMessage());
     }
   }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/importer/OpenRepositoryStep.java b/src/main/java/com/googlesource/gerrit/plugins/importer/OpenRepositoryStep.java
index 9386c68..06fb06c 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/importer/OpenRepositoryStep.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/importer/OpenRepositoryStep.java
@@ -22,6 +22,7 @@
 import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
 import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.git.GitRepositoryManager;
+import com.google.gerrit.server.permissions.PermissionBackendException;
 import com.google.gerrit.server.project.CreateProjectArgs;
 import com.google.gerrit.server.project.ProjectCache;
 import com.google.gerrit.server.project.ProjectsCollection;
@@ -58,7 +59,8 @@
 
   Repository open(Project.NameKey name, boolean resume, ProgressMonitor pm,
       Project.NameKey parent)
-      throws ResourceConflictException, IOException, UnprocessableEntityException {
+      throws ResourceConflictException, IOException, UnprocessableEntityException,
+      PermissionBackendException {
     pm.beginTask("Open repository", 1);
     try {
       Repository repo = git.openRepository(name);
@@ -83,10 +85,11 @@
   }
 
   private void beforeCreateProject(Project.NameKey name, Project.NameKey parent)
-      throws ResourceConflictException, UnprocessableEntityException, IOException {
+      throws ResourceConflictException, UnprocessableEntityException, IOException,
+      PermissionBackendException {
     CreateProjectArgs args = new CreateProjectArgs();
     args.setProjectName(name);
-    args.newParent = projectsCollection.get().parse(parent.get()).getControl();
+    args.newParent = projectsCollection.get().parse(parent.get()).getNameKey();
     for (ProjectCreationValidationListener l : projectCreationValidationListeners) {
       try {
         l.validateNewProject(args);
diff --git a/src/main/java/com/googlesource/gerrit/plugins/importer/ProjectCommand.java b/src/main/java/com/googlesource/gerrit/plugins/importer/ProjectCommand.java
index 5dbbaae..d55bb4c 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/importer/ProjectCommand.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/importer/ProjectCommand.java
@@ -21,6 +21,7 @@
 import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.config.ConfigResource;
 import com.google.gerrit.server.update.UpdateException;
+import com.google.gerrit.server.permissions.PermissionBackendException;
 import com.google.gerrit.server.project.NoSuchChangeException;
 import com.google.gerrit.server.validators.ValidationException;
 import com.google.gerrit.sshd.CommandMetaData;
@@ -73,7 +74,7 @@
   protected void run()
       throws OrmException, IOException, UnloggedFailure, ValidationException,
       GitAPIException, NoSuchChangeException, NoSuchAccountException,
-      UpdateException, ConfigInvalidException {
+      UpdateException, ConfigInvalidException, PermissionBackendException {
     ImportProject.Input input = new ImportProject.Input();
     input.from = url;
     input.name = name;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/importer/ProjectsCollection.java b/src/main/java/com/googlesource/gerrit/plugins/importer/ProjectsCollection.java
index 74d3efb..ded7130 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/importer/ProjectsCollection.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/importer/ProjectsCollection.java
@@ -136,7 +136,6 @@
   }
 
   @Override
-  @SuppressWarnings("unchecked")
   public ImportProject create(ConfigResource parent, IdString id)
       throws RestApiException {
     return importProjectFactory.create(new Project.NameKey(id.get()));
diff --git a/src/main/java/com/googlesource/gerrit/plugins/importer/ReplayChangesStep.java b/src/main/java/com/googlesource/gerrit/plugins/importer/ReplayChangesStep.java
index 200d7cc..2820b15 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/importer/ReplayChangesStep.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/importer/ReplayChangesStep.java
@@ -132,7 +132,7 @@
     this.resume = resume;
     this.importStatistic = importStatistic;
     this.pm = pm;
-    this.isNoteDbEnabled = migration.enabled();
+    this.isNoteDbEnabled = migration.readChanges();
   }
 
   void replay() throws IOException, OrmException,
@@ -173,11 +173,6 @@
       throws IOException, OrmException, NoSuchAccountException,
       NoSuchChangeException, RestApiException, IllegalArgumentException,
       UpdateException, ConfigInvalidException {
-    if (c.status == ChangeStatus.DRAFT) {
-      // no import of draft changes
-      return;
-    }
-
     Change change = resume ? findChange(c) : null;
     boolean resumeChange;
     if (change == null) {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/importer/ReplayInlineCommentsStep.java b/src/main/java/com/googlesource/gerrit/plugins/importer/ReplayInlineCommentsStep.java
index 8fabda0..b1ec866 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/importer/ReplayInlineCommentsStep.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/importer/ReplayInlineCommentsStep.java
@@ -216,7 +216,7 @@
     }
 
     Iterables.addAll(del, drafts.values());
-    ChangeUpdate update = updateFactory.create(ctrl, TimeUtil.nowTs());
+    ChangeUpdate update = updateFactory.create(ctrl.getNotes(), ctrl.getUser(), TimeUtil.nowTs());
     update.setPatchSetId(ps.getId());
 
     commentsUtil.deleteComments(db, update, del);
diff --git a/src/main/java/com/googlesource/gerrit/plugins/importer/ReplayMessagesStep.java b/src/main/java/com/googlesource/gerrit/plugins/importer/ReplayMessagesStep.java
index dde14ee..9b1d130 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/importer/ReplayMessagesStep.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/importer/ReplayMessagesStep.java
@@ -92,7 +92,8 @@
           : null;
       if (msg.author != null) {
         Account.Id userId = accountUtil.resolveUser(api, msg.author);
-        ChangeUpdate update = updateFactory.create(control(change, userId), ts);
+        ChangeControl ctrl = control(change, userId);
+        ChangeUpdate update = updateFactory.create(ctrl.getNotes(), ctrl.getUser(), ts);
         ChangeMessage cmsg = new ChangeMessage(msgKey, userId, ts, psId);
         cmsg.setMessage(msg.message);
         cmUtil.addChangeMessage(db, update, cmsg);
diff --git a/src/main/java/com/googlesource/gerrit/plugins/importer/ReplayRevisionsStep.java b/src/main/java/com/googlesource/gerrit/plugins/importer/ReplayRevisionsStep.java
index 85e1a07..d98df7d 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/importer/ReplayRevisionsStep.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/importer/ReplayRevisionsStep.java
@@ -88,10 +88,6 @@
     try {
       PatchSetInfo info = null;
       for (RevisionInfo r : revisions) {
-        if (r.draft != null && r.draft) {
-          // no import of draft patch sets
-          continue;
-        }
         PatchSet ps = new PatchSet(new PatchSet.Id(change.getId(), r._number));
         String newRef = ps.getId().toRefName();
         ObjectId newId = repo.resolve(newRef);
@@ -121,7 +117,6 @@
         ps.setUploader(accountUtil.resolveUser(api, r.uploader));
         ps.setCreatedOn(r.created);
         ps.setRevision(new RevId(commit.name()));
-        ps.setDraft(r.draft != null && r.draft);
 
         info = patchSetInfoFactory.get(rw, commit, ps.getId());
         if (info.getRevId().equals(changeInfo.currentRevision)) {
@@ -181,6 +176,8 @@
       case REJECTED:
       case REJECTED_CURRENT_BRANCH:
       case RENAMED:
+      case REJECTED_MISSING_OBJECT:
+      case REJECTED_OTHER_REASON:
       default:
         throw new IOException(String.format(
             "Failed to create ref %s, RefUpdate.Result = %s", ref, result));
diff --git a/src/main/java/com/googlesource/gerrit/plugins/importer/ResumeCopyProject.java b/src/main/java/com/googlesource/gerrit/plugins/importer/ResumeCopyProject.java
index f58d421..ae6ed9f 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/importer/ResumeCopyProject.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/importer/ResumeCopyProject.java
@@ -14,9 +14,12 @@
 
 package com.googlesource.gerrit.plugins.importer;
 
+import static com.google.gerrit.server.permissions.GlobalPermission.ADMINISTRATE_SERVER;
+
 import com.google.gerrit.common.errors.NoSuchAccountException;
 import com.google.gerrit.extensions.annotations.PluginName;
 import com.google.gerrit.extensions.annotations.RequiresCapability;
+import com.google.gerrit.extensions.api.access.PluginPermission;
 import com.google.gerrit.extensions.restapi.IdString;
 import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
 import com.google.gerrit.extensions.restapi.RestApiException;
@@ -24,9 +27,10 @@
 import com.google.gerrit.extensions.webui.UiAction;
 import com.google.gerrit.reviewdb.client.Project;
 import com.google.gerrit.server.CurrentUser;
-import com.google.gerrit.server.account.CapabilityControl;
 import com.google.gerrit.server.config.ConfigResource;
 import com.google.gerrit.server.update.UpdateException;
+import com.google.gerrit.server.permissions.PermissionBackend;
+import com.google.gerrit.server.permissions.PermissionBackendException;
 import com.google.gerrit.server.project.NoSuchChangeException;
 import com.google.gerrit.server.project.ProjectCache;
 import com.google.gerrit.server.project.ProjectResource;
@@ -55,6 +59,7 @@
   private final Provider<CurrentUser> currentUserProvider;
   private final String pluginName;
   private final ProjectCache projectCache;
+  private final PermissionBackend permissionBackend;
 
   private Writer err;
 
@@ -64,12 +69,14 @@
       ProjectsCollection projectsCollection,
       Provider<CurrentUser> currentUserProvider,
       @PluginName String pluginName,
-      ProjectCache projectCache) {
+      ProjectCache projectCache,
+      PermissionBackend permissionBackend) {
     this.resumeProjectImport = resumeProjectImport;
     this.projectsCollection = projectsCollection;
     this.currentUserProvider = currentUserProvider;
     this.pluginName = pluginName;
     this.projectCache = projectCache;
+    this.permissionBackend = permissionBackend;
   }
 
   ResumeCopyProject setErr(Writer err) {
@@ -81,7 +88,7 @@
   public ResumeImportStatistic apply(ProjectResource rsrc, Input input)
       throws RestApiException, IOException, OrmException, ValidationException,
       GitAPIException, NoSuchChangeException, NoSuchAccountException,
-      UpdateException, ConfigInvalidException {
+      UpdateException, ConfigInvalidException, PermissionBackendException {
     ImportProjectResource projectResource =
         projectsCollection.parse(new ConfigResource(),
             IdString.fromDecoded(rsrc.getName()));
@@ -103,10 +110,10 @@
   }
 
   private boolean canResumeCopy(ProjectResource rsrc) {
-    CapabilityControl ctl = currentUserProvider.get().getCapabilities();
-    return ctl.canAdministrateServer()
-        || (ctl.canPerform(pluginName + "-" + CopyProjectCapability.ID)
-            && rsrc.getControl().isOwner());
+    return permissionBackend.user(currentUserProvider).testOrFalse(ADMINISTRATE_SERVER) ||
+      (permissionBackend.user(currentUserProvider).testOrFalse(
+      new PluginPermission(pluginName, CopyProjectCapability.ID)) &&
+      rsrc.getControl().isOwner());
   }
 
   private boolean isCopied(ProjectResource rsrc) {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/importer/ResumeProjectImport.java b/src/main/java/com/googlesource/gerrit/plugins/importer/ResumeProjectImport.java
index 40e0d26..996c7e4 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/importer/ResumeProjectImport.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/importer/ResumeProjectImport.java
@@ -14,10 +14,13 @@
 
 package com.googlesource.gerrit.plugins.importer;
 
+import static com.google.gerrit.server.permissions.GlobalPermission.ADMINISTRATE_SERVER;
+
 import com.google.common.base.Strings;
 import com.google.gerrit.common.errors.NoSuchAccountException;
 import com.google.gerrit.extensions.annotations.PluginName;
 import com.google.gerrit.extensions.annotations.RequiresCapability;
+import com.google.gerrit.extensions.api.access.PluginPermission;
 import com.google.gerrit.extensions.restapi.BadRequestException;
 import com.google.gerrit.extensions.restapi.IdString;
 import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
@@ -25,9 +28,10 @@
 import com.google.gerrit.extensions.restapi.RestModifyView;
 import com.google.gerrit.extensions.webui.UiAction;
 import com.google.gerrit.server.CurrentUser;
-import com.google.gerrit.server.account.CapabilityControl;
 import com.google.gerrit.server.config.ConfigResource;
 import com.google.gerrit.server.update.UpdateException;
+import com.google.gerrit.server.permissions.PermissionBackend;
+import com.google.gerrit.server.permissions.PermissionBackendException;
 import com.google.gerrit.server.project.NoSuchChangeException;
 import com.google.gerrit.server.project.ProjectResource;
 import com.google.gerrit.server.validators.ValidationException;
@@ -95,7 +99,7 @@
   public ResumeImportStatistic apply(ImportProjectResource rsrc, Input input)
       throws RestApiException, IOException, OrmException, ValidationException,
       GitAPIException, NoSuchChangeException, NoSuchAccountException,
-      UpdateException, ConfigInvalidException {
+      UpdateException, ConfigInvalidException, PermissionBackendException {
     if (copy) {
       input.validateResumeCopy();
     } else {
@@ -115,24 +119,27 @@
     private final ResumeProjectImport resumeProjectImport;
     private final Provider<CurrentUser> currentUserProvider;
     private final String pluginName;
+    private final PermissionBackend permissionBackend;
 
     @Inject
     public OnProjects(
         ProjectsCollection projectsCollection,
         ResumeProjectImport resumeProjectImport,
         Provider<CurrentUser> currentUserProvider,
-        @PluginName String pluginName) {
+        @PluginName String pluginName,
+        PermissionBackend permissionBackend) {
       this.projectsCollection = projectsCollection;
       this.resumeProjectImport = resumeProjectImport;
       this.currentUserProvider = currentUserProvider;
       this.pluginName = pluginName;
+      this.permissionBackend = permissionBackend;
     }
 
     @Override
     public ResumeImportStatistic apply(ProjectResource rsrc, Input input)
         throws RestApiException, IOException, OrmException, ValidationException,
         GitAPIException, NoSuchChangeException, NoSuchAccountException,
-        UpdateException, ConfigInvalidException {
+        UpdateException, ConfigInvalidException, PermissionBackendException {
       ImportProjectResource projectResource =
           projectsCollection.parse(new ConfigResource(),
               IdString.fromDecoded(rsrc.getName()));
@@ -148,10 +155,10 @@
     }
 
     private boolean canResumeImport(ProjectResource rsrc) {
-      CapabilityControl ctl = currentUserProvider.get().getCapabilities();
-      return ctl.canAdministrateServer()
-          || (ctl.canPerform(pluginName + "-" + ImportCapability.ID)
-              && rsrc.getControl().isOwner());
+      return permissionBackend.user(currentUserProvider).testOrFalse(ADMINISTRATE_SERVER) ||
+        (permissionBackend.user(currentUserProvider).testOrFalse(
+        new PluginPermission(pluginName, ImportCapability.ID)) &&
+        rsrc.getControl().isOwner());
     }
 
     private boolean isImported(ProjectResource rsrc) {