Add project description to GetConfig and PutConfig REST endpoints

We already have REST endpoints to get and set the project description
(GET and PUT on /projects/*/description), however on the
ProjectInfoScreen we have a single save button to save both the project
description and the project configuration settings. Triggering two calls
in parallel with a callback group, one to update the project description
and one to update the project configuration, is likely failing because
both requests need to update the project.config file. If it happens in
parallel one request will get a LOCK_FAILURE. Also it would be bad to
create two commits for a single save action. This is why it makes sense
to also allow to get and set the project description via the GetConfig
and PutConfig REST endpoints.

Change-Id: I4044dc6b10f24215cc3c30a9e08afad60aa6284a
Signed-off-by: Edwin Kempin <edwin.kempin@sap.com>
diff --git a/Documentation/rest-api-projects.txt b/Documentation/rest-api-projects.txt
index 76e2f0e..628a11b 100644
--- a/Documentation/rest-api-projects.txt
+++ b/Documentation/rest-api-projects.txt
@@ -436,6 +436,7 @@
   )]}'
   {
     "kind": "gerritcodereview#project_config",
+    "description": "demo project",
     "use_contributor_agreements": {
       "value": true,
       "configured_value": "TRUE",
@@ -484,6 +485,7 @@
   Content-Type: application/json;charset=UTF-8
 
   {
+    "description": "demo project",
     "use_contributor_agreements": "FALSE",
     "use_content_merge": "INHERIT",
     "use_signed_off_by": "INHERIT",
@@ -1144,6 +1146,8 @@
 [options="header",width="50%",cols="1,^2,4"]
 |=========================================
 |Field Name                  ||Description
+|`description`               |optional|
+The description of the project.
 |`use_contributor_agreements`|optional|
 link:#inherited-boolean-info[InheritedBooleanInfo] that tells whether
 authors must complete a contributor agreement on the site before
@@ -1193,6 +1197,9 @@
 [options="header",width="50%",cols="1,^2,4"]
 |=========================================
 |Field Name                  ||Description
+|`description`               |optional|
+The new description of the project. +
+If not set, the description is removed.
 |`use_contributor_agreements`|optional|
 Whether authors must complete a contributor agreement on the site
 before pushing any commits or changes to this project. +
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/GetConfig.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/GetConfig.java
index 6140cb4..4f98408 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/GetConfig.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/GetConfig.java
@@ -14,6 +14,7 @@
 
 package com.google.gerrit.server.project;
 
+import com.google.common.base.Strings;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Maps;
 import com.google.gerrit.extensions.restapi.RestReadView;
@@ -42,6 +43,7 @@
   public static class ConfigInfo {
     public final String kind = "gerritcodereview#project_config";
 
+    public String description;
     public InheritedBooleanInfo useContributorAgreements;
     public InheritedBooleanInfo useContentMerge;
     public InheritedBooleanInfo useSignedOffBy;
@@ -55,6 +57,8 @@
 
     public ConfigInfo(ProjectState state, TransferConfig config) {
       Project p = state.getProject();
+      this.description = Strings.emptyToNull(p.getDescription());
+
       InheritedBooleanInfo useContributorAgreements =
           new InheritedBooleanInfo();
       InheritedBooleanInfo useSignedOffBy = new InheritedBooleanInfo();
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/PutConfig.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/PutConfig.java
index 173d589..05c009d 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/PutConfig.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/PutConfig.java
@@ -14,6 +14,7 @@
 
 package com.google.gerrit.server.project;
 
+import com.google.common.base.Strings;
 import com.google.gerrit.extensions.restapi.BadRequestException;
 import com.google.gerrit.extensions.restapi.ResourceConflictException;
 import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
@@ -37,6 +38,7 @@
 
 public class PutConfig implements RestModifyView<ProjectResource, Input> {
   public static class Input {
+    public String description;
     public InheritableBoolean useContributorAgreements;
     public InheritableBoolean useContentMerge;
     public InheritableBoolean useSignedOffBy;
@@ -90,6 +92,8 @@
       ProjectConfig projectConfig = ProjectConfig.read(md);
       Project p = projectConfig.getProject();
 
+      p.setDescription(Strings.emptyToNull(input.description));
+
       if (input.useContributorAgreements != null) {
         p.setUseContributorAgreements(input.useContributorAgreements);
       }