Merge "Fix displaying of file diff if draft patch has been deleted" into stable-2.5
diff --git a/Documentation/config-gerrit.txt b/Documentation/config-gerrit.txt
index 523823d..5e2cc18 100644
--- a/Documentation/config-gerrit.txt
+++ b/Documentation/config-gerrit.txt
@@ -1012,6 +1012,10 @@
 
 ----
 [download]
+  command = checkout
+  command = cherry_pick
+  command = pull
+  command = format_patch
   scheme = ssh
   scheme = http
   scheme = anon_http
@@ -1021,6 +1025,34 @@
 
 The download section configures the allowed download methods.
 
+[[download.command]]download.command::
++
+Commands that should be offered to download changes.
++
+Multiple commands are supported:
++
+* `checkout`
++
+Command to fetch and checkout the patch set.
++
+* `cherry_pick`
++
+Command to fetch the patch set and to cherry-pick it onto the current
+commit.
++
+* `pull`
++
+Command to pull the patch set.
++
+* `format_patch`
++
+Command to fetch the patch set and to feed it into the `format-patch`
+command.
+
++
+If `download.command` is not specified, all download commands are
+offered.
+
 [[download.scheme]]download.scheme::
 +
 Schemes that should be used to download changes.
@@ -1053,7 +1085,7 @@
 not default, as not all instances will deploy repo.
 
 +
-If download.scheme is not specified, SSH, HTTP and Anonymous HTTP
+If `download.scheme` is not specified, SSH, HTTP and Anonymous HTTP
 downloads are allowed.
 
 [[gerrit]]Section gerrit
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/GerritConfig.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/GerritConfig.java
index 8436456..7c16129 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/GerritConfig.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/GerritConfig.java
@@ -17,6 +17,7 @@
 import com.google.gerrit.common.auth.openid.OpenIdProviderPattern;
 import com.google.gerrit.reviewdb.client.Account;
 import com.google.gerrit.reviewdb.client.Account.FieldName;
+import com.google.gerrit.reviewdb.client.AccountGeneralPreferences.DownloadCommand;
 import com.google.gerrit.reviewdb.client.AccountGeneralPreferences.DownloadScheme;
 import com.google.gerrit.reviewdb.client.AuthType;
 import com.google.gerrit.reviewdb.client.Project;
@@ -38,6 +39,7 @@
   protected boolean allowRegisterNewEmail;
   protected AuthType authType;
   protected Set<DownloadScheme> downloadSchemes;
+  protected Set<DownloadCommand> downloadCommands;
   protected String gitDaemonUrl;
   protected String gitHttpUrl;
   protected String sshdAddress;
@@ -114,6 +116,14 @@
     downloadSchemes = s;
   }
 
