Add author and size information to output of query.

Add author information to output of query options:
 '--patch-sets'.
 '--current-patch-set'.

Add size information to output of query options:
 '--patch-sets'.
 '--current-patch-set'.
 '--files'.

This information can now be retrieved by both SSH and
the HTTP REST API.

Change-Id: I7ef0f2dce6a4d2bd2dd2532e4bb48a22522b659a
Signed-off-by: Bruce Zu <bruce.zu@sonymobile.com>
diff --git a/Documentation/cmd-query.txt b/Documentation/cmd-query.txt
index 2feea11..963d788 100644
--- a/Documentation/cmd-query.txt
+++ b/Documentation/cmd-query.txt
@@ -65,7 +65,8 @@
 
 --files::
 	Support for listing files with patch sets and their
-	attributes (ADDED, MODIFIED, DELETED, RENAMED, COPIED).
+	attributes (ADDED, MODIFIED, DELETED, RENAMED, COPIED)
+	and size information (number of insertions and deletions).
 	Note that this option requires either the --current-patch-set
 	or the --patch-sets option in order to give any file information.
 
diff --git a/Documentation/json.txt b/Documentation/json.txt
index aea9bac..4f86a9d 100644
--- a/Documentation/json.txt
+++ b/Documentation/json.txt
@@ -107,6 +107,8 @@
 
 uploader:: Uploader of the patch set in <<account,account attribute>>.
 
+author:: Author of this patchset in <<account,account attribute>>.
+
 createdOn:: Time in seconds since the UNIX epoch when this patchset
 was created.
 
@@ -116,6 +118,10 @@
 
 files:: All changed files in this patchset in <<patch,patch attributes>>.
 
+sizeInsertions:: Size information of insertions of this patchset.
+
+sizeDeletions:: Size information of deletions of this patchset.
+
 [[approval]]
 approval
 --------
@@ -257,6 +263,9 @@
 
   REWRITE;; Sufficient amount of content changed to claim the file was rewritten.
 
+insertions:: number of insertions of this patch.
+
+deletions::  number of deletions of this patch.
 
 SEE ALSO
 --------
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/change/DeprecatedChangeQueryServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/change/DeprecatedChangeQueryServlet.java
index cf443e7..da21c51 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/change/DeprecatedChangeQueryServlet.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/change/DeprecatedChangeQueryServlet.java
@@ -73,6 +73,7 @@
     p.setIncludeCurrentPatchSet(get(req, "current-patch-set", false));
     p.setIncludePatchSets(get(req, "patch-sets", false));
     p.setIncludeApprovals(get(req, "all-approvals", false));
+    p.setIncludeFiles(get(req, "files", false));
     p.setOutput(rsp.getOutputStream(), format);
     p.query(get(req, "q", "status:open"));
   }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/events/EventFactory.java b/gerrit-server/src/main/java/com/google/gerrit/server/events/EventFactory.java
index ab3ca56..fe367cb 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/events/EventFactory.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/events/EventFactory.java
@@ -21,6 +21,7 @@
 import com.google.gerrit.reviewdb.client.Branch;
 import com.google.gerrit.reviewdb.client.Change;
 import com.google.gerrit.reviewdb.client.ChangeMessage;
+import com.google.gerrit.reviewdb.client.Patch;
 import com.google.gerrit.reviewdb.client.PatchLineComment;
 import com.google.gerrit.reviewdb.client.PatchSet;
 import com.google.gerrit.reviewdb.client.PatchSetAncestor;
@@ -34,6 +35,8 @@
 import com.google.gerrit.server.patch.PatchListCache;
 import com.google.gerrit.server.patch.PatchListEntry;
 import com.google.gerrit.server.patch.PatchListNotAvailableException;
+import com.google.gerrit.server.patch.PatchSetInfoFactory;
+import com.google.gerrit.server.patch.PatchSetInfoNotAvailableException;
 import com.google.gwtorm.server.OrmException;
 import com.google.gwtorm.server.SchemaFactory;
 import com.google.inject.Inject;
