From a9288e554e55e843b95ab6f8109a4c610af64c83 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 29 Jan 2015 00:53:43 -0800 Subject: [PATCH] Cleanup and make contribution calendar faster --- app/assets/javascripts/calendar.js.coffee | 42 +----------- app/controllers/users_controller.rb | 19 +----- app/models/repository.rb | 33 +++++---- app/views/users/_calendar.html.haml | 6 +- app/views/users/_calendar_onclick.html.haml | 25 ------- app/views/users/show.html.haml | 4 +- lib/gitlab/commits_calendar.rb | 74 ++++----------------- spec/controllers/users_controller_spec.rb | 4 +- 8 files changed, 42 insertions(+), 165 deletions(-) delete mode 100644 app/views/users/_calendar_onclick.html.haml diff --git a/app/assets/javascripts/calendar.js.coffee b/app/assets/javascripts/calendar.js.coffee index c5465f92076..6a0d5e43567 100644 --- a/app/assets/javascripts/calendar.js.coffee +++ b/app/assets/javascripts/calendar.js.coffee @@ -4,11 +4,13 @@ class @calendar day: "numeric" year: "numeric" - constructor: (timestamps, starting_year, starting_month, activities_path) -> + constructor: (timestamps, starting_year, starting_month) -> cal = new CalHeatMap() cal.init itemName: ["commit"] data: timestamps + domain: "year" + subDomain: "month" start: new Date(starting_year, starting_month) domainLabelFormat: "%b" id: "cal-heatmap" @@ -29,43 +31,5 @@ class @calendar ] legendCellPadding: 3 onClick: (date, count) -> - $.ajax - url: activities_path - data: - date: date - - dataType: "json" - success: (data) -> - $("#loading_commits").fadeIn() - calendar.calendarOnClick data, date, count - setTimeout (-> - $("#calendar_onclick_placeholder").fadeIn 500 - return - ), 400 - setTimeout (-> - $("#loading_commits").hide() - return - ), 400 - return return return - - @calendarOnClick: (data, date, nb)-> - $("#calendar_onclick_placeholder").hide() - $("#calendar_onclick_placeholder").html -> - "" + - ((if nb is null then "no" else nb)) + - " commit" + - ((if (nb isnt 1) then "s" else "")) + " " + - date.toLocaleDateString("en-US", options) + - "
" - $.each data, (key, data) -> - $.each data, (index, data) -> - $("#calendar_onclick_placeholder").append -> - "Pushed " + ((if data is null then "no" else data)) + " commit" + - ((if (data isnt 1) then "s" else "")) + - " to " + - index + "
" - return - return - return diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 28de2707778..9e5ea6cfa45 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -25,12 +25,12 @@ class UsersController < ApplicationController @title = @user.name + # Get user repositories and collect timestamps for commits user_repositories = visible_projects.map(&:repository) - @timestamps = Gitlab::CommitsCalendar.create_timestamp(user_repositories, - @user, false) + calendar = Gitlab::CommitsCalendar.new(user_repositories, @user) + @timestamps = calendar.timestamps @starting_year = (Time.now - 1.year).strftime("%Y") @starting_month = Date.today.strftime("%m").to_i - @last_commit_date = Gitlab::CommitsCalendar.last_commit_date(@timestamps) respond_to do |format| format.html @@ -38,19 +38,6 @@ class UsersController < ApplicationController end end - def activities - user = User.find_by_username!(params[:username]) - # Projects user can view - visible_projects = ProjectsFinder.new.execute(current_user) - - user_repositories = visible_projects.map(&:repository) - user_activities = Gitlab::CommitsCalendar.create_timestamp(user_repositories, - user, true) - user_activities = Gitlab::CommitsCalendar.commit_activity_match( - user_activities, params[:date]) - render json: user_activities.to_json - end - def determine_layout if current_user 'navless' diff --git a/app/models/repository.rb b/app/models/repository.rb index e44ecca865c..f6400f7aff1 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -139,39 +139,36 @@ class Repository def graph_log Rails.cache.fetch(cache_key(:graph_log)) do - - # handle empty repos that don't have a root_ref set yet - unless raw_repository.root_ref.present? - raw_repository.root_ref = 'refs/heads/master' - end - - commits = raw_repository.log(limit: 6000, skip_merges: true, - ref: raw_repository.root_ref) + commits = raw_repository.log(limit: 6000, + skip_merges: true, + ref: root_ref) commits.map do |rugged_commit| - commit = Gitlab::Git::Commit.new(rugged_commit) + { author_name: commit.author_name.force_encoding('UTF-8'), author_email: commit.author_email.force_encoding('UTF-8'), additions: commit.stats.additions, deletions: commit.stats.deletions, - date: commit.committed_date } end end end - def graph_logs_by_user_email(user) - graph_log.select { |u_email| u_email[:author_email] == user.email } + def timestamps_by_user_log(user) + args = %W(git log --author=#{user.email} --since=#{(Date.today - 1.year).to_s} --pretty=format:%cd --date=short) + dates = Gitlab::Popen.popen(args, path_to_repo).first.split("\n") + + if dates.present? + dates + else + [] + end end - def timestamps_by_user_from_graph_log(user) - graph_logs_by_user_email(user).map { |graph_log| graph_log[:date].to_time.to_i } - end - - def commits_log_of_user_by_date(user) - timestamps_by_user_from_graph_log(user). + def commits_per_day_for_user(user) + timestamps_by_user_log(user). group_by { |commit_date| commit_date }. inject({}) do |hash, (timestamp_date, commits)| hash[timestamp_date] = commits.count diff --git a/app/views/users/_calendar.html.haml b/app/views/users/_calendar.html.haml index 70d5cca854d..b16a7305a32 100644 --- a/app/views/users/_calendar.html.haml +++ b/app/views/users/_calendar.html.haml @@ -1,9 +1,7 @@ #cal-heatmap.calendar - :javascript + :javascript new calendar( #{@timestamps.to_json}, #{@starting_year}, - #{@starting_month}, - '#{user_activities_path}' + #{@starting_month} ); -= render "calendar_onclick" diff --git a/app/views/users/_calendar_onclick.html.haml b/app/views/users/_calendar_onclick.html.haml deleted file mode 100644 index 1514b56bb23..00000000000 --- a/app/views/users/_calendar_onclick.html.haml +++ /dev/null @@ -1,25 +0,0 @@ -#calendar_commit_activity.calendar_commit_activity - %h4.activity_title Commit Activity: - - #loading_commits - %section.text-center - %h3 - %i.icon-spinner.icon-spin - - #calendar_onclick_placeholder.calendar_onclick_placeholder - %span.calendar_onclick_second.calendar_onclick_second - - if @timestamps.empty? - %span.calendar_activity_summary - %strong> #{@user.username} -   has no activity - - else - %span.calendar_activity_summary - %strong> #{@user.username} - 's last commit was on - %span.commit_date #{@last_commit_date} - - %hr.calendar_onclick_hr - -:javascript - $("#loading_commits").hide(); - diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml index 0d214d31607..c248a280475 100644 --- a/app/views/users/show.html.haml +++ b/app/views/users/show.html.haml @@ -18,8 +18,10 @@ %h4 Groups: = render 'groups', groups: @groups %hr + %h4 Calendar: - = render 'calendar' + %div= render 'calendar' + %hr %h4 User Activity: diff --git a/lib/gitlab/commits_calendar.rb b/lib/gitlab/commits_calendar.rb index 93256187fd2..b6699c585f6 100644 --- a/lib/gitlab/commits_calendar.rb +++ b/lib/gitlab/commits_calendar.rb @@ -1,71 +1,25 @@ module Gitlab class CommitsCalendar - def self.create_timestamp(repositories, user, show_activity) - timestamps = {} - repositories.each do |raw_repository| - if raw_repository.exists? - commits_log = raw_repository.commits_log_of_user_by_date(user) + attr_reader :timestamps - populated_timestamps = - if show_activity - populate_timestamps_by_project( - commits_log, - timestamps, - raw_repository - ) - else - populate_timestamps(commits_log, timestamps) - end - timestamps.merge!(populated_timestamps) - end + def initialize(repositories, 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 end - timestamps - end - def self.populate_timestamps(commits_log, timestamps) - commits_log.each do |timestamp_date, commits_count| - hash = { "#{timestamp_date}" => commits_count } - if timestamps.has_key?("#{timestamp_date}") - timestamps.merge!(hash) do |timestamp_date, commits_count, - new_commits_count| commits_count = commits_count.to_i + - new_commits_count - end - else - timestamps.merge!(hash) - end + date_timestamps = date_timestamps.inject do |collection, date| + collection.merge(date) { |k, old_v, new_v| old_v + new_v } end - timestamps - end - def self.populate_timestamps_by_project(commits_log, timestamps, - project) - commits_log.each do |timestamp_date, commits_count| - if timestamps.has_key?("#{timestamp_date}") - timestamps["#{timestamp_date}"]. - merge!(project.path_with_namespace => commits_count) - else - hash = { "#{timestamp_date}" => { project.path_with_namespace => - commits_count } } - timestamps.merge!(hash) - end + date_timestamps ||= [] + date_timestamps.each do |date, commits| + timestamp = Date.parse(date).to_time.to_i.to_s + @timestamps[timestamp] = commits end - timestamps - end - - def self.latest_commit_date(timestamps) - if timestamps.nil? || timestamps.empty? - DateTime.now.to_date - else - Time.at(timestamps.keys.first.to_i).to_date - end - end - - def self.last_commit_date(timestamps) - latest_commit_date(timestamps).to_formatted_s(:long).to_s - end - - def self.commit_activity_match(user_activities, date) - user_activities.select { |x| Time.at(x.to_i) == Time.parse(date) } end end end diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb index bfbe5254bbe..0c537a552c2 100644 --- a/spec/controllers/users_controller_spec.rb +++ b/spec/controllers/users_controller_spec.rb @@ -2,12 +2,12 @@ require 'spec_helper' describe UsersController do let(:user) { create(:user, username: "user1", name: "User 1", email: "user1@gitlab.com") } - + before do sign_in(user) end - describe "GET #show" do + describe "GET #show" do render_views before do get :show, username: user.username