+  public Set<DownloadCommand> getDownloadCommands() {
+    return downloadCommands;
+  }
+
+  public void setDownloadCommands(final Set<DownloadCommand> downloadCommands) {
+    this.downloadCommands = downloadCommands;
+  }
+
   public GitwebConfig getGitwebLink() {
     return gitweb;
   }
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeScreen.java
index 5fde797..f4ce04d 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeScreen.java
@@ -310,7 +310,8 @@
     if (detail.getNeededBy() != null) {
       for (final ChangeInfo ci : detail.getNeededBy()) {
         if ((ci.getStatus() == Change.Status.NEW) ||
-            (ci.getStatus() == Change.Status.SUBMITTED)) {
+            (ci.getStatus() == Change.Status.SUBMITTED) ||
+            (ci.getStatus() == Change.Status.DRAFT)) {
           depsOpen = true;
         }
       }
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PatchSetComplexDisclosurePanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PatchSetComplexDisclosurePanel.java
index 77099ab..7e314cc 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PatchSetComplexDisclosurePanel.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PatchSetComplexDisclosurePanel.java
@@ -209,6 +209,7 @@
     final DownloadCommandPanel commands = new DownloadCommandPanel();
     final DownloadUrlPanel urls = new DownloadUrlPanel(commands);
     final Set<DownloadScheme> allowedSchemes = Gerrit.getConfig().getDownloadSchemes();
+    final Set<DownloadCommand> allowedCommands = Gerrit.getConfig().getDownloadCommands();
 
     copyLabel.setStyleName(Gerrit.RESOURCES.css().downloadLinkCopyLabel());
 
@@ -323,39 +324,52 @@
     }
 
     if (!urls.isEmpty()) {
-      commands.add(new DownloadCommandLink(DownloadCommand.CHECKOUT, "checkout") {
-        @Override
-        void setCurrentUrl(DownloadUrlLink link) {
-          urls.setVisible(true);
-          copyLabel.setText("git fetch " + link.urlData
-              + " && git checkout FETCH_HEAD");
-        }
-      });
-      commands.add(new DownloadCommandLink(DownloadCommand.PULL, "pull") {
-        @Override
-        void setCurrentUrl(DownloadUrlLink link) {
-          urls.setVisible(true);
-          copyLabel.setText("git pull " + link.urlData);
-        }
-      });
-      commands.add(new DownloadCommandLink(DownloadCommand.CHERRY_PICK,
-          "cherry-pick") {
-        @Override
-        void setCurrentUrl(DownloadUrlLink link) {
-          urls.setVisible(true);
-          copyLabel.setText("git fetch " + link.urlData
-              + " && git cherry-pick FETCH_HEAD");
-        }
-      });
-      commands.add(new DownloadCommandLink(DownloadCommand.FORMAT_PATCH,
-          "patch") {
-        @Override
-        void setCurrentUrl(DownloadUrlLink link) {
-          urls.setVisible(true);
-          copyLabel.setText("git fetch " + link.urlData
-              + " && git format-patch -1 --stdout FETCH_HEAD");
-        }
-      });
+      if (allowedCommands.contains(DownloadCommand.CHECKOUT)
+          || allowedCommands.contains(DownloadCommand.DEFAULT_DOWNLOADS)) {
+        commands.add(new DownloadCommandLink(DownloadCommand.CHECKOUT,
+            "checkout") {
+          @Override
+          void setCurrentUrl(DownloadUrlLink link) {
+            urls.setVisible(true);
+            copyLabel.setText("git fetch " + link.urlData
+                + " && git checkout FETCH_HEAD");
+          }
+        });
+      }
+      if (allowedCommands.contains(DownloadCommand.PULL)
+          || allowedCommands.contains(DownloadCommand.DEFAULT_DOWNLOADS)) {
+        commands.add(new DownloadCommandLink(DownloadCommand.PULL, "pull") {
+          @Override
+          void setCurrentUrl(DownloadUrlLink link) {
+            urls.setVisible(true);
+            copyLabel.setText("git pull " + link.urlData);
+          }
+        });
+      }
+      if (allowedCommands.contains(DownloadCommand.CHERRY_PICK)
+          || allowedCommands.contains(DownloadCommand.DEFAULT_DOWNLOADS)) {
+        commands.add(new DownloadCommandLink(DownloadCommand.CHERRY_PICK,
+            "cherry-pick") {
+          @Override
+          void setCurrentUrl(DownloadUrlLink link) {
+            urls.setVisible(true);
+            copyLabel.setText("git fetch " + link.urlData
+                + " && git cherry-pick FETCH_HEAD");
+          }
+        });
+      }
+      if (allowedCommands.contains(DownloadCommand.FORMAT_PATCH)
+          || allowedCommands.contains(DownloadCommand.DEFAULT_DOWNLOADS)) {
+        commands.add(new DownloadCommandLink(DownloadCommand.FORMAT_PATCH,
+            "patch") {
+          @Override
+          void setCurrentUrl(DownloadUrlLink link) {
+            urls.setVisible(true);
+            copyLabel.setText("git fetch " + link.urlData
+                + " && git format-patch -1 --stdout FETCH_HEAD");
+          }
+        });
+      }
     }
 
     final FlowPanel fp = new FlowPanel();
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GerritConfigProvider.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GerritConfigProvider.java
index 2f09380..c1f3ae4 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GerritConfigProvider.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/GerritConfigProvider.java
@@ -22,7 +22,7 @@
 import com.google.gerrit.server.config.AllProjectsName;
 import com.google.gerrit.server.config.AnonymousCowardName;
 import com.google.gerrit.server.config.AuthConfig;
-import com.google.gerrit.server.config.DownloadSchemeConfig;
+import com.google.gerrit.server.config.DownloadConfig;
 import com.google.gerrit.server.config.GerritServerConfig;
 import com.google.gerrit.server.contact.ContactStore;
 import com.google.gerrit.server.mail.EmailSender;
@@ -48,7 +48,7 @@
   private final Realm realm;
   private final Config cfg;
   private final AuthConfig authConfig;
-  private final DownloadSchemeConfig schemeConfig;
+  private final DownloadConfig downloadConfig;
   private final GitWebConfig gitWebConfig;
   private final AllProjectsName wildProject;
   private final SshInfo sshInfo;
