Merge branch 'stable-2.11'

* stable-2.11:
  Do not create refs for imports and cache-automerge refs
  Document required capabilities to import SSH keys of created accounts
  Document that draft changes/patch sets and change edits are not imported
  Remove plugin name from logged warnings and errors
  Skip replay inline comments for revisions that do not exist in source
  Do not skip changes without current revision
  Handle changes with non-existing current revision
  Simplify Buck rules

Change-Id: Ia9d27d56b5f1a8957c7e8f52e29df8dba8ab01f6
diff --git a/BUCK b/BUCK
index 5f8ea76..11c5585 100644
--- a/BUCK
+++ b/BUCK
@@ -4,12 +4,8 @@
 
 if STANDALONE_MODE:
   HTTP_LIB = '//lib/http:http_lib'
-  GSON = '//lib/gson:gson'
-  LOG4J = '//lib/log:log4j'
 else:
   HTTP_LIB = '//plugins/importer/lib/http:http_lib'
-  GSON = '//plugins/importer/lib/gson:gson'
-  LOG4J = '//plugins/importer/lib/log:log4j'
 
 gerrit_plugin(
   name = 'importer',
@@ -28,8 +24,8 @@
     HTTP_LIB,
   ],
   provided_deps = [
-    LOG4J,
-    GSON,
+    '//lib:gson',
+    '//lib/log:log4j',
   ],
 )
 
diff --git a/lib/gson/BUCK b/lib/BUCK
similarity index 100%
rename from lib/gson/BUCK
rename to lib/BUCK
diff --git a/src/main/java/com/googlesource/gerrit/plugins/importer/AccountUtil.java b/src/main/java/com/googlesource/gerrit/plugins/importer/AccountUtil.java
index 31fecd4..fe76caf 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/importer/AccountUtil.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/importer/AccountUtil.java
@@ -15,7 +15,6 @@
 package com.googlesource.gerrit.plugins.importer;
 
 import com.google.gerrit.common.errors.NoSuchAccountException;
-import com.google.gerrit.extensions.annotations.PluginName;
 import com.google.gerrit.extensions.common.AccountInfo;
 import com.google.gerrit.extensions.restapi.BadRequestException;
 import com.google.gerrit.reviewdb.client.Account;
@@ -47,7 +46,6 @@
 class AccountUtil {
   private static Logger log = LoggerFactory.getLogger(AccountUtil.class);
 
-  private final String pluginName;
   private final AccountCache accountCache;
   private final AccountManager accountManager;
   private final AuthType authType;
@@ -55,12 +53,10 @@
 
   @Inject
   public AccountUtil(
-      @PluginName String pluginName,
       AccountCache accountCache,
       AccountManager accountManager,
       AuthConfig authConfig,
       Provider<ReviewDb> db) {
-    this.pluginName = pluginName;
     this.accountCache = accountCache;
     this.accountManager = accountManager;
     this.authType = authConfig.getAuthType();
@@ -90,8 +86,8 @@
     }
     if (!Objects.equals(a.getAccount().getPreferredEmail(), acc.email)) {
       log.warn(String.format(
-          "[%s] Email mismatch for user %s: expected %s but found %s",
-          pluginName, acc.username, acc.email, a.getAccount().getPreferredEmail()));
+          "Email mismatch for user %s: expected %s but found %s",
+          acc.username, acc.email, a.getAccount().getPreferredEmail()));
     }
 
     return a.getAccount().getId();
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 a4a31ae..b5deef0 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.annotations.PluginName;
 import com.google.gerrit.extensions.common.AccountInfo;
 import com.google.gerrit.extensions.common.ApprovalInfo;
 import com.google.gerrit.extensions.common.ChangeInfo;
@@ -61,7 +60,6 @@
   private final Change change;
   private final ChangeInfo changeInfo;
   private final boolean resume;
-  private final String pluginName;
 
   @Inject
   public AddApprovalsStep(AccountUtil accountUtil,
@@ -69,7 +67,6 @@
       ReviewDb db,
       IdentifiedUser.GenericFactory genericUserFactory,
       ChangeControl.GenericFactory changeControlFactory,
-      @PluginName String pluginName,
       @Assisted Change change,
       @Assisted ChangeInfo changeInfo,
       @Assisted boolean resume) {
@@ -81,7 +78,6 @@
     this.change = change;
     this.changeInfo = changeInfo;
     this.resume = resume;
-    this.pluginName = pluginName;
   }
 
   void add(GerritApi api) throws OrmException, NoSuchChangeException, IOException,
