Skip to content

Commit

Permalink
Get commit date
Browse files Browse the repository at this point in the history
  • Loading branch information
vstinner committed Oct 21, 2016
1 parent 4efd1cc commit 1bdc67a
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 80 deletions.
2 changes: 1 addition & 1 deletion codespeed/commits/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
from .logs import get_logs
from .logs import get_logs, get_commit_date
39 changes: 33 additions & 6 deletions codespeed/commits/logs.py
Original file line number Diff line number Diff line change
@@ -1,35 +1,62 @@
# -*- coding: utf-8 -*-
from __future__ import absolute_import, unicode_literals

import datetime
import logging

logger = logging.getLogger(__name__)


def get_logs(rev, startrev, update=False):
logs = []
project = rev.branch.project
def get_scm(project):
if project.repo_type == project.SUBVERSION:
from .subversion import getlogs, updaterepo
elif project.repo_type == project.MERCURIAL:
from .mercurial import getlogs, updaterepo
from .mercurial import Mercurial
return Mercurial(project)
elif project.repo_type == project.GIT:
from .git import getlogs, updaterepo
elif project.repo_type == project.GITHUB:
from .github import getlogs, updaterepo
else:
return None


def get_logs(rev, startrev, update=False):
logs = []
project = rev.branch.project

scm = get_scm(project)
if scm is None:
if project.repo_type not in (project.NO_LOGS, ""):
logger.warning("Don't know how to retrieve logs from %s project",
project.get_repo_type_display())
return logs

if update:
updaterepo(rev.branch.project)
scm.update_repo(project)

logs = getlogs(rev, startrev)
logs = scm.get_logs(rev, startrev)

# Remove last log because the startrev log shouldn't be shown
if len(logs) > 1 and logs[-1].get('commitid') == startrev.commitid:
logs.pop()

return logs


def _get_commit_date(project, commit_id):
scm = get_scm(project)
if scm is None:
return None

return scm.get_commit_date(commit_id)

def get_commit_date(project, commit_id):
date = _get_commit_date(project, commit_id)
if date is not None:
return date

if project.repo_type not in (project.NO_LOGS, ""):
logger.warning("Failed to get the date of the commit %r of project %s",
commit_id, project.get_repo_type_display())
return datetime.datetime.today()
163 changes: 93 additions & 70 deletions codespeed/commits/mercurial.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,80 +13,103 @@
logger = logging.getLogger(__name__)


def updaterepo(project, update=True):
if os.path.exists(project.working_copy):
if not update:
return
class Mercurial:
def __init__(self, project):
self.project = project

def update_repo(self, update=True):
project = self.project
if os.path.exists(project.working_copy):
if not update:
return

p = Popen(['hg', 'pull', '-u'], stdout=PIPE, stderr=PIPE,
cwd=project.working_copy)
stdout, stderr = p.communicate()

if p.returncode != 0 or stderr:
raise CommitLogError("hg pull returned %s: %s" % (p.returncode,
stderr))
else:
return [{'error': False}]
else:
# Clone repo
cmd = ['hg', 'clone', project.repo_path, project.repo_name]

p = Popen(cmd, stdout=PIPE, stderr=PIPE,
cwd=settings.REPOSITORY_BASE_PATH)
logger.debug('Cloning Mercurial repo {0} for project {1}'.format(
project.repo_path, project))
stdout, stderr = p.communicate()

if p.returncode != 0:
raise CommitLogError("%s returned %s: %s" % (" ".join(cmd),
p.returncode,
stderr))
else:
return [{'error': False}]

def get_logs(self, endrev, startrev):
self.update_repo(update=False)

cmd = ["hg", "log",
"-r", "%s::%s" % (startrev.commitid, endrev.commitid),
"--template", "{rev}:{node|short}\n{node}\n{author|user}\n{author|email}\n{date}\n{desc}\n=newlog=\n"]

p = Popen(['hg', 'pull', '-u'], stdout=PIPE, stderr=PIPE,
cwd=project.working_copy)
working_copy = self.project.working_copy
p = Popen(cmd,
stdout=PIPE, stderr=PIPE,
universal_newlines=True,
cwd=working_copy)
stdout, stderr = p.communicate()

if p.returncode != 0 or stderr:
raise CommitLogError("hg pull returned %s: %s" % (p.returncode,
stderr))
if p.returncode != 0:
raise CommitLogError(str(stderr))
else:
return [{'error': False}]
else:
# Clone repo
cmd = ['hg', 'clone', project.repo_path, project.repo_name]

