~edwargix/git.sr.ht

8d4410893a6555f235467f6ca3c26eda3fe2d030 — Ludovic Chabant 5 years ago 046cd38
Use scmsrht's contributors template and API
2 files changed, 8 insertions(+), 101 deletions(-)

M gitsrht/blueprints/stats.py
M gitsrht/templates/contributors.html
M gitsrht/blueprints/stats.py => gitsrht/blueprints/stats.py +6 -55
@@ 1,30 1,15 @@
import pygit2
from collections import defaultdict
from datetime import date, datetime, timedelta
from datetime import datetime, timedelta
from flask import Blueprint, render_template
from functools import lru_cache
from gitsrht.git import Repository as GitRepository
from gitsrht.types import User
from scmsrht.access import get_repo_or_redir
from scmsrht.stats import RepoContributions, get_contrib_chart_data

stats = Blueprint('stats', __name__)

def _week(time):
    """Used to group contributions by week"""
    return time.strftime('%Y/%W')

@lru_cache(maxsize=256)
def _user(email, name):
    """Used to grouped contributions by either username or email."""
    email = email.lower()
    user = User.query.filter_by(email=email).one_or_none()
    return (None, name, user.username) if user else (email, name, None)

def get_contributions(git_repo, tip, since):
    contributions = defaultdict(lambda: {
        "commits": 0,
        "weekly": defaultdict(lambda: 0)
    })
    contributions = RepoContributions(User)

    since_ts = since.timestamp()
    for commit in git_repo.walk(tip.id, pygit2.GIT_SORT_TIME):


@@ 32,46 17,12 @@ def get_contributions(git_repo, tip, since):
        if timestamp < since_ts:
            break

        try:
            week = _week(datetime.fromtimestamp(timestamp))
        except:
            continue
        user = _user(commit.author.email, commit.author.name)
        contributions[user]['commits'] += 1
        contributions[user]['weekly'][week] += 1
        user = contributions.get_or_create_user(
            commit.author.email, commit.author.name)
        user.add_commit(timestamp)

    return contributions

def get_contrib_chart_data(contributions):
    # Max number of commits by a contributor in a single week
    try:
        max_commits = max(
            max(commits for _, commits in data['weekly'].items())
            for _, data in contributions.items())
    except:
        max_commits = 0

    all_weeks = [_week(date.today() - timedelta(weeks=51 - n))
        for n in range(52)]

    def bars(contributions):
        bars = list()
        for ordinal, week in enumerate(all_weeks):
            if week in contributions:
                week_commits = contributions[week]
                bars.append({
                    "ordinal": ordinal,
                    "week": week,
                    "commits": week_commits,
                    "height": 100 * week_commits // max_commits
                })
        return bars

    chart_data = [
        (email, full_name, username, data['commits'], bars(data['weekly']))
        for (email, full_name, username), data in contributions.items()]
    return sorted(chart_data, key=lambda x: x[3], reverse=True)

@stats.route("/<owner>/<repo>/contributors")
def contributors(owner, repo):
    owner, repo = get_repo_or_redir(owner, repo)

M gitsrht/templates/contributors.html => gitsrht/templates/contributors.html +2 -46
@@ 8,53 8,9 @@
{% endblock %}

{% block head %}
  <style type="text/css">
    svg.contributors { background-color: WhiteSmoke }
    rect { fill: #116bdd }
    rect:hover { fill: #dc3545 }
  </style>
{% include "partials/scmcontrib-head.html" %}
{% endblock %}

{% block content %}
<div class="container">
  <p>
    Contributions to {{repo.owner.canonical_name}}/{{repo.name}}
    in the last 52 weeks:
  </p>
  <div class="row">
  {% for email, full_name, username, commits, bars in chart_data %}
    <div class="col-md-6">
      <h3>
        {% if username %}
          <a href="{{ url_for('public.user_index', username=username) }}">
            ~{{ username }}
          </a>
        {% else %}
          {{ full_name }}
        {% endif %}
        <small>{{ commits }} commits</small>
      </h3>

      <svg
        version="1.1"
        baseProfile="full"
        viewBox="0 0 520 100"
        xmlns="http://www.w3.org/2000/svg"
	class="contributors"
      >
        {% for bar in bars %}
          <rect
            x="{{ bar.ordinal * 10 }}"
            y="{{ 100 - bar.height }}%"
            width="11"
            height="{{ bar.height }}%"
          >
            <title>{{ bar.commits }} commits in the week of {{ bar.week }}</title>
          </rect>
        {% endfor %}
      </svg>
    </div>
  {% endfor %}
  </div>
</div>
{% include "partials/scmcontrib-body.html" %}
{% endblock %}