@@ -46,8 +49,8 @@
 
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Map;
 import java.util.List;
+import java.util.Map;
 
 import javax.annotation.Nullable;
 
@@ -59,17 +62,20 @@
   private final ApprovalTypes approvalTypes;
   private final PatchListCache patchListCache;
   private final SchemaFactory<ReviewDb> schema;
+  private final PatchSetInfoFactory psInfoFactory;
 
   @Inject
   EventFactory(AccountCache accountCache,
       @CanonicalWebUrl @Nullable Provider<String> urlProvider,
       ApprovalTypes approvalTypes,
+      final PatchSetInfoFactory psif,
       PatchListCache patchListCache, SchemaFactory<ReviewDb> schema) {
     this.accountCache = accountCache;
     this.urlProvider = urlProvider;
     this.approvalTypes = approvalTypes;
     this.patchListCache = patchListCache;
     this.schema = schema;
+    this.psInfoFactory = psif;
   }
 
   /**
@@ -286,6 +292,8 @@
         PatchAttribute p = new PatchAttribute();
         p.file = patch.getNewName();
         p.type = patch.getChangeType();
+        p.deletions -= patch.getDeletions();
+        p.insertions = patch.getInsertions();
         patchSetAttribute.files.add(p);
       }
     } catch (PatchListNotAvailableException e) {
@@ -323,6 +331,7 @@
     p.ref = patchSet.getRefName();
     p.uploader = asAccountAttribute(patchSet.getUploader());
     p.createdOn = patchSet.getCreatedOn().getTime() / 1000L;
+    final PatchSet.Id pId = patchSet.getId();
     try {
       final ReviewDb db = schema.open();
       try {
@@ -331,11 +340,28 @@
             patchSet.getId())) {
           p.parents.add(a.getAncestorRevision().get());
         }
+
+        p.author = asAccountAttribute(//
+            psInfoFactory.get(db, pId).getAuthor().getAccount());
+
+        Change change = db.changes().get(pId.getParentKey());
+        List<Patch> list =
+            patchListCache.get(change, patchSet).toPatchList(pId);
+        for (Patch pe : list) {
+          if (!Patch.COMMIT_MSG.equals(pe.getFileName())) {
+            p.sizeDeletions -= pe.getDeletions();
+            p.sizeInsertions += pe.getInsertions();
+          }
+        }
       } finally {
         db.close();
       }
     } catch (OrmException e) {
       log.error("Cannot load patch set data for " + patchSet.getId(), e);
+    } catch (PatchSetInfoNotAvailableException e) {
+      log.error(String.format("Cannot get authorEmail for %s.", pId), e);
+    } catch (PatchListNotAvailableException e) {
+      log.error(String.format("Cannot get size information for %s.", pId), e);
     }
     return p;
   }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/events/PatchAttribute.java b/gerrit-server/src/main/java/com/google/gerrit/server/events/PatchAttribute.java
index 3802fdd..0d2b054 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/events/PatchAttribute.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/events/PatchAttribute.java
@@ -19,4 +19,6 @@
 public class PatchAttribute {
     public String file;
     public ChangeType type;
+    public int insertions;
+    public int deletions;
 }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/events/PatchSetAttribute.java b/gerrit-server/src/main/java/com/google/gerrit/server/events/PatchSetAttribute.java
index f726ce3..1123e5f 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/events/PatchSetAttribute.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/events/PatchSetAttribute.java
@@ -23,8 +23,11 @@
   public String ref;
   public AccountAttribute uploader;
   public Long createdOn;
+  public AccountAttribute author;
 
   public List<ApprovalAttribute> approvals;
   public List<PatchSetCommentAttribute> comments;
   public List<PatchAttribute> files;
+  public int sizeInsertions;
+  public int sizeDeletions;
 }