1
1
import os
2
- from typing import Union
2
+ from typing import Optional , Union
3
3
4
4
from git import Repo
5
5
6
6
import file_utils
7
7
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 {}"
12
11
CONFORMANCE_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"
14
13
)
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
+
16
19
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
19
24
20
25
21
26
def 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:
30
35
os .makedirs (path_to_repo )
31
36
32
37
repo = Repo .init (path_to_repo )
38
+ repo .git .commit ("--allow-empty" , "-m" , INITIAL_COMMIT_MESSAGE )
33
39
34
40
return repo
35
41
@@ -74,10 +80,23 @@ def revert_changes(repo_path: Union[str, os.PathLike]) -> Repo:
74
80
return repo
75
81
76
82
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
+ """
79
93
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
+
81
100
repo .git .reset ("--hard" , commit )
82
101
repo .git .clean ("-xdf" )
83
102
return repo
@@ -99,20 +118,13 @@ def diff(repo_path: Union[str, os.PathLike], previous_frid: str = None) -> dict:
99
118
"""
100
119
repo = Repo (repo_path )
101
120
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 )
106
122
107
123
# Add all files to the index to get a clean diff
108
124
repo .git .add ("-N" , "." )
109
125
110
126
# 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" )
116
128
117
129
if not diff_output :
118
130
return {}
@@ -165,18 +177,37 @@ def diff(repo_path: Union[str, os.PathLike], previous_frid: str = None) -> dict:
165
177
return diff_dict
166
178
167
179
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
+
168
191
def _get_commit_with_frid (repo : Repo , frid : str ) -> str :
169
192
"""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 ))
174
194
if not commit :
175
- raise Exception (f"No commit with frid { frid } found." )
195
+ raise InvalidGitRepositoryError (f"No commit with frid { frid } found." )
176
196
return commit
177
197
178
198
179
199
def _get_base_folder_commit (repo : Repo ) -> str :
180
200
"""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