11import os
2- from typing import Union
2+ from typing import Optional , Union
33
44from git import Repo
55
66import file_utils
77
8- RENDERED_FRID_MESSAGE = "Changes related to Functional requirement ID (FRID): {}"
9- RENDER_ID_MESSAGE = "Render ID: {}"
10- BASE_FOLDER_COMMIT_MESSAGE = "Initialize build with Base Folder content"
11- REFACTORED_CODE_COMMIT_MESSAGE = "Refactored code after implementing {}"
8+ INITIAL_COMMIT_MESSAGE = "[Codeplain] Initial commit"
9+ BASE_FOLDER_COMMIT_MESSAGE = "[Codeplain] Initialize build with Base Folder content"
10+ REFACTORED_CODE_COMMIT_MESSAGE = "[Codeplain] Refactored code after implementing {}"
1211CONFORMANCE_TESTS_PASSED_COMMIT_MESSAGE = (
13- "Fixed issues in the implementation code identified during conformance testing"
12+ "[Codeplain] Fixed issues in the implementation code identified during conformance testing"
1413)
15- FUNCTIONAL_REQUIREMENT_FINISHED_COMMIT_MESSAGE = "Functional requirement ID (FRID): {} fully implemented"
14+ FUNCTIONAL_REQUIREMENT_FINISHED_COMMIT_MESSAGE = "[Codeplain] Functional requirement ID (FRID):{} fully implemented"
15+
16+ RENDERED_FRID_MESSAGE = "Changes related to Functional requirement ID (FRID): {}"
17+ RENDER_ID_MESSAGE = "Render ID: {}"
18+
1619
17- # The commit hash of the empty tree
18- EMPTY_TREE_COMMIT_HASH = "4b825dc642cb6eb9a060e54bf8d69288fbee4904"
20+ class InvalidGitRepositoryError (Exception ):
21+ """Raised when the git repository is in an invalid state."""
22+
23+ pass
1924
2025
2126def init_git_repo (path_to_repo : Union [str , os .PathLike ]) -> Repo :
@@ -30,6 +35,7 @@ def init_git_repo(path_to_repo: Union[str, os.PathLike]) -> Repo:
3035 os .makedirs (path_to_repo )
3136
3237 repo = Repo .init (path_to_repo )
38+ repo .git .commit ("--allow-empty" , "-m" , INITIAL_COMMIT_MESSAGE )
3339
3440 return repo
3541
@@ -74,10 +80,23 @@ def revert_changes(repo_path: Union[str, os.PathLike]) -> Repo:
7480 return repo
7581
7682
77- def revert_to_commit_with_frid (repo_path : Union [str , os .PathLike ], frid : str ) -> Repo :
78- """Finds commit with given frid mentioned in the commit message and reverts the branch to it."""
83+ def revert_to_commit_with_frid (repo_path : Union [str , os .PathLike ], frid : Optional [str ] = None ) -> Repo :
84+ """
85+ Finds commit with given frid mentioned in the commit message and reverts the branch to it.
86+
87+ If frid argument is not provided (None), repo is reverted to the initial state. In case the base folder doesn't exist,
88+ code is reverted to the initial repo commit. Otherwise, the repo is reverted to the base folder commit.
89+
90+ It is expected that the repo has at least one commit related to provided frid if frid is not None.
91+ In case the frid related commit is not found, an exception is raised.
92+ """
7993 repo = Repo (repo_path )
80- commit = _get_commit_with_frid (repo , frid )
94+
95+ commit = _get_commit (repo , frid )
96+
97+ if not commit :
98+ raise InvalidGitRepositoryError ("Git repository is in an invalid state. Relevant commit could not be found." )
99+
81100 repo .git .reset ("--hard" , commit )
82101 repo .git .clean ("-xdf" )
83102 return repo
@@ -99,20 +118,13 @@ def diff(repo_path: Union[str, os.PathLike], previous_frid: str = None) -> dict:
99118 """
100119 repo = Repo (repo_path )
101120
102- if previous_frid :
103- commit = _get_commit_with_frid (repo , previous_frid )
104- else :
105- commit = _get_base_folder_commit (repo )
121+ commit = _get_commit (repo , previous_frid )
106122
107123 # Add all files to the index to get a clean diff
108124 repo .git .add ("-N" , "." )
109125
110126 # Get the raw git diff output, excluding .pyc files
111- if not commit :
112- # If there is no base commit, we are listing all files as new
113- diff_output = repo .git .diff (EMPTY_TREE_COMMIT_HASH , "--text" , ":!*.pyc" )
114- else :
115- diff_output = repo .git .diff (commit , "--text" , ":!*.pyc" )
127+ diff_output = repo .git .diff (commit , "--text" , ":!*.pyc" )
116128
117129 if not diff_output :
118130 return {}
@@ -165,18 +177,37 @@ def diff(repo_path: Union[str, os.PathLike], previous_frid: str = None) -> dict:
165177 return diff_dict
166178
167179
180+ def _get_commit (repo : Repo , frid : str = None ) -> str :
181+ if frid :
182+ commit = _get_commit_with_frid (repo , frid )
183+ else :
184+ commit = _get_base_folder_commit (repo )
185+ if not commit :
186+ commit = _get_initial_commit (repo )
187+
188+ return commit
189+
190+
168191def _get_commit_with_frid (repo : Repo , frid : str ) -> str :
169192 """Finds commit with given frid mentioned in the commit message."""
170- current_branch = repo .active_branch .name
171- commit = repo .git .rev_list (
172- current_branch , "--grep" , FUNCTIONAL_REQUIREMENT_FINISHED_COMMIT_MESSAGE .format (frid ), "-n" , "1"
173- )
193+ commit = _get_commit_with_message (repo , FUNCTIONAL_REQUIREMENT_FINISHED_COMMIT_MESSAGE .format (frid ))
174194 if not commit :
175- raise Exception (f"No commit with frid { frid } found." )
195+ raise InvalidGitRepositoryError (f"No commit with frid { frid } found." )
176196 return commit
177197
178198
179199def _get_base_folder_commit (repo : Repo ) -> str :
180200 """Finds commit related to copy of the base folder."""
181- current_branch = repo .active_branch .name
182- return repo .git .rev_list (current_branch , "--grep" , BASE_FOLDER_COMMIT_MESSAGE , "-n" , "1" )
201+ return _get_commit_with_message (repo , BASE_FOLDER_COMMIT_MESSAGE )
202+
203+
204+ def _get_initial_commit (repo : Repo ) -> str :
205+ """Finds initial commit."""
206+ return _get_commit_with_message (repo , INITIAL_COMMIT_MESSAGE )
207+
208+
209+ def _get_commit_with_message (repo : Repo , message : str ) -> str :
210+ """Finds commit with given message."""
211+ escaped_message = message .replace ("[" , "\\ [" ).replace ("]" , "\\ ]" )
212+
213+ return repo .git .rev_list (repo .active_branch .name , "--grep" , escaped_message , "-n" , "1" )
0 commit comments