Page MenuHomec4science

git.py
No OneTemporary

File Metadata

Created
Mon, Jun 10, 10:29
"""
Gather info for git based repos
"""
import git
import binascii
import datetime as dt
from .. import export
from .. import version_info
from .. import print_colored
@export
class GITInfo(version_info.VersionInfo):
"""
git implementation of the version info class
"""
__repo = None
__other_names = []
def __init__(self, repo, filename, rev_to=None, **kwargs):
super().__init__(repo, filename, **kwargs)
self.__repo = git.Repo(self._repo)
self._name = filename.replace(self._repo, '')
commits = self._list_commits(rev_to=rev_to)
self._modification_dates = [c.authored_date for c in commits]
self.__other_names = self._list_names(commits)
# noinspection PyIncorrectDocstring
def populate(self, author_db, rev_from=None, rev_to=None):
"""
populate the internal variables
"""
_commits = self._list_commits(rev_to=rev_to,
rev_from=rev_from)
for c in _commits:
email = c.author.email
a = author_db.find_by_email(email)
auth = a.user_name
if auth not in self._author_list:
self._author_list[auth] = []
if not author_db.is_author_in_ignore_list(a):
self._authors.add(a)
d = c.authored_date
rev = c.hexsha
msg = c.message
self._author_list[auth].append((d, rev, msg))
def get_modifications(self, revision):
hexsha = binascii.unhexlify(revision)
commit = git.objects.commit.Commit(self.__repo, hexsha)
diffs = commit.diff(commit.parents, R=True, create_patch=True, paths=[self.__other_names])
return '\n'.join((d.diff.decode('UTF-8') for d in diffs))
def modifications_by_author(self, author):
auth = self._author_list[author]
res = []
for d, r, msg in auth:
date = dt.datetime.fromtimestamp(d).strftime("%d-%m-%Y")
short_sha = self.__repo.git.rev_parse(r, short=1)
info = print_colored("@ {0} rev {1} msg {2}".format(date, r, msg), 'blue', attrs=['bold'])
modif = self.get_modifications(r)
res.append([info, modif, modif.split("\n")])
return res
def _list_commits(self, rev_to=None, rev_from=None):
_args = {'follow': True,
'all': True,
'pretty': 'tformat:%H'}
if rev_from is not None:
_args['since'] = rev_from
if rev_to is not None:
_args['until'] = rev_to
git_cmd = git.cmd.Git(working_dir=self.__repo.working_dir)
str_c = git_cmd.log(self._name, **_args)
binhashes = (binascii.unhexlify(c) for c in str_c.split('\n'))
list_commits = [git.objects.commit.Commit(self.__repo, b) for b in binhashes]
return list_commits
def _list_names(self, commits):
"""
Finds all the names of a given file
"""
names = [self._name]
for c in commits:
diffs = c.diff(c.parents,
R=True, M=True)
for d in diffs.iter_change_type('R'):
if d.renamed and d.rename_to in names:
new_path = d.rename_from
self._names[new_path] = c.hexsha
names.append(new_path)
if len(self._names.keys()) == 0:
c = commits[-1]
self._names[self._name] = c.hexsha
names.reverse()
return names
@property
def oldest_name(self):
return self.__other_names[0]

Event Timeline