Last active
September 8, 2022 19:18
-
-
Save GrantBirki/046ca2a7675a313fc28afd11d4302209 to your computer and use it in GitHub Desktop.
GitDiff Python
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import git | |
from unidiff import PatchSet | |
import os | |
from io import StringIO | |
class GitDiff: | |
""" | |
Class to get the diff between two branches | |
""" | |
def __init__( | |
self, | |
repo_path=os.getcwd(), | |
base_branch=os.environ.get("BASE_BRANCH", "main"), | |
current_branch=os.environ.get("CURRENT_BRANCH", "HEAD"), | |
): | |
""" | |
Init function | |
:param repo_path: path to the git repo, default is current working directory | |
:param base_branch: base branch to compare with, default is main | |
:param current_branch: current branch to compare, default is HEAD | |
""" | |
self.base_branch = base_branch | |
self.current_branch = current_branch | |
self.repository = git.Repo(repo_path) | |
def json(self): | |
""" | |
Returns a git diff between two branches in json format | |
:return: Array of dicts | |
""" | |
uni_diff_text = self.repository.git.diff( | |
self.base_branch, | |
self.current_branch, | |
ignore_blank_lines=True, | |
ignore_space_at_eol=True, | |
) | |
patch_set = PatchSet(StringIO(uni_diff_text)) | |
change_list = [] | |
for patched_file in patch_set: | |
file_path = patched_file.path | |
added_lines = [] | |
for hunk in patched_file: | |
for line in hunk: | |
if line.is_added and line.value.strip() != "": | |
added_lines.append( | |
{"line_number": line.target_line_no, "line": line.value} | |
) | |
deleted_lines = [] | |
for hunk in patched_file: | |
for line in hunk: | |
if line.is_removed and line.value.strip() != "": | |
deleted_lines.append( | |
{"line_number": line.source_line_no, "line": line.value} | |
) | |
# get modifed lines by comparing added and deleted lines | |
added_to_remove = [] | |
del_to_remove = [] | |
modified_lines = [] | |
for added_line in added_lines: | |
for deleted_line in deleted_lines: | |
if added_line["line_number"] == deleted_line["line_number"]: | |
modified_lines.append( | |
{ | |
"line_number": added_line["line_number"], | |
"line": added_line["line"], | |
} | |
) | |
added_to_remove.append(added_line) | |
del_to_remove.append(deleted_line) | |
# remove modified lines from added and deleted lines | |
for line in added_to_remove: | |
added_lines.remove(line) | |
for line in del_to_remove: | |
deleted_lines.remove(line) | |
change_list.append( | |
{ | |
"file_path": file_path, | |
"added": added_lines, | |
"deleted": deleted_lines, | |
"modified": modified_lines, | |
} | |
) | |
return change_list |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Usage 🔨
Set your env vars:
Use the class: