@@ -109,33 +109,43 @@ def revert_to_commit_with_frid(repo_path: Union[str, os.PathLike], frid: Optiona
109109 return repo
110110
111111
112- def diff (repo_path : Union [str , os .PathLike ], previous_frid : str = None ) -> dict :
112+ def checkout_commit_with_frid (repo_path : Union [str , os .PathLike ], frid : Optional [ str ] = None ) -> Repo :
113113 """
114- Get the git diff between the current code state and the previous frid using git's native diff command.
115- If previous_frid is not provided, we try to find the commit related to the copy of the base folder.
116- Removes the 'diff --git' and 'index' lines to get clean unified diff format.
114+ Finds commit with given frid mentioned in the commit message and checks out that commit.
115+
116+ If frid argument is not provided (None), repo is checked out to the initial state. In case the base folder doesn't exist,
117+ code is checked out to the initial repo commit. Otherwise, the repo is checked out to the base folder commit.
117118
119+ It is expected that the repo has at least one commit related to provided frid if frid is not None.
120+ In case the frid related commit is not found, an exception is raised.
121+ """
122+ repo = Repo (repo_path )
123+
124+ commit = _get_commit (repo , frid )
125+
126+ if not commit :
127+ raise InvalidGitRepositoryError ("Git repository is in an invalid state. Relevant commit could not be found." )
128+
129+ repo .git .checkout (commit )
130+ return repo
131+
132+
133+ def checkout_previous_branch (repo_path : Union [str , os .PathLike ]) -> Repo :
134+ """
135+ Checks out the previous branch using 'git checkout -'.
118136
119137 Args:
120138 repo_path (str | os.PathLike): Path to the git repository
121- previous_frid (str): Functional requirement ID (FRID) of the previous commit
122139
123140 Returns:
124- dict: Dictionary with file names as keys and their clean diff strings as values
141+ Repo: The git repository object
125142 """
126143 repo = Repo (repo_path )
144+ repo .git .checkout ("-" )
145+ return repo
127146
128- commit = _get_commit (repo , previous_frid )
129-
130- # Add all files to the index to get a clean diff
131- repo .git .add ("-N" , "." )
132-
133- # Get the raw git diff output, excluding .pyc files
134- diff_output = repo .git .diff (commit , "--text" , ":!*.pyc" )
135-
136- if not diff_output :
137- return {}
138147
148+ def _get_diff_dict (diff_output : str ) -> dict :
139149 diff_dict = {}
140150 current_file = None
141151 current_diff_lines = []
@@ -184,6 +194,36 @@ def diff(repo_path: Union[str, os.PathLike], previous_frid: str = None) -> dict:
184194 return diff_dict
185195
186196
197+ def diff (repo_path : Union [str , os .PathLike ], previous_frid : str = None ) -> dict :
198+ """
199+ Get the git diff between the current code state and the previous frid using git's native diff command.
200+ If previous_frid is not provided, we try to find the commit related to the copy of the base folder.
201+ Removes the 'diff --git' and 'index' lines to get clean unified diff format.
202+
203+
204+ Args:
205+ repo_path (str | os.PathLike): Path to the git repository
206+ previous_frid (str): Functional requirement ID (FRID) of the previous commit
207+
208+ Returns:
209+ dict: Dictionary with file names as keys and their clean diff strings as values
210+ """
211+ repo = Repo (repo_path )
212+
213+ commit = _get_commit (repo , previous_frid )
214+
215+ # Add all files to the index to get a clean diff
216+ repo .git .add ("-N" , "." )
217+
218+ # Get the raw git diff output, excluding .pyc files
219+ diff_output = repo .git .diff (commit , "--text" , ":!*.pyc" )
220+
221+ if not diff_output :
222+ return {}
223+
224+ return _get_diff_dict (diff_output )
225+
226+
187227def _get_commit (repo : Repo , frid : str = None ) -> str :
188228 if frid :
189229 commit = _get_commit_with_frid (repo , frid )
@@ -218,3 +258,47 @@ def _get_commit_with_message(repo: Repo, message: str) -> str:
218258 escaped_message = message .replace ("[" , "\\ [" ).replace ("]" , "\\ ]" )
219259
220260 return repo .git .rev_list (repo .active_branch .name , "--grep" , escaped_message , "-n" , "1" )
261+
262+
263+ def get_implementation_code_diff (repo_path : Union [str , os .PathLike ], frid : str , previous_frid : str ) -> dict :
264+ repo = Repo (repo_path )
265+
266+ implementation_commit = _get_commit_with_message (repo , REFACTORED_CODE_COMMIT_MESSAGE .format (frid ))
267+ if not implementation_commit :
268+ implementation_commit = _get_commit_with_message (
269+ repo , FUNCTIONAL_REQUIREMENT_IMPLEMENTED_COMMIT_MESSAGE .format (frid )
270+ )
271+
272+ previous_frid_commit = _get_commit (repo , previous_frid )
273+
274+ # Get the raw git diff output, excluding .pyc files
275+ diff_output = repo .git .diff (previous_frid_commit , implementation_commit , "--text" , ":!*.pyc" )
276+
277+ if not diff_output :
278+ return {}
279+
280+ return _get_diff_dict (diff_output )
281+
282+
283+ def get_fixed_implementation_code_diff (repo_path : Union [str , os .PathLike ], frid : str ) -> dict :
284+ repo = Repo (repo_path )
285+
286+ implementation_commit = _get_commit_with_message (repo , REFACTORED_CODE_COMMIT_MESSAGE .format (frid ))
287+ if not implementation_commit :
288+ implementation_commit = _get_commit_with_message (
289+ repo , FUNCTIONAL_REQUIREMENT_IMPLEMENTED_COMMIT_MESSAGE .format (frid )
290+ )
291+
292+ conformance_tests_passed_commit = _get_commit_with_message (
293+ repo , CONFORMANCE_TESTS_PASSED_COMMIT_MESSAGE .format (frid )
294+ )
295+ if not conformance_tests_passed_commit :
296+ return None
297+
298+ # Get the raw git diff output, excluding .pyc files
299+ diff_output = repo .git .diff (implementation_commit , conformance_tests_passed_commit , "--text" , ":!*.pyc" )
300+
301+ if not diff_output :
302+ return {}
303+
304+ return _get_diff_dict (diff_output )
0 commit comments