@@ -101,13 +97,13 @@
           ChangeControl ctrl = control(change, a);
           LabelType labelType = ctrl.getLabelTypes().byLabel(labelName);
           if(labelType == null) {
-            log.warn(String.format("[%s] Label '%s' not found in target system."
+            log.warn(String.format("Label '%s' not found in target system."
                 + " This label was referenced by an approval provided from '%s'"
                 + " for change '%s'."
                 + " This approval will be skipped. In order to import this"
                 + " approval configure the missing label and resume the import"
                 + " with the force option."
-                , pluginName, labelName, a.username, changeInfo.id));
+                , labelName, a.username, changeInfo.id));
             continue;
           }
           short shortValue = a.value != null ? a.value.shortValue() : 0;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/importer/AddHashtagsStep.java b/src/main/java/com/googlesource/gerrit/plugins/importer/AddHashtagsStep.java
index f8aaef9..f04c435 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/importer/AddHashtagsStep.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/importer/AddHashtagsStep.java
@@ -14,7 +14,6 @@
 
 package com.googlesource.gerrit.plugins.importer;
 
-import com.google.gerrit.extensions.annotations.PluginName;
 import com.google.gerrit.extensions.api.changes.HashtagsInput;
 import com.google.gerrit.extensions.common.ChangeInfo;
 import com.google.gerrit.extensions.restapi.AuthException;
@@ -47,7 +46,6 @@
   private final HashtagsUtil hashtagsUtil;
   private final CurrentUser currentUser;
   private final ChangeControl.GenericFactory changeControlFactory;
-  private final String pluginName;
   private final Change change;
   private final ChangeInfo changeInfo;
   private final boolean resume;