@@ -63,12 +63,12 @@
   GerritConfigProvider(final Realm r, @GerritServerConfig final Config gsc,
       final AuthConfig ac, final GitWebConfig gwc, final AllProjectsName wp,
       final SshInfo si, final ApprovalTypes at, final ContactStore cs,
-      final ServletContext sc, final DownloadSchemeConfig dc,
+      final ServletContext sc, final DownloadConfig dc,
       final @AnonymousCowardName String acn) {
     realm = r;
     cfg = gsc;
     authConfig = ac;
-    schemeConfig = dc;
+    downloadConfig = dc;
     gitWebConfig = gwc;
     sshInfo = si;
     wildProject = wp;
@@ -111,7 +111,8 @@
     config.setGitDaemonUrl(cfg.getString("gerrit", null, "canonicalgiturl"));
     config.setGitHttpUrl(cfg.getString("gerrit", null, "gitHttpUrl"));
     config.setUseContactInfo(contactStore != null && contactStore.isEnabled());
-    config.setDownloadSchemes(schemeConfig.getDownloadScheme());
+    config.setDownloadSchemes(downloadConfig.getDownloadSchemes());
+    config.setDownloadCommands(downloadConfig.getDownloadCommands());
     config.setAuthType(authConfig.getAuthType());
     config.setWildProject(wildProject);
     config.setApprovalTypes(approvalTypes);
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AccountGeneralPreferences.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AccountGeneralPreferences.java
index 185255c..6f121ee 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AccountGeneralPreferences.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/AccountGeneralPreferences.java
@@ -32,7 +32,7 @@
 
   /** Preferred method to download a change. */
   public static enum DownloadCommand {
-    REPO_DOWNLOAD, PULL, CHECKOUT, CHERRY_PICK, FORMAT_PATCH;
+    REPO_DOWNLOAD, PULL, CHECKOUT, CHERRY_PICK, FORMAT_PATCH, DEFAULT_DOWNLOADS;
   }
 
   public static enum DateFormat {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/DownloadSchemeConfig.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/DownloadConfig.java
similarity index 66%
rename from gerrit-server/src/main/java/com/google/gerrit/server/config/DownloadSchemeConfig.java
rename to gerrit-server/src/main/java/com/google/gerrit/server/config/DownloadConfig.java
index ecfe4f5..f259871 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/config/DownloadSchemeConfig.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/DownloadConfig.java
@@ -14,8 +14,9 @@
 
 package com.google.gerrit.server.config;
 
-import com.google.gerrit.reviewdb.client.SystemConfig;
+import com.google.gerrit.reviewdb.client.AccountGeneralPreferences.DownloadCommand;
 import com.google.gerrit.reviewdb.client.AccountGeneralPreferences.DownloadScheme;
+import com.google.gerrit.reviewdb.client.SystemConfig;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
 
@@ -28,22 +29,33 @@
 
 /** Download protocol from {@code gerrit.config}. */
 @Singleton
-public class DownloadSchemeConfig {
+public class DownloadConfig {
   private final Set<DownloadScheme> downloadSchemes;
+  private final Set<DownloadCommand> downloadCommands;
 
   @Inject
-  DownloadSchemeConfig(@GerritServerConfig final Config cfg,
+  DownloadConfig(@GerritServerConfig final Config cfg,
       final SystemConfig s) {
-    List<DownloadScheme> all =
+    List<DownloadScheme> allSchemes =
         ConfigUtil.getEnumList(cfg, "download", null, "scheme",
             DownloadScheme.DEFAULT_DOWNLOADS);
-
     downloadSchemes =
-        Collections.unmodifiableSet(new HashSet<DownloadScheme>(all));
+        Collections.unmodifiableSet(new HashSet<DownloadScheme>(allSchemes));
+
+    List<DownloadCommand> allCommands =
+        ConfigUtil.getEnumList(cfg, "download", null, "command",
+            DownloadCommand.DEFAULT_DOWNLOADS);
+    downloadCommands =
+        Collections.unmodifiableSet(new HashSet<DownloadCommand>(allCommands));
   }
 
   /** Scheme used to download. */
-  public Set<DownloadScheme> getDownloadScheme() {
+  public Set<DownloadScheme> getDownloadSchemes() {
     return downloadSchemes;
   }
+
+  /** Command used to download. */
+  public Set<DownloadCommand> getDownloadCommands() {
+    return downloadCommands;
+  }
 }
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/SetAccountCommand.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/SetAccountCommand.java
index 9cf3586..fe588e6 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/SetAccountCommand.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/SetAccountCommand.java
@@ -175,8 +175,6 @@
     if (sshKeysUpdated) {
       sshKeyCache.evict(account.getUserName());
     }
-
-    db.close();
   }
 
   private void addSshKeys(final List<String> keys, final Account account)