p = Popen(cmd, stdout=PIPE, stderr=PIPE,
cwd=settings.REPOSITORY_BASE_PATH)
logger.debug('Cloning Mercurial repo {0} for project {1}'.format(
project.repo_path, project))
stdout = stdout.rstrip('\n') # Remove last newline
logs = []
for log in stdout.split("=newlog=\n"):
elements = []
elements = log.split('\n')[:-1]
if len(elements) < 6:
# "Malformed" log
logs.append(
{'date': '-', 'message': 'error parsing log', 'commitid': '-'})
else:
short_commit_id = elements.pop(0)
commit_id = elements.pop(0)
author_name = elements.pop(0)
author_email = elements.pop(0)
date = elements.pop(0)
# All other newlines should belong to the description text. Join.
message = '\n'.join(elements)

# Parse date
date = date.split('-')[0]
date = datetime.datetime.fromtimestamp(float(date)).strftime("%Y-%m-%d %H:%M:%S")

# Add changeset info
logs.append({
'date': date, 'author': author_name,
'author_email': author_email, 'message': message,
'short_commit_id': short_commit_id, 'commitid': commit_id})
# Remove last log here because mercurial saves the short hast as commitid now
if len(logs) > 1 and logs[-1].get('short_commit_id') == startrev.commitid:
logs.pop()
return logs

def get_commit_date(self, commit_id):
self.update_repo(update=False)

cmd = ["hg", "log", "-r", commit_id, "--template", "{date|rfc3339date}\n"]

p = Popen(cmd,
stdout=PIPE, stderr=PIPE,
universal_newlines=True,
cwd=self.project.working_copy)
stdout, stderr = p.communicate()

if p.returncode != 0:
raise CommitLogError("%s returned %s: %s" % (" ".join(cmd),
p.returncode,
stderr))
else:
return [{'error': False}]


def getlogs(endrev, startrev):
updaterepo(endrev.branch.project, update=False)

cmd = ["hg", "log",
"-r", "%s::%s" % (startrev.commitid, endrev.commitid),
"--template", "{rev}:{node|short}\n{node}\n{author|user}\n{author|email}\n{date}\n{desc}\n=newlog=\n"]

working_copy = endrev.branch.project.working_copy
p = Popen(cmd, stdout=PIPE, stderr=PIPE, cwd=working_copy)
stdout, stderr = p.communicate()

if p.returncode != 0:
raise CommitLogError(str(stderr))
else:
stdout = stdout.rstrip('\n') # Remove last newline
logs = []
for log in stdout.split("=newlog=\n"):
elements = []
elements = log.split('\n')[:-1]
if len(elements) < 6:
# "Malformed" log
logs.append(
{'date': '-', 'message': 'error parsing log', 'commitid': '-'})
else:
short_commit_id = elements.pop(0)
commit_id = elements.pop(0)
author_name = elements.pop(0)
author_email = elements.pop(0)
date = elements.pop(0)
# All other newlines should belong to the description text. Join.
message = '\n'.join(elements)

# Parse date
date = date.split('-')[0]
date = datetime.datetime.fromtimestamp(float(date)).strftime("%Y-%m-%d %H:%M:%S")

# Add changeset info
logs.append({
'date': date, 'author': author_name,
'author_email': author_email, 'message': message,
'short_commit_id': short_commit_id, 'commitid': commit_id})
# Remove last log here because mercurial saves the short hast as commitid now
if len(logs) > 1 and logs[-1].get('short_commit_id') == startrev.commitid:
logs.pop()
return logs
raise CommitLogError(str(stderr))

return stdout.rstrip()
7 changes: 4 additions & 3 deletions codespeed/results.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,14 +72,15 @@ def save_result(data):
b.full_clean()
b.save()

commit_id = data['commitid']
try:
rev = branch.revisions.get(commitid=data['commitid'])
rev = branch.revisions.get(commitid=commit_id)
except Revision.DoesNotExist:
rev_date = data.get("revision_date")
# "None" (as string) can happen when we urlencode the POST data
if not rev_date or rev_date in ["", "None"]:
rev_date = datetime.today()
rev = Revision(branch=branch, project=p, commitid=data['commitid'],
rev_date = commits.get_commit_date(p, commit_id)
rev = Revision(branch=branch, project=p, commitid=commit_id,
date=rev_date)
try:
rev.full_clean()
Expand Down

0 comments on commit 1bdc67a

Please sign in to comment.