@@ -56,14 +54,12 @@
   AddHashtagsStep(HashtagsUtil hashtagsUtil,
       CurrentUser currentUser,
       ChangeControl.GenericFactory changeControlFactory,
-      @PluginName String pluginName,
       @Assisted Change change,
       @Assisted ChangeInfo changeInfo,
       @Assisted boolean resume) {
     this.hashtagsUtil = hashtagsUtil;
     this.currentUser = currentUser;
     this.changeControlFactory = changeControlFactory;
-    this.pluginName = pluginName;
     this.change = change;
     this.changeInfo = changeInfo;
     this.resume = resume;
@@ -85,11 +81,11 @@
       hashtagsUtil.setHashtags(ctrl, input, false, false);
     } catch (AuthException e) {
       log.warn(String.format(
-          "[%s] Hashtags cannot be set on change %s because the importing"
+          "Hashtags cannot be set on change %s because the importing"
               + " user %s doesn't have permissions to edit hashtags"
               + " (e.g. assign the 'Edit Hashtags' global capability"
               + " and resume the import with the force option).",
-          pluginName, ChangeTriplet.format(change), currentUser.getUserName()));
+          ChangeTriplet.format(change), currentUser.getUserName()));
     }
   }
 }
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 2f7f2ba..2fc0f59 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/importer/GitFetchStep.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/importer/GitFetchStep.java
@@ -55,13 +55,19 @@
         ConfigureRepositoryStep.R_IMPORTS);
     for (Map.Entry<String, Ref> e : refs.entrySet()) {
       String name = e.getKey();
+      if (name.startsWith("imports/")) {
+        continue;
+      }
+      if (name.startsWith("cache-automerge/")) {
+        continue;
+      }
       if (name.startsWith("changes/")) {
         continue;
       }
       if (name.startsWith("users/") && name.contains("/edit")) {
         continue;
       }
-      String targetRef = Constants.R_REFS + e.getKey();
+      String targetRef = Constants.R_REFS + name;
       RefUpdate ru = repo.updateRef(targetRef);
       ru.setNewObjectId(e.getValue().getObjectId());
       RefUpdate.Result result = ru.forceUpdate();
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 49ae2eb..7675235 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/importer/ImportGroup.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/importer/ImportGroup.java
@@ -17,7 +17,6 @@
 import static com.google.gerrit.reviewdb.client.AccountGroup.isInternalGroup;
 
 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.common.AccountInfo;
 import com.google.gerrit.extensions.common.GroupInfo;
@@ -76,7 +75,6 @@
 
   private static Logger log = LoggerFactory.getLogger(ImportGroup.class);
 
-  private final String pluginName;
   private final Config cfg;
   private final ReviewDb db;
   private final AccountUtil accountUtil;
@@ -91,7 +89,6 @@
 
   @Inject
   ImportGroup(
-      @PluginName String pluginName,
       @GerritServerConfig Config cfg,
       ReviewDb db,
       AccountUtil accountUtil,
@@ -102,7 +99,6 @@
       ImportGroup.Factory importGroupFactory,
       GerritApi.Factory apiFactory,
       @Assisted AccountGroup.NameKey group) {
-    this.pluginName = pluginName;
     this.cfg = cfg;
     this.db = db;
     this.accountUtil = accountUtil;
@@ -208,8 +204,8 @@
       IOException, PreconditionFailedException, MethodNotAllowedException {
     String uniqueName = getUniqueGroupName(info.name);
     if (!info.name.equals(uniqueName)) {
-      log.warn(String.format("[%s] Group %s with UUID %s is imported with name %s",
-          pluginName, info.name, info.id, uniqueName));
+      log.warn(String.format("Group %s with UUID %s is imported with name %s",
+          info.name, info.id, uniqueName));
       info.name = uniqueName;
     }
     AccountGroup group = createAccountGroup(info);
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 ca6efb5..bc8061e 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/importer/ImportProject.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/importer/ImportProject.java
@@ -19,7 +19,6 @@
 
 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.restapi.BadRequestException;
 import com.google.gerrit.extensions.restapi.ResourceConflictException;
@@ -99,7 +98,6 @@
   private static Logger log = LoggerFactory.getLogger(ImportProject.class);
   private static Version v2_11 = new Version("2.11");
 
-  private final String pluginName;
   private final ProjectCache projectCache;
   private final OpenRepositoryStep openRepoStep;
   private final ConfigureRepositoryStep configRepoStep;
@@ -124,7 +122,6 @@
 
   @Inject
   ImportProject(
-      @PluginName String pluginName,
       ProjectCache projectCache,
       OpenRepositoryStep openRepoStep,
       ConfigureRepositoryStep configRepoStep,
@@ -138,7 +135,6 @@
       ImportLog importLog,
       ProjectsCollection projects,
       @Assisted Project.NameKey targetProject) {
-    this.pluginName = pluginName;
     this.projectCache = projectCache;
     this.openRepoStep = openRepoStep;
     this.configRepoStep = configRepoStep;
@@ -257,11 +253,11 @@
       importLog.onImport((IdentifiedUser) currentUser.get(), srcProject,
           targetProject, input.from, e);
       String msg = input.from != null
-          ? format("[%s] Unable to transfer project '%s' from"
+          ? format("Unable to transfer project '%s' from"
               + " source gerrit host '%s'.",
-              pluginName, srcProject.get(), input.from)
-          : format("[%s] Unable to copy project '%s'.",
-              pluginName, srcProject.get());
+              srcProject.get(), input.from)
+          : format("Unable to copy project '%s'.",
+              srcProject.get());
       log.error(msg, e);
       throw e;
     }
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 69b5789..6d1d388 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/importer/ReplayChangesStep.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/importer/ReplayChangesStep.java
@@ -17,7 +17,6 @@
 import com.google.common.collect.Iterators;
 import com.google.gerrit.common.Nullable;
 import com.google.gerrit.common.errors.NoSuchAccountException;
-import com.google.gerrit.extensions.annotations.PluginName;
 import com.google.gerrit.extensions.client.ChangeStatus;
 import com.google.gerrit.extensions.common.ChangeInfo;
 import com.google.gerrit.extensions.restapi.BadRequestException;
@@ -65,7 +64,6 @@
 
   private static Logger log = LoggerFactory.getLogger(ReplayChangesStep.class);
 
-  private final String pluginName;
   private final ReplayRevisionsStep.Factory replayRevisionsFactory;
   private final ReplayInlineCommentsStep.Factory replayInlineCommentsFactory;
   private final ReplayMessagesStep.Factory replayMessagesFactory;
@@ -88,7 +86,6 @@
 
   @Inject
   ReplayChangesStep(
-      @PluginName String pluginName,
       ReplayRevisionsStep.Factory replayRevisionsFactory,
       ReplayInlineCommentsStep.Factory replayInlineCommentsFactory,
       ReplayMessagesStep.Factory replayMessagesFactory,
@@ -108,7 +105,6 @@
       @Assisted("resume") boolean resume,
       @Assisted ResumeImportStatistic importStatistic,
       @Assisted ProgressMonitor pm) {
-    this.pluginName = pluginName;
     this.replayRevisionsFactory = replayRevisionsFactory;
     this.replayInlineCommentsFactory = replayInlineCommentsFactory;
     this.replayMessagesFactory = replayMessagesFactory;
@@ -142,8 +138,8 @@
         try {
           replayChange(rw, c);
         } catch (Exception e) {
-          log.error(String.format("[%s] Failed to replay change %s.",
-              pluginName, Url.decode(c.id)), e);
+          log.error(String.format("Failed to replay change %s.",
+              Url.decode(c.id)), e);
           throw e;
         }
         pm.update(1);
@@ -176,14 +172,7 @@
     }
 
     if (c.revisions.isEmpty()) {
-      log.warn(String.format("[%s] Change %s has no revisions.",
-          pluginName, c.id));
-      return;
-    }
-    if (c.currentRevision == null) {
-      log.warn(String.format(
-          "[%s] Change %s has no current revision.",
-          pluginName, c.id));
+      log.warn(String.format("Change %s has no revisions.", c.id));
       return;
     }
 
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 7ce0212..0dda6e6 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/importer/ReplayInlineCommentsStep.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/importer/ReplayInlineCommentsStep.java
@@ -22,7 +22,6 @@
 import com.google.common.collect.Multimap;
 import com.google.gerrit.common.TimeUtil;
 import com.google.gerrit.common.errors.NoSuchAccountException;
-import com.google.gerrit.extensions.annotations.PluginName;
 import com.google.gerrit.extensions.client.Side;
 import com.google.gerrit.extensions.common.ChangeInfo;
 import com.google.gerrit.extensions.common.CommentInfo;
@@ -73,7 +72,6 @@
   private final ChangeUpdate.Factory updateFactory;
   private final PatchLineCommentsUtil plcUtil;
   private final PatchListCache patchListCache;
-  private final String pluginName;
   private final Change change;
   private final ChangeInfo changeInfo;
   private final GerritApi api;
@@ -87,7 +85,6 @@
       ChangeUpdate.Factory updateFactory,
       PatchLineCommentsUtil plcUtil,
       PatchListCache patchListCache,
-      @PluginName String pluginName,
       @Assisted Change change,
       @Assisted ChangeInfo changeInfo,
       @Assisted GerritApi api,
@@ -99,7 +96,6 @@
     this.updateFactory = updateFactory;
     this.plcUtil = plcUtil;
     this.patchListCache = patchListCache;
-    this.pluginName = pluginName;
     this.change = change;
     this.changeInfo = changeInfo;
     this.api = api;
@@ -117,14 +113,22 @@
           // it must be a revision that was created in the target system after
           // the initial import
           log.warn(String.format(
-              "[%s] Project %s was modified in target system: "
+              "Project %s was modified in target system: "
                   + "Skip replay inline comments for patch set %s"
                   + " which doesn't exist in the source system.",
-              pluginName, change.getProject().get(), ps.getId().toString()));
+              change.getProject().get(), ps.getId().toString()));
           continue;
         }
 
         comments = filterComments(ps, comments);
