1#!/usr/bin/env python3
2# coding=utf-8
3#
4# Copyright (c) 2022-2024 Huawei Device Co., Ltd.
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17import os
18import re
19import sys
20
21import git
22
23LINTER_PATH = 'ets2panda/linter'
24
25merge_re = re.compile(r'Merge pull request !')
26revert_re = re.compile(r'This reverts commit (.+)\.')
27cherry_pick_re = re.compile(r'\(cherry picked from commit (.+)\)')
28
29
30def get_branch_map(repo, branch_name, path):
31    result = {}
32
33    commits = list(repo.iter_commits(branch_name, path))
34    commits.reverse()
35    for commit in commits:
36        msg = commit.message
37        if merge_re.search(msg) is not None:
38            continue
39
40        revert_match = revert_re.search(msg)
41        if revert_match is not None:
42            sha = revert_match.group(1)
43            if sha in result:
44                del result[sha]
45                continue
46
47        cherry_pick_match = cherry_pick_re.search(msg)
48        sha = commit.hexsha if cherry_pick_match is None else cherry_pick_match.group(1)
49        if sha not in result:
50            result[sha] = commit
51        else:
52            raise Exception(f'Duplicate commit {sha}')
53
54    return result
55
56
57def print_complement(of, to):
58    print('-' * 40)
59    for sha in to:
60        if sha not in of:
61            commit = to[sha]
62            print('{}\n\n{}'.format(commit.hexsha, commit.message.strip('\n')))
63            print('-' * 40)
64
65
66def main():
67    if len(sys.argv) != 3:
68        print('Usage:\n{} first_branch_name second_branch_name'.format(sys.argv[0]))
69        return -1
70
71    first_branch_name = sys.argv[1]
72    second_branch_name = sys.argv[2]
73
74    repo = git.Repo(os.getcwd() + '/../..')
75    first_branch_map = get_branch_map(repo, first_branch_name, LINTER_PATH)
76    second_branch_map = get_branch_map(repo, second_branch_name, LINTER_PATH)
77
78    print('Commits in `{}`, but not in `{}`:\n'.format(first_branch_name, second_branch_name))
79    print_complement(second_branch_map, first_branch_map)
80
81    print('\n')
82    print('=' * 80)
83    print('\n')
84
85    print('Commits in `{}`, but not in `{}`:\n'.format(second_branch_name, first_branch_name))
86    print_complement(first_branch_map, second_branch_map)
87
88    return 0
89
90if __name__ == '__main__':
91    sys.exit(main())
92