Allow statistics of empty commits without files

Git allows creating a commit with simply a message and no file
changes associated. To avoid our commit statistics to blow up
it is needed to protect against reduction of empty files stats.

Change-Id: If491eb37e21a0e5d4540a39914943f77177c0f14
diff --git a/src/main/scala/com/googlesource/gerrit/plugins/analytics/Contributors.scala b/src/main/scala/com/googlesource/gerrit/plugins/analytics/Contributors.scala
index 4711ee3..23ff03c 100644
--- a/src/main/scala/com/googlesource/gerrit/plugins/analytics/Contributors.scala
+++ b/src/main/scala/com/googlesource/gerrit/plugins/analytics/Contributors.scala
@@ -105,7 +105,7 @@
   private var granularity: Option[AggregationStrategy] = None
 
   @ArgOption(name = "--granularity", aliases = Array("--aggregate", "-g"), metaVar = "QUERY",
-    usage = "(excluded) end timestamp. Must be in the format 2006-01-02[ 15:04:05[.890][ -0700]]")
+    usage = "can be one of EMAIL, EMAIL_HOUR, EMAIL_DAY, EMAIL_MONTH, EMAIL_YEAR, defaulting to EMAIL")
   def setGranularity(value: String) {
     try {
       granularity = Some(AggregationStrategy.apply(value))
diff --git a/src/main/scala/com/googlesource/gerrit/plugins/analytics/common/CommitsStatistics.scala b/src/main/scala/com/googlesource/gerrit/plugins/analytics/common/CommitsStatistics.scala
index baa60ed..efff4cb 100644
--- a/src/main/scala/com/googlesource/gerrit/plugins/analytics/common/CommitsStatistics.scala
+++ b/src/main/scala/com/googlesource/gerrit/plugins/analytics/common/CommitsStatistics.scala
@@ -25,6 +25,10 @@
 
 case class CommitsStatistics(numFiles: Int, addedLines: Int, deletedLines: Int)
 
+object CommitsStatistics {
+  val Empty = CommitsStatistics(0, 0, 0)
+}
+
 class Statistics(repo: Repository) {
 
   def find(objectIds: Seq[ObjectId]): CommitsStatistics =
@@ -63,7 +67,7 @@
       val lines = (for {
         diff <- diffs
         edit <- df.toFileHeader(diff).toEditList
-      } yield Lines(edit.getEndA - edit.getBeginA, edit.getEndB - edit.getBeginB)).reduce(_ + _)
+      } yield Lines(edit.getEndA - edit.getBeginA, edit.getEndB - edit.getBeginB)).fold(Lines(0, 0))(_ + _)
 
       CommitsStatistics(diffs.size, lines.added, lines.deleted)
     }
diff --git a/src/test/scala/com/googlesource/gerrit/plugins/analytics/test/CommitStatisticsSpec.scala b/src/test/scala/com/googlesource/gerrit/plugins/analytics/test/CommitStatisticsSpec.scala
index d37a4a1..315369f 100644
--- a/src/test/scala/com/googlesource/gerrit/plugins/analytics/test/CommitStatisticsSpec.scala
+++ b/src/test/scala/com/googlesource/gerrit/plugins/analytics/test/CommitStatisticsSpec.scala
@@ -82,4 +82,11 @@
       s.deletedLines should be(1)
     }
   }
+
+  it should "not return any stats if the commit does not include any file" in new TestEnvironment {
+    val emptyCommit = add(testRepo,
+      List.empty[String].asJava,
+      List.empty[String].asJava, "Empty commit")
+    stats.find(emptyCommit) shouldBe CommitsStatistics.Empty
+  }
 }