1#!/usr/bin/env python3
2#
3# This file is part of GCC.
4#
5# GCC is free software; you can redistribute it and/or modify it under
6# the terms of the GNU General Public License as published by the Free
7# Software Foundation; either version 3, or (at your option) any later
8# version.
9#
10# GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11# WARRANTY; without even the implied warranty of MERCHANTABILITY or
12# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13# for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with GCC; see the file COPYING3.  If not see
17# <http://www.gnu.org/licenses/>.  */
18
19from datetime import datetime
20
21try:
22    from git import Repo
23except ImportError:
24    print('Cannot import GitPython package, please install the package:')
25    print('  Fedora, openSUSE: python3-GitPython')
26    print('  Debian, Ubuntu: python3-git')
27    exit(1)
28
29from git_commit import GitCommit, GitInfo, decode_path
30
31
32def parse_git_revisions(repo_path, revisions, ref_name=None):
33    repo = Repo(repo_path)
34
35    def commit_to_info(commit):
36        try:
37            c = repo.commit(commit)
38            diff = repo.commit(commit + '~').diff(commit)
39
40            modified_files = []
41            for file in diff:
42                if hasattr(file, 'renamed_file'):
43                    is_renamed = file.renamed_file
44                else:
45                    is_renamed = file.renamed
46                if file.new_file:
47                    t = 'A'
48                elif file.deleted_file:
49                    t = 'D'
50                elif is_renamed:
51                    # Consider that renamed files are two operations:
52                    # the deletion of the original name
53                    # and the addition of the new one.
54                    modified_files.append((decode_path(file.a_path), 'D'))
55                    t = 'A'
56                else:
57                    t = 'M'
58                modified_files.append((decode_path(file.b_path), t))
59
60            date = datetime.utcfromtimestamp(c.committed_date)
61            author = '%s  <%s>' % (c.author.name, c.author.email)
62            git_info = GitInfo(c.hexsha, date, author,
63                               c.message.split('\n'), modified_files)
64            return git_info
65        except ValueError:
66            return None
67
68    parsed_commits = []
69    if '..' in revisions:
70        commits = list(repo.iter_commits(revisions))
71    else:
72        commits = [repo.commit(revisions)]
73
74    for commit in commits:
75        git_commit = GitCommit(commit_to_info(commit.hexsha),
76                               commit_to_info_hook=commit_to_info,
77                               ref_name=ref_name)
78        parsed_commits.append(git_commit)
79    return parsed_commits
80