+      } else if (comments == null) {
+        log.warn(String.format(
+            "Cannot retrieve comments for revision %s, "
+                + "revision not found in source system: "
+                + "Skip replay inline comments for patch set %s of project %s.",
+            ps.getRevision().get(), ps.getId().toString(),
+            change.getProject().get()));
+        continue;
       }
 
       Multimap<Account.Id, CommentInfo> commentsByAuthor = ArrayListMultimap.create();
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 084d3cb..a4b4601 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/importer/ReplayRevisionsStep.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/importer/ReplayRevisionsStep.java
@@ -15,7 +15,6 @@
 package com.googlesource.gerrit.plugins.importer;
 
 import com.google.gerrit.common.errors.NoSuchAccountException;
-import com.google.gerrit.extensions.annotations.PluginName;
 import com.google.gerrit.extensions.common.ChangeInfo;
 import com.google.gerrit.extensions.common.RevisionInfo;
 import com.google.gerrit.extensions.restapi.BadRequestException;
@@ -58,7 +57,6 @@
   private final AccountUtil accountUtil;
   private final ReviewDb db;
   private final PatchSetInfoFactory patchSetInfoFactory;
-  private final String pluginName;
   private final Repository repo;
   private final RevWalk rw;
   private final Change change;
@@ -68,7 +66,6 @@
   public ReplayRevisionsStep(AccountUtil accountUtil,
       ReviewDb db,
       PatchSetInfoFactory patchSetInfoFactory,
-      @PluginName String pluginName,
       @Assisted Repository repo,
       @Assisted RevWalk rw,
       @Assisted Change change,
@@ -76,7 +73,6 @@
     this.accountUtil = accountUtil;
     this.db = db;
     this.patchSetInfoFactory = patchSetInfoFactory;
-    this.pluginName = pluginName;
     this.repo = repo;
     this.rw = rw;
     this.change = change;
@@ -91,6 +87,7 @@
 
     db.changes().beginTransaction(change.getId());
     try {
+      PatchSetInfo info = null;
       for (RevisionInfo r : revisions) {
         if (r.draft != null && r.draft) {
           // no import of draft patch sets
@@ -114,9 +111,9 @@
             // a patch set with the same number was created both in the source
             // and in the target system
             log.warn(String.format(
-                "[%s] Project %s was modified in target system: "
+                "Project %s was modified in target system: "
                     + "Skip replay revision for patch set %s.",
-                pluginName, change.getProject().get(), ps.getId().toString()));
+                change.getProject().get(), ps.getId().toString()));
             continue;
           }
         }
