-
Notifications
You must be signed in to change notification settings - Fork 3
/
git.py
120 lines (97 loc) · 3.68 KB
/
git.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
"""This module contains code for git operations"""
import re
import subprocess
from pydriller import GitRepository
def get_git_repo(project_folder):
"""Return a GitRepository"""
if not project_folder:
res = subprocess.check_output(
"git rev-parse --show-toplevel".split(),
stderr=subprocess.DEVNULL,
)
project_folder = res.decode().strip()
return GitRepository(project_folder)
def is_git_repo():
"""Check if current directory or any parent directory is a git repo"""
try:
subprocess.check_output(
"git rev-parse --show-toplevel".split(),
stderr=subprocess.DEVNULL,
)
return True
except subprocess.CalledProcessError:
return False
def repo_has_commits():
"""Check if current repository has commits"""
try:
subprocess.check_output(
["git", "log"],
stderr=subprocess.DEVNULL,
)
return True
except subprocess.CalledProcessError:
return False
def changed_files_between_commits(commit1, commit2, project_folder=None):
"""Get changed files between two commits"""
repo = get_git_repo(project_folder)
return repo.repo.git.diff("--name-only", commit1, commit2).split()
def changed_files_current(project_folder=None):
"""Get changed files in git working directory"""
repo = get_git_repo(project_folder)
return repo.repo.git.diff("--name-only").split()
def file_diff_data_between_commits(
filename, commithash1, commithash2, project_folder=None
):
"""Get git diff for a file from changes between two commits"""
repo = get_git_repo(project_folder)
return repo.repo.git.diff("-U0", commithash1, commithash2, "--", filename)
def file_diff_data_current(filename, project_folder=None):
"""Get git diff for a file in git working directory"""
repo = get_git_repo(project_folder)
return repo.repo.git.diff("-U0", "--", filename)
def get_test_lines_and_update_lines(diff):
"""Parse changed lines, line number updates and new lines from git diff -U0 output"""
regex = r"[@][@]\s+[-][0-9]+(?:,[0-9]+)?\s+[+][0-9]+(?:,[0-9]+)?\s+[@][@]"
line_changes = re.findall(regex, diff)
lines_to_query = []
updates_to_lines = []
new_lines = []
cum_diff = 0
for change in line_changes:
changed_line = change.strip("@").split()
if "," not in changed_line[0]:
changed_line[0] += ",1"
if "," not in changed_line[1]:
changed_line[1] += ",1"
old = changed_line[0].split(",")
old[0] = old[0].strip("-")
new = changed_line[1].split(",")
new[0] = new[0].strip("+")
line_diff = (
((int(new[0]) + int(new[1])) - int(new[0]))
- ((int(old[0]) + int(old[1])) - int(old[0]))
+ cum_diff
)
cum_diff = line_diff
update_tuple = (int(old[0]), line_diff)
updates_to_lines.append(update_tuple)
# example data:
# @@ -old0,old1 +new0,new1 @@
# old0 to old0 + old1 are now new0 to new0+new1
# changed lines: old0 to old0 + old1
# correct?
if int(old[1]) == 0:
lines_to_query.append(int(old[0]))
else:
for i in range(int(old[0]), int(old[0]) + int(old[1])):
lines_to_query.append(i)
# Extract new lines
if int(new[1]) == 0:
new_lines.append(int(new[0]))
else:
for i in range(int(new[0]), int(new[0]) + int(new[1])):
new_lines.append(i)
return lines_to_query, updates_to_lines, new_lines
def get_current_head_hash():
"""Return current git HEAD hash"""
return get_git_repo(None).repo.head.object.hexsha