Merge branch 'stable-2.8' into stable-2.9

* stable-2.8:
  Fix: Wrong exception mapping in ReceiveCommmits
  Fix REST example for removing included groups from a group
  rest-api-groups.txt: Correct input examples to use [] for lists

Change-Id: I36518fec208e4ab101192118aebeb6c5e0d7e34c
diff --git a/Documentation/rest-api-groups.txt b/Documentation/rest-api-groups.txt
index 26f8f94..5ca3039 100644
--- a/Documentation/rest-api-groups.txt
+++ b/Documentation/rest-api-groups.txt
@@ -1004,10 +1004,10 @@
   Content-Type: application/json;charset=UTF-8
 
   {
-    "groups": {
+    "groups": [
       "MyGroup",
       "MyOtherGroup"
-    }
+    ]
   }
 ----
 
@@ -1086,10 +1086,10 @@
   Content-Type: application/json;charset=UTF-8
 
   {
-    "members": {
+    "groups": [
       "MyGroup",
       "MyOtherGroup"
-    }
+    ]
   }
 ----
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/InsertException.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/InsertException.java
new file mode 100644
index 0000000..575ad52
--- /dev/null
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/InsertException.java
@@ -0,0 +1,30 @@
+//Copyright (C) 2014 The Android Open Source Project
+//
+//Licensed under the Apache License, Version 2.0 (the "License");
+//you may not use this file except in compliance with the License.
+//You may obtain a copy of the License at
+//
+//http://www.apache.org/licenses/LICENSE-2.0
+//
+//Unless required by applicable law or agreed to in writing, software
+//distributed under the License is distributed on an "AS IS" BASIS,
+//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//See the License for the specific language governing permissions and
+//limitations under the License.
+
+package com.google.gerrit.server.git;
+
+/**
+ * Thrown in inserting change or patchset, e.g. OrmException or IOException.
+ */
+public class InsertException extends Exception {
+  private static final long serialVersionUID = 1L;
+
+  InsertException(final String msg) {
+    super(msg, null);
+  }
+
+  InsertException(final String msg, final Throwable why) {
+    super(msg, why);
+  }
+}
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 457c827..400b2ba 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
@@ -245,14 +245,17 @@
     }
   }
 
-  private static final Function<Exception, OrmException> ORM_EXCEPTION =
-      new Function<Exception, OrmException>() {
+  private static final Function<Exception, InsertException> INSERT_EXCEPTION =
+      new Function<Exception, InsertException>() {
         @Override
-        public OrmException apply(Exception input) {
+        public InsertException apply(Exception input) {
           if (input instanceof OrmException) {
-            return (OrmException) input;
+            return new InsertException("ORM error", input);
           }
-          return new OrmException("Error updating database", input);
+          if (input instanceof IOException) {
+            return new InsertException("IO error", input);
+          }
+          return new InsertException("Error inserting change/patchset", input);
         }
       };
 
@@ -691,7 +694,7 @@
           log.error(String.format(
               "Cannot add patch set to %d of %s",
               e.getKey().get(), project.getName()), err);
-        } catch (OrmException err) {
+        } catch (InsertException err) {
           reject(replace.inputCommand, "internal server error");
           log.error(String.format(
               "Cannot add patch set to %d of %s",
@@ -725,7 +728,7 @@
     }
 
     try {
-      List<CheckedFuture<?, OrmException>> futures = Lists.newArrayList();
+      List<CheckedFuture<?, InsertException>> futures = Lists.newArrayList();
       for (ReplaceRequest replace : replaceByChange.values()) {
         if (magicBranch != null && replace.inputCommand == magicBranch.cmd) {
           futures.add(replace.insertPatchSet());
@@ -736,12 +739,12 @@
         futures.add(create.insertChange());
       }
 
-      for (CheckedFuture<?, OrmException> f : futures) {
+      for (CheckedFuture<?, InsertException> f : futures) {
         f.checkedGet();
       }
       magicBranch.cmd.setResult(OK);
-    } catch (OrmException err) {
-      log.error("Can't insert changes for " + project.getName(), err);
+    } catch (InsertException err) {
+      log.error("Can't insert change/patchset for " + project.getName(), err);
       reject(magicBranch.cmd, "internal server error");
     } catch (IOException err) {
       log.error("Can't read commits for " + project.getName(), err);
@@ -1545,7 +1548,7 @@
           ins.getPatchSet().getRefName());
     }
 
-    CheckedFuture<Void, OrmException> insertChange() throws IOException {
+    CheckedFuture<Void, InsertException> insertChange() throws IOException {
       rp.getRevWalk().parseBody(commit);
 
       final Thread caller = Thread.currentThread();
@@ -1569,7 +1572,7 @@
           return null;
         }
       }));
-      return Futures.makeChecked(future, ORM_EXCEPTION);
+      return Futures.makeChecked(future, INSERT_EXCEPTION);
     }
 
     private void insertChange(ReviewDb db) throws OrmException, IOException {
@@ -1873,7 +1876,7 @@
       return true;
     }
 
-    CheckedFuture<PatchSet.Id, OrmException> insertPatchSet()
+    CheckedFuture<PatchSet.Id, InsertException> insertPatchSet()
         throws IOException {
       rp.getRevWalk().parseBody(newCommit);
 
@@ -1900,7 +1903,7 @@
           }
         }
       }));
-      return Futures.makeChecked(future, ORM_EXCEPTION);
+      return Futures.makeChecked(future, INSERT_EXCEPTION);
     }
 
     PatchSet.Id insertPatchSet(ReviewDb db) throws OrmException, IOException {
@@ -2266,6 +2269,8 @@
               codeReviewCommit, rw, repo, project, new ArrayList<Change>(),
               new HashMap<Change.Id, CodeReviewCommit>());
       subOp.update();
+    } catch (InsertException e) {
+      log.error("Can't insert patchset", e);
     } catch (IOException e) {
       log.error("Can't scan for changes to close", e);
     } catch (OrmException e) {