@@ -128,8 +125,8 @@
         ps.setRevision(new RevId(commit.name()));
         ps.setDraft(r.draft != null && r.draft);
 
-        PatchSetInfo info = patchSetInfoFactory.get(commit, ps.getId());
-        if (changeInfo.currentRevision.equals(info.getRevId())) {
+        info = patchSetInfoFactory.get(commit, ps.getId());
+        if (info.getRevId().equals(changeInfo.currentRevision)) {
           change.setCurrentPatchSet(info);
         }
 
@@ -138,6 +135,21 @@
         updateRef(repo, ps);
       }
 
+      if (change.currentPatchSetId() == null) {
+        if (changeInfo.currentRevision != null) {
+          log.warn(String.format(
+              "Current revision %s of change %s not found."
+              + " Setting lastest revision %s as current patch set.",
+              changeInfo.currentRevision, changeInfo.id, info.getRevId()));
+        } else {
+          log.warn(String.format(
+              "Change %s has no current revision."
+              + " Setting lastest revision %s as current patch set.",
+              changeInfo.id, info.getRevId()));
+        }
+        change.setCurrentPatchSet(info);
+      }
+
       db.patchSets().insert(patchSets);
       db.commit();
     } finally {
diff --git a/src/main/resources/Documentation/about.md b/src/main/resources/Documentation/about.md
index e320dfe..e69aed0 100644
--- a/src/main/resources/Documentation/about.md
+++ b/src/main/resources/Documentation/about.md
@@ -41,6 +41,8 @@
 On project import the configured max object size on the target Gerrit
 server is ignored.
 
+Draft changes, draft patch sets and change edits are *not* imported.
+
 <a id="project-import-process">
 #### Process
 
@@ -87,7 +89,10 @@
 For auth type 'LDAP', 'HTTP\_LDAP' or 'CLIENT\_SSL\_CERT\_LDAP' missing
 user accounts are automatically created. The public SSH keys of a user
 are automatically retrieved from the source Gerrit server and added to
-the new account in the target Gerrit server.
+the new account in the target Gerrit server. For this the remote user
+must have the link:access-control.html#capability_modifyAccount[Modify
+Account] or the link:access-control.html#capability_administrateServer[
+Administrate Server] capability assigned on the source system.
 
 Gerrit internal users (e.g. service users) are never automatically
 created but must be created in the target Gerrit server before the