From f1cf49218fb40b61f82ff74dbb7eaba32b439a5a Mon Sep 17 00:00:00 2001
From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
Date: Thu, 29 Jan 2015 17:07:44 -0800
Subject: [PATCH] Improve contribution calendar on user page

* cache user contributions for day
* ignore forks in calendar contribtuions
---
 app/controllers/users_controller.rb |  9 +++------
 app/models/project_contributions.rb | 23 +++++++++++++++++++++++
 lib/gitlab/commits_calendar.rb      | 16 ++++++++++++----
 3 files changed, 38 insertions(+), 10 deletions(-)
 create mode 100644 app/models/project_contributions.rb

diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index ff5e31067fb..57d8ef09faf 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -28,13 +28,10 @@ class UsersController < ApplicationController
 
   def calendar
     visible_projects = ProjectsFinder.new.execute(current_user)
-
-    # Get user repositories and collect timestamps for commits
-    user_repositories = visible_projects.map(&:repository)
-    calendar = Gitlab::CommitsCalendar.new(user_repositories, @user)
+    calendar = Gitlab::CommitsCalendar.new(visible_projects, @user)
     @timestamps = calendar.timestamps
-    @starting_year = (Time.now - 1.year).strftime("%Y")
-    @starting_month = Date.today.strftime("%m").to_i
+    @starting_year = calendar.starting_year
+    @starting_month = calendar.starting_month
 
     render 'calendar', layout: false
   end
diff --git a/app/models/project_contributions.rb b/app/models/project_contributions.rb
new file mode 100644
index 00000000000..8ab2d814a94
--- /dev/null
+++ b/app/models/project_contributions.rb
@@ -0,0 +1,23 @@
+class ProjectContributions
+  attr_reader :project, :user
+
+  def initialize(project, user)
+    @project, @user = project, user
+  end
+
+  def commits_log
+    repository = project.repository
+
+    if !repository.exists? || repository.empty?
+      return {}
+    end
+
+    Rails.cache.fetch(cache_key) do
+      repository.commits_per_day_for_user(user)
+    end
+  end
+
+  def cache_key
+    "#{Date.today.to_s}-commits-log-#{project.id}-#{user.email}"
+  end
+end
diff --git a/lib/gitlab/commits_calendar.rb b/lib/gitlab/commits_calendar.rb
index ccc80d080af..2f30d238e6b 100644
--- a/lib/gitlab/commits_calendar.rb
+++ b/lib/gitlab/commits_calendar.rb
@@ -2,15 +2,15 @@ module Gitlab
   class CommitsCalendar
     attr_reader :timestamps
 
-    def initialize(repositories, user)
+    def initialize(projects, user)
       @timestamps = {}
       date_timestamps = []
 
-      repositories.select(&:exists?).reject(&:empty?).each do |raw_repository|
-        commits_log = raw_repository.commits_per_day_for_user(user)
-        date_timestamps << commits_log
+      projects.reject(&:forked?).each do |project|
+        date_timestamps << ProjectContributions.new(project, user).commits_log
       end
 
+      # Sumarrize commits from all projects per days
       date_timestamps = date_timestamps.inject do |collection, date|
         collection.merge(date) { |k, old_v, new_v| old_v + new_v }
       end
@@ -21,5 +21,13 @@ module Gitlab
         @timestamps[timestamp] = commits if timestamp
       end
     end
+
+    def starting_year
+      (Time.now - 1.year).strftime("%Y")
+    end
+
+    def starting_month
+      Date.today.strftime("%m").to_i
+    end
   end
 end
-- 
GitLab