Skip to content
This repository has been archived by the owner on May 22, 2019. It is now read-only.

Timeline tags #7

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 67 additions & 2 deletions tracext/git/git_fs.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

from trac.core import *
from trac.util import TracError, shorten_line
from trac.util.datefmt import FixedOffset, to_timestamp, format_datetime
from trac.util.datefmt import FixedOffset, to_timestamp, format_datetime, parse_date
from trac.util.text import to_unicode
from trac.versioncontrol.api import \
Changeset, Node, Repository, IRepositoryConnector, NoSuchChangeset, NoSuchNode
Expand All @@ -24,6 +24,9 @@
from trac.config import BoolOption, IntOption, PathOption, Option
from trac.web.chrome import Chrome

from trac.versioncontrol.api import RepositoryManager
from trac.timeline.api import ITimelineEventProvider

from genshi.builder import tag

from datetime import datetime
Expand Down Expand Up @@ -107,7 +110,7 @@ def _parse_user_time(s):
return user, time

class GitConnector(Component):
implements(IRepositoryConnector, IWikiSyntaxProvider)
implements(IRepositoryConnector, IWikiSyntaxProvider, ITimelineEventProvider)

def __init__(self):
self._version = None
Expand All @@ -124,6 +127,68 @@ def __init__(self):
self.log.error("GIT version %s installed not compatible (need >= %s)" %
(self._version['v_str'], self._version['v_min_str']))

#########################
# ITimelineEventProvider

def get_timeline_filters(self, req):
# (internal name, human-readable name, on-by-default)
return [('git-tags', 'Git Tags', True)]

def get_timeline_events(self, req, start, stop, filters):
# if git-tags is enabled, get all the git repositories, then
# get the tags from each repository and compare their timestamp
# to the requested time range. If they are between start and
# stop, return them using Trac's event tuple
tags = []
if 'git-tags' in filters:
rm = RepositoryManager(self.env)
all_repositories = rm.get_all_repositories()
for reponame in all_repositories:
repoinfo = all_repositories[reponame]
if 'type' in repoinfo and repoinfo['type'] == 'git':
repo = rm.get_repository(reponame)
for_each_args = [ '--sort=-taggerdate',
'--format=%(refname:short)|+%(*objectname)|+' +
'%(taggername) %(taggeremail)|+%(taggerdate:iso8601)|+' +
'%(subject)',
'refs/tags' ]
if self._cached_repository:
tag_info = repo.repos.git.repo.for_each_ref(*for_each_args)
else:
tag_info = repo.git.repo.for_each_ref(*for_each_args)
for line in tag_info.splitlines():
(tag_name,tag_deref,user,tag_time_str,tag_msg) = line.split('|+')
if not tag_time_str:
continue # probably a lightweight tag

# Parse time using Trac's parse_time (requires T and Z unfortunately)
date_str, time_str, tz_str = tag_time_str.rsplit(None, 2)
tag_time = parse_date(date_str+'T'+time_str+'Z'+tz_str)

if tag_time > start and tag_time < stop:
self.log.debug( 'found tag %s in repo %s'%(tag_name,repoinfo['name']) )
# (internal-name,date,author,opaque-data)
tags.append(('git-tags',tag_time,user,
{ 'name':tag_name,
'repo':repoinfo['name'],
'deref':tag_deref,
'msg':tag_msg }))
elif tag_time < start:
# git returns tags in reverse chronological order, so if the current
# tag is before the start, all the remaining will also be
break
return tags

def render_timeline_event(self, context, field, event):
# Timeline will create "<a href="url">title by user<a><br>description"
if field == 'title':
title = 'Tag %s created in %s'%(event[3]['name'], event[3]['repo'])
return title
elif field == 'description':
return event[3]['msg']
elif field == 'url':
return context.href.changeset(event[3]['deref'], event[3]['repo'] or None)

#######################
# IWikiSyntaxProvider

Expand Down